diff options
author | Rod Evans <Rod.Evans@Sun.COM> | 2008-09-02 13:24:37 -0700 |
---|---|---|
committer | Rod Evans <Rod.Evans@Sun.COM> | 2008-09-02 13:24:37 -0700 |
commit | 0e233487902b546a8949e2147ff8af45b1afc77c (patch) | |
tree | 23346b4e8f5c8758e4ff67535d37c13878bc9306 /usr/src | |
parent | 0b1b4412cfd6c4ac5467dbe6f4088dcec4f55fe8 (diff) | |
download | illumos-joyent-0e233487902b546a8949e2147ff8af45b1afc77c.tar.gz |
6735939 ld(1) discarded symbol relocations errors (Studio and GNU).
6354160 Solaris linker includes more than one copy of code in binary when linking gnu object code
6732920 mdb doesn't quite handle Extended ELF sections
Diffstat (limited to 'usr/src')
28 files changed, 982 insertions, 638 deletions
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_gelf.c b/usr/src/cmd/mdb/common/mdb/mdb_gelf.c index 4bf43aec25..bc680aad79 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_gelf.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_gelf.c @@ -23,8 +23,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/isa_defs.h> #include <sys/link.h> #include <strings.h> @@ -48,7 +46,8 @@ static mdb_gelf_file_t * gelf_sect_init(mdb_gelf_file_t *gf) { mdb_gelf_sect_t *gsp, *shstr = &gf->gf_sects[gf->gf_shstrndx]; - GElf_Half i, npbit = 0; + size_t i; + GElf_Half npbit = 0; GElf_Shdr *shp; GElf_Phdr *gpp; @@ -78,7 +77,7 @@ gelf_sect_init(mdb_gelf_file_t *gf) if (shp->sh_name >= shstr->gs_shdr.sh_size) { warn("section name for %s:[%u] is corrupt: %u\n", - IOP_NAME(gf->gf_io), (uint_t)i, shp->sh_name); + IOP_NAME(gf->gf_io), i, shp->sh_name); gsp->gs_name = shstr->gs_data; /* empty string */ } @@ -231,12 +230,12 @@ gelf_shdrs_init(mdb_gelf_file_t *gf, size_t shdr_size, GElf_Shdr *(*elf2gelf)(const void *, GElf_Shdr *)) { caddr_t shdrs, shp; - GElf_Half i; + size_t i; mdb_gelf_sect_t *gsp; size_t nbytes; - mdb_dprintf(MDB_DBG_ELF, "loading %s section headers (%hu entries)\n", + mdb_dprintf(MDB_DBG_ELF, "loading %s section headers (%u entries)\n", IOP_NAME(gf->gf_io), gf->gf_shnum); if (gf->gf_shnum == 0) @@ -353,7 +352,7 @@ gelf_phdrs_init(mdb_gelf_file_t *gf, size_t phdr_size, GElf_Phdr *(*elf2gelf)(const void *, GElf_Phdr *)) { caddr_t phdrs, php; - GElf_Half i; + size_t i; GElf_Phdr *gpp; size_t nbytes; @@ -827,7 +826,7 @@ void mdb_gelf_destroy(mdb_gelf_file_t *gf) { mdb_gelf_sect_t *gsp; - GElf_Half i; + size_t i; for (gsp = gf->gf_sects, i = 0; i < gf->gf_shnum; i++, gsp++) { if (gsp->gs_data != NULL) @@ -1092,7 +1091,7 @@ mdb_gelf_symtab_create_file(mdb_gelf_file_t *gf, GElf_Word elftype, mdb_gelf_sect_t *gsp; const char *dsname = NULL; const char *ssname; - GElf_Half i; + size_t i; GElf_Word link; /* @@ -1130,7 +1129,7 @@ mdb_gelf_symtab_create_file_by_name(mdb_gelf_file_t *gf, { mdb_gelf_symtab_t *gst; mdb_gelf_sect_t *gsp; - GElf_Half i; + size_t i; gst = mdb_alloc(sizeof (mdb_gelf_symtab_t), UM_SLEEP); (void) mdb_nv_create(&gst->gst_nv, UM_SLEEP); @@ -1864,7 +1863,7 @@ static const GElf_Phdr * gelf_phdr_lookup(mdb_gelf_file_t *gf, uintptr_t addr) { const GElf_Phdr *gpp = gf->gf_phdrs; - GElf_Half i; + size_t i; for (i = 0; i < gf->gf_npload; i++, gpp++) { if (addr >= gpp->p_vaddr && addr < gpp->p_vaddr + gpp->p_memsz) @@ -1918,7 +1917,7 @@ mdb_gelf_rw(mdb_gelf_file_t *gf, void *buf, size_t nbytes, uintptr_t addr, mdb_gelf_sect_t * mdb_gelf_sect_by_name(mdb_gelf_file_t *gf, const char *name) { - int i; + size_t i; for (i = 0; i < gf->gf_shnum; i++) { if (strcmp(gf->gf_sects[i].gs_name, name) == 0) diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.c b/usr/src/cmd/sgs/elfdump/common/elfdump.c index a1fab8f81c..ea51519c27 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.c +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c @@ -23,7 +23,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * Dump an elf file. @@ -177,10 +176,10 @@ string(Cache *refsec, Word ndx, Cache *strsec, const char *file, Word name) */ static const char * relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum, - Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file, - uint_t flags) + Word relndx, Sym *syms, char *secstr, size_t secsz, const char *file) { - Sym *sym; + Sym *sym; + const char *name; if (symndx >= symnum) { (void) fprintf(stderr, MSG_INTL(MSG_ERR_RELBADSYMNDX), @@ -189,24 +188,22 @@ relsymname(Cache *cache, Cache *csec, Cache *strsec, Word symndx, Word symnum, } sym = (Sym *)(syms + symndx); + name = string(csec, symndx, strsec, file, sym->st_name); /* * If the symbol represents a section offset construct an appropriate - * string. + * string. Note, although section symbol table entries typically have + * a NULL name pointer, entries do exist that point into the string + * table to their own NULL strings. */ - if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) && (sym->st_name == 0)) { - if (flags & FLG_CTL_LONGNAME) - (void) snprintf(secstr, secsz, - MSG_INTL(MSG_STR_L_SECTION), - cache[sym->st_shndx].c_name); - else - (void) snprintf(secstr, secsz, - MSG_INTL(MSG_STR_SECTION), - cache[sym->st_shndx].c_name); + if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) && + ((sym->st_name == 0) || (*name == '\0'))) { + (void) snprintf(secstr, secsz, MSG_INTL(MSG_STR_SECTION), + cache[sym->st_shndx].c_name); return ((const char *)secstr); } - return (string(csec, symndx, strsec, file, sym->st_name)); + return (name); } /* @@ -1399,7 +1396,7 @@ init_symtbl_state(SYMTBL_STATE *state, Cache *cache, Word shnum, Word secndx, * Determine the extended section index used for symbol tables entries. */ static void -symbols_getxindex(SYMTBL_STATE * state) +symbols_getxindex(SYMTBL_STATE *state) { uint_t symn; Word symcnt; @@ -1779,7 +1776,7 @@ sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, VERSYM_STATE *versym, continue; } /* Fallthrough to process associated dynsym */ - /*FALLTHROUGH*/ + /* FALLTHROUGH */ case SHT_DYNSYM: if (!init_symtbl_state(&dynsym_state, cache, shnum, symsecndx, ehdr, versym, file, flags)) @@ -1847,8 +1844,7 @@ sunw_sort(Cache *cache, Word shnum, Ehdr *ehdr, VERSYM_STATE *versym, * Search for and process any relocation sections. */ static void -reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, - uint_t flags) +reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *file) { Word cnt; @@ -1935,8 +1931,7 @@ reloc(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, } symname = relsymname(cache, _cache, strsec, symndx, - symnum, relndx, syms, section, BUFSIZ, file, - flags); + symnum, relndx, syms, section, BUFSIZ, file); /* * A zero symbol index is only valid for a few @@ -2112,7 +2107,6 @@ dyn_test(dyn_test_t test_type, Word sh_type, Cache *sec_cache, Dyn *dyn, * ehdr - ELF header for file * file - Name of file */ - static void dyn_symtest(Dyn *dyn, const char *symname, Cache *symtab_cache, Cache *dynsym_cache, Cache *ldynsym_cache, Cache *cache, @@ -2712,8 +2706,7 @@ move(Cache *cache, Word shnum, const char *file, uint_t flags) } symname = relsymname(cache, _cache, strsec, - symndx, symnum, ndx, syms, section, BUFSIZ, file, - flags); + symndx, symnum, ndx, syms, section, BUFSIZ, file); sym = (Sym *)(syms + symndx); /* @@ -3256,7 +3249,7 @@ group(Cache *cache, Word shnum, const char *file, uint_t flags) } static void -got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags) +got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file) { Cache *gotcache = NULL, *symtab = NULL; Addr gotbgn, gotend; @@ -3436,7 +3429,7 @@ got(Cache *cache, Word shnum, Ehdr *ehdr, const char *file, uint_t flags) if (symndx) gip->g_symname = relsymname(cache, _cache, strsec, symndx, symnum, relndx, syms, - section, BUFSIZ, file, flags); + section, BUFSIZ, file); gip->g_reltype = reltype; gip->g_rel = rels; } @@ -3524,7 +3517,7 @@ sort_shdr_ndx_arr(const void *v1, const void *v2) static int shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx, - size_t shnum, Cache **cache_ret) + size_t shnum, Cache **cache_ret, Word flags) { Elf_Scn *scn; Elf_Data *data; @@ -3646,8 +3639,44 @@ shdr_cache(const char *file, Elf *elf, Ehdr *ehdr, size_t shstrndx, if (_cache->c_shdr->sh_name && /* LINTED */ (nameshdr->sh_size > _cache->c_shdr->sh_name)) { - _cache->c_name = - names + _cache->c_shdr->sh_name; + const char *symname; + char *secname; + + secname = names + _cache->c_shdr->sh_name; + + /* + * A SUN naming convention employs a "%" within + * a section name to indicate a section/symbol + * name. This originated from the compilers + * -xF option, that places functions into their + * own sections. This convention (which has no + * formal standard) has also been followed for + * COMDAT sections. To demangle the symbol + * name, the name must be separated from the + * section name. + */ + if (((flags & FLG_CTL_DEMANGLE) == 0) || + ((symname = strchr(secname, '%')) == NULL)) + _cache->c_name = secname; + else { + size_t secsz = ++symname - secname; + size_t strsz; + + symname = demangle(symname, flags); + strsz = secsz + strlen(symname) + 1; + + if ((_cache->c_name = + malloc(strsz)) == NULL) { + int err = errno; + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_MALLOC), + file, strerror(err)); + return (0); + } + (void) snprintf(_cache->c_name, strsz, + MSG_ORIG(MSG_FMT_SECSYM), + EC_WORD(secsz), secname, symname); + } continue; } @@ -3910,7 +3939,8 @@ regular(const char *file, int fd, Elf *elf, uint_t flags, if (fake_shdr_cache(file, fd, elf, ehdr, &cache, &shnum) == 0) return (ret); } else { - if (shdr_cache(file, elf, ehdr, shstrndx, shnum, &cache) == 0) + if (shdr_cache(file, elf, ehdr, shstrndx, shnum, + &cache, flags) == 0) return (ret); } @@ -4062,7 +4092,7 @@ regular(const char *file, int fd, Elf *elf, uint_t flags, hash(cache, shnum, file, flags); if (flags & FLG_SHOW_GOT) - got(cache, shnum, ehdr, file, flags); + got(cache, shnum, ehdr, file); if (flags & FLG_SHOW_GROUP) group(cache, shnum, file, flags); @@ -4071,7 +4101,7 @@ regular(const char *file, int fd, Elf *elf, uint_t flags, syminfo(cache, shnum, file); if (flags & FLG_SHOW_RELOC) - reloc(cache, shnum, ehdr, file, flags); + reloc(cache, shnum, ehdr, file); if (flags & FLG_SHOW_DYNAMIC) dynamic(cache, shnum, ehdr, file); diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg index 92d8f0cdd6..0f091677b6 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg @@ -23,8 +23,6 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# @ _START_ @@ -204,8 +202,7 @@ @ MSG_STR_NULL "(null)" @ MSG_STR_DEPRECATED "(deprecated value)" @ MSG_STR_UNKNOWN "<unknown>" -@ MSG_STR_SECTION "%.12s (section)" -@ MSG_STR_L_SECTION "%s (section)" +@ MSG_STR_SECTION "%s (section)" @ MSG_STR_CHECKSUM "elf checksum: 0x%lx" @ MSG_FMT_SCNNDX "section[%d]" @@ -304,6 +301,7 @@ @ MSG_FMT_ARNAME "%s(%s)" @ MSG_FMT_NLSTR "\n%s:" @ MSG_FMT_NLSTRNL "\n%s:\n" +@ MSG_FMT_SECSYM "%.*s%s" @ MSG_HEXDUMP_ROW "%*s%-*s%s" @ MSG_HEXDUMP_TOK "%2.2x" diff --git a/usr/src/cmd/sgs/include/debug.h b/usr/src/cmd/sgs/include/debug.h index 4cf05c52c1..a0ae2495b3 100644 --- a/usr/src/cmd/sgs/include/debug.h +++ b/usr/src/cmd/sgs/include/debug.h @@ -27,8 +27,6 @@ #ifndef _DEBUG_H #define _DEBUG_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Global include file for lddbg debugging. * @@ -333,9 +331,11 @@ extern uintptr_t Dbg_setup(const char *, Dbg_desc *); #define Dbg_sec_discarded Dbg64_sec_discarded #define Dbg_sec_genstr_compress Dbg64_sec_genstr_compress #define Dbg_sec_group Dbg64_sec_group +#define Dbg_sec_gnu_comdat Dbg64_sec_gnu_comdat #define Dbg_sec_in Dbg64_sec_in #define Dbg_sec_order_error Dbg64_sec_order_error #define Dbg_sec_order_list Dbg64_sec_order_list +#define Dbg_sec_redirected Dbg64_sec_redirected #define Dbg_sec_strtab Dbg64_sec_strtab #define Dbg_sec_unsup_strmerge Dbg64_sec_unsup_strmerge @@ -536,9 +536,11 @@ extern uintptr_t Dbg_setup(const char *, Dbg_desc *); #define Dbg_sec_discarded Dbg32_sec_discarded #define Dbg_sec_genstr_compress Dbg32_sec_genstr_compress #define Dbg_sec_group Dbg32_sec_group +#define Dbg_sec_gnu_comdat Dbg32_sec_gnu_comdat #define Dbg_sec_in Dbg32_sec_in #define Dbg_sec_order_error Dbg32_sec_order_error #define Dbg_sec_order_list Dbg32_sec_order_list +#define Dbg_sec_redirected Dbg32_sec_redirected #define Dbg_sec_strtab Dbg32_sec_strtab #define Dbg_sec_unsup_strmerge Dbg32_sec_unsup_strmerge @@ -774,9 +776,11 @@ extern void Dbg_sec_discarded(Lm_list *, Is_desc *, Is_desc *); extern void Dbg_sec_genstr_compress(Lm_list *, const char *, Xword, Xword); extern void Dbg_sec_group(Lm_list *, Is_desc *, Group_desc *); +extern void Dbg_sec_gnu_comdat(Lm_list *, const char *, uint_t, uint_t); extern void Dbg_sec_in(Lm_list *, Is_desc *); extern void Dbg_sec_order_error(Lm_list *, Ifl_desc *, Word, int); extern void Dbg_sec_order_list(Ofl_desc *, int); +extern void Dbg_sec_redirected(Lm_list *, const char *, const char *); extern void Dbg_sec_strtab(Lm_list *, Os_desc *, Str_tbl *); extern void Dbg_sec_unsup_strmerge(Lm_list *, Is_desc *); diff --git a/usr/src/cmd/sgs/include/libld.h b/usr/src/cmd/sgs/include/libld.h index 2cfa28905e..2e870ea913 100644 --- a/usr/src/cmd/sgs/include/libld.h +++ b/usr/src/cmd/sgs/include/libld.h @@ -30,8 +30,6 @@ #ifndef _LIBLD_H #define _LIBLD_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdlib.h> #include <libelf.h> #include <sgs.h> @@ -309,7 +307,7 @@ struct ofl_desc { #define FLG_OF_VERDEF 0x00400000 /* record version definitions */ #define FLG_OF_VERNEED 0x00800000 /* record version dependencies */ #define FLG_OF_NOVERSEC 0x01000000 /* don't record version sections */ - +#define FLG_OF_KEY 0x02000000 /* file requires sort keys */ #define FLG_OF_PROCRED 0x04000000 /* process any symbol reductions by */ /* effecting the symbol table */ /* output and relocations */ @@ -329,6 +327,7 @@ struct ofl_desc { #define FLG_OF_AUTOELM 0x002000000000 /* automatically eliminate */ /* unspecified global symbols */ #define FLG_OF_REDLSYM 0x004000000000 /* reduce local symbols */ +#define FLG_OF_SECORDER 0x008000000000 /* section ordering is required */ /* * In the flags1 arena, establish any options that are applicable to archive @@ -348,7 +347,8 @@ struct ofl_desc { #define FLG_OF1_OVHWCAP 0x00000040 /* override any input hardware or */ #define FLG_OF1_OVSFCAP 0x00000080 /* software capabilities */ #define FLG_OF1_RELDYN 0x00000100 /* process .dynamic in rel obj */ - +#define FLG_OF1_NRLXREL 0x00000200 /* -z norelaxreloc flag set */ +#define FLG_OF1_RLXREL 0x00000400 /* -z relaxreloc flag set */ #define FLG_OF1_IGNORE 0x00000800 /* ignore unused dependencies */ #define FLG_OF1_TEXTOFF 0x00002000 /* text relocations are ok */ @@ -364,7 +364,7 @@ struct ofl_desc { #define FLG_OF1_TLSOREL 0x00100000 /* output relocation against .tlsbss */ /* section */ #define FLG_OF1_MEMORY 0x00200000 /* produce a memory model */ -#define FLG_OF1_RLXREL 0x00400000 /* -z relaxreloc flag set */ + #define FLG_OF1_ENCDIFF 0x00800000 /* Host running linker has different */ /* byte order than output object */ #define FLG_OF1_VADDR 0x01000000 /* vaddr was explicitly set */ @@ -549,11 +549,11 @@ struct ifl_desc { /* input file descriptor */ /* is included in the output */ /* allocatable image */ #define FLG_IF_GNUVER 0x00010000 /* file used GNU-style versioning */ +#define FLG_IF_ORDERED 0x00020000 /* ordered section processing */ + /* required */ struct is_desc { /* input section descriptor */ - const char *is_name; /* the section name */ - const char *is_basename; /* original section name (without */ - /* .<sect>%<func> munging */ + const char *is_name; /* original section name */ Shdr *is_shdr; /* the elf section header */ Ifl_desc *is_file; /* infile desc for this section */ Os_desc *is_osdesc; /* new output section for this */ @@ -564,16 +564,14 @@ struct is_desc { /* input section descriptor */ Word is_txtndx; /* Index for section. Used to decide */ /* where to insert section when */ /* reordering sections */ - Word is_ident; /* preserved IDENT used for ordered */ - /* sections. */ - uint_t is_namehash; /* hash on section name */ - Half is_key; /* Used for SHF_ORDERED */ - Half is_flags; /* Various flags */ + Word is_keyident; /* key for SHF_ORDERED processing */ + /* and identifier used for */ + /* placing/ordering sections */ + Word is_flags; /* Various flags */ }; -#define FLG_IS_ORDERED 0x0001 /* This is a SHF_ORDERED section */ -#define FLG_IS_KEY 0x0002 /* This is a section pointed by */ - /* sh_info of a SHF_ORDERED section */ +#define FLG_IS_ORDERED 0x0001 /* this is a SHF_ORDERED section */ +#define FLG_IS_KEY 0x0002 /* section requires sort keys */ #define FLG_IS_DISCARD 0x0004 /* section is to be discarded */ #define FLG_IS_RELUPD 0x0008 /* symbol defined here may have moved */ #define FLG_IS_SECTREF 0x0010 /* section has been referenced */ @@ -581,7 +579,9 @@ struct is_desc { /* input section descriptor */ #define FLG_IS_EXTERNAL 0x0040 /* isp from an user file */ #define FLG_IS_INSTRMRG 0x0080 /* Usable SHF_MERGE|SHF_STRINGS sec */ #define FLG_IS_GNSTRMRG 0x0100 /* Generated mergeable string section */ - +#define FLG_IS_GROUPS 0x0200 /* section has groups to process */ +#define FLG_IS_PLACE 0x0400 /* section requires to be placed */ +#define FLG_IS_COMDAT 0x0800 /* section is COMDAT */ /* * Map file and output file processing structures @@ -598,7 +598,7 @@ struct os_desc { /* Output section descriptor */ Sort_desc *os_sort; /* used for sorting sections */ Sg_desc *os_sgdesc; /* segment os_desc is placed on */ Elf_Data *os_outdata; /* output sections raw data */ - List os_comdats; /* list of COMDAT sections present */ + APlist *os_comdats; /* list of COMDAT sections present */ /* in current output section */ Word os_scnsymndx; /* index in output symtab of section */ /* symbol for this section */ @@ -610,7 +610,7 @@ struct os_desc { /* Output section descriptor */ uchar_t os_flags; /* various flags */ }; -#define FLG_OS_ORDER_KEY 0x01 /* include a sort key section */ +#define FLG_OS_KEY 0x01 /* section requires sort keys */ #define FLG_OS_OUTREL 0x02 /* output rel against this section */ #define FLG_OS_SECTREF 0x04 /* isps are not affected by -zignore */ @@ -657,7 +657,7 @@ struct sg_desc { /* output segment descriptor */ #define FLG_SG_EMPTY 0x0200 /* an empty segment specification */ /* no input sections will be */ /* associated to this section */ -#define FLG_SG_KEY 0x0400 /* include a key section */ +#define FLG_SG_KEY 0x0400 /* segment requires sort keys */ #define FLG_SG_DISABLED 0x0800 /* this segment is disabled */ #define FLG_SG_PHREQ 0x1000 /* this segment requires a program */ /* header */ @@ -1007,22 +1007,19 @@ struct uts_desc { size_t uts_osrelsz; /* and associated size */ }; - /* * SHT_GROUP descriptor - used to track group sections at the global - * level to resolve conflicts/determine which to keep. + * level to resolve conflicts and determine which to keep. */ struct group_desc { - const char *gd_gsectname; /* group section name */ - const char *gd_symname; /* symbol name */ + Is_desc *gd_isc; /* input section descriptor */ + Is_desc *gd_oisc; /* overriding input section */ + /* descriptor when discarded */ + const char *gd_name; /* group name (signature symbol) */ Word *gd_data; /* data for group section */ - size_t gd_scnndx; /* group section index */ size_t gd_cnt; /* number of entries in group data */ - Word gd_flags; }; -#define GRP_FLG_DISCARD 0x0001 /* group is to be discarded */ - /* * Indexes into the ld_support_funcs[] table. */ @@ -1038,7 +1035,6 @@ typedef enum { LDS_NUM } Support_ndx; - /* * Structure to manage archive member caching. Each archive has an archive * descriptor (Ar_desc) associated with it. This contains pointers to the diff --git a/usr/src/cmd/sgs/include/sgs.h b/usr/src/cmd/sgs/include/sgs.h index 89d61ef677..c3648c29fa 100644 --- a/usr/src/cmd/sgs/include/sgs.h +++ b/usr/src/cmd/sgs/include/sgs.h @@ -33,9 +33,6 @@ #ifndef _SGS_H #define _SGS_H -#pragma ident "%Z%%M% %I% %E% SMI" - - #ifdef __cplusplus extern "C" { #endif @@ -227,9 +224,9 @@ typedef struct { #define realloc libld_realloc #define libld_calloc(x, a) libld_malloc(((size_t)x) * ((size_t)a)) -extern void libld_free(void *); -extern void *libld_malloc(size_t); -extern void *libld_realloc(void *, size_t); +extern void libld_free(void *); +extern void *libld_malloc(size_t); +extern void *libld_realloc(void *, size_t); #endif diff --git a/usr/src/cmd/sgs/libld/common/_libld.h b/usr/src/cmd/sgs/libld/common/_libld.h index f67d3dd7b8..3637e6ce6d 100644 --- a/usr/src/cmd/sgs/libld/common/_libld.h +++ b/usr/src/cmd/sgs/libld/common/_libld.h @@ -333,6 +333,7 @@ typedef struct { #define AL_CNT_OFL_DTSFLTRS 4 /* ofl_dtsfltrs initial alist count */ #define AL_CNT_OFL_SYMFLTRS 20 /* ofl_symfltrs initial alist count */ #define AL_CNT_OS_MSTRISDESCS 10 /* os_mstrisdescs */ +#define AL_CNT_OS_COMDATS 20 /* os_comdats */ #define AL_CNT_SG_OSDESC 40 /* sg_osdescs initial alist count */ #define AL_CNT_SG_SECORDER 40 /* sg_secorder initial alist count */ #define AL_CNT_STRMRGREL 500 /* ld_make_strmerge() reloc alist cnt */ @@ -525,6 +526,7 @@ extern Sdf_desc *sdf_find(const char *, List *); #define ld_find_library ld64_find_library #define ld_finish_libs ld64_finish_libs #define ld_get_group ld64_get_group +#define ld_group_process ld64_group_process #define ld_lib_setup ld64_lib_setup #define ld_init ld64_init #define ld_lcm ld64_lcm @@ -608,6 +610,7 @@ extern Sdf_desc *sdf_find(const char *, List *); #define ld_finish_libs ld32_finish_libs #define ld_section_reld_name ld32_section_reld_name #define ld_get_group ld32_get_group +#define ld_group_process ld32_group_process #define ld_lib_setup ld32_lib_setup #define ld_init ld32_init #define ld_lcm ld32_lcm @@ -701,6 +704,7 @@ extern uintptr_t ld_finish_libs(Ofl_desc *); extern const char *ld_section_reld_name(Sym_desc *, Is_desc *); extern Group_desc *ld_get_group(Ofl_desc *, Is_desc *); +extern uintptr_t ld_group_process(Is_desc *, Ofl_desc *); extern uintptr_t ld_lib_setup(Ofl_desc *); diff --git a/usr/src/cmd/sgs/libld/common/args.c b/usr/src/cmd/sgs/libld/common/args.c index dce5b0cc44..4e528cb546 100644 --- a/usr/src/cmd/sgs/libld/common/args.c +++ b/usr/src/cmd/sgs/libld/common/args.c @@ -48,6 +48,9 @@ * -z nointerp suppress the addition of an interpreter * section. This is used to generate the kernel, * but makes no sense to be used by anyone else. + * + * -z norelaxreloc suppress the automatic addition of relaxed + * relocations to GNU linkonce/COMDAT sections. */ #include <sys/link.h> #include <stdio.h> @@ -256,6 +259,14 @@ check_flags(Ofl_desc * ofl, int argc) ofl->ofl_flags |= FLG_OF_FATAL; } + if ((ofl->ofl_flags1 & (FLG_OF1_NRLXREL | FLG_OF1_RLXREL)) == + (FLG_OF1_NRLXREL | FLG_OF1_RLXREL)) { + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP), + MSG_ORIG(MSG_ARG_ZRELAXRELOC), + MSG_ORIG(MSG_ARG_ZNORELAXRELOC)); + ofl->ofl_flags |= FLG_OF_FATAL; + } + if (dflag != SET_FALSE) { /* * Set -Bdynamic on by default, setting is rechecked as input @@ -1118,6 +1129,9 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error) MSG_ORIG(MSG_ARG_RELAXRELOC)) == 0) { ofl->ofl_flags1 |= FLG_OF1_RLXREL; } else if (strcmp(optarg, + MSG_ORIG(MSG_ARG_NORELAXRELOC)) == 0) { + ofl->ofl_flags1 |= FLG_OF1_NRLXREL; + } else if (strcmp(optarg, MSG_ORIG(MSG_ARG_NOLDYNSYM)) == 0) { ofl->ofl_flags |= FLG_OF_NOLDYNSYM; } else if (strcmp(optarg, diff --git a/usr/src/cmd/sgs/libld/common/files.c b/usr/src/cmd/sgs/libld/common/files.c index c1d743683a..52927ba177 100644 --- a/usr/src/cmd/sgs/libld/common/files.c +++ b/usr/src/cmd/sgs/libld/common/files.c @@ -50,7 +50,7 @@ * Decide if we can link against this input file. */ static int -ifl_verify(Ehdr * ehdr, Ofl_desc * ofl, Rej_desc * rej) +ifl_verify(Ehdr *ehdr, Ofl_desc *ofl, Rej_desc *rej) { /* * Check the validity of the elf header information for compatibility @@ -180,8 +180,8 @@ process_section(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, isp->is_name = name; isp->is_scnndx = ndx; isp->is_flags = FLG_IS_EXTERNAL; - /* LINTED */ - isp->is_key = (Half)ident; + isp->is_keyident = ident; + if ((isp->is_indata = elf_getdata(scn, NULL)) == NULL) { eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_GETDATA), ifl->ifl_name); @@ -196,25 +196,19 @@ process_section(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, /* * Add the new input section to the files input section list and - * to the output section list (some sections like .strtab and - * .shstrtab are not added to the output section list). - * - * If the section has the SHF_ORDERED flag on, do the ld_place_section() - * after all input sections from this file are read in. + * flag whether the section needs placing in an output section. This + * placement is deferred until all input section processing has been + * completed, as SHT_GROUP sections can provide information that will + * affect how other sections within the file should be placed. */ ifl->ifl_isdesc[ndx] = isp; - if (ident && (shdr->sh_flags & ALL_SHF_ORDER) == 0) - return ((uintptr_t)ld_place_section(ofl, isp, ident, 0)); - if (ident && (shdr->sh_flags & ALL_SHF_ORDER)) { - isp->is_flags |= FLG_IS_ORDERED; - isp->is_ident = ident; - - if ((ndx != 0) && (ndx == shdr->sh_link) && - (shdr->sh_flags & SHF_ORDERED)) { - return ((uintptr_t)ld_place_section(ofl, isp, - ident, 0)); + if (ident) { + if (shdr->sh_flags & ALL_SHF_ORDER) { + isp->is_flags |= FLG_IS_ORDERED; + ifl->ifl_flags |= FLG_IF_ORDERED; } + isp->is_flags |= FLG_IS_PLACE; } return (1); } @@ -398,7 +392,7 @@ process_cap(Ifl_desc *ifl, Is_desc *cisp, Ofl_desc *ofl) static uintptr_t /* ARGSUSED5 */ process_input(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, - Word ndx, int ident, Ofl_desc *ofl) + Word ndx, int ident, Ofl_desc *ofl) { return (process_section(name, ifl, shdr, scn, ndx, ld_targ.t_id.id_null, ofl)); @@ -413,7 +407,7 @@ process_input(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, static uintptr_t /* ARGSUSED5 */ process_reloc(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, - Word ndx, int ident, Ofl_desc *ofl) + Word ndx, int ident, Ofl_desc *ofl) { if (process_section(name, ifl, shdr, scn, ndx, ld_targ.t_id.id_null, ofl) == S_ERROR) @@ -438,7 +432,7 @@ process_reloc(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, */ static uintptr_t process_strtab(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, - Word ndx, int ident, Ofl_desc *ofl) + Word ndx, int ident, Ofl_desc *ofl) { char *data; size_t size; @@ -618,27 +612,38 @@ static uintptr_t process_array(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, Word ndx, int ident, Ofl_desc *ofl) { - Os_desc *osp; - Is_desc *isp; + uintptr_t error; if (ident) ident = ld_targ.t_id.id_array; - if (process_section(name, ifl, shdr, scn, ndx, ident, ofl) == S_ERROR) - return (S_ERROR); + error = process_section(name, ifl, shdr, scn, ndx, ident, ofl); + if ((error == 0) || (error == S_ERROR)) + return (error); + + return (1); +} + +static uintptr_t +/* ARGSUSED1 */ +array_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) +{ + Os_desc *osp; + Shdr *shdr; - if (((isp = ifl->ifl_isdesc[ndx]) == 0) || - ((osp = isp->is_osdesc) == 0)) + if ((isc == NULL) || ((osp = isc->is_osdesc) == NULL)) return (0); + shdr = isc->is_shdr; + if ((shdr->sh_type == SHT_FINI_ARRAY) && - (ofl->ofl_osfiniarray == 0)) + (ofl->ofl_osfiniarray == NULL)) ofl->ofl_osfiniarray = osp; else if ((shdr->sh_type == SHT_INIT_ARRAY) && - (ofl->ofl_osinitarray == 0)) + (ofl->ofl_osinitarray == NULL)) ofl->ofl_osinitarray = osp; else if ((shdr->sh_type == SHT_PREINIT_ARRAY) && - (ofl->ofl_ospreinitarray == 0)) + (ofl->ofl_ospreinitarray == NULL)) ofl->ofl_ospreinitarray = osp; return (1); @@ -1019,9 +1024,11 @@ process_dynamic_isgnu(const char *name, Ifl_desc *ifl, Shdr *shdr, { Dyn *dyn; Elf_Data *dp; + uintptr_t error; - if (process_section(name, ifl, shdr, scn, ndx, ident, ofl) == S_ERROR) - return (S_ERROR); + error = process_section(name, ifl, shdr, scn, ndx, ident, ofl); + if ((error == 0) || (error == S_ERROR)) + return (error); /* Get the .dynamic data */ dp = elf_getdata(scn, NULL); @@ -1153,7 +1160,7 @@ process_dynamic(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) * Perform some SONAME sanity checks. */ if (ifl->ifl_flags & FLG_IF_NEEDED) { - Ifl_desc * sifl; + Ifl_desc *sifl; /* * Determine if anyone else will cause the same SONAME to be @@ -1218,6 +1225,28 @@ process_dynamic(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) } /* + * Process a group section. + */ +static uintptr_t +process_group(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, + Word ndx, int ident, Ofl_desc *ofl) +{ + uintptr_t error; + + error = process_section(name, ifl, shdr, scn, ndx, ident, ofl); + if ((error == 0) || (error == S_ERROR)) + return (error); + + /* + * Indicate that this input file has groups to process. Groups are + * processed after all input sections have been processed. + */ + ifl->ifl_flags |= FLG_IS_GROUPS; + + return (1); +} + +/* * Process a relocation entry. At this point all input sections from this * input file have been assigned an input section descriptor which is saved * in the `ifl_isdesc' array. @@ -1327,53 +1356,6 @@ process_exclude(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn, return (process_section(name, ifl, shdr, scn, ndx, 0, ofl)); } -#if defined(_ELF64) - -static uintptr_t -process_amd64_unwind(const char *name, Ifl_desc *ifl, Shdr *shdr, - Elf_Scn *scn, Word ndx, int ident, Ofl_desc *ofl) -{ - Os_desc *osp, *eosp; - Is_desc *isp; - Listnode *lnp; - - if (process_section(name, ifl, shdr, scn, ndx, ident, ofl) == S_ERROR) - return (S_ERROR); - - /* - * When producing a relocatable object - just collect the sections. - */ - if (ofl->ofl_flags & FLG_OF_RELOBJ) - return (1); - - /* - * If producing a executable or shared library, keep track of all the - * output UNWIND sections to allow the creation of the appropriate - * frame_hdr information. - * - * If the section hasn't been placed in the output file, then there's - * nothing for us to do. - */ - if (((isp = ifl->ifl_isdesc[ndx]) == 0) || - ((osp = isp->is_osdesc) == 0)) - return (1); - - /* - * Check to see if this output section is already on the list, and if - * not, add it. - */ - for (LIST_TRAVERSE(&ofl->ofl_unwind, lnp, eosp)) - if (osp == eosp) - return (1); - - if (list_appendc(&ofl->ofl_unwind, osp) == 0) - return (S_ERROR); - - return (1); -} - -#endif - /* * Section processing state table. `Initial' describes the required initial * procedure to be called (if any), `Final' describes the final processing @@ -1401,7 +1383,7 @@ static uintptr_t (*Initial[SHT_NUM][2])() = { /* SHT_INIT_ARRAY */ process_array, NULL, /* SHT_FINI_ARRAY */ process_array, NULL, /* SHT_PREINIT_ARRAY */ process_array, NULL, -/* SHT_GROUP */ process_section, invalid_section, +/* SHT_GROUP */ process_group, invalid_section, /* SHT_SYMTAB_SHNDX */ process_sym_shndx, NULL }; @@ -1421,9 +1403,9 @@ static uintptr_t (*Final[SHT_NUM][2])() = { /* SHT_DYNSYM */ NULL, ld_sym_process, /* SHT_UNKNOWN12 */ NULL, NULL, /* SHT_UNKNOWN13 */ NULL, NULL, -/* SHT_INIT_ARRAY */ NULL, NULL, -/* SHT_FINI_ARRAY */ NULL, NULL, -/* SHT_PREINIT_ARRAY */ NULL, NULL, +/* SHT_INIT_ARRAY */ array_process, NULL, +/* SHT_FINI_ARRAY */ array_process, NULL, +/* SHT_PREINIT_ARRAY */ array_process, NULL, /* SHT_GROUP */ NULL, NULL, /* SHT_SYMTAB_SHNDX */ sym_shndx_process, NULL }; @@ -1440,15 +1422,13 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl) { Elf_Scn *scn; Shdr *shdr; - Word ndx, sndx; + Word ndx, sndx, ordndx = 0, ordcnt = 0; char *str, *name, _name[MAXNDXSIZE]; Word row, column; int ident; uintptr_t error; Is_desc *vdfisp, *vndisp, *vsyisp, *sifisp, *capisp; Sdf_desc *sdf; - Word ordered_shndx = 0; /* index to first ordered section */ - Word ordered_cnt = 0; /* * First process the .shstrtab section so that later sections can @@ -1526,6 +1506,7 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl) scn = NULL; while (scn = elf_nextscn(elf, scn)) { ndx++; + /* * As we've already processed the .shstrtab don't do it again. */ @@ -1632,10 +1613,15 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl) sifisp = ifl->ifl_isdesc[ndx]; break; case SHT_SUNW_ANNOTATE: + if (process_progbits(name, ifl, shdr, scn, + ndx, ident, ofl) == S_ERROR) + return (S_ERROR); + break; case SHT_SUNW_COMDAT: if (process_progbits(name, ifl, shdr, scn, ndx, ident, ofl) == S_ERROR) return (S_ERROR); + ifl->ifl_isdesc[ndx]->is_flags |= FLG_IS_COMDAT; break; case SHT_SUNW_verdef: if (process_section(name, ifl, shdr, scn, @@ -1680,6 +1666,7 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl) */ if (ld_targ.t_m.m_mach != EM_AMD64) goto do_default; + /* * Target is x86, so this really is * SHT_AMD64_UNWIND @@ -1688,10 +1675,9 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl) /* * column == ET_REL */ - if (process_amd64_unwind(name, ifl, - shdr, scn, ndx, - ld_targ.t_id.id_unwind, ofl) == - S_ERROR) + if (process_section(name, ifl, shdr, + scn, ndx, ld_targ.t_id.id_unwind, + ofl) == S_ERROR) return (S_ERROR); } break; @@ -1706,61 +1692,91 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl) break; } } + } + + /* + * Now that all input sections have been analyzed, and prior to placing + * any input sections to their output sections, process any groups. + * Groups can contribute COMDAT items, which may get discarded as part + * of placement. In addition, COMDAT names may require transformation + * to indicate different output section placement. + */ + if (ifl->ifl_flags & FLG_IS_GROUPS) { + for (ndx = 1; ndx < ifl->ifl_shnum; ndx++) { + Is_desc *isp; + + if (((isp = ifl->ifl_isdesc[ndx]) == NULL) || + (isp->is_shdr->sh_type != SHT_GROUP)) + continue; + + if (ld_group_process(isp, ofl) == S_ERROR) + return (S_ERROR); + } + } + + /* + * Now that all of input sections have been processed, place them + * in the appropriate output sections. + */ + for (ndx = 1; ndx < ifl->ifl_shnum; ndx++) { + Is_desc *isp; + Shdr *shdr; + + if (((isp = ifl->ifl_isdesc[ndx]) == NULL) || + ((isp->is_flags & FLG_IS_PLACE) == 0)) + continue; + + shdr = isp->is_shdr; + + /* + * Place all non-ordered sections within their appropriate + * output section. + * + * Ordered sections are sorted based on the relative ordering + * of the section pointed to by the sh_info entry. An ordered + * section, whose sh_link points to itself, must also be placed + * in the output image so as to control the ordered processing + * that follows (see FLG_IF_ORDERED below). + */ + if (((isp->is_flags & FLG_IS_ORDERED) == 0) || + ((ndx == shdr->sh_link) && + (shdr->sh_flags & SHF_ORDERED))) { + if (ld_place_section(ofl, isp, + isp->is_keyident, 0) == (Os_desc *)S_ERROR) + return (S_ERROR); + } /* - * If we have any sections that require ORDERED processing, - * remember the index of the first ordered section. This let's - * us know if we need an ORDERED place_section pass, and if so, - * where to start. + * If a section requires ordered processing, keep track of the + * section index and count to optimize later section traversal. */ - if (ifl->ifl_isdesc[ndx] && - (ifl->ifl_isdesc[ndx]->is_shdr->sh_flags & ALL_SHF_ORDER)) { - ordered_cnt++; - if (ordered_shndx == 0) - ordered_shndx = ndx; + if (isp->is_flags & FLG_IS_ORDERED) { + ordcnt++; + if (ordndx == 0) + ordndx = ndx; } } /* - * Now that all of sections have been placed, scan through any sections - * which have special ordering requirements and place them now. + * Some sections have special ordering requirements, that are based off + * of the section pointed to by their sh_info entry. This controlling + * section will have been placed (above), and thus any ordered sections + * can now be processed. */ - if (ordered_shndx) { - Word cnt; + if (ifl->ifl_flags & FLG_IF_ORDERED) { + Word cnt = 0; - for (ndx = ordered_shndx, cnt = 0; - (ndx < ifl->ifl_shnum) && (cnt < ordered_cnt); ndx++) { + for (ndx = ordndx; + (ndx < ifl->ifl_shnum) && (cnt < ordcnt); ndx++) { Is_desc *isp; - /* LINTED */ - Os_desc *osp; - if (((isp = ifl->ifl_isdesc[ndx]) == 0) || - ((isp->is_shdr->sh_flags & ALL_SHF_ORDER) == 0)) + if (((isp = ifl->ifl_isdesc[ndx]) == NULL) || + ((isp->is_flags & FLG_IS_ORDERED) == 0)) continue; - /* - * If this is an ordered section, process it. - */ - cnt++; - if ((osp = (Os_desc *)ld_process_ordered(ifl, ofl, ndx, - ifl->ifl_shnum)) == (Os_desc *)S_ERROR) + if (ld_process_ordered(ifl, ofl, ndx, + ifl->ifl_shnum) == S_ERROR) return (S_ERROR); - -#if defined(_ELF64) - /* - * If this section is 'ordered' then it was not - * caught in the previous 'place_section' operation. - * - * So - now that we have a OSP section for - * the unwind info - record it. - */ - if (osp && - (osp->os_shdr->sh_type == SHT_AMD64_UNWIND) && - (ld_targ.t_uw.uw_append_unwind != NULL) && - ((*ld_targ.t_uw.uw_append_unwind)(osp, ofl) == - S_ERROR)) - return (S_ERROR); -#endif } } @@ -1824,7 +1840,7 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl) * processing if necessary. */ for (ndx = 0; ndx < ifl->ifl_shnum; ndx++) { - Is_desc * isp; + Is_desc *isp; if ((isp = ifl->ifl_isdesc[ndx]) == 0) continue; @@ -1848,10 +1864,29 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl) * appropriate action routine. */ if (row < SHT_NUM) { - if (Final[row][column] != NULL) - if (Final[row][column](isp, ifl, ofl) == - S_ERROR) + if (Final[row][column] != NULL) { + if (Final[row][column](isp, ifl, + ofl) == S_ERROR) return (S_ERROR); + } +#if defined(_ELF64) + } else if ((row == SHT_AMD64_UNWIND) && (column == 0)) { + Os_desc *osp = isp->is_osdesc; + + /* + * SHT_AMD64_UNWIND (0x70000001) is in the SHT_LOPROC - + * SHT_HIPROC range reserved for processor-specific + * semantics, and is only meaningful for amd64 targets. + * + * Only process unwind contents from relocatable + * objects. + */ + if (osp && (ld_targ.t_m.m_mach == EM_AMD64) && + (ld_targ.t_uw.uw_append_unwind != NULL) && + ((*ld_targ.t_uw.uw_append_unwind)(osp, ofl) == + S_ERROR)) + return (S_ERROR); +#endif } } @@ -2009,7 +2044,7 @@ ld_process_ifl(const char *name, const char *soname, int fd, Elf *elf, * Determine if we've already come across this file. */ if (!(flags & FLG_IF_EXTRACT)) { - List * lst; + List *lst; if (ehdr->e_type == ET_REL) lst = &ofl->ofl_objs; @@ -2214,7 +2249,7 @@ ld_process_open(const char *opath, const char *ofile, int *fd, Ofl_desc *ofl, */ static Ifl_desc * process_req_lib(Sdf_desc *sdf, const char *dir, const char *file, - Ofl_desc * ofl, Rej_desc * rej) + Ofl_desc *ofl, Rej_desc *rej) { size_t dlen, plen; int fd; diff --git a/usr/src/cmd/sgs/libld/common/groups.c b/usr/src/cmd/sgs/libld/common/groups.c index 2478fd229e..aa76e2ed4a 100644 --- a/usr/src/cmd/sgs/libld/common/groups.c +++ b/usr/src/cmd/sgs/libld/common/groups.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <string.h> #include <link.h> @@ -39,12 +37,13 @@ */ typedef struct { const char *gn_name; /* group name */ + Is_desc *gn_isc; /* group input section */ avl_node_t gn_avl; /* avl book-keeping (see SGSOFFSETOF) */ uint_t gn_hash; /* group name hash value */ } Grp_node; static int -gnavl_compare(const void * n1, const void * n2) +gnavl_compare(const void *n1, const void *n2) { uint_t hash1, hash2; const char *st1, *st2; @@ -71,10 +70,14 @@ gnavl_compare(const void * n1, const void * n2) /* * Determine whether a (COMDAT) group has already been encountered. If so, - * tag the new group having the same name as discardable. + * indicate that the group descriptor has an overriding group (gd_oisc). This + * indication triggers the ld_place_section() to discard this group, while the + * gd_oisc information provides for complete diagnostics of the override. + * Otherwise, this is the first occurrence of this group, therefore the group + * descriptor is saved for future comparisons. */ static uintptr_t -gpavl_loaded(Ofl_desc *ofl, Group_desc * gdp) +gpavl_loaded(Ofl_desc *ofl, Group_desc *gdp) { Grp_node gpn, *gpnp; avl_tree_t *avlt; @@ -91,11 +94,11 @@ gpavl_loaded(Ofl_desc *ofl, Group_desc * gdp) ofl->ofl_groups = avlt; } - gpn.gn_name = gdp->gd_symname; - gpn.gn_hash = sgs_str_hash(gdp->gd_symname); + gpn.gn_name = gdp->gd_name; + gpn.gn_hash = sgs_str_hash(gdp->gd_name); if ((gpnp = avl_find(avlt, &gpn, &where)) != NULL) { - gdp->gd_flags |= GRP_FLG_DISCARD; + gdp->gd_oisc = gpnp->gn_isc; return (1); } @@ -107,6 +110,7 @@ gpavl_loaded(Ofl_desc *ofl, Group_desc * gdp) gpnp->gn_name = gpn.gn_name; gpnp->gn_hash = gpn.gn_hash; + gpnp->gn_isc = gdp->gd_isc; avl_insert(avlt, gpnp, where); return (0); @@ -116,116 +120,20 @@ Group_desc * ld_get_group(Ofl_desc *ofl, Is_desc *isp) { Ifl_desc *ifl = isp->is_file; - Elf *elf = ifl->ifl_elf; uint_t scnndx = isp->is_scnndx; Group_desc *gdp; Aliste idx; /* - * If this is the first SHF_GROUP section encountered for this file, - * establish what group sections exist. - */ - if (ifl->ifl_groups == NULL) { - Elf_Scn *scn = 0; - - while (scn = elf_nextscn(elf, scn)) { - Shdr *shdr, *_shdr; - Sym *sym; - Elf_Scn *_scn; - Elf_Data *data; - Group_desc gd; - - shdr = elf_getshdr(scn); - if (shdr->sh_type != SHT_GROUP) - continue; - - /* - * Confirm that the sh_link points to a valid section. - */ - if ((shdr->sh_link == SHN_UNDEF) || - (shdr->sh_link >= ifl->ifl_shnum)) { - eprintf(ofl->ofl_lml, ERR_FATAL, - MSG_INTL(MSG_FIL_INVSHLINK), - ifl->ifl_name, elf_strptr(elf, - ifl->ifl_shstrndx, shdr->sh_name), - EC_XWORD(shdr->sh_link)); - ofl->ofl_flags |= FLG_OF_FATAL; - continue; - } - - if (shdr->sh_entsize == 0) { - eprintf(ofl->ofl_lml, ERR_FATAL, - MSG_INTL(MSG_FIL_INVSHENTSIZE), - ifl->ifl_name, elf_strptr(elf, - ifl->ifl_shstrndx, shdr->sh_name), - EC_XWORD(shdr->sh_entsize)); - ofl->ofl_flags |= FLG_OF_FATAL; - continue; - } - - /* - * Get associated symbol table. - */ - _scn = elf_getscn(elf, shdr->sh_link); - _shdr = elf_getshdr(_scn); - - /* - * Sanity check the sh_link field (which points to - * a symbol table entry) against the size of the - * symbol table. - */ - if ((shdr->sh_info == SHN_UNDEF) || - (shdr->sh_info >= (Word)(_shdr->sh_size / - _shdr->sh_entsize))) { - eprintf(ofl->ofl_lml, ERR_FATAL, - MSG_INTL(MSG_FIL_INVSHINFO), - ifl->ifl_name, elf_strptr(elf, - ifl->ifl_shstrndx, shdr->sh_name), - EC_XWORD(shdr->sh_info)); - ofl->ofl_flags |= FLG_OF_FATAL; - continue; - } - - data = elf_getdata(_scn, 0); - sym = data->d_buf; - sym += shdr->sh_info; - data = elf_getdata(scn, 0); - - gd.gd_gsectname = - elf_strptr(elf, ifl->ifl_shstrndx, shdr->sh_name); - gd.gd_symname = - elf_strptr(elf, _shdr->sh_link, sym->st_name); - gd.gd_scnndx = elf_ndxscn(scn); - gd.gd_data = data->d_buf; - gd.gd_cnt = data->d_size / sizeof (Word); - gd.gd_flags = 0; - - /* - * If this group is a COMDAT group, determine whether - * this 'signature' symbol has already been detected. - */ - if ((gd.gd_data[0] & GRP_COMDAT) && - (ELF_ST_BIND(sym->st_info) != STB_LOCAL) && - (sym->st_shndx != SHN_UNDEF) && - (gpavl_loaded(ofl, &gd) == S_ERROR)) - return ((Group_desc *)S_ERROR); - - if (alist_append(&(ifl->ifl_groups), - &gd, sizeof (Group_desc), AL_CNT_IFL_GROUPS) == 0) - return ((Group_desc *)S_ERROR); - } - } - - /* * Scan the GROUP sections associated with this file to find the * matching group section. */ for (ALIST_TRAVERSE(ifl->ifl_groups, idx, gdp)) { size_t ndx; - Word * data; + Word *data; if (isp->is_shdr->sh_type == SHT_GROUP) { - if (isp->is_scnndx == gdp->gd_scnndx) + if (isp->is_scnndx == gdp->gd_isc->is_scnndx) return (gdp); continue; } @@ -240,5 +148,118 @@ ld_get_group(Ofl_desc *ofl, Is_desc *isp) eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ELF_NOGROUPSECT), ifl->ifl_name, isp->is_name); ofl->ofl_flags |= FLG_OF_FATAL; - return (0); + return (NULL); +} + +uintptr_t +ld_group_process(Is_desc *gisc, Ofl_desc *ofl) +{ + Ifl_desc *gifl = gisc->is_file; + Shdr *sshdr, *gshdr = gisc->is_shdr; + Is_desc *isc; + Sym *sym; + char *str; + Group_desc gd; + size_t ndx; + + /* + * Confirm that the sh_link points to a valid section. + */ + if ((gshdr->sh_link == SHN_UNDEF) || + (gshdr->sh_link >= gifl->ifl_shnum) || + ((isc = gifl->ifl_isdesc[gshdr->sh_link]) == NULL)) { + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_FIL_INVSHLINK), + gifl->ifl_name, gisc->is_name, EC_XWORD(gshdr->sh_link)); + ofl->ofl_flags |= FLG_OF_FATAL; + return (0); + } + if (gshdr->sh_entsize == 0) { + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_FIL_INVSHENTSIZE), + gifl->ifl_name, gisc->is_name, EC_XWORD(gshdr->sh_entsize)); + ofl->ofl_flags |= FLG_OF_FATAL; + return (0); + } + + /* + * Get the associated symbol table. Sanity check the sh_info field + * (which points to the signature symbol table entry) against the size + * of the symbol table. + */ + sshdr = isc->is_shdr; + sym = (Sym *)isc->is_indata->d_buf; + + if ((sshdr->sh_info == SHN_UNDEF) || + (gshdr->sh_info >= (Word)(sshdr->sh_size / sshdr->sh_entsize)) || + ((isc = gifl->ifl_isdesc[sshdr->sh_link]) == NULL)) { + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_FIL_INVSHINFO), + gifl->ifl_name, gisc->is_name, EC_XWORD(gshdr->sh_info)); + ofl->ofl_flags |= FLG_OF_FATAL; + return (0); + } + + sym += gshdr->sh_info; + + /* + * Get the symbol name from the associated string table. + */ + str = (char *)isc->is_indata->d_buf; + str += sym->st_name; + + /* + * Generate a group descriptor. + */ + gd.gd_isc = gisc; + gd.gd_oisc = NULL; + gd.gd_name = str; + gd.gd_data = gisc->is_indata->d_buf; + gd.gd_cnt = gisc->is_indata->d_size / sizeof (Word); + + /* + * If this group is a COMDAT group, validate the signature symbol. + */ + if ((gd.gd_data[0] & GRP_COMDAT) && + ((ELF_ST_BIND(sym->st_info) == STB_LOCAL) || + (sym->st_shndx == SHN_UNDEF))) { + /* FATAL or ignore? */ + eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_GRP_INVALSYM), + gifl->ifl_name, gisc->is_name, str); + ofl->ofl_flags |= FLG_OF_FATAL; + return (0); + } + + /* + * Validate the section indices within the group. If this is a COMDAT + * group, mark each section as COMDAT. + */ + for (ndx = 1; ndx < gd.gd_cnt; ndx++) { + Word gndx; + + if ((gndx = gd.gd_data[ndx]) >= gifl->ifl_shnum) { + eprintf(ofl->ofl_lml, ERR_FATAL, + MSG_INTL(MSG_GRP_INVALNDX), gifl->ifl_name, + gisc->is_name, ndx, gndx); + ofl->ofl_flags |= FLG_OF_FATAL; + return (0); + } + + if (gd.gd_data[0] & GRP_COMDAT) + gifl->ifl_isdesc[gndx]->is_flags |= FLG_IS_COMDAT; + } + + /* + * If this is a COMDAT group, determine whether this group has already + * been encountered, or whether this is the first instance of the group. + */ + if ((gd.gd_data[0] & GRP_COMDAT) && + (gpavl_loaded(ofl, &gd) == S_ERROR)) + return (S_ERROR); + + /* + * Associate the group descriptor with this input file. + */ + if (alist_append(&(gifl->ifl_groups), &gd, sizeof (Group_desc), + AL_CNT_IFL_GROUPS) == NULL) + return (S_ERROR); + + return (1); } diff --git a/usr/src/cmd/sgs/libld/common/ldmain.c b/usr/src/cmd/sgs/libld/common/ldmain.c index 0d2999bb8c..206de2af9a 100644 --- a/usr/src/cmd/sgs/libld/common/ldmain.c +++ b/usr/src/cmd/sgs/libld/common/ldmain.c @@ -26,7 +26,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * Processing of relocatable objects and shared objects. @@ -340,12 +339,14 @@ ld_main(int argc, char **argv, Half mach) return (ld_exit(ofl)); /* - * Now that all sections have been added to the output file, check to - * see if any section ordering was specified and if so give a warning - * if any ordering directives were not matched. + * Now that all sections have been added to the output file, determine + * whether any mapfile section ordering was specified, and verify that + * all mapfile ordering directives have been matched. Issue a warning + * for any directives that have not been matched. * Also, if SHF_ORDERED sections exist, set up sort key values. */ - ld_sec_validate(ofl); + if (ofl->ofl_flags & (FLG_OF_SECORDER | FLG_OF_KEY)) + ld_sec_validate(ofl); /* * Having collected all the input data create the initial output file diff --git a/usr/src/cmd/sgs/libld/common/libld.msg b/usr/src/cmd/sgs/libld/common/libld.msg index d1f028baea..b26537e748 100644 --- a/usr/src/cmd/sgs/libld/common/libld.msg +++ b/usr/src/cmd/sgs/libld/common/libld.msg @@ -209,9 +209,9 @@ # # TRANSLATION_NOTE -- End of USAGE message # - -@ MSG_GRP_INVALNDX "group section error: %s: file %s: entry %d: \ +@ MSG_GRP_INVALNDX "file: %s: group section: %s: entry %d: \ invalid section index: %d" +@ MSG_GRP_INVALSYM "file: %s: group section: %s: invalid group symbol %s:" # Relocation processing messages (some of these are required to satisfy # do_reloc(), which is common code used by cmd/sgs/rtld - make sure both @@ -259,8 +259,9 @@ unexpected relocation; generic processing performed" @ MSG_REL_UNEXPSYM "relocation error: %s: file %s: symbol %s: \ unexpected symbol referenced from file %s" -@ MSG_REL_SYMDISC "relocation error: file: %s section: %s symbol: %s: \ - symbol has been discarded with discarded section: %s" +@ MSG_REL_SYMDISC "relocation error: %s: file: %s section: %s \ + symbol: %s: symbol has been discarded with discarded \ + section: %s" @ MSG_REL_NOSYMBOL "relocation error: %s: file %s: section: %s: \ offset: 0x%llx: relocation requires reference symbol" @ MSG_REL_DISPREL1 "relocation error: %s: file %s: symbol %s: \ @@ -289,11 +290,15 @@ object" @ MSG_REL_SLOPCDATNONAM "relocation warning: %s: file %s: section %s: \ - relocation against discarded COMDAT section %s \ + relocation against discarded COMDAT section %s: \ redirected to file %s" @ MSG_REL_SLOPCDATNAM "relocation warning: %s: file %s: section %s: \ symbol %s: relocation against discarded COMDAT \ - section %s redirected to file %s" + section %s: redirected to file %s" +@ MSG_REL_SLOPCDATNOSYM "relocation warning: %s: file %s: section %s: \ + symbol %s: relocation against discarded COMDAT \ + section %s: symbol not found, relocation ignored" + @ MSG_REL_NOREG "relocation error: REGISTER relocation not supported \ on target architecture" @@ -385,8 +390,7 @@ @ MSG_SYS_OPEN "file %s: open failed: %s" @ MSG_SYS_UNLINK "file %s: unlink failed: %s" -@ MSG_SYS_MMAP "file %s: mmap failed: %s" -@ MSG_SYS_MMAPANON "file %s: mmap anon failed: %s" +@ MSG_SYS_MMAPANON "mmap anon failed: %s" # Messages related to platform support @@ -623,7 +627,6 @@ @ MSG_FMT_NULLSYMNAM "%s[%d]" @ MSG_PTH_RTLD "/usr/lib/ld.so.1" -@ MSG_PTH_DEVZERO "/dev/zero" @ MSG_SUNW_OST_SGS "SUNW_OST_SGS" @@ -634,6 +637,7 @@ @ MSG_SCN_DATA ".data" @ MSG_SCN_COMMENT ".comment" @ MSG_SCN_DEBUG ".debug" +@ MSG_SCN_DEBUG_INFO ".debug_info" @ MSG_SCN_DYNAMIC ".dynamic" @ MSG_SCN_DYNSYMSORT ".SUNW_dynsymsort" @ MSG_SCN_DYNTLSSORT ".SUNW_dyntlssort" @@ -648,18 +652,25 @@ @ MSG_SCN_FINI ".fini" @ MSG_SCN_FINIARRAY ".finiarray" @ MSG_SCN_GOT ".got" +@ MSG_SCN_GNU_LINKONCE ".gnu.linkonce." @ MSG_SCN_HASH ".hash" @ MSG_SCN_INDEX ".index" @ MSG_SCN_INIT ".init" @ MSG_SCN_INITARRAY ".initarray" @ MSG_SCN_INTERP ".interp" @ MSG_SCN_LBSS ".lbss" +@ MSG_SCN_LDATA ".ldata" @ MSG_SCN_LINE ".line" @ MSG_SCN_LRODATA ".lrodata" @ MSG_SCN_PLT ".plt" @ MSG_SCN_PREINITARRAY ".preinitarray" @ MSG_SCN_REL ".rel" @ MSG_SCN_RELA ".rela" +@ MSG_SCN_RODATA ".rodata" +@ MSG_SCN_SBSS ".sbss" +@ MSG_SCN_SBSS2 ".sbss2" +@ MSG_SCN_SDATA ".sdata" +@ MSG_SCN_SDATA2 ".sdata2" @ MSG_SCN_SHSTRTAB ".shstrtab" @ MSG_SCN_STAB ".stab" @ MSG_SCN_STABEXCL ".stab.exclstr" @@ -675,6 +686,7 @@ @ MSG_SCN_SYMTAB ".symtab" @ MSG_SCN_SYMTAB_SHNDX ".symtab_shndx" @ MSG_SCN_TBSS ".tbss" +@ MSG_SCN_TDATA ".tdata" @ MSG_SCN_TEXT ".text" @ MSG_SYM_FINIARRAY "finiarray" @@ -1075,6 +1087,8 @@ @ MSG_ARG_ZDEFNODEF "-z[defs|nodefs]" @ MSG_ARG_ZNODEF "-znodefs" @ MSG_ARG_ZNOINTERP "-znointerp" +@ MSG_ARG_ZRELAXRELOC "-zrelaxreloc" +@ MSG_ARG_ZNORELAXRELOC "-znorelaxreloc" @ MSG_ARG_ZTEXT "-ztext" @ MSG_ARG_ZTEXTOFF "-ztextoff" @ MSG_ARG_ZTEXTWARN "-ztextwarn" @@ -1131,6 +1145,7 @@ @ MSG_ARG_RESCAN "rescan" @ MSG_ARG_NOLDYNSYM "noldynsym" @ MSG_ARG_RELAXRELOC "relaxreloc" +@ MSG_ARG_NORELAXRELOC "norelaxreloc" @ MSG_ARG_GLOBAUDIT "globalaudit" @ MSG_ARG_TARGET "target=" @@ -1201,3 +1216,4 @@ @ MSG_FMT_INDEX "[%lld]" @ MSG_STR_DTRACE "PT_SUNWDTRACE" + diff --git a/usr/src/cmd/sgs/libld/common/map.c b/usr/src/cmd/sgs/libld/common/map.c index ee89746bc5..5673d05cc5 100644 --- a/usr/src/cmd/sgs/libld/common/map.c +++ b/usr/src/cmd/sgs/libld/common/map.c @@ -26,7 +26,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * Map file parsing. @@ -1114,6 +1113,7 @@ map_pipe(Ofl_desc *ofl, const char *mapfile, Sg_desc *sgp) AL_CNT_SG_SECORDER) == NULL) return (S_ERROR); + ofl->ofl_flags |= FLG_OF_SECORDER; DBG_CALL(Dbg_map_pipe(ofl->ofl_lml, sgp, sec_name, index)); if ((tok = gettoken(ofl, mapfile, 0)) != TK_SEMICOLON) { diff --git a/usr/src/cmd/sgs/libld/common/order.c b/usr/src/cmd/sgs/libld/common/order.c index c9980434c9..b30e36f576 100644 --- a/usr/src/cmd/sgs/libld/common/order.c +++ b/usr/src/cmd/sgs/libld/common/order.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Processing of SHF_ORDERED sections. */ @@ -176,9 +174,10 @@ ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) if ((error = is_keylink_ok(ifl, keylink, limit)) != 0) { DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); isp->is_flags &= ~FLG_IS_ORDERED; - if (isp->is_osdesc == NULL) + if (isp->is_osdesc == NULL) { return ((uintptr_t)ld_place_section(ofl, isp, - isp->is_key, 0)); + isp->is_keyident, 0)); + } return ((uintptr_t)isp->is_osdesc); } @@ -191,9 +190,10 @@ ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) if ((dest_ndx = get_shfordered_dest(ofl, ifl, ndx, limit)) == 0) { isp->is_flags &= ~FLG_IS_ORDERED; - if (isp->is_osdesc == NULL) + if (isp->is_osdesc == NULL) { return ((uintptr_t)ld_place_section(ofl, isp, - isp->is_key, 0)); + isp->is_keyident, 0)); + } return ((uintptr_t)isp->is_osdesc); } } else { @@ -208,7 +208,7 @@ ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) * Place the section into it's output section. */ if ((osp = isp->is_osdesc) == NULL) { - if ((osp = ld_place_section(ofl, isp, isp->is_ident, + if ((osp = ld_place_section(ofl, isp, isp->is_keyident, dest_ndx)) == (Os_desc *)S_ERROR) return ((uintptr_t)S_ERROR); if (!osp) @@ -254,10 +254,20 @@ ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) isp2->is_scnndx); return (S_ERROR); } + + /* + * Indicate that this ordered input section will require a sort + * key created. Propagate the key requirement through to the + * associated output section, segment and file, to trigger the + * sort key creation. See ld_sec_validate(); + */ + isp2->is_flags |= FLG_IS_KEY; + osp2 = isp2->is_osdesc; - osp2->os_flags |= FLG_OS_ORDER_KEY; + osp2->os_flags |= FLG_OS_KEY; osp2->os_sgdesc->sg_flags |= FLG_SG_KEY; - isp2->is_flags |= FLG_IS_KEY; + + ofl->ofl_flags |= FLG_OF_KEY; } return ((uintptr_t)osp); @@ -277,7 +287,7 @@ ld_sec_validate(Ofl_desc *ofl) { Listnode *lnp1; Sg_desc *sgp; - int key = 1; + Word key = 1; for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { Sec_order *scop; @@ -298,12 +308,12 @@ ld_sec_validate(Ofl_desc *ofl) Listnode *lnp2; Is_desc *isp; - if ((osp->os_flags & FLG_OS_ORDER_KEY) == 0) + if ((osp->os_flags & FLG_OS_KEY) == 0) continue; for (LIST_TRAVERSE(&(osp->os_isdescs), lnp2, isp)) { if (isp->is_flags & FLG_IS_KEY) - isp->is_key = key++; + isp->is_keyident = key++; } } } @@ -372,24 +382,22 @@ comp(const void *ss1, const void *ss2) Is_desc *i1, *i2; Word ndx1, ndx2; - if (s1->is_shdr->sh_flags & SHF_ORDERED) { + if (s1->is_shdr->sh_flags & SHF_ORDERED) ndx1 = s1->is_shdr->sh_info; - } else { + else ndx1 = s1->is_shdr->sh_link; - } - if (s2->is_shdr->sh_flags & SHF_ORDERED) { + if (s2->is_shdr->sh_flags & SHF_ORDERED) ndx2 = s2->is_shdr->sh_info; - } else { + else ndx2 = s2->is_shdr->sh_link; - } i1 = s1->is_file->ifl_isdesc[ndx1]; i2 = s2->is_file->ifl_isdesc[ndx2]; - if (i1->is_key > i2->is_key) + if (i1->is_keyident > i2->is_keyident) return (1); - if (i1->is_key < i2->is_key) + if (i1->is_keyident < i2->is_keyident) return (-1); return (0); } diff --git a/usr/src/cmd/sgs/libld/common/place.c b/usr/src/cmd/sgs/libld/common/place.c index 1a30ff2c80..279c2d8a30 100644 --- a/usr/src/cmd/sgs/libld/common/place.c +++ b/usr/src/cmd/sgs/libld/common/place.c @@ -26,7 +26,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * Map file parsing and input section to output segment mapping. @@ -50,7 +49,7 @@ static void set_addralign(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp) { - Shdr * shdr = isp->is_shdr; + Shdr *shdr = isp->is_shdr; /* A discarded section has no influence on the output */ if (isp->is_flags & FLG_IS_DISCARD) @@ -146,20 +145,194 @@ ld_append_isp(Ofl_desc * ofl, Os_desc *osp, Is_desc *isp, int mstr_only) } /* + * Determine whether this input COMDAT section already exists for the associated + * output section. If so, then discard this input section. Otherwise, this + * must be the first COMDAT section, thus it is kept for future comparisons. + */ +static uintptr_t +add_comdat(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp) +{ + Aliste idx; + Is_desc *cisp; + + for (APLIST_TRAVERSE(osp->os_comdats, idx, cisp)) { + if (strcmp(isp->is_name, cisp->is_name)) + continue; + + isp->is_osdesc = osp; + + /* + * If this section hasn't already been identified as discarded, + * generate a suitable diagnostic. + */ + if ((isp->is_flags & FLG_IS_DISCARD) == 0) { + isp->is_flags |= FLG_IS_DISCARD; + DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml, isp, cisp)); + } + + /* + * A discarded section does not require assignment to an output + * section. However, if relaxed relocations have been enabled + * (either from -z relaxreloc, or asserted with .gnu.linkonce + * processing), then this section must still be assigned to an + * output section so that the sloppy relocation logic will have + * the information necessary to do its work. + */ + if (ofl->ofl_flags1 & FLG_OF1_RLXREL) + return (1); + else + return (0); + } + + /* + * This is a new COMDAT section - so keep it. + */ + if (aplist_append(&(osp->os_comdats), isp, AL_CNT_OS_COMDATS) == NULL) + return (S_ERROR); + + return (1); +} + +/* + * Determine whether a GNU group COMDAT section name follows the convention + * + * section-name.symbol-name + * + * Each section within the input file is compared to see if the full section + * name matches the beginning of the COMDAT section, with a following '.'. + * A pointer to the symbol name, starting with the '.' is returned so that the + * caller can strip off the required section name. + */ +static char * +gnu_comdat_sym(Ifl_desc *ifl, Is_desc *gisp) +{ + size_t ndx; + + for (ndx = 1; ndx < ifl->ifl_shnum; ndx++) { + Is_desc *isp; + size_t ssize; + + if (((isp = ifl->ifl_isdesc[ndx]) == NULL) || + (isp == gisp) || (isp->is_name == NULL)) + continue; + + /* + * It's questionable whether this size should be cached in the + * Is_desc. However, this seems an infrequent operation and + * adding Is_desc members can escalate memory usage for large + * link-edits. For now, size the section name dynamically. + */ + ssize = strlen(isp->is_name); + if ((strncmp(isp->is_name, gisp->is_name, ssize) != NULL) && + (gisp->is_name[ssize] == '.')) + return ((char *)&gisp->is_name[ssize]); + } + return (NULL); +} + +/* + * GNU .gnu.linkonce sections follow a naming convention that indicates the + * required association with an output section. Determine whether this input + * section follows the convention, and if so return the appropriate output + * section name. + * + * .gnu.linkonce.b.* -> .bss + * .gnu.linkonce.d.* -> .data + * .gnu.linkonce.l.* -> .ldata + * .gnu.linkonce.lb.* -> .lbss + * .gnu.linkonce.lr.* -> .lrodata + * .gnu.linkonce.r.* -> .rodata + * .gnu.linkonce.s.* -> .sdata + * .gnu.linkonce.s2.* -> .sdata2 + * .gnu.linkonce.sb.* -> .sbss + * .gnu.linkonce.sb2.* -> .sbss2 + * .gnu.linkonce.t.* -> .text + * .gnu.linkonce.tb.* -> .tbss + * .gnu.linkonce.td.* -> .tdata + * .gnu.linkonce.wi.* -> .debug_info + */ +#define NSTR_CH1(ch) (*(nstr + 1) == (ch)) +#define NSTR_CH2(ch) (*(nstr + 2) == (ch)) +#define NSTR_CH3(ch) (*(nstr + 3) == (ch)) + +static const char * +gnu_linkonce_sec(const char *ostr) +{ + const char *nstr = &ostr[MSG_SCN_GNU_LINKONCE_SIZE]; + + switch (*nstr) { + case 'b': + if (NSTR_CH1('.')) + return (MSG_ORIG(MSG_SCN_BSS)); + break; + case 'd': + if (NSTR_CH1('.')) + return (MSG_ORIG(MSG_SCN_DATA)); + break; + case 'l': + if (NSTR_CH1('.')) + return (MSG_ORIG(MSG_SCN_LDATA)); + else if (NSTR_CH1('b') && NSTR_CH2('.')) + return (MSG_ORIG(MSG_SCN_LBSS)); + else if (NSTR_CH1('r') && NSTR_CH2('.')) + return (MSG_ORIG(MSG_SCN_LRODATA)); + break; + case 'r': + if (NSTR_CH1('.')) + return (MSG_ORIG(MSG_SCN_RODATA)); + break; + case 's': + if (NSTR_CH1('.')) + return (MSG_ORIG(MSG_SCN_SDATA)); + else if (NSTR_CH1('2') && NSTR_CH2('.')) + return (MSG_ORIG(MSG_SCN_SDATA2)); + else if (NSTR_CH1('b') && NSTR_CH2('.')) + return (MSG_ORIG(MSG_SCN_SBSS)); + else if (NSTR_CH1('b') && NSTR_CH2('2') && NSTR_CH3('.')) + return (MSG_ORIG(MSG_SCN_SBSS2)); + break; + case 't': + if (NSTR_CH1('.')) + return (MSG_ORIG(MSG_SCN_TEXT)); + else if (NSTR_CH1('b') && NSTR_CH2('.')) + return (MSG_ORIG(MSG_SCN_TBSS)); + else if (NSTR_CH1('d') && NSTR_CH2('.')) + return (MSG_ORIG(MSG_SCN_TDATA)); + break; + case 'w': + if (NSTR_CH1('i') && NSTR_CH2('.')) + return (MSG_ORIG(MSG_SCN_DEBUG_INFO)); + break; + default: + break; + } + + /* + * No special name match found. + */ + return (ostr); +} +#undef NSTR_CH1 +#undef NSTR_CH2 +#undef NSTR_CH3 + +/* * Place a section into the appropriate segment. */ Os_desc * -ld_place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) +ld_place_section(Ofl_desc *ofl, Is_desc *isp, int ident, Word link) { - Listnode * lnp1, * lnp2; - Ent_desc * enp; - Sg_desc * sgp; + Listnode *lnp1, *lnp2; + Ent_desc *enp; + Sg_desc *sgp; Os_desc *osp; Aliste idx1, idx2; int os_ndx; - Shdr * shdr = isp->is_shdr; + Shdr *shdr = isp->is_shdr; Xword shflagmask, shflags = shdr->sh_flags; - Ifl_desc * ifl = isp->is_file; + Ifl_desc *ifl = isp->is_file; + char *oname, *sname; + uint_t onamehash; /* * Define any sections that must be thought of as referenced. These @@ -181,21 +354,24 @@ ld_place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) DBG_CALL(Dbg_sec_in(ofl->ofl_lml, isp)); + /* + * If this section identfies group members, or this section indicates + * that it is a member of a group, determine whether the section is + * still required. + */ if ((shflags & SHF_GROUP) || (shdr->sh_type == SHT_GROUP)) { - Group_desc * gdesc; - - if ((gdesc = ld_get_group(ofl, isp)) == (Group_desc *)S_ERROR) - return ((Os_desc *)S_ERROR); + Group_desc *gdesc; - if (gdesc) { + if ((gdesc = ld_get_group(ofl, isp)) != NULL) { DBG_CALL(Dbg_sec_group(ofl->ofl_lml, isp, gdesc)); /* - * If this group is marked as discarded, then this - * section needs to be discarded. + * If this group has been replaced by another group, + * then this section needs to be discarded. */ - if (gdesc->gd_flags & GRP_FLG_DISCARD) { + if (gdesc->gd_oisc) { isp->is_flags |= FLG_IS_DISCARD; + /* * Since we're discarding the section, we * can skip assigning it to an output section. @@ -288,73 +464,141 @@ ld_place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) if ((sgp = enp->ec_segment) == 0) sgp = ((Ent_desc *)(ofl->ofl_ents.tail->data))->ec_segment; - isp->is_basename = isp->is_name; - /* - * Strip out the % from the section name in all cases except when '-r' - * is used without '-M', and '-r' is used with '-M' without - * the ?O flag. + * By default, the output section for an input section has the same + * section name as in the input sections name. COMDAT, SHT_GROUP and + * GNU name translations that follow, may indicate that a different + * output section name be the target for this input section. */ - if (((ofl->ofl_flags & FLG_OF_RELOBJ) && - (sgp->sg_flags & FLG_SG_ORDER)) || - !(ofl->ofl_flags & FLG_OF_RELOBJ)) { - char *cp; + oname = (char *)isp->is_name; - if ((cp = strchr(isp->is_name, '%')) != NULL) { - char *name; - size_t size = (size_t)(cp - isp->is_name); + /* + * Solaris section names may follow the convention: + * + * section-name%symbol-name + * + * This convention has been used to order the layout of sections within + * segments for objects built with the compilers -xF option. However, + * the final object should not contain individual section headers for + * all such input sections, instead the symbol name is stripped from the + * name to establish the final output section name. + * + * This convention has also been followed for COMDAT and sections + * identified though SHT_GROUP data. + * + * Strip out the % from the section name in all cases except: + * + * i. when '-r' is used without '-M', and + * ii. when '-r' is used with '-M' but without the ?O flag. + */ + if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) || + (sgp->sg_flags & FLG_SG_ORDER)) { + if ((sname = strchr(isp->is_name, '%')) != NULL) { + size_t size = sname - isp->is_name; - if ((name = libld_malloc(size + 1)) == 0) + if ((oname = libld_malloc(size + 1)) == NULL) return ((Os_desc *)S_ERROR); - (void) strncpy(name, isp->is_name, size); - cp = name + size; - *cp = '\0'; - isp->is_name = name; + (void) strncpy(oname, isp->is_name, size); + oname[size] = '\0'; + DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp->is_name, + oname)); } isp->is_txtndx = enp->ec_ndx; } /* - * Assign a hash value now that the section name has been finalized. + * GNU section names may follow the convention: + * + * .gnu.linkonce.* + * + * The .gnu.linkonce is a section naming convention that indicates a + * COMDAT requirement. Determine whether this section follows the GNU + * pattern, and if so, determine whether this section should be + * discarded or retained. The comparison of 'g' and 'l' are an + * optimization to skip using strncmp() too much. + */ + if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && + (isp->is_name == oname) && + (isp->is_name[1] == 'g') && (isp->is_name[5] == 'l') && + (strncmp(MSG_ORIG(MSG_SCN_GNU_LINKONCE), isp->is_name, + MSG_SCN_GNU_LINKONCE_SIZE) == 0)) { + if ((oname = + (char *)gnu_linkonce_sec(isp->is_name)) != isp->is_name) { + DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp->is_name, + oname)); + } + + /* + * Explicitly identify this section type as COMDAT. Also, + * enable lazy relocation processing, as this is typically a + * requirement with .gnu.linkonce sections. + */ + isp->is_flags |= FLG_IS_COMDAT; + if ((ofl->ofl_flags1 & FLG_OF1_NRLXREL) == 0) + ofl->ofl_flags1 |= FLG_OF1_RLXREL; + Dbg_sec_gnu_comdat(ofl->ofl_lml, isp->is_name, 1, + (ofl->ofl_flags1 & FLG_OF1_RLXREL)); + } + + /* + * GNU section names may also follow the convention: + * + * section-name.symbol-name + * + * This convention is used when defining SHT_GROUP sections of type + * COMDAT. Thus, any group processing will have discovered any group + * sections, and this identification can be triggered by a pattern + * match section names. */ - isp->is_namehash = sgs_str_hash(isp->is_name); + if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && + (isp->is_name == oname) && (isp->is_flags & FLG_IS_COMDAT) && + ((sname = gnu_comdat_sym(ifl, isp)) != NULL)) { + size_t size = sname - isp->is_name; + + if ((oname = libld_malloc(size + 1)) == NULL) + return ((Os_desc *)S_ERROR); + (void) strncpy(oname, isp->is_name, size); + oname[size] = '\0'; + DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp->is_name, + oname)); + + /* + * Enable lazy relocation processing, as this is typically a + * requirement with GNU COMDAT sections. + */ + if ((ofl->ofl_flags1 & FLG_OF1_NRLXREL) == 0) { + ofl->ofl_flags1 |= FLG_OF1_RLXREL; + Dbg_sec_gnu_comdat(ofl->ofl_lml, isp->is_name, 0, + (ofl->ofl_flags1 & FLG_OF1_RLXREL)); + } + } + + /* + * Assign a hash value now that the output section name has been + * finalized. + */ + onamehash = sgs_str_hash(oname); if (sgp->sg_flags & FLG_SG_ORDER) enp->ec_flags |= FLG_EC_USED; /* - * If the link is not 0, then the input section is going to be appended - * to the output section. The append occurs at the input section + * If the link is not 0, then the input section is appended to the + * defined output section. The append occurs at the input section * pointed to by the link. */ - if (link != 0) { + if (link) { + uintptr_t err; + osp = isp->is_file->ifl_isdesc[link]->is_osdesc; /* - * If this is a COMDAT section, then see if this - * section is a keeper and/or if it is to be discarded. + * Process any COMDAT section, keeping the first and + * discarding all others. */ - if (shdr->sh_type == SHT_SUNW_COMDAT) { - Listnode * clist; - Is_desc * cisp; - - for (LIST_TRAVERSE(&(osp->os_comdats), clist, cisp)) { - if (strcmp(isp->is_basename, cisp->is_basename)) - continue; - - isp->is_flags |= FLG_IS_DISCARD; - isp->is_osdesc = osp; - DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml, - isp, cisp)); - return (0); - } - - /* - * This is a new COMDAT section - so keep it. - */ - if (list_appendc(&(osp->os_comdats), isp) == 0) - return ((Os_desc *)S_ERROR); - } + if ((isp->is_flags & FLG_IS_COMDAT) && + ((err = add_comdat(ofl, osp, isp)) != 1)) + return ((Os_desc *)err); /* * Set alignment @@ -382,7 +626,7 @@ ld_place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) Sec_order *scop; for (APLIST_TRAVERSE(sgp->sg_secorder, idx, scop)) { - if (strcmp(scop->sco_secname, isp->is_name) == 0) { + if (strcmp(scop->sco_secname, oname) == 0) { scop->sco_flags |= FLG_SGO_USED; os_ndx = scop->sco_index; break; @@ -414,7 +658,7 @@ ld_place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) if ((ident == osp->os_scnsymndx) && (ident != ld_targ.t_id.id_rel) && - (isp->is_namehash == osp->os_namehash) && + (onamehash == osp->os_namehash) && (shdr->sh_type != SHT_GROUP) && (shdr->sh_type != SHT_SUNW_dof) && ((shdr->sh_type == _shdr->sh_type) || @@ -422,34 +666,16 @@ ld_place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) (_shdr->sh_type == SHT_PROGBITS))) && ((shflags & ~shflagmask) == (_shdr->sh_flags & ~shflagmask)) && - (strcmp(isp->is_name, osp->os_name) == 0)) { + (strcmp(oname, osp->os_name) == 0)) { + uintptr_t err; + /* - * If this is a COMDAT section, determine if this - * section is a keeper, and/or if it is to be discarded. + * Process any COMDAT section, keeping the first and + * discarding all others. */ - if (shdr->sh_type == SHT_SUNW_COMDAT) { - Listnode * clist; - Is_desc * cisp; - - for (LIST_TRAVERSE(&(osp->os_comdats), - clist, cisp)) { - if (strcmp(isp->is_basename, - cisp->is_basename)) - continue; - - isp->is_flags |= FLG_IS_DISCARD; - isp->is_osdesc = osp; - DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml, - isp, cisp)); - return (0); - } - - /* - * This is a new COMDAT section - so keep it. - */ - if (list_appendc(&(osp->os_comdats), isp) == 0) - return ((Os_desc *)S_ERROR); - } + if ((isp->is_flags & FLG_IS_COMDAT) && + ((err = add_comdat(ofl, osp, isp)) != 1)) + return ((Os_desc *)err); /* * Set alignment @@ -552,7 +778,7 @@ ld_place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) * count and associated string size. */ ofl->ofl_shdrcnt++; - if (st_insert(ofl->ofl_shdrsttab, isp->is_name) == -1) + if (st_insert(ofl->ofl_shdrsttab, oname) == -1) return ((Os_desc *)S_ERROR); /* @@ -564,26 +790,28 @@ ld_place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) return ((Os_desc *)S_ERROR); /* - * We convert COMDAT sections to PROGBITS if this is the first - * section of a output section. + * Convert COMDAT section to PROGBITS as this the first section of the + * output section. Save any COMDAT section for later processing, as + * additional COMDAT sections that match this section need discarding. */ if (shdr->sh_type == SHT_SUNW_COMDAT) { - Shdr * tshdr; + Shdr *tshdr; - if ((tshdr = libld_malloc(sizeof (Shdr))) == 0) + if ((tshdr = libld_malloc(sizeof (Shdr))) == NULL) return ((Os_desc *)S_ERROR); *tshdr = *shdr; isp->is_shdr = shdr = tshdr; shdr->sh_type = SHT_PROGBITS; - if (list_appendc(&(osp->os_comdats), isp) == 0) - return ((Os_desc *)S_ERROR); } + if ((isp->is_flags & FLG_IS_COMDAT) && + (aplist_append(&(osp->os_comdats), isp, AL_CNT_OS_COMDATS) == NULL)) + return ((Os_desc *)S_ERROR); osp->os_shdr->sh_type = shdr->sh_type; osp->os_shdr->sh_flags = shdr->sh_flags; osp->os_shdr->sh_entsize = shdr->sh_entsize; - osp->os_name = isp->is_name; - osp->os_namehash = isp->is_namehash; + osp->os_name = oname; + osp->os_namehash = onamehash; osp->os_txtndx = os_ndx; osp->os_sgdesc = sgp; diff --git a/usr/src/cmd/sgs/libld/common/relocate.c b/usr/src/cmd/sgs/libld/common/relocate.c index d9d7d3ef0b..da4bb7b829 100644 --- a/usr/src/cmd/sgs/libld/common/relocate.c +++ b/usr/src/cmd/sgs/libld/common/relocate.c @@ -26,7 +26,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * set-up for relocations @@ -1358,9 +1357,9 @@ ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp, } /* - * Given a relocation that references a local symbol from a discarded - * COMDAT (or SHF_GROUP) section, replace the symbol with the - * corresponding symbol from the section that was kept. + * Given a relocation that references a local symbol from a discarded COMDAT + * section, replace the symbol with the corresponding symbol from the section + * that was kept. * * entry: * reld - Relocation @@ -1371,11 +1370,10 @@ ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp, * found, and NULL otherwise. * * note: - * [Note that I'm using the word "COMDAT" here loosely, to refer - * to actual COMDAT sections as well as to groups tied together - * with an SHF_GROUP section. SHF_GROUP is simply a more advanced - * version of the same idea: That multiple versions of the same thing - * can come in, but only one of them is used for the output.] + * The word "COMDAT" is used to refer to actual COMDAT sections, COMDAT + * groups tied together with an SHF_GROUP section, and .gnu.linkonce + * sections which provide a simplified COMDAT requirement. COMDAT + * sections are identified with the FLG_IS_COMDAT section flag. * * In principle, this sort of sloppy relocation remapping is * a questionable practice. All self-referential sections should @@ -1395,9 +1393,9 @@ ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp, * that our heuristic is somewhat different than theirs, but the * end result is close enough to solve the same problem. * - * It is our hope that gcc will eventually phase out the need - * for sloppy relocations, and this won't be needed. In the - * meantime, the option allows us to interoperate. + * gcc may eventually phase out the need for sloppy relocations, and + * then this logic won't be needed. In the meantime, relaxed relocation + * processing allows us to interoperate. * * Here is how we do it: The symbol points at the input section, * and the input section points at the output section to which it @@ -1415,53 +1413,31 @@ sloppy_comdat_reloc(Ofl_desc *ofl, Rel_desc *reld, Sym_desc *sdp) { Listnode *lnp; Is_desc *rep_isp; - const char *is_name; Sym *sym = sdp->sd_sym; Is_desc *isp = sdp->sd_isc; + Ifl_desc *ifl = sdp->sd_file; Conv_inv_buf_t inv_buf; /* - * ld_place_section() can alter the section name if it contains - * a '%' character. We need to use the original name in this - * case. - */ - is_name = isp->is_basename ? isp->is_basename : isp->is_name; - - /* - * 1) The caller is required to ensure that the input symbol is - * local. We don't check for that here. - * 2) If the discarded section has not been assigned to an - * output section, we won't be able to continue. - * 3) This operation only applies to SHT_SUNW_COMDAT sections - * or sections contained within a COMDAT group (SHF_GROUP). - */ - if ((isp->is_osdesc == NULL) || - ((isp->is_shdr->sh_type != SHT_SUNW_COMDAT) && - ((isp->is_shdr->sh_flags & SHF_GROUP) == 0))) - return (NULL); - - /* * Examine each input section assigned to this output section. * The replacement section must: * - Have the same name as the original * - Not have been discarded * - Have the same size - * - Have the same section type (and note that this type may - * be SHT_SUNW_COMDAT). + * - Have the same section type * - Have the same SHF_GROUP flag setting (either on or off) * - Must be a COMDAT section of one form or the other. */ /* BEGIN CSTYLED */ for (LIST_TRAVERSE(&isp->is_osdesc->os_isdescs, lnp, rep_isp)) { - const char *rep_is_name = rep_isp->is_basename ? - rep_isp->is_basename : rep_isp->is_name; - if (!(rep_isp->is_flags & FLG_IS_DISCARD) && + if (((rep_isp->is_flags & + (FLG_IS_COMDAT | FLG_IS_DISCARD)) == FLG_IS_COMDAT) && (isp->is_indata->d_size == rep_isp->is_indata->d_size) && (isp->is_shdr->sh_type == rep_isp->is_shdr->sh_type) && ((isp->is_shdr->sh_flags & SHF_GROUP) == (rep_isp->is_shdr->sh_flags & SHF_GROUP)) && - (strcmp(rep_is_name, is_name) == 0)) { + (strcmp(rep_isp->is_name, isp->is_name) == 0)) { /* * We found the kept COMDAT section. Now, look at all of the * symbols from the input file that contains it to find the @@ -1498,15 +1474,13 @@ sloppy_comdat_reloc(Ofl_desc *ofl, Rel_desc *reld, Sym_desc *sdp) (sym->st_other == rep_sym->st_other)) { if (ofl->ofl_flags & FLG_OF_VERBOSE) { - Ifl_desc *ifl = sdp->sd_file; - if (sym->st_name != 0) { eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_REL_SLOPCDATNAM), conv_reloc_type(ifl->ifl_ehdr->e_machine, reld->rel_rtype, 0, &inv_buf), ifl->ifl_name, reld->rel_isdesc->is_name, - rep_sdp->sd_name, is_name, + rep_sdp->sd_name, isp->is_name, rep_sdp->sd_file->ifl_name); } else { eprintf(ofl->ofl_lml, ERR_WARNING, @@ -1515,11 +1489,11 @@ sloppy_comdat_reloc(Ofl_desc *ofl, Rel_desc *reld, Sym_desc *sdp) ifl->ifl_ehdr->e_machine, reld->rel_rtype, 0, &inv_buf), ifl->ifl_name, reld->rel_isdesc->is_name, - is_name, rep_sdp->sd_file->ifl_name); + isp->is_name, rep_sdp->sd_file->ifl_name); } } DBG_CALL(Dbg_reloc_sloppycomdat(ofl->ofl_lml, - is_name, rep_sdp)); + isp->is_name, rep_sdp)); return (rep_sdp); } } @@ -1531,7 +1505,6 @@ sloppy_comdat_reloc(Ofl_desc *ofl, Rel_desc *reld, Sym_desc *sdp) return (NULL); } - /* * Generate a name for a relocation descriptor that has an STT_SECTION * symbol associated with it. If it is a regular input section, it will @@ -1595,7 +1568,6 @@ ld_section_reld_name(Sym_desc *sdp, Is_desc *sd_isc) return (NULL); } - /* * Generate relocation descriptor and dispatch */ @@ -1711,21 +1683,44 @@ process_reld(Ofl_desc *ofl, Is_desc *isp, Rel_desc *reld, Word rsndx, if (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL) { /* - * If "-z relaxreloc", then check to see if - * this is a reference to a discarded COMDAT - * section that can be replaced with the - * one that was kept. + * If "-z relaxreloc", and the input section is COMDAT + * that has been assigned to an output section, then + * determine if this is a reference to a discarded + * COMDAT section that can be replaced with a COMDAT + * that has been kept. + * + * If a matching symbol can not be found, issue a + * warning and ignore the relocation. Note, the GNU + * linker will act as though the symbol were defined at + * the same offset in the copy of the linkonce section + * that was kept. This seems rather dangerous, and as + * the situation only seems to apply to debugging + * information, our choise is to ignore the relocation. */ - if (ofl->ofl_flags1 & FLG_OF1_RLXREL) - nsdp = sloppy_comdat_reloc(ofl, reld, sdp); - } else if (reld->rel_sname == sdp->sd_name) { + if ((ofl->ofl_flags1 & FLG_OF1_RLXREL) && + sdp->sd_isc->is_osdesc && + (sdp->sd_isc->is_flags & FLG_IS_COMDAT) && + ((nsdp = sloppy_comdat_reloc(ofl, reld, + sdp)) == NULL)) { + eprintf(ofl->ofl_lml, ERR_WARNING, + MSG_INTL(MSG_REL_SLOPCDATNOSYM), + conv_reloc_type(ifl->ifl_ehdr->e_machine, + reld->rel_rtype, 0, &inv_buf), + ifl->ifl_name, isp->is_name, + demangle(reld->rel_sname), + sdp->sd_isc->is_name); + return (1); + } + } else if (reld->rel_sname == sdp->sd_name) nsdp = ld_sym_find(sdp->sd_name, SYM_NOHASH, 0, ofl); - } - if (nsdp == 0) { + + if (nsdp == NULL) { eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_SYMDISC), - ifl->ifl_name, isp->is_name, - demangle(sdp->sd_name), sdp->sd_isc->is_name); + conv_reloc_type(ifl->ifl_ehdr->e_machine, + reld->rel_rtype, 0, &inv_buf), ifl->ifl_name, + isp->is_name, demangle(reld->rel_sname), + sdp->sd_isc->is_name); return (S_ERROR); } ifl->ifl_oldndx[rsndx] = sdp = nsdp; diff --git a/usr/src/cmd/sgs/libld/common/sections.c b/usr/src/cmd/sgs/libld/common/sections.c index 19549501d2..0472ceadec 100644 --- a/usr/src/cmd/sgs/libld/common/sections.c +++ b/usr/src/cmd/sgs/libld/common/sections.c @@ -26,7 +26,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * Module sections. Initialize special sections @@ -742,11 +741,11 @@ make_array(Ofl_desc *ofl, Word shtype, const char *sectname, List *list) osp = isec->is_osdesc; - if ((ofl->ofl_osinitarray == 0) && (shtype == SHT_INIT_ARRAY)) + if ((ofl->ofl_osinitarray == NULL) && (shtype == SHT_INIT_ARRAY)) ofl->ofl_osinitarray = osp; - if ((ofl->ofl_ospreinitarray == 0) && (shtype == SHT_PREINIT_ARRAY)) + if ((ofl->ofl_ospreinitarray == NULL) && (shtype == SHT_PREINIT_ARRAY)) ofl->ofl_ospreinitarray = osp; - else if ((ofl->ofl_osfiniarray == 0) && (shtype == SHT_FINI_ARRAY)) + else if ((ofl->ofl_osfiniarray == NULL) && (shtype == SHT_FINI_ARRAY)) ofl->ofl_osfiniarray = osp; /* @@ -849,7 +848,6 @@ make_dynamic(Ofl_desc *ofl) * objects. See the comment at the head of update_odynamic() in * update.c for details. */ - if (new_section(ofl, SHT_DYNAMIC, MSG_ORIG(MSG_SCN_DYNAMIC), 0, &isec, &shdr, &data) == S_ERROR) return (S_ERROR); @@ -865,7 +863,7 @@ make_dynamic(Ofl_desc *ofl) * Reserve entries for any needed dependencies. */ for (LIST_TRAVERSE(&ofl->ofl_sos, lnp, ifl)) { - Sdf_desc * sdf; + Sdf_desc *sdf; if (!(ifl->ifl_flags & (FLG_IF_NEEDED | FLG_IF_NEEDSTR))) continue; @@ -1455,6 +1453,7 @@ make_symtab(Ofl_desc *ofl) ld_targ.t_id.id_symtab_ndx, 0)) == (Os_desc *)S_ERROR) return (S_ERROR); } + /* * Calculated number of symbols, which need to be augmented by * the null first entry, the FILE symbol, and the .shstrtab entry. @@ -1585,7 +1584,6 @@ make_dynsort(Ofl_desc *ofl) Elf_Data *data; Is_desc *isec; - /* Only do it if the .SUNW_ldynsym section is present */ if (!OFL_ALLOW_LDYNSYM(ofl)) return (1); @@ -1771,7 +1769,7 @@ make_dynstr(Ofl_desc *ofl) int ndx; for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) { - Sym_desc * sdp; + Sym_desc *sdp; if ((sdp = ofl->ofl_regsyms[ndx]) == 0) continue; @@ -2142,8 +2140,8 @@ ld_make_sunwmove(Ofl_desc *ofl, int mv_nums) * Copy move entries */ for (LIST_TRAVERSE(&ofl->ofl_parsym, lnp1, psym)) { - Listnode * lnp2; - Mv_itm * mvitm; + Listnode *lnp2; + Mv_itm *mvitm; if (psym->psym_symd->sd_flags & FLG_SY_PAREXPN) continue; diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c index a7eac0d7fb..d33ee869c4 100644 --- a/usr/src/cmd/sgs/libld/common/update.c +++ b/usr/src/cmd/sgs/libld/common/update.c @@ -26,7 +26,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * Update the new output file image, perform virtual address, offset and @@ -3055,7 +3054,7 @@ update_move(Ofl_desc *ofl) * sh_link/sh_info fields as well as the section contents. */ static uintptr_t -update_ogroup(Ofl_desc * ofl) +update_ogroup(Ofl_desc *ofl) { Listnode *lnp; Os_desc *osp; @@ -3087,31 +3086,16 @@ update_ogroup(Ofl_desc * ofl) */ grpcnt = shdr->sh_size / shdr->sh_entsize; gdata = (Word *)osp->os_outdata->d_buf; - for (i = 1; i < grpcnt; i++) { - Is_desc * _isp; - Os_desc * _osp; - - /* - * Perform a sanity check that the section index - * stored in the SHT_GROUP section is valid - * for the file it came from. - */ - if (gdata[i] >= ifl->ifl_shnum) { - eprintf(ofl->ofl_lml, ERR_FATAL, - MSG_INTL(MSG_GRP_INVALNDX), isp->is_name, - ifl->ifl_name, i, gdata[i]); - error = S_ERROR; - gdata[i] = 0; - continue; - } - _isp = ifl->ifl_isdesc[gdata[i]]; + for (i = 1; i < grpcnt; i++) { + Os_desc *_osp; + Is_desc *_isp = ifl->ifl_isdesc[gdata[i]]; /* * If the referenced section didn't make it to the * output file - just zero out the entry. */ - if ((_osp = _isp->is_osdesc) == 0) + if ((_osp = _isp->is_osdesc) == NULL) gdata[i] = 0; else gdata[i] = (Word)elf_ndxscn(_osp->os_scn); diff --git a/usr/src/cmd/sgs/libld/common/util.c b/usr/src/cmd/sgs/libld/common/util.c index 2c2c83c0b8..2164b854fe 100644 --- a/usr/src/cmd/sgs/libld/common/util.c +++ b/usr/src/cmd/sgs/libld/common/util.c @@ -29,8 +29,6 @@ * All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Utility functions */ @@ -85,46 +83,18 @@ * by libld_malloc() must be 8 byte-aligned. Even in a 32-bit environment, * u_longlog_t pointers are employed. * - * MAP_ANON arrived in Solaris 8, thus a fall-back is provided for older - * systems. + * Map anonymous memory via MAP_ANON (added in Solaris 8). */ static void * dz_map(size_t size) { void *addr; - int err; - -#if defined(MAP_ANON) - static int noanon = 0; - - if (noanon == 0) { - if ((addr = mmap(0, size, (PROT_READ | PROT_WRITE | PROT_EXEC), - (MAP_PRIVATE | MAP_ANON), -1, 0)) != MAP_FAILED) - return (addr); - - if ((errno != EBADF) && (errno != EINVAL)) { - err = errno; - eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON), - MSG_ORIG(MSG_PTH_DEVZERO), strerror(err)); - return (MAP_FAILED); - } else - noanon = 1; - } -#endif - if (dz_fd == -1) { - if ((dz_fd = open(MSG_ORIG(MSG_PTH_DEVZERO), O_RDONLY)) == -1) { - err = errno; - eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), - MSG_ORIG(MSG_PTH_DEVZERO), strerror(err)); - return (MAP_FAILED); - } - } if ((addr = mmap(0, size, (PROT_READ | PROT_WRITE | PROT_EXEC), - MAP_PRIVATE, dz_fd, 0)) == MAP_FAILED) { - err = errno; - eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_MMAP), - MSG_ORIG(MSG_PTH_DEVZERO), strerror(err)); + (MAP_PRIVATE | MAP_ANON), -1, 0)) == MAP_FAILED) { + int err = errno; + eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON), + strerror(err)); return (MAP_FAILED); } return (addr); @@ -154,7 +124,7 @@ libld_malloc(size_t size) tsize = HEAPBLOCK; if ((nhp = dz_map(tsize)) == MAP_FAILED) - return (0); + return (NULL); nhp->lh_next = chp; nhp->lh_free = (void *)((size_t)nhp + hsize); @@ -222,8 +192,8 @@ list_appendc(List *lst, const void *item) { Listnode *_lnp; - if ((_lnp = libld_malloc(sizeof (Listnode))) == 0) - return (0); + if ((_lnp = libld_malloc(sizeof (Listnode))) == NULL) + return (NULL); _lnp->data = (void *)item; _lnp->next = NULL; @@ -246,8 +216,8 @@ list_insertc(List *lst, const void *item, Listnode *lnp) { Listnode *_lnp; - if ((_lnp = libld_malloc(sizeof (Listnode))) == 0) - return (0); + if ((_lnp = libld_malloc(sizeof (Listnode))) == NULL) + return (NULL); _lnp->data = (void *)item; _lnp->next = lnp->next; @@ -266,8 +236,8 @@ list_prependc(List *lst, const void *item) { Listnode *_lnp; - if ((_lnp = libld_malloc(sizeof (Listnode))) == 0) - return (0); + if ((_lnp = libld_malloc(sizeof (Listnode))) == NULL) + return (NULL); _lnp->data = (void *)item; @@ -380,7 +350,7 @@ sdf_find(const char *name, List *lst) if (strcmp(name, sdf->sdf_name) == 0) return (sdf); - return (0); + return (NULL); } Sdf_desc * @@ -427,11 +397,11 @@ add_string(char *old, char *str) } len = strlen(old) + strlen(str) + 2; - if ((new = libld_calloc(1, len)) == 0) + if ((new = libld_calloc(1, len)) == NULL) return ((char *)S_ERROR); (void) snprintf(new, len, MSG_ORIG(MSG_FMT_COLPATH), old, str); } else { - if ((new = libld_malloc(strlen(str) + 1)) == 0) + if ((new = libld_malloc(strlen(str) + 1)) == NULL) return ((char *)S_ERROR); (void) strcpy(new, str); } diff --git a/usr/src/cmd/sgs/liblddbg/common/debug.c b/usr/src/cmd/sgs/liblddbg/common/debug.c index 3953ea403c..c4f30bc9fa 100644 --- a/usr/src/cmd/sgs/liblddbg/common/debug.c +++ b/usr/src/cmd/sgs/liblddbg/common/debug.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <libintl.h> #include <sys/varargs.h> #include <stdio.h> diff --git a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg index 776b93b27a..f0f49653ad 100644 --- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg @@ -23,8 +23,6 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# @ _START_ @@ -174,8 +172,8 @@ # symbols display symbol table processing; detail flag shows internal # symbol table addition and resolution (ld only) # statistics display processing statistics (ld only) -# strtab display information about string table compression (ld only) -# detail shows layout of string tables +# strtab display information about string table compression; detail +# flag shows layout of string tables (ld only) # tls display TLS processing # unused display unused/unreferenced files; detail flag shows unused # sections (ld only), and unused search paths (ld.so.1 only) @@ -270,7 +268,7 @@ # TRANSLATION_NOTE -- do not translate the first token `strtab'. @ MSG_USE_STRTAB "strtab\t display information about string table \ compression; detail" -@ MSG_USE_STRTAB_2 "\t\t shows layout of string tables (ld only)" +@ MSG_USE_STRTAB_2 "\t\t flag shows layout of string tables (ld only)" # TRANSLATION_NOTE -- do not translate the first token `tls/TLS'. @ MSG_USE_TLS "tls\t display TLS processing info" @@ -559,17 +557,27 @@ @ MSG_SEC_INPUT_GENSTR "section=%s; input generated merged string section" @ MSG_SEC_ADDED "section=%s; added to segment=%s" @ MSG_SEC_CREATED "section=%s; added to segment=%s (created)" +@ MSG_SEC_REDIRECTED "section=%s; redirected to section=%s" @ MSG_SEC_DISCARDED "section=%s; input from file=%s; \ - discarded in favor of section=%s from file=%s" -@ MSG_SEC_STRMERGE_DISCARDED "section=%s; input from file=%s; \ + discarded in favor of section=%s; file=%s" + +@ MSG_SEC_GNU_COMDAT_1 "section=%s; identified as COMDAT with \ + relaxed relocations enabled" +@ MSG_SEC_GNU_COMDAT_2 "section=%s; identified as COMDAT" +@ MSG_SEC_GNU_COMDAT_3 "section=%s; relaxed relocations enabled" + +@ MSG_SEC_GRP_DEFINE "section=%s; input from file=%s; defines %s\ + group: signature symbol: %s" +@ MSG_SEC_GRP_MEMBER "section=%s; input from file=%s; member of %s\ + group: signature symbol: %s" +@ MSG_SEC_GRP_DISCARDED "section=%s; input from file=%s; discarded in favor of \ + group: signature symbol: %s: file=%s" + +@ MSG_SEC_STRMERGE_DISCARDED "section=%s; input from file=%s; \ discarded in favor of generated merged string section" @ MSG_SEC_STRMERGE_UNSUP "section=%s; input from file=%s; sh_addralign=%lld; \ sh_entsize=%lld; unable to merge sections with this \ size and alignment" -@ MSG_SEC_GRP_INPUT "section=%s; input from file=%s; \ - member of group: %s:%s" -@ MSG_SEC_GRP_DISCARDED "section=%s; input from file=%s; \ - discarded: member of existing group: %s:%s" @ MSG_SEC_STRTAB_STND "strtab=%s; full size: %lld; uncompressed" @ MSG_SEC_STRTAB_COMP "strtab=%s; full size: %lld; compressed down to: %lld" @@ -697,7 +705,7 @@ @ MSG_ORD_TITLE_0 " section=%s from %s is not an ordered section" @ MSG_ORD_TITLE_1 " section=%s from %s, %s=SHN_BEGIN" @ MSG_ORD_TITLE_2 " section=%s from %s, %s=SHN_AFTER" -@ MSG_ORD_TITLE_3 " section=%s from %s, %s=%s, sort_val=%d" +@ MSG_ORD_TITLE_3 " section=%s from %s, %s=%s, sort key=%u" @ MSG_ORD_ERR_TITLE "the SHF_ORDERED section %s from %s has \ an error; flag ignored" @@ -1131,6 +1139,7 @@ @ MSG_STR_EMPTY "" @ MSG_STR_DELIMIT ",:" +@ MSG_STR_COMDAT "COMDAT " @ MSG_SCN_GOT ".got" @ MSG_SCN_PLT ".plt" diff --git a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg index cd83abd77d..cf414caa9a 100644 --- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg @@ -26,8 +26,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/auxv.h> #include <debug.h> @@ -288,12 +286,16 @@ void Dbg32_sec_discarded(Lm_list *, Is_desc *, Is_desc *); void Dbg64_sec_discarded(Lm_list *, Is_desc *, Is_desc *); void Dbg32_sec_group(Lm_list *, Is_desc *, Group_desc *); void Dbg64_sec_group(Lm_list *, Is_desc *, Group_desc *); +void Dbg32_sec_gnu_comdat(Lm_list *, const char *, uint_t, uint_t); +void Dbg64_sec_gnu_comdat(Lm_list *, const char *, uint_t, uint_t); void Dbg32_sec_in(Lm_list *, Is_desc *); void Dbg64_sec_in(Lm_list *, Is_desc *); void Dbg32_sec_order_error(Lm_list *, Ifl_desc *, Elf32_Word, int); void Dbg64_sec_order_error(Lm_list *, Ifl_desc *, Elf64_Word, int); void Dbg32_sec_order_list(Ofl_desc *, int); void Dbg64_sec_order_list(Ofl_desc *, int); +void Dbg32_sec_redirected(Lm_list *, const char *, const char *); +void Dbg64_sec_redirected(Lm_list *, const char *, const char *); void Dbg32_sec_strtab(Lm_list *, Os_desc *, Str_tbl *); void Dbg64_sec_strtab(Lm_list *, Os_desc *, Str_tbl *); diff --git a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers index b3508a35ac..d569e946f7 100644 --- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers @@ -23,7 +23,7 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" + # # Generic interface definition for usr/src/cmd/sgs/liblddbg. # @@ -38,7 +38,7 @@ # Policy for Shared Library Version Names and Interface Definitions -SUNWprivate_4.63 { +SUNWprivate_4.64 { global: dbg_desc = NODIRECT; # interposed - ld.so.1(1) dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1) @@ -276,12 +276,16 @@ SUNWprivate_4.63 { Dbg64_sec_genstr_compress; Dbg32_sec_group; Dbg64_sec_group; + Dbg32_sec_gnu_comdat; + Dbg64_sec_gnu_comdat; Dbg32_sec_in; Dbg64_sec_in; Dbg32_sec_order_error; Dbg64_sec_order_error; Dbg32_sec_order_list; Dbg64_sec_order_list; + Dbg32_sec_redirected; + Dbg64_sec_redirected; Dbg32_sec_strtab; Dbg64_sec_strtab; Dbg32_sec_unsup_strmerge; diff --git a/usr/src/cmd/sgs/liblddbg/common/relocate.c b/usr/src/cmd/sgs/liblddbg/common/relocate.c index 19de13e4c9..23c2a41873 100644 --- a/usr/src/cmd/sgs/liblddbg/common/relocate.c +++ b/usr/src/cmd/sgs/liblddbg/common/relocate.c @@ -23,7 +23,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/elf_SPARC.h> #include <debug.h> @@ -243,7 +242,7 @@ Dbg_reloc_discard(Lm_list *lml, Half mach, Rel_desc *rsp) return; isp = rsp->rel_isdesc; - dbg_print(lml, MSG_INTL(MSG_REL_DISCARDED), isp->is_basename, + dbg_print(lml, MSG_INTL(MSG_REL_DISCARDED), isp->is_name, isp->is_file->ifl_name, conv_reloc_type(mach, rsp->rel_rtype, 0, &inv_buf), EC_OFF(rsp->rel_roffset)); @@ -261,7 +260,7 @@ Dbg_reloc_transition(Lm_list *lml, Half mach, Word rtype, Rel_desc *rsp) isp = rsp->rel_isdesc; dbg_print(lml, MSG_INTL(MSG_REL_TRANSITION), conv_reloc_type(mach, rsp->rel_rtype, 0, &inv_buf1), - isp->is_basename, isp->is_file->ifl_name, + isp->is_name, isp->is_file->ifl_name, EC_OFF(rsp->rel_roffset), rsp->rel_sname, conv_reloc_type(mach, rtype, 0, &inv_buf2)); } diff --git a/usr/src/cmd/sgs/liblddbg/common/sections.c b/usr/src/cmd/sgs/liblddbg/common/sections.c index 02bb9d779f..82d4175ffc 100644 --- a/usr/src/cmd/sgs/liblddbg/common/sections.c +++ b/usr/src/cmd/sgs/liblddbg/common/sections.c @@ -23,8 +23,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "msg.h" #include "_debug.h" #include "libld.h" @@ -115,7 +113,7 @@ Dbg_sec_unsup_strmerge(Lm_list *lml, Is_desc *isp) str = (isp->is_file != NULL) ? isp->is_file->ifl_name : MSG_INTL(MSG_STR_NULL); dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_UNSUP), - isp->is_basename, str, EC_XWORD(isp->is_shdr->sh_addralign), + isp->is_name, str, EC_XWORD(isp->is_shdr->sh_addralign), EC_XWORD(isp->is_shdr->sh_entsize)); } } @@ -191,11 +189,11 @@ Dbg_sec_discarded(Lm_list *lml, Is_desc *isp, Is_desc *disp) * discarded in favor of the generated merged string section. */ dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_DISCARDED), - isp->is_basename, isp->is_file->ifl_name); + isp->is_name, isp->is_file->ifl_name); } else { /* Generic section discard */ - dbg_print(lml, MSG_INTL(MSG_SEC_DISCARDED), isp->is_basename, - isp->is_file->ifl_name, disp->is_basename, + dbg_print(lml, MSG_INTL(MSG_SEC_DISCARDED), isp->is_name, + isp->is_file->ifl_name, disp->is_name, disp->is_file->ifl_name); } } @@ -203,18 +201,29 @@ Dbg_sec_discarded(Lm_list *lml, Is_desc *isp, Is_desc *disp) void Dbg_sec_group(Lm_list *lml, Is_desc *isp, Group_desc *gdp) { - const char *fmt; + const char *comdat; if (DBG_NOTCLASS(DBG_C_SECTIONS)) return; - if (gdp->gd_flags & GRP_FLG_DISCARD) - fmt = MSG_INTL(MSG_SEC_GRP_DISCARDED); + if (gdp->gd_data[0] & GRP_COMDAT) + comdat = MSG_ORIG(MSG_STR_COMDAT); else - fmt = MSG_INTL(MSG_SEC_GRP_INPUT); + comdat = MSG_ORIG(MSG_STR_EMPTY); + + if (isp->is_shdr->sh_type == SHT_GROUP) { + dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DEFINE), isp->is_name, + isp->is_file->ifl_name, comdat, gdp->gd_name); + } else { + dbg_print(lml, MSG_INTL(MSG_SEC_GRP_MEMBER), isp->is_name, + isp->is_file->ifl_name, comdat, gdp->gd_name); + } - dbg_print(lml, fmt, isp->is_name, isp->is_file->ifl_name, - gdp->gd_gsectname, gdp->gd_symname); + if (gdp->gd_oisc) { + dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DISCARDED), isp->is_name, + isp->is_file->ifl_name, gdp->gd_name, + gdp->gd_oisc->is_file->ifl_name); + } } void @@ -287,7 +296,7 @@ Dbg_sec_order_list(Ofl_desc *ofl, int flag) isp2 = ifl->ifl_isdesc[link]; dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_3), isp1->is_name, ifl->ifl_name, msg, isp2->is_name, - isp2->is_key); + EC_WORD(isp2->is_keyident)); } } Dbg_util_nl(lml, DBG_NL_STD); @@ -322,3 +331,30 @@ Dbg_sec_order_error(Lm_list *lml, Ifl_desc *ifl, Word ndx, int error) if (error) dbg_print(lml, MSG_INTL(order_errors[error - 1])); } + +void +Dbg_sec_redirected(Lm_list *lml, const char *oname, const char *nname) +{ + if (DBG_NOTCLASS(DBG_C_SECTIONS)) + return; + + dbg_print(lml, MSG_INTL(MSG_SEC_REDIRECTED), oname, nname); +} + +void +Dbg_sec_gnu_comdat(Lm_list *lml, const char *name, uint_t comdat, uint_t relax) +{ + const char *fmt; + + if (DBG_NOTCLASS(DBG_C_SECTIONS)) + return; + + if (comdat && relax) + fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_1); + else if (comdat) + fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_2); + else + fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_3); + + dbg_print(lml, fmt, name); +} diff --git a/usr/src/cmd/sgs/liblddbg/common/syms.c b/usr/src/cmd/sgs/liblddbg/common/syms.c index 44f1f23d17..2bcf8a19c2 100644 --- a/usr/src/cmd/sgs/liblddbg/common/syms.c +++ b/usr/src/cmd/sgs/liblddbg/common/syms.c @@ -23,7 +23,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <stdio.h> #include <dlfcn.h> @@ -204,12 +203,9 @@ Dbg_syms_discarded(Lm_list *lml, Sym_desc *sdp) file = MSG_INTL(MSG_STR_UNKNOWN); if (sdp->sd_isc) { - const char *sec; - - if ((sec = sdp->sd_isc->is_basename) == 0) - sec = sdp->sd_isc->is_name; dbg_print(lml, MSG_INTL(MSG_SYM_DISCARD_SEC), - Dbg_demangle_name(sdp->sd_name), sec, file); + Dbg_demangle_name(sdp->sd_name), sdp->sd_isc->is_name, + file); } else dbg_print(lml, MSG_INTL(MSG_SYM_DISCARD_FILE), Dbg_demangle_name(sdp->sd_name), file); diff --git a/usr/src/cmd/sgs/liblddbg/common/unused.c b/usr/src/cmd/sgs/liblddbg/common/unused.c index c0bcdf9e41..4d28b6312c 100644 --- a/usr/src/cmd/sgs/liblddbg/common/unused.c +++ b/usr/src/cmd/sgs/liblddbg/common/unused.c @@ -23,7 +23,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include "msg.h" #include "_debug.h" @@ -64,7 +63,7 @@ Dbg_unused_sec(Lm_list *lml, Is_desc *isp) else str = MSG_ORIG(MSG_STR_EMPTY); - dbg_print(lml, MSG_INTL(MSG_USD_SEC), isp->is_basename, + dbg_print(lml, MSG_INTL(MSG_USD_SEC), isp->is_name, EC_XWORD(isp->is_shdr->sh_size), isp->is_file->ifl_name, str); } diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README index 0d66750f8b..98e31561e7 100644 --- a/usr/src/cmd/sgs/packages/common/SUNWonld-README +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README @@ -1371,3 +1371,6 @@ Bugid Risk Synopsis 6728555 Fix for amd64 aw (6617475) breaks pure gcc builds 6734598 ld(1) archive processing failure due to mismatched file descriptors 6684577 ld should propagate SHF_LINK_ORDER flag to ET_REL objects +6735939 ld(1) discarded symbol relocations errors (Studio and GNU). +6354160 Solaris linker includes more than one copy of code in binary when + linking gnu object code |