diff options
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 |