Mercurial > illumos > illumos-gate
changeset 3875:aede79dcec2e
6516665 The link-editors should be more resilient against gcc's symbol versioning
line wrap: on
line diff
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.c Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c Wed Mar 21 10:53:55 2007 -0700 @@ -41,6 +41,49 @@ #include <msg.h> #include <_elfdump.h> + + +/* + * VERSYM_STATE is used to maintain information about the VERSYM section + * in the object being analyzed. It is filled in by versions(), and used + * by init_symtbl_state() when displaying symbol information. + * + * Note that the value of the gnu field is a hueristic guess, + * based on the section names. + */ +typedef struct { + Cache *cache; /* Pointer to cache entry for VERSYM */ + Versym *data; /* Pointer to versym array */ + int num_verdef; /* # of versions defined in object */ + int gnu; /* True if we think obj produced by GNU tools */ +} VERSYM_STATE; + +/* + * SYMTBL_STATE is used to maintain information about a single symbol + * table section, for use by the routines that display symbol information. + */ +typedef struct { + const char *file; /* Name of file */ + Ehdr *ehdr; /* ELF header for file */ + Cache *cache; /* Cache of all section headers */ + Word shnum; /* # of sections in cache */ + Cache *seccache; /* Cache of symbol table section hdr */ + Word secndx; /* Index of symbol table section hdr */ + const char *secname; /* Name of section */ + uint_t flags; /* Command line option flags */ + struct { /* Extended section index data */ + int checked; /* TRUE if already checked for shxndx */ + Word *data; /* NULL, or extended section index */ + /* used for symbol table entries */ + uint_t n; /* # items in shxndx.data */ + } shxndx; + VERSYM_STATE *versym; /* NULL, or associated VERSYM section */ + Sym *sym; /* Array of symbols */ + Word symn; /* # of symbols */ +} SYMTBL_STATE; + + + /* * Focal point for verifying symbol names. */ @@ -978,15 +1021,27 @@ } /* - * Search for any version sections - the Versym output is possibly used by the - * symbols() printing. If VERSYM is specified - then display the version - * information. + * Display version section information if the flags require it. + * Return version information needed by other output. + * + * entry: + * cache - Cache of all section headers + * shnum - # of sections in cache + * file - Name of file + * flags - Command line option flags + * versym - VERSYM_STATE block to be filled in. */ -static Cache * -versions(Cache *cache, Word shnum, const char *file, uint_t flags) +static void +versions(Cache *cache, Word shnum, const char *file, uint_t flags, + VERSYM_STATE *versym) { GElf_Word cnt; - Cache *versymcache = 0; + const char *gnu_prefix; + size_t gnu_prefix_len; + + bzero(versym, sizeof (*versym)); + gnu_prefix = MSG_ORIG(MSG_GNU_VERNAMPREFIX); + gnu_prefix_len = strlen(gnu_prefix); for (cnt = 1; cnt < shnum; cnt++) { void *ver; @@ -996,14 +1051,31 @@ const char *secname = _cache->c_name; /* - * If this is the version symbol table simply record its - * data address for possible use in later symbol processing. + * If the section names starts with the .gnu.version prefix, + * then this object was almost certainly produced by the + * GNU ld and not the native Solaris ld. */ - if (shdr->sh_type == SHT_SUNW_versym) { - versymcache = _cache; + if (strncmp(gnu_prefix, secname, gnu_prefix_len) == 0) + versym->gnu = 1; + + /* + * If this is the version symbol table record its data + * address for later symbol processing. + */ + if ((shdr->sh_type == SHT_SUNW_versym) && + (_cache->c_data != NULL)) { + versym->cache = _cache; + versym->data = _cache->c_data->d_buf; continue; } + /* + * If this is a version definition section, retain # of + * version definitions for later symbol processing. + */ + if (shdr->sh_type == SHT_SUNW_verdef) + versym->num_verdef = shdr->sh_info; + if ((flags & FLG_VERSIONS) == 0) continue; @@ -1046,34 +1118,9 @@ &cache[shdr->sh_link], file); } } - return (versymcache); } /* - * SYMTBL_STATE is used to maintain information about a single symbol - * table section, for use by the routines that display symbol information. - */ -typedef struct { - const char *file; /* Name of file */ - Ehdr *ehdr; /* ELF header for file */ - Cache *cache; /* Cache of all section headers */ - Word shnum; /* # of sections in cache */ - Cache *seccache; /* Cache of symbol table section hdr */ - Word secndx; /* Index of symbol table section hdr */ - const char *secname; /* Name of section */ - uint_t flags; /* Command line option flags */ - struct { /* Extended section index data */ - int checked; /* TRUE if already checked for shxndx */ - Word *data; /* NULL, or extended section index */ - /* used for symbol table entries */ - uint_t n; /* # items in shxndx.data */ - } shxndx; - Versym *versym; /* NULL, or versym array for symtbl */ - Sym *sym; /* Array of symbols */ - Word symn; /* # of symbols */ -} SYMTBL_STATE; - -/* * Initialize a symbol table state structure * * entry: @@ -1082,13 +1129,13 @@ * shnum - # of sections in cache * secndx - Index of symbol table section * ehdr - ELF header for file - * versymcache - NULL, or cache of versym section + * versym - Information about versym section * file - Name of file * flags - Command line option flags */ static int init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, - Ehdr *ehdr, Cache *versymcache, const char *file, uint_t flags) + Ehdr *ehdr, VERSYM_STATE *versym, const char *file, uint_t flags) { Shdr *shdr; @@ -1134,9 +1181,9 @@ * Determine if there is a associated Versym section * with this Symbol Table. */ - if (versymcache && (versymcache->c_shdr->sh_link == state->secndx) && - versymcache->c_data) - state->versym = versymcache->c_data->d_buf; + if (versym->cache && + (versym->cache->c_shdr->sh_link == state->secndx)) + state->versym = versym; else state->versym = NULL; @@ -1180,12 +1227,12 @@ * Produce a line of output for the given symbol * * entry: + * state - Symbol table state * symndx - Index of symbol within the table * symndx_disp - Index to display. This may not be the same * as symndx if the display is relative to the logical * combination of the SUNW_ldynsym/dynsym tables. * sym - Symbol to display - * state - Symbol table state */ static void output_symbol(SYMTBL_STATE *state, Word symndx, Word disp_symndx, Sym *sym) @@ -1209,7 +1256,7 @@ char index[MAXNDXSIZE], *sec; const char *symname; - int verndx; + Versym verndx; uchar_t type; Shdr *tshdr; Word shndx; @@ -1277,12 +1324,44 @@ /* * If versioning is available display the - * version index. + * version index. If not, then use 0. */ - if (state->versym) - verndx = (int)state->versym[symndx]; - else + if (state->versym) { + verndx = state->versym->data[symndx]; + + /* + * Check to see if this is a defined symbol with a + * version index that is outside the valid range for + * the file. If so, then there are two possiblities: + * + * - Files produced by the GNU ld use the top (16th) bit + * as a "hidden symbol" marker. If we have + * detected that this object comes from GNU ld, + * then check to see if this is the case and that + * the resulting masked version is in range. If so, + * issue a warning describing it. + * - If this is not a GNU "hidden bit" issue, then + * issue a generic "out of range" error. + */ + if (VERNDX_INVALID(sym->st_shndx, state->versym->num_verdef, + state->versym->data, verndx)) { + if (state->versym->gnu && (verndx & 0x8000) && + ((verndx & ~0x8000) <= + state->versym->num_verdef)) { + (void) fprintf(stderr, + MSG_INTL(MSG_WARN_GNUVER), state->file, + state->secname, EC_WORD(symndx), + EC_HALF(verndx & ~0x8000)); + } else { /* Generic version range error */ + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_BADVER), state->file, + state->secname, EC_WORD(symndx), + EC_HALF(verndx), state->versym->num_verdef); + } + } + } else { verndx = 0; + } /* * Error checking for TLS. @@ -1345,7 +1424,7 @@ */ void symbols(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, - Cache *versymcache, const char *file, uint_t flags) + VERSYM_STATE *versym, const char *file, uint_t flags) { SYMTBL_STATE state; Cache *_cache; @@ -1366,7 +1445,7 @@ continue; if (!init_symtbl_state(&state, cache, shnum, secndx, ehdr, - versymcache, file, flags)) + versym, file, flags)) continue; /* * Loop through the symbol tables entries. @@ -1387,7 +1466,7 @@ */ static void sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, - Cache *versymcache, const char *file, uint_t flags) + VERSYM_STATE *versym, const char *file, uint_t flags) { SYMTBL_STATE ldynsym_state, dynsym_state; Cache *sortcache, *symcache; @@ -1429,7 +1508,7 @@ switch (symshdr->sh_type) { case SHT_SUNW_LDYNSYM: if (!init_symtbl_state(&ldynsym_state, cache, shnum, - symsecndx, ehdr, versymcache, file, flags)) + symsecndx, ehdr, versym, file, flags)) continue; ldynsym_cnt = ldynsym_state.symn; /* @@ -1455,7 +1534,7 @@ /*FALLTHROUGH*/ case SHT_DYNSYM: if (!init_symtbl_state(&dynsym_state, cache, shnum, - symsecndx, ehdr, versymcache, file, flags)) + symsecndx, ehdr, versym, file, flags)) continue; break; default: @@ -2574,7 +2653,7 @@ Shdr *nameshdr, *shdr; char *names = 0; Cache *cache, *_cache; - Cache *versymcache = 0; + VERSYM_STATE versym; if ((ehdr = elf_getehdr(elf)) == NULL) { failure(file, MSG_ORIG(MSG_ELF_GETEHDR)); @@ -2848,13 +2927,13 @@ if (flags & FLG_INTERP) interp(file, cache, shnum, phnum, elf); - versymcache = versions(cache, shnum, file, flags); + versions(cache, shnum, file, flags, &versym); if (flags & FLG_SYMBOLS) - symbols(cache, shnum, ehdr, Nname, versymcache, file, flags); + symbols(cache, shnum, ehdr, Nname, &versym, file, flags); if (flags & FLG_SORT) - sunw_sort(cache, shnum, ehdr, Nname, versymcache, file, flags); + sunw_sort(cache, shnum, ehdr, Nname, &versym, file, flags); if (flags & FLG_HASH) hash(cache, shnum, Nname, file, flags);
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg Wed Mar 21 10:53:55 2007 -0700 @@ -106,8 +106,11 @@ @ MSG_ERR_BADHASH "%s: %s: bad hash entry: symbol %s: exists in bucket \ %d, should be bucket %ld\n" @ MSG_ERR_NODYNSYM "%s: %s: associated SHT_DYNSYM section not found\n" -@ MSG_ERR_BADNDXSEC "%s: %s: unexpected section type associated with index section: %s\n" +@ MSG_ERR_BADNDXSEC "%s: %s: unexpected section type associated with \ + index section: %s\n" @ MSG_ERR_BADSORTNDX "%s: %s: sort section has bad symbol index: %d\n" +@ MSG_ERR_BADVER "%s: %s: index[%d]: version %d is out of range: \ + version definitions available: 0-%d\n" @ MSG_ERR_LDYNNOTADJ "%s: bad dynamic symbol table layout: %s and %s \ sections are not adjacent\n" @@ -124,6 +127,7 @@ header\n" @ MSG_WARN_INVCAP3 "%s: capabilities section: %s: and PT_CAP program \ header have conflicting size or offsets\n" +@ MSG_WARN_GNUVER "%s: %s: index[%d]: GNU hidden symbol with version %d\n" # Elf Output Messages @@ -246,6 +250,8 @@ @ MSG_STR_EMPTY "" +@ MSG_GNU_VERNAMPREFIX ".gnu.version" + @ MSG_FMT_INDENT " %s" @ MSG_FMT_INDEX " [%lld]" @ MSG_FMT_INDEX2 "[%d]"
--- a/usr/src/cmd/sgs/include/conv.h Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/include/conv.h Wed Mar 21 10:53:55 2007 -0700 @@ -173,6 +173,7 @@ extern int conv_sys_eclass(); extern Uts_desc *conv_uts(void); extern const char *conv_ver_flags(Half); +extern const char *conv_ver_index(Versym); /* * Define all class specific routines.
--- a/usr/src/cmd/sgs/include/debug.h Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/include/debug.h Wed Mar 21 10:53:55 2007 -0700 @@ -335,6 +335,7 @@ #define Dbg_syms_entry Dbg64_syms_entry #define Dbg_syms_global Dbg64_syms_global #define Dbg_syms_ignore Dbg64_syms_ignore +#define Dbg_syms_ignore_badver Dbg64_syms_ignore_badver #define Dbg_syms_lazy_rescan Dbg64_syms_lazy_rescan #define Dbg_syms_lookup Dbg64_syms_lookup #define Dbg_syms_new Dbg64_syms_new @@ -532,6 +533,7 @@ #define Dbg_syms_entry Dbg32_syms_entry #define Dbg_syms_global Dbg32_syms_global #define Dbg_syms_ignore Dbg32_syms_ignore +#define Dbg_syms_ignore_badver Dbg32_syms_ignore_badver #define Dbg_syms_lazy_rescan Dbg32_syms_lazy_rescan #define Dbg_syms_lookup Dbg32_syms_lookup #define Dbg_syms_lookup_aout Dbg32_syms_lookup_aout @@ -767,6 +769,7 @@ extern void Dbg_syms_entry(Lm_list *, Word, Sym_desc *); extern void Dbg_syms_global(Lm_list *, Word, const char *); extern void Dbg_syms_ignore(Ofl_desc *, Sym_desc *); +extern void Dbg_syms_ignore_badver(Rt_map *, const char *, Word, Versym); extern void Dbg_syms_lazy_rescan(Lm_list *, const char *); extern void Dbg_syms_lookup(Rt_map *, const char *, const char *); #if !(defined(_ELF64)) @@ -945,7 +948,7 @@ extern void Elf_shdr(Lm_list *, Half, Shdr *); extern void Elf_syms_table_entry(Lm_list *, int, const char *, Half, Sym *, - Word, const char *, const char *); + Versym, const char *, const char *); extern void Elf_syms_table_title(Lm_list *, int); extern void Elf_ver_def_title(Lm_list *);
--- a/usr/src/cmd/sgs/include/libld.h Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/include/libld.h Wed Mar 21 10:53:55 2007 -0700 @@ -933,6 +933,58 @@ /* + * Test to see if a symbol verson index is outside of the valid range + * of version indexes. + * + * entry: + * _shndx - Symbol section index + * _vercnt - # of versions defined by object containing symbol + * _versym_arr - NULL, or pointer to versym array + * _verndx - Version index of symbol. Note that this argument is + * only evaluated if _versym_arr is non-NULL. + * + * note: + * _vercnt and _verndx are evaluated more than once. Beware + * of expensive computations, or computations with side effects. + * + * If we encounter a defined symbol with a version that is outside the + * range of the valid versions supplied by the file, then we quietly + * ignore that symbol. This can't happen in a native Solaris object. + * However, the GNU 'ld' uses the top bit (0x8000) of the version as a + * flag to the system that says the symbol should be treated as if it + * doesn't exist. The Solaris linker does not support this mechanism, + * or the model of interface evolution that it allows. However, we do + * wish to be able to link against objects produced that way. Ignoring + * such symbols gives the desired GNU-compatible "ignore" behavior, + * without committing us to their model, while reserving the ability + * to adopt it or do something different at a later date. + * + * Note that it is possible to see "version 1" in a file that contains 0 + * version definitions. This happens when a mapfile is used to reduce + * global symbols to local. For instance: + * + * { + * global: + * main; + * eprintf; + * local: + * *; + * }; + * + * In this case, there will be a versym section (containing version + * indexes 0 and 1). However, there are no versions defined, and + * hence no corresponding verdef section. We treat this case specially: + * If the versym section is present (_versym_arr is non-NULL) + * and the verdef section is not, we act as if _vercnt is 1. + */ +#define VERNDX_INVALID(_shndx, _vercnt, _versym_arr, _verndx) \ + (((_shndx) != SHN_UNDEF) && (_versym_arr != NULL) && \ + ((_verndx) > ((_vercnt == 0) ? 1 : _vercnt)) && \ + ((_verndx) < VER_NDX_LORESERVE)) + + + +/* * isalist(1) descriptor - used to break an isalist string into its component * options. */
--- a/usr/src/cmd/sgs/libconv/common/llib-lconv Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/llib-lconv Wed Mar 21 10:53:55 2007 -0700 @@ -58,6 +58,7 @@ int conv_sys_eclass(void); Uts_desc *conv_uts(void); const char *conv_ver_flags(Half); +const char *conv_ver_index(Versym verndx); /* * Define all class specific routines.
--- a/usr/src/cmd/sgs/libconv/common/symbols.c Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/symbols.c Wed Mar 21 10:53:55 2007 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -133,6 +133,7 @@ (mach == EM_SPARCV9)) && (type == STT_SPARC_REGISTER)) return (conv_sym_SPARC_value(value, 0)); - (void) sprintf(string, MSG_ORIG(MSG_SYM_FMT_VAL), EC_ADDR(value)); + (void) snprintf(string, sizeof (string), MSG_ORIG(MSG_SYM_FMT_VAL), + EC_ADDR(value)); return (string); }
--- a/usr/src/cmd/sgs/libconv/common/version.c Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/version.c Wed Mar 21 10:53:55 2007 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -42,3 +42,22 @@ else return (MSG_ORIG(MSG_GBL_NULL)); } + + +/* + * Format a version index as contained in a VERSYM section + */ +const char * +conv_ver_index(Versym verndx) +{ + static Conv_inv_buf_t string; + + /* Special case versions starting at VER_NDX_LORESERVE */ + if (verndx == VER_NDX_ELIMINATE) + return (MSG_ORIG(MSG_VERSYM_ELIMINATE)); + + /* format as numeric */ + (void) snprintf(string, sizeof (string), MSG_ORIG(MSG_VERSYM_FMT), + EC_HALF(verndx)); + return (string); +}
--- a/usr/src/cmd/sgs/libconv/common/version.msg Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/libconv/common/version.msg Wed Mar 21 10:53:55 2007 -0700 @@ -1,13 +1,12 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -29,4 +28,8 @@ @ MSG_VER_FLG_WEAK "[ WEAK ]" @ MSG_VER_FLG_BASE "[ BASE ]" +@ MSG_VERSYM_ELIMINATE "ELIM" + @ MSG_GBL_NULL "" + +@ MSG_VERSYM_FMT "%d"
--- a/usr/src/cmd/sgs/libld/common/syms.c Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/libld/common/syms.c Wed Mar 21 10:53:55 2007 -0700 @@ -1144,7 +1144,7 @@ if (undef) { /* - * If an non-weak reference remains undefined, or if a + * If a non-weak reference remains undefined, or if a * mapfile reference is not bound to the relocatable * objects that make up the object being built, we have * a fatal error. @@ -2005,6 +2005,17 @@ } /* + * To accomodate objects built with the GNU ld, we quietly + * ignore symbols with a version that is outside the range + * of the valid versions supplied by the file. See the + * comment that accompanies the VERSYM_INVALID macro in libld.h + * for additional details. + */ + if (VERNDX_INVALID(shndx, ifl->ifl_vercnt, ifl->ifl_versym, + ifl->ifl_versym[ndx])) + continue; + + /* * The linker itself will generate symbols for _end, _etext, * _edata, _DYNAMIC and _PROCEDURE_LINKAGE_TABLE_, so don't * bother entering these symbols from shared objects. This
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Wed Mar 21 10:53:55 2007 -0700 @@ -643,6 +643,9 @@ @ MSG_SYM_DUPSORTADDR "section %s: symbol `%s' and symbol `%s' have the \ same address: %#llx" +@ MSG_SYM_IGNBADVER "symbol=%s; hash index=%d; version=%d; skipping \ + symbol with out of range version in file=%s" + # Syminfo string @ MSG_SYMINFO_INFO "syminfo information" @@ -820,7 +823,7 @@ oth ver shndx name" @ MSG_SYM_LDS_TITLE_32 " value size type bind \ oth ver shndx" -@ MSG_SYM_EFS_ENTRY_32 "%10.10s %10.10s 0x%8.8x %4s %4s %2s %4d \ +@ MSG_SYM_EFS_ENTRY_32 "%10.10s %10.10s 0x%8.8x %4s %4s %2s %4s \ %-14.14s %s" # TRANSLATION_NOTE - the following entries provide for a series of one or more @@ -830,7 +833,7 @@ oth ver shndx / name" @ MSG_SYM_LDL_TITLE_32 " value size type bind \ oth ver shndx" -@ MSG_SYM_EFL_ENTRY_32 "%10.10s %10.10s 0x%8.8x %4s %4s %2s %4d \ +@ MSG_SYM_EFL_ENTRY_32 "%10.10s %10.10s 0x%8.8x %4s %4s %2s %4s \ %-14s %s" # TRANSLATION_NOTE - the following entries provide for a series of one or more @@ -840,7 +843,7 @@ type bind oth ver shndx name" @ MSG_SYM_LDS_TITLE_64 " value size \ type bind oth ver shndx" -@ MSG_SYM_EFS_ENTRY_64 "%10.10s %18.18s 0x%16.16llx %4s %4s %2s %4d \ +@ MSG_SYM_EFS_ENTRY_64 "%10.10s %18.18s 0x%16.16llx %4s %4s %2s %4s \ %-14.14s %s" # TRANSLATION_NOTE - the following entries provide for a series of one or more @@ -850,7 +853,7 @@ type bind oth ver shndx / name" @ MSG_SYM_LDL_TITLE_64 " value size \ type bind oth ver shndx" -@ MSG_SYM_EFL_ENTRY_64 "%10.10s %18.18s 0x%16.16llx %4s %4s %2s %4d \ +@ MSG_SYM_EFL_ENTRY_64 "%10.10s %18.18s 0x%16.16llx %4s %4s %2s %4s \ %-14s %s"
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Wed Mar 21 10:53:55 2007 -0700 @@ -490,8 +490,8 @@ void Elf32_shdr(Lm_list *, Elf32_Half, Elf32_Shdr *); void Elf64_syms_table_entry(Lm_list *, int, const char *, Elf64_Half, - Elf64_Sym *, Elf64_Word, const char *, const char *); + Elf64_Sym *, Elf64_Versym, const char *, const char *); void Elf32_syms_table_entry(Lm_list *, int, const char *, Elf32_Half, - Elf32_Sym *, Elf32_Word, const char *, const char *); + Elf32_Sym *, Elf32_Versym, const char *, const char *); void Elf64_syms_table_title(Lm_list *, int); void Elf32_syms_table_title(Lm_list *, int);
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Wed Mar 21 10:53:55 2007 -0700 @@ -38,7 +38,7 @@ # Policy for Shared Library Version Names and Interface Definitions -SUNWprivate_4.58 { +SUNWprivate_4.59 { global: dbg_desc = NODIRECT; # interposed - ld.so.1(1) dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1) @@ -332,6 +332,8 @@ Dbg64_syms_global; Dbg32_syms_ignore; Dbg64_syms_ignore; + Dbg32_syms_ignore_badver; + Dbg64_syms_ignore_badver; Dbg32_syms_lazy_rescan; Dbg64_syms_lazy_rescan; Dbg32_syms_lookup;
--- a/usr/src/cmd/sgs/liblddbg/common/syms.c Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/syms.c Wed Mar 21 10:53:55 2007 -0700 @@ -57,6 +57,19 @@ } void +Dbg_syms_ignore_badver(Rt_map *lmp, const char *name, Word symndx, + Versym verndx) +{ + Lm_list *lml = LIST(lmp); + + if (DBG_NOTCLASS(DBG_C_SYMBOLS)) + return; + + dbg_print(lml, MSG_INTL(MSG_SYM_IGNBADVER), Dbg_demangle_name(name), + EC_WORD(symndx), EC_HALF(verndx), NAME(lmp)); +} + +void Dbg_syms_dlsym(Rt_map *clmp, const char *sym, const char *next, int flag) { const char *str, *from = NAME(clmp); @@ -505,7 +518,7 @@ void Elf_syms_table_entry(Lm_list *lml, int caller, const char *prestr, Half mach, - Sym *sym, Word verndx, const char *sec, const char *poststr) + Sym *sym, Versym verndx, const char *sec, const char *poststr) { uchar_t type = ELF_ST_TYPE(sym->st_info); uchar_t bind = ELF_ST_BIND(sym->st_info); @@ -522,7 +535,8 @@ conv_sym_value(mach, type, sym->st_value), sym->st_size, conv_sym_info_type(mach, type, 0), conv_sym_info_bind(bind, 0), conv_sym_other(sym->st_other), - verndx, sec ? sec : conv_sym_shndx(sym->st_shndx), + conv_ver_index(verndx), + sec ? sec : conv_sym_shndx(sym->st_shndx), Elf_demangle_name(poststr)); } }
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README Wed Mar 21 10:53:55 2007 -0700 @@ -1223,3 +1223,5 @@ 6516118 Reserved space needed in ELF dynamic section and string table (D) PSARC/2007/127 Reserved space for editing ELF dynamic sections 6535688 elfdump could be more robust in the face of Purify (D) +6516665 The link-editors should be more resilient against gcc's symbol + versioning
--- a/usr/src/cmd/sgs/rtld/common/_elf.h Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/rtld/common/_elf.h Wed Mar 21 10:53:55 2007 -0700 @@ -114,6 +114,7 @@ int e_verneednum; /* their associated count */ Verdef *e_verdef; /* versions defined by this image and */ int e_verdefnum; /* their associated count */ + Versym *e_versym; /* Per-symbol versions */ ulong_t e_syminent; /* syminfo entry size */ void *e_pltpad; /* PLTpad table */ void *e_pltpadend; /* end of PLTpad table */ @@ -147,6 +148,7 @@ #define VERNEEDNUM(X) (((Rt_elfp *)(X)->rt_priv)->e_verneednum) #define VERDEF(X) (((Rt_elfp *)(X)->rt_priv)->e_verdef) #define VERDEFNUM(X) (((Rt_elfp *)(X)->rt_priv)->e_verdefnum) +#define VERSYM(X) (((Rt_elfp *)(X)->rt_priv)->e_versym) #define SUNWBSS(X) (((Rt_elfp *)(X)->rt_priv)->e_sunwbss) #define SYMINENT(X) (((Rt_elfp *)(X)->rt_priv)->e_syminent) #define PLTPAD(X) (((Rt_elfp *)(X)->rt_priv)->e_pltpad)
--- a/usr/src/cmd/sgs/rtld/common/elf.c Wed Mar 21 10:51:01 2007 -0700 +++ b/usr/src/cmd/sgs/rtld/common/elf.c Wed Mar 21 10:53:55 2007 -0700 @@ -1846,6 +1846,22 @@ } /* + * To accomodate objects built with the GNU ld, we quietly + * ignore symbols with a version that is outside the range + * of the valid versions supplied by the file. See the + * comment that accompanies the VERSYM_INVALID macro in libld.h + * for additional details. + */ + if (VERNDX_INVALID(sym->st_shndx, VERDEFNUM(ilmp), + VERSYM(ilmp), VERSYM(ilmp)[ndx])) { + DBG_CALL(Dbg_syms_ignore_badver(ilmp, name, + ndx, VERSYM(ilmp)[ndx])); + if ((ndx = chainptr[ndx]) != 0) + continue; + return ((Sym *)0); + } + + /* * If we're only here to establish a symbols index, we're done. */ if (slp->sl_flags & LKUP_SYMNDX) @@ -2216,6 +2232,9 @@ /* LINTED */ VERDEFNUM(lmp) = (int)ld->d_un.d_val; break; + case DT_VERSYM: + VERSYM(lmp) = (Versym *)(ld->d_un.d_ptr + base); + break; case DT_BIND_NOW: if ((ld->d_un.d_val & DF_BIND_NOW) && ((rtld_flags2 & RT_FL2_BINDLAZY) == 0)) {