Message ID | 1286792263-9244-1-git-send-email-andi@firstfloor.org |
---|---|
State | New |
Headers | show |
On Mon, 11 Oct 2010, Andi Kleen wrote: > Controlled by a define in the OS specific config file. > I only enabled this on x86 Linux for now. OBJECT_FORMAT_ELF is already defined in elfos.h where it belongs (and in several target-specific headers where it doesn't belong - some duplicating the definition in elfos.h, others ELF targets that don't use elfos.h for whatever reason). > +#if !defined (HAVE_LIBELF_H) || !defined (HAVE_GELF_H) \ > + || !defined (HAVE_UNISTD_H) || !defined (HAVE_FCNTL_H) \ > + || defined (CROSS_DIRECTORY_STRUCTURE) Why the CROSS_DIRECTORY_STRUCTURE conditional?
On Mon, Oct 11, 2010 at 02:33:07PM +0000, Joseph S. Myers wrote: > On Mon, 11 Oct 2010, Andi Kleen wrote: > > > Controlled by a define in the OS specific config file. > > I only enabled this on x86 Linux for now. > > OBJECT_FORMAT_ELF is already defined in elfos.h where it belongs (and in > several target-specific headers where it doesn't belong - some duplicating > the definition in elfos.h, others ELF targets that don't use elfos.h for > whatever reason). What do you suggest? Use a different name? > > > +#if !defined (HAVE_LIBELF_H) || !defined (HAVE_GELF_H) \ > > + || !defined (HAVE_UNISTD_H) || !defined (HAVE_FCNTL_H) \ > > + || defined (CROSS_DIRECTORY_STRUCTURE) > > Why the CROSS_DIRECTORY_STRUCTURE conditional? I wasn't sure if the host libelf works from cross compilation. Also some of the other elf format code had checks for it so I thought it was safer to exclude. -Andi
On Mon, 11 Oct 2010, Andi Kleen wrote: > On Mon, Oct 11, 2010 at 02:33:07PM +0000, Joseph S. Myers wrote: > > On Mon, 11 Oct 2010, Andi Kleen wrote: > > > > > Controlled by a define in the OS specific config file. > > > I only enabled this on x86 Linux for now. > > > > OBJECT_FORMAT_ELF is already defined in elfos.h where it belongs (and in > > several target-specific headers where it doesn't belong - some duplicating > > the definition in elfos.h, others ELF targets that don't use elfos.h for > > whatever reason). > > What do you suggest? Use a different name? No. Just allow this code to apply for all ELF targets like it should, rather than trying to enable it specially only for one particular target. > > > +#if !defined (HAVE_LIBELF_H) || !defined (HAVE_GELF_H) \ > > > + || !defined (HAVE_UNISTD_H) || !defined (HAVE_FCNTL_H) \ > > > + || defined (CROSS_DIRECTORY_STRUCTURE) > > > > Why the CROSS_DIRECTORY_STRUCTURE conditional? > > I wasn't sure if the host libelf works from cross compilation. libelf should work for all targets for any host. > Also some of the other elf format code had checks for it so > I thought it was safer to exclude. What code are you talking about? The compiler should never behave differently for a particular target depending on the host unless you have a properly understood reason for it; such a difference certainly isn't "safer", it's dangerous. If it's a matter of non-GNU native linkers, the conditional should be on the choice of linker, not on whether it's a cross compiler. If it's a matter of native system headers describing an object file format, that won't apply with libelf (and in any case, adding equivalent GNU headers describing the format is the correct approach). CROSS_DIRECTORY_STRUCTURE should only ever be used when it is genuinely the *directory structure* - the locations of various files - that is relevant.
"Joseph S. Myers" <joseph@codesourcery.com> writes: > On Mon, 11 Oct 2010, Andi Kleen wrote: > >> On Mon, Oct 11, 2010 at 02:33:07PM +0000, Joseph S. Myers wrote: >> > On Mon, 11 Oct 2010, Andi Kleen wrote: >> > >> > > Controlled by a define in the OS specific config file. >> > > I only enabled this on x86 Linux for now. >> > >> > OBJECT_FORMAT_ELF is already defined in elfos.h where it belongs (and in >> > several target-specific headers where it doesn't belong - some duplicating >> > the definition in elfos.h, others ELF targets that don't use elfos.h for >> > whatever reason). >> >> What do you suggest? Use a different name? > > No. Just allow this code to apply for all ELF targets like it should, > rather than trying to enable it specially only for one particular target. Ok I can do that and drop the cross compile check, but I am only able to test all that on Linux. -Andi
On Mon, Oct 11, 2010 at 04:54:07PM +0100, Dave Korn wrote: > On 11/10/2010 11:17, Andi Kleen wrote: > > From: Andi Kleen <ak@linux.intel.com> > > > > Change collect2 to read the symbol table directly on ELF systems > > using libelf. Also add support for the LTO symbol table. > > This way collect2 can resolve symbols in a object file > > that only has LTO information. > > > > The LTO parser is closely patterned after the code > > in the lto-plugin. > > Rather than duplicating that code, did you consider implementing the plugin > API into collect2? No I didn't consider that and I don't think it makes a lot of sense, because you would need a ELF plugin too. One thing I considered was calling nm with plugin or calling a new lto-nm I wrote, but just doing it directly was much nicer. -Andi
On 11/10/2010 11:17, Andi Kleen wrote: > From: Andi Kleen <ak@linux.intel.com> > > Change collect2 to read the symbol table directly on ELF systems > using libelf. Also add support for the LTO symbol table. > This way collect2 can resolve symbols in a object file > that only has LTO information. > > The LTO parser is closely patterned after the code > in the lto-plugin. Rather than duplicating that code, did you consider implementing the plugin API into collect2? I think this might be quite easy (based on the partial implementation in lto-plugin/lto-symtab.c), and I think if you did it that way you would gain object file format neutrality "for free" as a side-effect. + /* REMOVEME */ You didn't removeme that one! cheers, DaveK
> I'm not clear here: by "an ELF plugin", do you mean one that would return > the native ELF symbols rather than LTO ones? Wouldn't need to be a new plugin > at all, that could easily be done by sending a plugin option to the existing one. The existing plugin only does LTO, not native ELF. > > One thing I considered was calling nm with plugin or calling > > a new lto-nm I wrote, but just doing it directly was much nicer. > > Or, as you say, could use nm with the plugin. I think reusing code is > "nicer" than copy-pasting it with minor variations into multiple locations. I > think it would be really nice clean design if we had just one plugin, capable > of doing "whatever we want", and used it in as many locations as we can, using > a consistent plugin API. I think you're missing the point. collect2 does far more than the linker plugin does. e.g. it scans for all kinds of different sections and does other special magic, which is not done by the LTO plugin which just looks through the symbol table. The code to read the LTO symbol table is also quite small, about 40 lines or so. I don't think it makes sense to go through connotations just to share it. The code to dynamically link the plugin would be also far from being system independent. -Andi
On 11/10/2010 16:34, Andi Kleen wrote: > On Mon, Oct 11, 2010 at 04:54:07PM +0100, Dave Korn wrote: >> On 11/10/2010 11:17, Andi Kleen wrote: >>> >>> Change collect2 to read the symbol table directly on ELF systems >>> using libelf. Also add support for the LTO symbol table. >>> This way collect2 can resolve symbols in a object file >>> that only has LTO information. >>> >>> The LTO parser is closely patterned after the code >>> in the lto-plugin. >> Rather than duplicating that code, did you consider implementing the plugin >> API into collect2? > > No I didn't consider that and I don't think it makes a lot of sense, > because you would need a ELF plugin too. I'm not clear here: by "an ELF plugin", do you mean one that would return the native ELF symbols rather than LTO ones? Wouldn't need to be a new plugin at all, that could easily be done by sending a plugin option to the existing one. > One thing I considered was calling nm with plugin or calling > a new lto-nm I wrote, but just doing it directly was much nicer. Or, as you say, could use nm with the plugin. I think reusing code is "nicer" than copy-pasting it with minor variations into multiple locations. I think it would be really nice clean design if we had just one plugin, capable of doing "whatever we want", and used it in as many locations as we can, using a consistent plugin API. cheers, DaveK
Dave Korn <dave.korn.cygwin@gmail.com> writes: > On 11/10/2010 16:54, Andi Kleen wrote: >>> I'm not clear here: by "an ELF plugin", do you mean one that would return >>> the native ELF symbols rather than LTO ones? Wouldn't need to be a new plugin >>> at all, that could easily be done by sending a plugin option to the existing one. >> >> The existing plugin only does LTO, not native ELF. > > That didn't make anything clearer, I already understood that you were > talking about a plugin that "does" something with ELF, I was trying to get you > to tell me what that "something" was. I'm going to assume the answer > to my Well you're making the suggestions, so I assume you know what the code you're suggesting to use, actually does. > first question was "yes", and your phrase "an ELF plugin" does indeed mean one > that would read the ELF native symbol table rather than the LTO symtab section. Yes. > But I think you're missing my point: collect2 "does" all those other things > *by means of* looking at the symbol table, doesn't it? Which is what > the Actually no: it has some more knowledge, although it's mostly symbol table today. At least some of the changes I plan to implement -- and why I wrote all this in the first place -- will require looking at all sections. > Ah, that's actually a problem that would require libltdl, and even then > might not be possible on all host platforms. Which is a shame, because I'd > really like it if we could control the proliferation of target object-format > dependent code and have it somehow centralized or abstracted, and the > linker If you're worrying about COFF: collect2 already has native COFF support. -Andi
On 11/10/2010 16:54, Andi Kleen wrote: >> I'm not clear here: by "an ELF plugin", do you mean one that would return >> the native ELF symbols rather than LTO ones? Wouldn't need to be a new plugin >> at all, that could easily be done by sending a plugin option to the existing one. > > The existing plugin only does LTO, not native ELF. That didn't make anything clearer, I already understood that you were talking about a plugin that "does" something with ELF, I was trying to get you to tell me what that "something" was. I'm going to assume the answer to my first question was "yes", and your phrase "an ELF plugin" does indeed mean one that would read the ELF native symbol table rather than the LTO symtab section. >>> One thing I considered was calling nm with plugin or calling >>> a new lto-nm I wrote, but just doing it directly was much nicer. >> Or, as you say, could use nm with the plugin. I think reusing code is >> "nicer" than copy-pasting it with minor variations into multiple locations. I >> think it would be really nice clean design if we had just one plugin, capable >> of doing "whatever we want", and used it in as many locations as we can, using >> a consistent plugin API. > > I think you're missing the point. collect2 does far more than the linker plugin > does. > > e.g. it scans for all kinds of different sections and does other special > magic, which is not done by the LTO plugin which just looks through the > symbol table. But I think you're missing my point: collect2 "does" all those other things *by means of* looking at the symbol table, doesn't it? Which is what the lto-plugin a) already does for LTO symbols and b) could trivially easily do likewise for the native ELF symbols. Unless I've overlooked something? > The code to read the LTO symbol table is also quite small, about 40 lines > or so. I don't think it makes sense to go through connotations just > to share it. The code to dynamically link the plugin would be also far > from being system independent. Ah, that's actually a problem that would require libltdl, and even then might not be possible on all host platforms. Which is a shame, because I'd really like it if we could control the proliferation of target object-format dependent code and have it somehow centralized or abstracted, and the linker plugin seemed like a good place to do so. We could then have started getting rid of the existing OBJECT_FORMAT_xxx code in collect2. I have to admit though that I don't know enough about the entire range of GCC targets to know if this would be a sufficiently portable solution, but it ought to work for ELF and COFF. cheers, DaveK
On 11/10/2010 17:28, Andi Kleen wrote: > Dave Korn <dave.korn.cygwin@gmail.com> writes: >> But I think you're missing my point: collect2 "does" all those other things >> *by means of* looking at the symbol table, doesn't it? Which is what >> the > > Actually no: it has some more knowledge, although it's mostly symbol > table today. I think the only other thing apart from symbols is the dynamic library dependencies that it gathers using ldd on some systems. > At least some of the changes I plan to implement -- and why > I wrote all this in the first place -- will require looking at all > sections. Ah well, that's new and certainly doesn't fit with the existing plugin api, otherwise it could have been a good idea. What (out of curiosity and to help with long-term planning) are the new changes you're looking to implement? >> Ah, that's actually a problem that would require libltdl, and even then >> might not be possible on all host platforms. Which is a shame, because I'd >> really like it if we could control the proliferation of target object-format >> dependent code and have it somehow centralized or abstracted, and the >> linker > > If you're worrying about COFF: collect2 already has native COFF support. Yes, I was thinking how nice it would be to remove that! cheers, DaveK
On Mon, Oct 11, 2010 at 06:12:30PM +0100, Dave Korn wrote: > On 11/10/2010 17:28, Andi Kleen wrote: > > Dave Korn <dave.korn.cygwin@gmail.com> writes: > > >> But I think you're missing my point: collect2 "does" all those other things > >> *by means of* looking at the symbol table, doesn't it? Which is what > >> the > > > > Actually no: it has some more knowledge, although it's mostly symbol > > table today. > > I think the only other thing apart from symbols is the dynamic library > dependencies that it gathers using ldd on some systems. It also checks the type for once. > Ah well, that's new and certainly doesn't fit with the existing plugin api, > otherwise it could have been a good idea. > > What (out of curiosity and to help with long-term planning) are the new > changes you're looking to implement? The two changes (which will come soon) are: detecting automatically when -fwhopr is needed and in slim mode pass through data that is non LTOed, but mixed in a object file. This can happen with ld -r, e.g. if some of the input files are assembler. -Andi
diff --git a/gcc/collect2.c b/gcc/collect2.c index a8cd232..cc85dad 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -68,12 +68,20 @@ along with GCC; see the file COPYING3. If not see #undef REAL_STRIP_FILE_NAME #endif +#if !defined (HAVE_LIBELF_H) || !defined (HAVE_GELF_H) \ + || !defined (HAVE_UNISTD_H) || !defined (HAVE_FCNTL_H) \ + || defined (CROSS_DIRECTORY_STRUCTURE) +#undef OBJECT_FORMAT_ELF +#else +#undef REAL_NM_FILE_NAME +#endif + /* If we cannot use a special method, use the ordinary one: run nm to find what symbols are present. In a cross-compiler, this means you need a cross nm, but that is not quite as unpleasant as special headers. */ -#if !defined (OBJECT_FORMAT_COFF) +#if !defined (OBJECT_FORMAT_COFF) && !defined(OBJECT_FORMAT_ELF) #define OBJECT_FORMAT_NONE #endif @@ -869,7 +877,7 @@ prefix_from_string (const char *p, struct path_prefix *pprefix) free (nstore); } -#ifdef OBJECT_FORMAT_NONE +#if defined(OBJECT_FORMAT_NONE) || defined(OBJECT_FORMAT_ELF) /* Add an entry for the object file NAME to object file list LIST. New entries are added at the end of the list. The original pointer @@ -889,7 +897,7 @@ add_lto_object (struct lto_object_list *list, const char *name) list->last = n; } -#endif /* OBJECT_FORMAT_NONE */ +#endif /* OBJECT_FORMAT_NONE || OBJECT_FORMAT_ELF */ /* Perform a link-time recompilation and relink if any of the object @@ -1070,6 +1078,8 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, } } +bool use_plugin = false; + /* Main program. */ int @@ -1132,7 +1142,6 @@ main (int argc, char **argv) const char **c_ptr; char **ld1_argv; const char **ld1; - bool use_plugin = false; /* The kinds of symbols we will have to consider when scanning the outcome of a first pass link. This is ALL to start with, then might @@ -2521,6 +2530,63 @@ write_aix_file (FILE *stream, struct id *list) } #endif +#if defined (OBJECT_FORMAT_NONE) || defined (OBJECT_FORMAT_ELF) + +/* Handle a defined symbol */ + +static void +handle_pass (const char *name, scanpass which_pass, scanfilter filter, + const char *prog_name) +{ + switch (is_ctor_dtor (name)) + { + case SYM_CTOR: + if (! (filter & SCAN_CTOR)) + break; + if (which_pass != PASS_LIB) + add_to_list (&constructors, name); + break; + + case SYM_DTOR: + if (! (filter & SCAN_DTOR)) + break; + if (which_pass != PASS_LIB) + add_to_list (&destructors, name); + break; + + case SYM_INIT: + if (! (filter & SCAN_INIT)) + break; + if (which_pass != PASS_LIB) + fatal ("init function found in object %s", prog_name); +#ifndef LD_INIT_SWITCH + add_to_list (&constructors, name); +#endif + break; + + case SYM_FINI: + if (! (filter & SCAN_FINI)) + break; + if (which_pass != PASS_LIB) + fatal ("fini function found in object %s", prog_name); +#ifndef LD_FINI_SWITCH + add_to_list (&destructors, name); +#endif + break; + + case SYM_DWEH: + if (! (filter & SCAN_DWEH)) + break; + if (which_pass != PASS_LIB) + add_to_list (&frame_tables, name); + break; + + case SYM_REGULAR: + break; + } +} +#endif + #ifdef OBJECT_FORMAT_NONE /* Check to make sure the file is an LTO object file. */ @@ -2703,52 +2769,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass, *end = '\0'; - switch (is_ctor_dtor (name)) - { - case SYM_CTOR: - if (! (filter & SCAN_CTOR)) - break; - if (which_pass != PASS_LIB) - add_to_list (&constructors, name); - break; - - case SYM_DTOR: - if (! (filter & SCAN_DTOR)) - break; - if (which_pass != PASS_LIB) - add_to_list (&destructors, name); - break; - - case SYM_INIT: - if (! (filter & SCAN_INIT)) - break; - if (which_pass != PASS_LIB) - fatal ("init function found in object %s", prog_name); -#ifndef LD_INIT_SWITCH - add_to_list (&constructors, name); -#endif - break; - - case SYM_FINI: - if (! (filter & SCAN_FINI)) - break; - if (which_pass != PASS_LIB) - fatal ("fini function found in object %s", prog_name); -#ifndef LD_FINI_SWITCH - add_to_list (&destructors, name); -#endif - break; - - case SYM_DWEH: - if (! (filter & SCAN_DWEH)) - break; - if (which_pass != PASS_LIB) - add_to_list (&frame_tables, name); - break; - - default: /* not a constructor or destructor */ - continue; - } + handle_pass (name, which_pass, filter, prog_name); } if (debug) @@ -3218,3 +3239,194 @@ resolve_lib_name (const char *name) return (NULL); } #endif /* COLLECT_EXPORT_LIST */ + +#ifdef OBJECT_FORMAT_ELF +#include <libelf.h> +#include <gelf.h> +#include <plugin-api.h> + +#include <sys/fcntl.h> +#include <unistd.h> + +#define LTO_SYMTAB_NAME ".gnu.lto_.symtab" + +/* Scan a LTO symbol table section. */ + +static unsigned +scan_lto_symtab (Elf_Data *tab, scanpass which_pass, + scanfilter filter, const char *prog_name) +{ + unsigned nsyms = 0; + char *p; + + for (p = (char *)tab->d_buf; p < (char *)tab->d_buf + tab->d_size; ) + { + const char *name; + int skip = 0; + + /* Done in the same way as the lto-plugin. */ + + /* name */ + name = p; + while (*p++) + ; + /* comdat */ + while (*p++) + ; + /* translate */ + if (*p == LDPK_UNDEF || *p == LDPK_WEAKUNDEF) + skip = 1; + p++; + /* visibility */ + p++; + /* size */ + p += 8; + /* slot */ + p += 4; + + if (!skip) + handle_pass (name, which_pass, filter, prog_name); + nsyms++; + } + return nsyms; +} + +/* Scan a ELF symbol table */ + +static unsigned +scan_elf_symtab (Elf *elf, Elf_Data *data, GElf_Shdr *shdr, + scanpass which_pass, scanfilter filter, const char *prog_name) +{ + unsigned i; + unsigned nsyms = shdr->sh_size / shdr->sh_entsize; + unsigned proc = 0; + + for (i = 0; i < nsyms; i++) + { + GElf_Sym sym; + const char *name; + + gelf_getsym (data, i, &sym); + + if (ELF32_ST_TYPE (sym.st_info) >= STT_SECTION) + continue; + if (sym.st_shndx == SHN_UNDEF || sym.st_shndx >= SHN_LORESERVE) + continue; + name = elf_strptr (elf, shdr->sh_link, sym.st_name); + handle_pass (name, which_pass, filter, prog_name); + proc++; + } + + /* REMOVEME */ + fprintf (stderr, "nsyms = %u skipped = %u\n", nsyms, nsyms - proc); + return nsyms; +} + +/* Is FD an ar file? */ + +static int +is_ar (int fd) +{ + char buf[8]; + bool isar = false; + + if (read (fd, buf, 8) == 8) + isar = !memcmp (buf, "!<arch>\r", 8); + lseek (fd, 0, SEEK_SET); + return isar; +} + +/* ELF version to scan the name list of the loaded program for + the symbols g++ uses for static constructors and destructors. + This also supports LTO symbol tables. */ + +static void +scan_prog_file (const char *prog_name, scanpass which_pass, + scanfilter filter) +{ + int fd; + GElf_Ehdr header; + Elf *elf; + Elf_Scn *section; + unsigned syms = 0; + unsigned sections = 0; + unsigned lto = 0; + + if (which_pass == PASS_SECOND) + return; + + if (debug) + fprintf (stderr, "Scanning file '%s'\n", prog_name); + + elf_version (EV_CURRENT); + fd = open (prog_name, O_RDONLY); + if (fd < 0) + { + fprintf (stderr, "Cannot open %s\n", prog_name); + return; + } + + /* It is difficult to figure out if an ar file needs LTO or not. + If we use the linker plugin and it is an ar file just handle + it like a LTO file unconditionally. */ + if (which_pass == PASS_LTOINFO && use_plugin && is_ar (fd)) + { + if (debug) + fprintf (stderr, "Handling ar file %s as LTO\n", prog_name); + add_lto_object (<o_objects, prog_name); + return; + } + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + fprintf (stderr, "Cannot run elf_begin on %s: %s\n", prog_name, + elf_errmsg (0)); + close (fd); + return; + } + if (!gelf_getehdr (elf, &header)) + fatal ("Cannot find EHDR in %s: %s", prog_name, elf_errmsg (0)); + + section = NULL; + while ((section = elf_nextscn (elf, section)) != 0) + { + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (section, &shdr_mem); + char *name; + int islto; + + sections++; + + if (!shdr) + fatal("Cannot read SHDR for section %d: %s", sections, elf_errmsg (0)); + + name = elf_strptr (elf, header.e_shstrndx, shdr->sh_name); + islto = !strncmp (name, LTO_SYMTAB_NAME, strlen (LTO_SYMTAB_NAME)); + lto += islto; + + if (which_pass == PASS_LTOINFO) + { + if (!islto) + continue; + add_lto_object (<o_objects, prog_name); + break; + } + + if (islto) + syms += scan_lto_symtab (elf_getdata (section, NULL), which_pass, + filter, prog_name); + else if (shdr->sh_type == SHT_SYMTAB && shdr->sh_entsize > 0) + syms += scan_elf_symtab (elf, elf_getdata (section, NULL), shdr, + which_pass, filter, prog_name); + } + + if (debug) + fprintf (stderr, "Scanned %u symbols, %u sections, %u LTO\n", syms, + sections, lto); + + elf_end (elf); + close (fd); +} + +#endif diff --git a/gcc/config.in b/gcc/config.in index 4576de0..d141e6a 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1017,6 +1017,12 @@ #endif +/* Define to 1 if you have the <gelf.h> header file. */ +#ifndef USED_FOR_TARGET +#undef HAVE_GELF_H +#endif + + /* Define to 1 if you have the `getchar_unlocked' function. */ #ifndef USED_FOR_TARGET #undef HAVE_GETCHAR_UNLOCKED @@ -1215,6 +1221,12 @@ #endif +/* Define to 1 if you have the <libelf.h> header file. */ +#ifndef USED_FOR_TARGET +#undef HAVE_LIBELF_H +#endif + + /* Define to 1 if you have the <limits.h> header file. */ #ifndef USED_FOR_TARGET #undef HAVE_LIMITS_H diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h index 7564c70..4ef951e 100644 --- a/gcc/config/i386/linux.h +++ b/gcc/config/i386/linux.h @@ -223,3 +223,5 @@ along with GCC; see the file COPYING3. If not see #define TARGET_CAN_SPLIT_STACK #define TARGET_THREAD_SPLIT_STACK_OFFSET 0x30 #endif + +#define OBJECT_FORMAT_ELF 1 diff --git a/gcc/configure b/gcc/configure index 27962d5..babda31 100755 --- a/gcc/configure +++ b/gcc/configure @@ -7870,7 +7870,8 @@ fi for ac_header in limits.h stddef.h string.h strings.h stdlib.h time.h iconv.h \ fcntl.h unistd.h sys/file.h sys/time.h sys/mman.h \ sys/resource.h sys/param.h sys/times.h sys/stat.h \ - direct.h malloc.h langinfo.h ldfcn.h locale.h wchar.h + direct.h malloc.h langinfo.h ldfcn.h locale.h wchar.h \ + libelf.h gelf.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header" @@ -8209,7 +8210,7 @@ if test "${gcc_cv_collect2_libs+set}" = set; then : $as_echo_n "(cached) " >&6 else save_LIBS="$LIBS" -for libs in '' -lld -lmld \ +for libs in '' -lelf -lld -lmld \ '-L/usr/lib/cmplrs/cc2.11 -lmld' \ '-L/usr/lib/cmplrs/cc3.11 -lmld' do @@ -8238,6 +8239,31 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done +LIBS=-lelf +test -z "$gcc_cv_collect2_libs" && +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char elf_version (); +int +main () +{ +return elf_version (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gcc_cv_collect2_libs=-lelf +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" test -z "$gcc_cv_collect2_libs" && gcc_cv_collect2_libs='none required' fi diff --git a/gcc/configure.ac b/gcc/configure.ac index 1534f7f..e87b86b 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -893,7 +893,8 @@ AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(limits.h stddef.h string.h strings.h stdlib.h time.h iconv.h \ fcntl.h unistd.h sys/file.h sys/time.h sys/mman.h \ sys/resource.h sys/param.h sys/times.h sys/stat.h \ - direct.h malloc.h langinfo.h ldfcn.h locale.h wchar.h) + direct.h malloc.h langinfo.h ldfcn.h locale.h wchar.h \ + libelf.h gelf.h) # Check for thread headers. AC_CHECK_HEADER(thread.h, [have_thread_h=yes], [have_thread_h=]) @@ -912,7 +913,7 @@ AC_C_BIGENDIAN # We may need a special search path to get them linked. AC_CACHE_CHECK(for collect2 libraries, gcc_cv_collect2_libs, [save_LIBS="$LIBS" -for libs in '' -lld -lmld \ +for libs in '' -lelf -lld -lmld \ '-L/usr/lib/cmplrs/cc2.11 -lmld' \ '-L/usr/lib/cmplrs/cc3.11 -lmld' do @@ -920,6 +921,9 @@ do AC_TRY_LINK_FUNC(ldopen, [gcc_cv_collect2_libs="$libs"; break]) done +LIBS=-lelf +test -z "$gcc_cv_collect2_libs" && +AC_TRY_LINK_FUNC(elf_version, [gcc_cv_collect2_libs=-lelf]) LIBS="$save_LIBS" test -z "$gcc_cv_collect2_libs" && gcc_cv_collect2_libs='none required']) case $gcc_cv_collect2_libs in
From: Andi Kleen <ak@linux.intel.com> Change collect2 to read the symbol table directly on ELF systems using libelf. Also add support for the LTO symbol table. This way collect2 can resolve symbols in a object file that only has LTO information. The LTO parser is closely patterned after the code in the lto-plugin. Controlled by a define in the OS specific config file. I only enabled this on x86 Linux for now. gcc/ 2010-10-07 Andi Kleen <ak@linux.intel.com> * collect2.c: Add ifdefs for OBJECT_FORMAT_ELF. (main): Move use_plugin to top level. (scan_prog_file): Move switch statement to .. (handle_pass): Separate function here. (LTO_SYMTAB_NAME, scan_lto_symtab, scan_elf_symtab, is_ar, scan_prog_file): Add. * config.in: Regenerate. * config/i386/linux.h (OBJECT_FORMAT_ELF): Define. * configure: Regenerate. * configure.ac: Check for libelf.h and gelf.h. Adjust libelf test. --- gcc/collect2.c | 312 +++++++++++++++++++++++++++++++++++++++-------- gcc/config.in | 12 ++ gcc/config/i386/linux.h | 2 + gcc/configure | 30 ++++- gcc/configure.ac | 8 +- 5 files changed, 310 insertions(+), 54 deletions(-)