summaryrefslogtreecommitdiff
path: root/lto-plugin/lto-plugin.c
diff options
context:
space:
mode:
authordavek <davek@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-03 09:14:32 +0000
committerdavek <davek@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-03 09:14:32 +0000
commit25630dc79a217ae6e7ccac9ef62c93b88490d036 (patch)
tree727195368f3f7531be4fdf5a82d599ea20456d83 /lto-plugin/lto-plugin.c
parentbf07bf98a8277a332920f508ae5d22f29c0dd450 (diff)
downloadgcc-25630dc79a217ae6e7ccac9ef62c93b88490d036.tar.gz
ChangeLog:
2010-11-03 Ian Lance Taylor <iant@google.com> Dave Korn <dave.korn.cygwin@gmail.com> PR lto/46273 * configure.ac: Remove libelf tests. Build lto-plugin on ELF always and on other supported platforms whenever LTO is enabled. * configure: Rebuild. gcc/ChangeLog: 2010-11-03 Ian Lance Taylor <iant@google.com> PR lto/46273 * gcc/config.gcc: Don't set lto_binary_reader. * doc/install.texi (Prerequisites): Remove libelf paragraphs. (Configuration): Mention --disable-lto. Remove --with-libelf paragraph. lto-plugin/ChangeLog: 2010-11-03 Dave Korn <dave.korn.cygwin@gmail.com> PR lto/46273 * lto-plugin.h: Delete. * lto-plugin-elf.c: Likewise. * lto-plugin-coff.c: Likewise. * configure.ac: Don't use libelf, don't source config.gcc. (LIBELFLIBS): Delete. (LIBELFINC): Delete. (LTO_FORMAT): Delete. (SYM_STYLE): Add AC_DEFINE var, set based on $target. (config.h): Add AC_CONFIG_HEADERS directive. * Makefile.am (LIBELFLIBS): Delete. (LIBELFINC): Delete. (LTO_FORMAT): Delete. (DEFS): Import. (AM_CPPFLAGS): Use it. Don't use LIBELFINC. (liblto_plugin_la_SOURCES): Don't use LTO_FORMAT, don't include any object-format-specific source file in the link. (liblto_plugin_la_LIBADD): Don't use LIBELFLIBS. * config.h.in: Generate. * configure: Regenerate. * Makefile.in: Likewise. * lto-plugin.c (O_BINARY): Definition moved here from lto-plugin.h. (LTO_SEGMENT_NAME): New definition. (LTO_SECTION_PREFIX): Definition moved here from lto-plugin.h. (LTO_SECTION_PREFIX_LEN): New definition. (struct sym_aux): Struct definition moved here from lto-plugin.h. (struct plugin_symtab): Likewise. (struct plugin_objfile): Likewise. (struct plugin_objfile): New struct def. (enum symbol_style): New enum type. (add_symbols): Make static. (claimed_files): Likewise. (num_claimed_files): Likewise. (sym_style): New global. (check): Make static. (parse_table_entry): Likewise. Respect sym_style when extracting symbol from symtab entry. (translate): Make static. (resolve_conflicts): Likewise. (process_symtab): New function, per-section callback version of old object-format-specific handling from deleted lto-plugin-elf.c. (claim_file_handler): Convert ELF-specific version from deleted lto-plugin-elf.c to simple_object interface and move here. (process_options): Allow new '-sym-style=' option. (onload): Don't call deleted onload_format_checks hook. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166233 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'lto-plugin/lto-plugin.c')
-rw-r--r--lto-plugin/lto-plugin.c248
1 files changed, 231 insertions, 17 deletions
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
index 433f545391f..7df0d6f3c01 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -32,6 +32,9 @@ along with this program; see the file COPYING3. If not see
-nop: Instead of running lto-wrapper, pass the original to the plugin. This
only works if the input files are hybrid. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <assert.h>
#include <string.h>
#include <stdlib.h>
@@ -46,9 +49,72 @@ along with this program; see the file COPYING3. If not see
#include <libiberty.h>
#include <hashtab.h>
#include "../gcc/lto/common.h"
+#include "simple-object.h"
+#include "plugin-api.h"
-/* Common definitions for/from the object format dependent code. */
-#include "lto-plugin.h"
+/* Handle opening elf files on hosts, such as Windows, that may use
+ text file handling that will break binary access. */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+/* Segment name for LTO sections. This is only used for Mach-O.
+ FIXME: This needs to be kept in sync with darwin.c. */
+
+#define LTO_SEGMENT_NAME "__GNU_LTO"
+
+/* LTO magic section name. */
+
+#define LTO_SECTION_PREFIX ".gnu.lto_.symtab"
+#define LTO_SECTION_PREFIX_LEN (sizeof (LTO_SECTION_PREFIX) - 1)
+
+/* The part of the symbol table the plugin has to keep track of. Note that we
+ must keep SYMS until all_symbols_read is called to give the linker time to
+ copy the symbol information. */
+
+struct sym_aux
+{
+ uint32_t slot;
+ unsigned id;
+ unsigned next_conflict;
+};
+
+struct plugin_symtab
+{
+ int nsyms;
+ struct sym_aux *aux;
+ struct ld_plugin_symbol *syms;
+ unsigned id;
+};
+
+/* Encapsulates object file data during symbol scan. */
+struct plugin_objfile
+{
+ int found;
+ simple_object_read *objfile;
+ struct plugin_symtab *out;
+ const struct ld_plugin_input_file *file;
+};
+
+/* All that we have to remember about a file. */
+
+struct plugin_file_info
+{
+ char *name;
+ void *handle;
+ struct plugin_symtab symtab;
+ struct plugin_symtab conflicts;
+};
+
+/* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
+ stdio file streams, we do simple label translation here. */
+
+enum symbol_style
+{
+ ss_none, /* No underscore prefix. */
+ ss_win32, /* Underscore prefix any symbol not beginning with '@'. */
+ ss_uscore, /* Underscore prefix all symbols. */
+};
static char *arguments_file_name;
static ld_plugin_register_claim_file register_claim_file;
@@ -58,13 +124,10 @@ static ld_plugin_register_cleanup register_cleanup;
static ld_plugin_add_input_file add_input_file;
static ld_plugin_add_input_library add_input_library;
static ld_plugin_message message;
+static ld_plugin_add_symbols add_symbols;
-/* These are not static because the object format dependent
- claim_file hooks in lto-plugin-{coff,elf}.c need them. */
-ld_plugin_add_symbols add_symbols;
-
-struct plugin_file_info *claimed_files = NULL;
-unsigned int num_claimed_files = 0;
+static struct plugin_file_info *claimed_files = NULL;
+static unsigned int num_claimed_files = 0;
static char **output_files = NULL;
static unsigned int num_output_files = 0;
@@ -79,7 +142,12 @@ static bool debug;
static bool nop;
static char *resolution_file = NULL;
-void
+/* Set by default from configure.ac, but can be overridden at runtime
+ by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
+ (in fact, only first letter of style arg is checked.) */
+static enum symbol_style sym_style = SYM_STYLE;
+
+static void
check (bool gate, enum ld_plugin_level level, const char *text)
{
if (gate)
@@ -100,7 +168,7 @@ check (bool gate, enum ld_plugin_level level, const char *text)
by P and the result is written in ENTRY. The slot number is stored in SLOT.
Returns the address of the next entry. */
-char *
+static char *
parse_table_entry (char *p, struct ld_plugin_symbol *entry,
struct sym_aux *aux)
{
@@ -122,7 +190,24 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry,
LDPV_HIDDEN
};
- entry->name = xstrdup (p);
+ switch (sym_style)
+ {
+ case ss_win32:
+ if (p[0] == '@')
+ {
+ /* cf. Duff's device. */
+ case ss_none:
+ entry->name = xstrdup (p);
+ break;
+ }
+ /* FALL-THROUGH. */
+ case ss_uscore:
+ entry->name = concat ("_", p, NULL);
+ break;
+ default:
+ check (false, LDPL_FATAL, "invalid symbol style requested");
+ break;
+ }
while (*p)
p++;
p++;
@@ -165,7 +250,7 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry,
/* Translate the IL symbol table located between DATA and END. Append the
slots and symbols to OUT. */
-void
+static void
translate (char *data, char *end, struct plugin_symtab *out)
{
struct sym_aux *aux;
@@ -621,7 +706,7 @@ static int symbol_strength (struct ld_plugin_symbol *s)
XXX how to handle common? */
-void
+static void
resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
{
htab_t symtab = htab_create (t->nsyms, hash_sym, eq_sym, NULL);
@@ -689,6 +774,124 @@ resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
htab_delete (symtab);
}
+/* Process one section of an object file. */
+
+static int
+process_symtab (void *data, const char *name, off_t offset, off_t length)
+{
+ struct plugin_objfile *obj = (struct plugin_objfile *)data;
+ char *s;
+ char *secdata;
+
+ if (strncmp (name, LTO_SECTION_PREFIX, LTO_SECTION_PREFIX_LEN) != 0)
+ return 1;
+
+ s = strrchr (name, '.');
+ if (s)
+ sscanf (s, ".%x", &obj->out->id);
+ secdata = xmalloc (length);
+ offset += obj->file->offset;
+ if (offset != lseek (obj->file->fd, offset, SEEK_SET)
+ || length != read (obj->file->fd, secdata, length))
+ {
+ if (message)
+ message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
+ /* Force claim_file_handler to abandon this file. */
+ obj->found = 0;
+ free (secdata);
+ return 0;
+ }
+
+ translate (secdata, secdata + length, obj->out);
+ obj->found++;
+ free (secdata);
+ return 1;
+}
+
+/* Callback used by gold to check if the plugin will claim FILE. Writes
+ the result in CLAIMED. */
+
+static enum ld_plugin_status
+claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
+{
+ enum ld_plugin_status status;
+ struct plugin_objfile obj;
+ struct plugin_file_info lto_file;
+ int err;
+ const char *errmsg;
+
+ memset (&lto_file, 0, sizeof (struct plugin_file_info));
+
+ if (file->offset != 0)
+ {
+ char *objname;
+ /* We pass the offset of the actual file, not the archive header. */
+ int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
+ (int64_t) file->offset);
+ check (t >= 0, LDPL_FATAL, "asprintf failed");
+ lto_file.name = objname;
+ }
+ else
+ {
+ lto_file.name = xstrdup (file->name);
+ }
+ lto_file.handle = file->handle;
+
+ *claimed = 0;
+ obj.file = file;
+ obj.found = 0;
+ obj.out = &lto_file.symtab;
+ errmsg = NULL;
+ obj.objfile = simple_object_start_read (file->fd, file->offset, LTO_SEGMENT_NAME,
+ &errmsg, &err);
+ /* No file, but also no error code means unrecognized format; just skip it. */
+ if (!obj.objfile && !err)
+ goto err;
+
+ if (obj.objfile)
+ errmsg = simple_object_find_sections (obj.objfile, process_symtab, &obj, &err);
+
+ if (!obj.objfile || errmsg)
+ {
+ if (err && message)
+ message (LDPL_FATAL, "%s: %s: %s", file->name, errmsg,
+ xstrerror (err));
+ else if (message)
+ message (LDPL_FATAL, "%s: %s", file->name, errmsg);
+ goto err;
+ }
+
+ if (obj.found == 0)
+ goto err;
+
+ if (obj.found > 1)
+ resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
+
+ status = add_symbols (file->handle, lto_file.symtab.nsyms,
+ lto_file.symtab.syms);
+ check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
+
+ *claimed = 1;
+ num_claimed_files++;
+ claimed_files =
+ xrealloc (claimed_files,
+ num_claimed_files * sizeof (struct plugin_file_info));
+ claimed_files[num_claimed_files - 1] = lto_file;
+
+ goto cleanup;
+
+ err:
+ free (lto_file.name);
+
+ cleanup:
+ if (obj.objfile)
+ simple_object_release_read (obj.objfile);
+ if (file->fd >= 0)
+ close (file->fd);
+
+ return LDPS_OK;
+}
+
/* Parse the plugin options. */
static void
@@ -706,6 +909,21 @@ process_option (const char *option)
pass_through_items[num_pass_through_items - 1] =
xstrdup (option + strlen ("-pass-through="));
}
+ else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
+ {
+ switch (option[sizeof ("-sym-style=") - 1])
+ {
+ case 'w':
+ sym_style = ss_win32;
+ break;
+ case 'u':
+ sym_style = ss_uscore;
+ break;
+ default:
+ sym_style = ss_none;
+ break;
+ }
+ }
else
{
int size;
@@ -727,10 +945,6 @@ onload (struct ld_plugin_tv *tv)
struct ld_plugin_tv *p;
enum ld_plugin_status status;
- status = onload_format_checks (tv);
- if (status != LDPS_OK)
- return status;
-
p = tv;
while (p->tv_tag)
{