diff options
author | ab196087 <none@none> | 2006-09-19 15:38:37 -0700 |
---|---|---|
committer | ab196087 <none@none> | 2006-09-19 15:38:37 -0700 |
commit | 9039eeaf76678a41be39feb97b4f724272ef7e18 (patch) | |
tree | a212dbf67415286780fcda66a0fdebf596d758f2 /usr/src | |
parent | ef4c14d24cff432d9d11d0a63d2676aa5d58fefe (diff) | |
download | illumos-gate-9039eeaf76678a41be39feb97b4f724272ef7e18.tar.gz |
PSARC 2006/526 SHT_SUNW_LDYNSYM - default local symbol addition
4934427 runtime linker should load up static symbol names visible to dladdr()
Diffstat (limited to 'usr/src')
24 files changed, 941 insertions, 835 deletions
diff --git a/usr/src/cmd/sgs/dump/common/dump.c b/usr/src/cmd/sgs/dump/common/dump.c index 4e8cdc49f0..94b5b1f2a3 100644 --- a/usr/src/cmd/sgs/dump/common/dump.c +++ b/usr/src/cmd/sgs/dump/common/dump.c @@ -1142,6 +1142,7 @@ dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename) case DT_PREINIT_ARRAYSZ: case DT_SUNW_RTLDINF: case DT_SUNW_CAP: + case DT_SUNW_SYMTAB: case DT_PLTPAD: case DT_MOVETAB: case DT_SYMINFO: @@ -1202,6 +1203,7 @@ dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename) case DT_SYMINENT: case DT_VERNEEDNUM: case DT_SPARC_REGISTER: + case DT_SUNW_SYMSZ: (void) printf(pdyn_Fmtptr, EC_XWORD(p_dyn.d_un.d_val)); break; diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.c b/usr/src/cmd/sgs/elfdump/common/elfdump.c index 1d8d152b49..32c573cf89 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.c +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c @@ -1077,7 +1077,8 @@ symbols(Cache *cache, Word shnum, Ehdr *ehdr, const char *name, uint_t symnshxndx; if ((shdr->sh_type != SHT_SYMTAB) && - (shdr->sh_type != SHT_DYNSYM)) + (shdr->sh_type != SHT_DYNSYM) && + (shdr->sh_type != SHT_SUNW_LDYNSYM)) continue; if (name && strcmp(name, secname)) continue; diff --git a/usr/src/cmd/sgs/include/i386/machdep.h b/usr/src/cmd/sgs/include/i386/machdep.h index 3afe3d9ec6..ccbf80a21a 100644 --- a/usr/src/cmd/sgs/include/i386/machdep.h +++ b/usr/src/cmd/sgs/include/i386/machdep.h @@ -309,13 +309,14 @@ extern "C" { #define M_ID_UNWIND 0x06 #define M_ID_SYMINFO 0x07 #define M_ID_HASH 0x08 -#define M_ID_DYNSYM 0x09 -#define M_ID_DYNSTR 0x0a -#define M_ID_VERSION 0x0b -#define M_ID_REL 0x0c -#define M_ID_PLT 0x0d /* SHF_ALLOC + SHF_EXECISNTR */ -#define M_ID_TEXT 0x0e -#define M_ID_DATA 0x0f +#define M_ID_LDYNSYM 0x09 /* always right before DYNSYM */ +#define M_ID_DYNSYM 0x0a +#define M_ID_DYNSTR 0x0b +#define M_ID_VERSION 0x0c +#define M_ID_REL 0x0d +#define M_ID_PLT 0x0e /* SHF_ALLOC + SHF_EXECISNTR */ +#define M_ID_TEXT 0x0f +#define M_ID_DATA 0x10 /* M_ID_USER 0x02 dual entry - listed above */ #define M_ID_GOT 0x03 /* SHF_ALLOC + SHF_WRITE */ diff --git a/usr/src/cmd/sgs/include/libld.h b/usr/src/cmd/sgs/include/libld.h index ce300143c9..ebbaa0b4cd 100644 --- a/usr/src/cmd/sgs/include/libld.h +++ b/usr/src/cmd/sgs/include/libld.h @@ -208,8 +208,10 @@ struct ofl_desc { Word ofl_entercnt; /* no. of global symbols entered */ Word ofl_globcnt; /* no. of global symbols to output */ Word ofl_scopecnt; /* no. of scoped symbols to output */ + Word ofl_dynscopecnt; /* no. scoped syms in .SUNW_ldynsym */ Word ofl_elimcnt; /* no. of eliminated symbols */ - Word ofl_locscnt; /* no. of local symbols to output */ + Word ofl_locscnt; /* no. of local symbols in .symtab */ + Word ofl_dynlocscnt; /* no. local symbols in .SUNW_ldynsym */ Word ofl_dynshdrcnt; /* no. of output section in .dynsym */ Word ofl_shdrcnt; /* no. of output sections */ Str_tbl *ofl_shdrsttab; /* Str_tbl for shdr strtab */ @@ -239,6 +241,7 @@ struct ofl_desc { Is_desc *ofl_issunwbss; /* .SUNW_bss input section (globals) */ Os_desc *ofl_osdynamic; /* .dynamic output section */ Os_desc *ofl_osdynsym; /* .dynsym output section */ + Os_desc *ofl_osldynsym; /* .SUNW_ldynsym output section */ Os_desc *ofl_osdynstr; /* .dynstr output section */ Os_desc *ofl_osgot; /* .got output section */ Os_desc *ofl_oshash; /* .hash output section */ @@ -256,6 +259,7 @@ struct ofl_desc { Os_desc *ofl_ossymtab; /* .symtab output section */ Os_desc *ofl_ossymshndx; /* .symtab_shndx output section */ Os_desc *ofl_osdynshndx; /* .dynsym_shndx output section */ + Os_desc *ofl_osldynshndx; /* .SUNW_ldynsym_shndx output sec */ Os_desc *ofl_osverdef; /* .version definition output section */ Os_desc *ofl_osverneed; /* .version needed output section */ Os_desc *ofl_osversym; /* .version symbol ndx output section */ @@ -291,7 +295,7 @@ struct ofl_desc { #define FLG_OF_DYNLIBS 0x00001000 /* dynamic input allowed: -Bdynamic */ #define FLG_OF_SYMBOLIC 0x00002000 /* bind global symbols: -Bsymbolic */ #define FLG_OF_ADDVERS 0x00004000 /* add version stamp: -Qy */ -#define FLG_OF_MEMORY 0x00008000 /* produce a memory model */ +#define FLG_OF_NOLDYNSYM 0x00008000 /* -znoldynsym set */ #define FLG_OF_SEGORDER 0x00010000 /* segment ordering is required */ #define FLG_OF_SEGSORT 0x00020000 /* segment sorting is required */ #define FLG_OF_TEXTREL 0x00040000 /* text relocations have been found */ @@ -347,6 +351,7 @@ struct ofl_desc { /* section */ #define FLG_OF1_TLSOREL 0x00100000 /* output relocation against .tlsbss */ /* section */ +#define FLG_OF1_MEMORY 0x00200000 /* produce a memory model */ #define FLG_OF1_VADDR 0x01000000 /* vaddr was explicitly set */ #define FLG_OF1_EXTRACT 0x02000000 /* archive member has been extracted */ #define FLG_OF1_RESCAN 0x04000000 /* any archives should be rescanned */ @@ -359,6 +364,23 @@ struct ofl_desc { /* exported interfaces. */ /* + * Test to see if the output file would allow the presence of + * a .dynsym section. + */ +#define OFL_ALLOW_DYNSYM(ofl) ((ofl->ofl_flags & \ + (FLG_OF_DYNAMIC | FLG_OF_RELOBJ)) == FLG_OF_DYNAMIC) + +/* + * Test to see if the output file would allow the presence of + * a .SUNW_ldynsym section. The requirements are that a .dynsym + * is allowed, and -znoldynsym has not been specified. Note that + * even if the answer is True (1), we will only generate one if there + * are local symbols that require it. + */ +#define OFL_ALLOW_LDYNSYM(ofl) ((ofl->ofl_flags & \ + (FLG_OF_DYNAMIC | FLG_OF_RELOBJ | FLG_OF_NOLDYNSYM)) == FLG_OF_DYNAMIC) + +/* * Relocation (active & output) processing structure - transparent to common * code. */ diff --git a/usr/src/cmd/sgs/include/sparc/machdep.h b/usr/src/cmd/sgs/include/sparc/machdep.h index 0bd96d29d0..4f2a2e6175 100644 --- a/usr/src/cmd/sgs/include/sparc/machdep.h +++ b/usr/src/cmd/sgs/include/sparc/machdep.h @@ -319,10 +319,11 @@ extern "C" { #define M_ID_CAP 0x03 #define M_ID_SYMINFO 0x04 #define M_ID_HASH 0x05 -#define M_ID_DYNSYM 0x06 -#define M_ID_DYNSTR 0x07 -#define M_ID_VERSION 0x08 -#define M_ID_REL 0x09 +#define M_ID_LDYNSYM 0x06 /* always right before DYNSYM */ +#define M_ID_DYNSYM 0x07 +#define M_ID_DYNSTR 0x08 +#define M_ID_VERSION 0x09 +#define M_ID_REL 0x0a #define M_ID_TEXT 0x0b /* SHF_ALLOC + SHF_EXECINSTR */ #define M_ID_DATA 0x0c diff --git a/usr/src/cmd/sgs/libconv/common/dynamic.c b/usr/src/cmd/sgs/libconv/common/dynamic.c index 1cd1f7e31c..9afd25c710 100644 --- a/usr/src/cmd/sgs/libconv/common/dynamic.c +++ b/usr/src/cmd/sgs/libconv/common/dynamic.c @@ -263,6 +263,10 @@ conv_dyn_tag(Xword tag, Half mach, int fmt_flags) return (MSG_ORIG(MSG_DYN_SUNW_FILTER)); else if (tag == DT_SUNW_CAP) return (MSG_ORIG(MSG_DYN_SUNW_CAP)); + else if (tag == DT_SUNW_SYMTAB) + return (MSG_ORIG(MSG_DYN_SUNW_SYMTAB)); + else if (tag == DT_SUNW_SYMSZ) + return (MSG_ORIG(MSG_DYN_SUNW_SYMSZ)); /* * SUNW: DT_VALRNGLO - DT_VALRNGHI range. diff --git a/usr/src/cmd/sgs/libconv/common/dynamic.msg b/usr/src/cmd/sgs/libconv/common/dynamic.msg index 150410207f..f81befa7c6 100644 --- a/usr/src/cmd/sgs/libconv/common/dynamic.msg +++ b/usr/src/cmd/sgs/libconv/common/dynamic.msg @@ -93,6 +93,8 @@ @ MSG_DYN_SUNW_RTLDINF "SUNW_RTLDINF" @ MSG_DYN_SUNW_FILTER "SUNW_FILTER" @ MSG_DYN_SUNW_CAP "SUNW_CAP" +@ MSG_DYN_SUNW_SYMTAB "SUNW_SYMTAB" +@ MSG_DYN_SUNW_SYMSZ "SUNW_SYMSZ" @ MSG_DF_ORIGIN "ORIGIN" @ MSG_DF_SYMBOLIC "SYMBOLIC" diff --git a/usr/src/cmd/sgs/libconv/common/sections.c b/usr/src/cmd/sgs/libconv/common/sections.c index 272705641c..817c5cfb94 100644 --- a/usr/src/cmd/sgs/libconv/common/sections.c +++ b/usr/src/cmd/sgs/libconv/common/sections.c @@ -65,22 +65,24 @@ static const Msg secs_alt[SHT_NUM] = { #endif static const Msg usecs[SHT_HISUNW - SHT_LOSUNW + 1] = { - MSG_SHT_SUNW_dof, MSG_SHT_SUNW_cap, - MSG_SHT_SUNW_SIGNATURE, MSG_SHT_SUNW_ANNOTATE, - MSG_SHT_SUNW_DEBUGSTR, MSG_SHT_SUNW_DEBUG, - MSG_SHT_SUNW_move, MSG_SHT_SUNW_COMDAT, - MSG_SHT_SUNW_syminfo, MSG_SHT_SUNW_verdef, - MSG_SHT_SUNW_verneed, MSG_SHT_SUNW_versym + MSG_SHT_SUNW_LDYNSYM, MSG_SHT_SUNW_dof, + MSG_SHT_SUNW_cap, MSG_SHT_SUNW_SIGNATURE, + MSG_SHT_SUNW_ANNOTATE, MSG_SHT_SUNW_DEBUGSTR, + MSG_SHT_SUNW_DEBUG, MSG_SHT_SUNW_move, + MSG_SHT_SUNW_COMDAT, MSG_SHT_SUNW_syminfo, + MSG_SHT_SUNW_verdef, MSG_SHT_SUNW_verneed, + MSG_SHT_SUNW_versym }; static const Msg usecs_alt[SHT_HISUNW - SHT_LOSUNW + 1] = { - MSG_SHT_SUNW_dof_ALT, MSG_SHT_SUNW_cap_ALT, - MSG_SHT_SUNW_SIGNATURE_ALT, MSG_SHT_SUNW_ANNOTATE_ALT, - MSG_SHT_SUNW_DEBUGSTR_ALT, MSG_SHT_SUNW_DEBUG_ALT, - MSG_SHT_SUNW_move_ALT, MSG_SHT_SUNW_COMDAT_ALT, - MSG_SHT_SUNW_syminfo_ALT, MSG_SHT_SUNW_verdef_ALT, - MSG_SHT_SUNW_verneed_ALT, MSG_SHT_SUNW_versym_ALT + MSG_SHT_SUNW_LDYNSYM_ALT, MSG_SHT_SUNW_dof_ALT, + MSG_SHT_SUNW_cap_ALT, MSG_SHT_SUNW_SIGNATURE_ALT, + MSG_SHT_SUNW_ANNOTATE_ALT, MSG_SHT_SUNW_DEBUGSTR_ALT, + MSG_SHT_SUNW_DEBUG_ALT, MSG_SHT_SUNW_move_ALT, + MSG_SHT_SUNW_COMDAT_ALT, MSG_SHT_SUNW_syminfo_ALT, + MSG_SHT_SUNW_verdef_ALT, MSG_SHT_SUNW_verneed_ALT, + MSG_SHT_SUNW_versym_ALT }; -#if (SHT_LOSUNW != SHT_SUNW_dof) +#if (SHT_LOSUNW != SHT_SUNW_LDYNSYM) #error "SHT_LOSUNW has moved" #endif diff --git a/usr/src/cmd/sgs/libconv/common/sections.msg b/usr/src/cmd/sgs/libconv/common/sections.msg index 3dd183a551..17d7954935 100644 --- a/usr/src/cmd/sgs/libconv/common/sections.msg +++ b/usr/src/cmd/sgs/libconv/common/sections.msg @@ -62,6 +62,8 @@ @ MSG_SHT_SYMTAB_SHNDX "[ SHT_SYMTAB_SHNDX ]" @ MSG_SHT_SYMTAB_SHNDX_ALT "SHDX" +@ MSG_SHT_SUNW_LDYNSYM "[ SHT_SUNW_LDYNSYM ]" +@ MSG_SHT_SUNW_LDYNSYM_ALT "LDYNSYM" @ MSG_SHT_SUNW_dof "[ SHT_SUNW_dof ]" @ MSG_SHT_SUNW_dof_ALT "DOF " @ MSG_SHT_SUNW_cap "[ SHT_SUNW_cap ]" diff --git a/usr/src/cmd/sgs/libld/common/args.c b/usr/src/cmd/sgs/libld/common/args.c index 31a1b22161..bf3e7ad16b 100644 --- a/usr/src/cmd/sgs/libld/common/args.c +++ b/usr/src/cmd/sgs/libld/common/args.c @@ -717,6 +717,18 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error) case 'b': bflag = TRUE; + + /* + * This is a hack, and may be undone later. + * The -b option is only used to build the Unix + * kernel and its related kernel-mode modules. + * We do not want those files to get a .SUNW_ldynsym + * section. At least for now, the kernel makes no + * use of .SUNW_ldynsym, and we do not want to use + * the space to hold it. Therefore, we overload + * the use of -b to also imply -znoldynsym. + */ + ofl->ofl_flags |= FLG_OF_NOLDYNSYM; break; case 'c': @@ -1040,7 +1052,9 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error) } else if (strcmp(optarg, MSG_ORIG(MSG_ARG_IGNORE)) == 0) { ofl->ofl_flags1 |= FLG_OF1_IGNPRC; - + } else if (strcmp(optarg, + MSG_ORIG(MSG_ARG_NOLDYNSYM)) == 0) { + ofl->ofl_flags |= FLG_OF_NOLDYNSYM; /* * The following options just need validation as they * are interpreted on the second pass through the diff --git a/usr/src/cmd/sgs/libld/common/libld.msg b/usr/src/cmd/sgs/libld/common/libld.msg index 823e0c2555..1a4ed84f40 100644 --- a/usr/src/cmd/sgs/libld/common/libld.msg +++ b/usr/src/cmd/sgs/libld/common/libld.msg @@ -385,7 +385,7 @@ @ MSG_ELF_ARSYM "file %s ignored: unable to locate archive symbol table" @ MSG_ELF_VERSYM "file %s: version symbol section entry mismatch:\n\t\ - (section %s entries=%d; section %s entires=%d)" + (section %s entries=%d; section %s entries=%d)" @ MSG_ELF_NOGROUPSECT "file %s: section %s: SHF_GROUP flag set, but no \ corresponding SHT_GROUP section found" @@ -550,7 +550,6 @@ @ MSG_ELF_NEWPHDR "file %s: elf_newphdr" @ MSG_ELF_STRPTR "file %s: elf_strptr" @ MSG_ELF_UPDATE "file %s: elf_update" -@ MSG_ELF_FSIZE "file %s: elf_fsize" @ MSG_REJ_MACH "file %s: wrong ELF machine type: %s" @@ -604,6 +603,8 @@ @ MSG_SCN_DYNSTR ".dynstr" @ MSG_SCN_DYNSYM ".dynsym" @ MSG_SCN_DYNSYM_SHNDX ".dynsym_shndx" +@ MSG_SCN_LDYNSYM ".SUNW_ldynsym" +@ MSG_SCN_LDYNSYM_SHNDX ".SUNW_ldynsym_shndx" @ MSG_SCN_EX_SHARED ".ex_shared" @ MSG_SCN_EX_RANGES ".exception_ranges" @ MSG_SCN_EXCL ".excl" @@ -1062,6 +1063,7 @@ @ MSG_ARG_LD32 "ld32=" @ MSG_ARG_LD64 "ld64=" @ MSG_ARG_RESCAN "rescan" +@ MSG_ARG_NOLDYNSYM "noldynsym" @ MSG_ARG_HELP "help" @ MSG_ARG_GROUP "group" diff --git a/usr/src/cmd/sgs/libld/common/outfile.c b/usr/src/cmd/sgs/libld/common/outfile.c index 901dae481b..3dce24204c 100644 --- a/usr/src/cmd/sgs/libld/common/outfile.c +++ b/usr/src/cmd/sgs/libld/common/outfile.c @@ -371,6 +371,7 @@ ld_create_outfile(Ofl_desc *ofl) Elf_Data *tlsdata = 0; Aliste off; Word flags = ofl->ofl_flags; + Word flags1 = ofl->ofl_flags1; size_t ndx = 0, fndx = 0; Elf_Cmd cmd; Boolean fixalign = FALSE; @@ -380,12 +381,12 @@ ld_create_outfile(Ofl_desc *ofl) * If DF_1_NOHDR was set in map_parse() or FLG_OF1_VADDR was set, * we need to do alignment adjustment. */ - if ((ofl->ofl_flags1 & FLG_OF1_VADDR) || + if ((flags1 & FLG_OF1_VADDR) || (ofl->ofl_dtflags_1 & DF_1_NOHDR)) { fixalign = TRUE; } - if (flags & FLG_OF_MEMORY) { + if (flags1 & FLG_OF1_MEMORY) { cmd = ELF_C_IMAGE; fd = 0; } else { @@ -671,7 +672,7 @@ ld_create_outfile(Ofl_desc *ofl) /* * If we need to generate a memory model, pad the image. */ - if (flags & FLG_OF_MEMORY) { + if (flags1 & FLG_OF1_MEMORY) { if (pad_outfile(ofl) == S_ERROR) return (S_ERROR); } diff --git a/usr/src/cmd/sgs/libld/common/sections.c b/usr/src/cmd/sgs/libld/common/sections.c index 56da722f36..661148a14c 100644 --- a/usr/src/cmd/sgs/libld/common/sections.c +++ b/usr/src/cmd/sgs/libld/common/sections.c @@ -62,6 +62,9 @@ ignore_section_processing(Ofl_desc *ofl) Listnode *lnp; Ifl_desc *ifl; Rel_cache *rcp; + int allow_ldynsym; + + allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl); for (LIST_TRAVERSE(&ofl->ofl_objs, lnp, ifl)) { uint_t num, discard; @@ -136,6 +139,15 @@ ignore_section_processing(Ofl_desc *ofl) err = st_delstring(ofl->ofl_strtab, sdp->sd_name); assert(err != -1); + if (allow_ldynsym && + (ELF_ST_TYPE(symp->st_info) == + STT_FILE)) { + ofl->ofl_dynlocscnt--; + err = st_delstring( + ofl->ofl_dynstrtab, + sdp->sd_name); + assert(err != -1); + } } sdp->sd_flags |= FLG_SY_ISDISC; continue; @@ -173,11 +185,19 @@ ignore_section_processing(Ofl_desc *ofl) if ((ofl->ofl_flags1 & FLG_OF1_REDLSYM) == 0) { ofl->ofl_locscnt--; - err = st_delstring( ofl->ofl_strtab, sdp->sd_name); assert(err != -1); + if (allow_ldynsym && + (ELF_ST_TYPE(symp->st_info) + == STT_FUNC)) { + ofl->ofl_dynlocscnt--; + err = st_delstring( + ofl->ofl_dynstrtab, + sdp->sd_name); + assert(err != -1); + } } sdp->sd_flags |= FLG_SY_ISDISC; } @@ -200,6 +220,15 @@ ignore_section_processing(Ofl_desc *ofl) assert(err != -1); sdp->sd_flags1 |= FLG_SY1_ELIM; + if (allow_ldynsym && + (ELF_ST_TYPE(symp->st_info) == + STT_FUNC)) { + ofl->ofl_dynscopecnt--; + err = st_delstring( + ofl->ofl_dynstrtab, + sdp->sd_name); + assert(err != -1); + } } DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp, sdp->sd_isc)); @@ -262,31 +291,208 @@ ignore_section_processing(Ofl_desc *ofl) } /* - * Build a .bss section for allocation of tentative definitions. Any `static' - * .bss definitions would have been associated to their own .bss sections and - * thus collected from the input files. `global' .bss definitions are tagged - * as COMMON and do not cause any associated .bss section elements to be - * generated. Here we add up all these COMMON symbols and generate the .bss - * section required to represent them. + * Allocate Elf_Data, Shdr, and Is_desc structures for a new + * section. + * + * entry: + * ofl - Output file descriptor + * shtype - SHT_ type code for section. + * shname - String giving the name for the new section. + * entcnt - # of items contained in the data part of the new section. + * This value is multiplied against the known element size + * for the section type to determine the size of the data + * area for the section. It is only meaningful in cases where + * the section type has a non-zero element size. In other cases, + * the caller must set the size fields in the *ret_data and + * *ret_shdr structs manually. + * ret_isec, ret_shdr, ret_data - Address of pointers to + * receive address of newly allocated structs. + * + * exit: + * On error, returns S_ERROR. On success, returns (1), and the + * ret_ pointers have been updated to point at the new structures, + * which has been filled in. To finish the task, the caller must + * update any fields within the supplied descriptors that differ + * from its needs, and then call ld_place_section(). */ -uintptr_t -ld_make_bss(Ofl_desc *ofl, Xword size, Xword align, Bss_Type which) +static uintptr_t +new_section(Ofl_desc *ofl, Word shtype, const char *shname, Xword entcnt, + Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data) { + typedef struct sec_info { + Word d_type; + Word align; /* Used in both data and section header */ + Word sh_flags; + Word sh_entsize; + } SEC_INFO_T; + + const SEC_INFO_T *sec_info; + Shdr *shdr; Elf_Data *data; Is_desc *isec; - Os_desc *osp; - uint_t ident; - Xword rsize = (Xword)ofl->ofl_relocbsssz; + size_t size; + + /* + * For each type of section, we have a distinct set of + * SEC_INFO_T values. This macro defines a static structure + * containing those values and generates code to set the sec_info + * pointer to refer to it. The pointer in sec_info remains valid + * outside of the declaration scope because the info_s struct is static. + */ +#define SET_SEC_INFO(d_type, d_align, sh_flags, sh_entsize) \ + { \ + static const SEC_INFO_T info_s = { d_type, d_align, sh_flags, \ + sh_entsize}; \ + sec_info = &info_s; \ + } + + switch (shtype) { + case SHT_PROGBITS: + /* + * SHT_PROGBITS sections contain are used for many + * different sections. Alignments and flags differ. + * Some have a standard entsize, and others don't. + * We set some defaults here, but there is no expectation + * that they are correct or complete for any specific + * purpose. The caller must provide the correct values. + */ + SET_SEC_INFO(ELF_T_BYTE, M_WORD_ALIGN, SHF_ALLOC, 0) + break; + + case SHT_SYMTAB: + SET_SEC_INFO(ELF_T_SYM, M_WORD_ALIGN, 0, sizeof (Sym)) + break; + + case SHT_DYNSYM: + case SHT_SUNW_LDYNSYM: + SET_SEC_INFO(ELF_T_SYM, M_WORD_ALIGN, SHF_ALLOC, sizeof (Sym)) + break; + + case SHT_STRTAB: + /* + * A string table may or may not be allocable, depending + * on context, so we leave that flag unset and leave it to + * the caller to add it if necessary. + * + * String tables do not have a standard entsize, so + * we set it to 0. + */ + SET_SEC_INFO(ELF_T_BYTE, 1, SHF_STRINGS, 0) + break; + + case SHT_RELA: + /* + * Relocations with an addend (Everything except 32-bit X86). + * The caller is expected to set all section header flags. + */ + SET_SEC_INFO(ELF_T_RELA, M_WORD_ALIGN, 0, sizeof (Rela)) + break; + + case SHT_REL: + /* + * Relocations without an addend (32-bit X86 only). + * The caller is expected to set all section header flags. + */ + SET_SEC_INFO(ELF_T_REL, M_WORD_ALIGN, 0, sizeof (Rel)) + break; + + case SHT_HASH: + SET_SEC_INFO(ELF_T_WORD, M_WORD_ALIGN, SHF_ALLOC, sizeof (Word)) + break; + + case SHT_DYNAMIC: + /* + * A dynamic section may or may not be allocable, depending + * on context, so we leave that flag unset and leave it to + * the caller to add it if necessary. + */ + SET_SEC_INFO(ELF_T_DYN, M_WORD_ALIGN, SHF_WRITE, sizeof (Dyn)) + break; + + case SHT_NOBITS: + /* + * SHT_NOBITS is used for BSS-type sections. The size and + * alignment depend on the specific use and must be adjusted + * by the caller. + */ + SET_SEC_INFO(ELF_T_BYTE, 0, SHF_ALLOC | SHF_WRITE, 0) + break; + + case SHT_INIT_ARRAY: + case SHT_FINI_ARRAY: + case SHT_PREINIT_ARRAY: + SET_SEC_INFO(ELF_T_ADDR, sizeof (Addr), SHF_ALLOC | SHF_WRITE, + sizeof (Addr)) + break; + + case SHT_SYMTAB_SHNDX: + /* + * Note that these sections are created to be associated + * with both symtab and dynsym symbol tables. However, they + * are non-allocable in all cases, because the runtime + * linker has no need for this information. It is purely + * informational, used by elfdump(1), debuggers, etc. + */ + SET_SEC_INFO(ELF_T_WORD, M_WORD_ALIGN, 0, sizeof (Word)); + break; + + case SHT_SUNW_cap: + SET_SEC_INFO(ELF_T_CAP, M_WORD_ALIGN, SHF_ALLOC, sizeof (Cap)); + break; + + case SHT_SUNW_move: + /* + * The sh_info field of the SHT_*_syminfo section points + * to the header index of the associated .dynamic section, + * so we also set SHF_INFO_LINK. + */ + SET_SEC_INFO(ELF_T_BYTE, sizeof (Lword), + SHF_ALLOC | SHF_WRITE, sizeof (Move)); + break; + + case SHT_SUNW_syminfo: + /* + * The sh_info field of the SHT_*_syminfo section points + * to the header index of the associated .dynamic section, + * so we also set SHF_INFO_LINK. + */ + SET_SEC_INFO(ELF_T_BYTE, M_WORD_ALIGN, + SHF_ALLOC | SHF_INFO_LINK, sizeof (Syminfo)); + break; + + case SHT_SUNW_verneed: + case SHT_SUNW_verdef: + /* + * The info for verneed and versym happen to be the same. + * The entries in these sections are not of uniform size, + * so we set the entsize to 0. + */ + SET_SEC_INFO(ELF_T_BYTE, M_WORD_ALIGN, SHF_ALLOC, 0); + break; + + case SHT_SUNW_versym: + SET_SEC_INFO(ELF_T_BYTE, M_WORD_ALIGN, SHF_ALLOC, + sizeof (Versym)); + break; + + default: + /* Should not happen: fcn called with unknown section type */ + assert(0); + return (S_ERROR); + } +#undef SET_SEC_INFO + + size = entcnt * sec_info->sh_entsize; /* * Allocate and initialize the Elf_Data structure. */ if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) return (S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_size = (size_t)size; - data->d_align = (size_t)align; + data->d_type = sec_info->d_type; + data->d_size = size; + data->d_align = sec_info->align; data->d_version = ofl->ofl_dehdr->e_version; /* @@ -294,20 +500,61 @@ ld_make_bss(Ofl_desc *ofl, Xword size, Xword align, Bss_Type which) */ if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) return (S_ERROR); - shdr->sh_type = SHT_NOBITS; - shdr->sh_flags = SHF_ALLOC | SHF_WRITE; + shdr->sh_type = shtype; shdr->sh_size = size; - shdr->sh_addralign = align; + shdr->sh_flags = sec_info->sh_flags; + shdr->sh_addralign = sec_info->align; + shdr->sh_entsize = sec_info->sh_entsize; /* * Allocate and initialize the Is_desc structure. */ if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) return (S_ERROR); - + isec->is_name = shname; isec->is_shdr = shdr; isec->is_indata = data; + + *ret_isec = isec; + *ret_shdr = shdr; + *ret_data = data; + return (1); +} + +/* + * Build a .bss section for allocation of tentative definitions. Any `static' + * .bss definitions would have been associated to their own .bss sections and + * thus collected from the input files. `global' .bss definitions are tagged + * as COMMON and do not cause any associated .bss section elements to be + * generated. Here we add up all these COMMON symbols and generate the .bss + * section required to represent them. + */ +uintptr_t +ld_make_bss(Ofl_desc *ofl, Xword size, Xword align, Bss_Type which) +{ + Shdr *shdr; + Elf_Data *data; + Is_desc *isec; + Os_desc *osp; + uint_t ident; + Xword rsize = (Xword)ofl->ofl_relocbsssz; + + /* + * Allocate header structs. We will set the name ourselves below, + * and there is no entcnt for a BSS. So, the shname and entcnt + * arguments are 0. + */ + if (new_section(ofl, SHT_NOBITS, NULL, 0, + &isec, &shdr, &data) == S_ERROR) + return (S_ERROR); + + data->d_size = (size_t)size; + data->d_align = (size_t)align; + + shdr->sh_size = size; + shdr->sh_addralign = align; + if (which == MAKE_TLS) { isec->is_name = MSG_ORIG(MSG_SCN_TBSS); ident = M_ID_TLSBSS; @@ -383,37 +630,12 @@ make_array(Ofl_desc *ofl, Word shtype, const char *sectname, List *list) for (LIST_TRAVERSE(list, lnp, sdp)) entcount++; - /* - * Allocate and initialize the Elf_Data structure. - */ - if (((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) || - ((data->d_buf = libld_calloc(sizeof (Addr), entcount)) == 0)) + if (new_section(ofl, shtype, sectname, entcount, &isec, &shdr, &data) == + S_ERROR) return (S_ERROR); - data->d_type = ELF_T_ADDR; - data->d_size = sizeof (Addr) * entcount; - data->d_align = sizeof (Addr); - data->d_version = ofl->ofl_dehdr->e_version; - - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) + if ((data->d_buf = libld_calloc(sizeof (Addr), entcount)) == 0) return (S_ERROR); - shdr->sh_type = shtype; - shdr->sh_size = (Xword)data->d_size; - shdr->sh_entsize = sizeof (Addr); - shdr->sh_addralign = (Xword)data->d_align; - shdr->sh_flags = SHF_ALLOC | SHF_WRITE; - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = sectname; - isec->is_shdr = shdr; - isec->is_indata = data; if (ld_place_section(ofl, isec, M_ID_ARRAY, 0) == (Os_desc *)S_ERROR) return (S_ERROR); @@ -479,35 +701,18 @@ make_comment(Ofl_desc *ofl) Elf_Data *data; Is_desc *isec; - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_COMMENT), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_BYTE; + data->d_buf = (void *)ofl->ofl_sgsid; data->d_size = strlen(ofl->ofl_sgsid) + 1; data->d_align = 1; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = SHT_PROGBITS; shdr->sh_size = (Xword)data->d_size; + shdr->sh_flags = 0; shdr->sh_addralign = 1; - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_COMMENT); - isec->is_shdr = shdr; - isec->is_indata = data; - return ((uintptr_t)ld_place_section(ofl, isec, M_ID_NOTE, 0)); } @@ -531,42 +736,13 @@ make_dynamic(Ofl_desc *ofl) Word flags = ofl->ofl_flags; int unused = 0; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) + if (new_section(ofl, SHT_DYNAMIC, MSG_ORIG(MSG_SCN_DYNAMIC), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - shdr->sh_type = SHT_DYNAMIC; - shdr->sh_flags = SHF_WRITE; + + /* new_section() does not set SHF_ALLOC. Add it if needed */ if (!(flags & FLG_OF_RELOBJ)) shdr->sh_flags |= SHF_ALLOC; - shdr->sh_addralign = M_WORD_ALIGN; - if ((shdr->sh_entsize = (Xword)elf_fsize(ELF_T_DYN, 1, - ofl->ofl_dehdr->e_version)) == 0) { - eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_FSIZE), - ofl->ofl_name); - return (S_ERROR); - } - - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) - return (S_ERROR); - data->d_type = ELF_T_DYN; - data->d_size = 0; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == - (Is_desc *)0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_DYNAMIC); - isec->is_shdr = shdr; - isec->is_indata = data; osp = ofl->ofl_osdynamic = ld_place_section(ofl, isec, M_ID_DYNAMIC, 0); @@ -732,6 +908,15 @@ make_dynamic(Ofl_desc *ofl) */ cnt += 6; + /* + * If we are including local functions at the head of + * the dynsym, then also reserve entries for DT_SUNW_SYMTAB + * and DT_SUNW_SYMSZ. + */ + if (!(ofl->ofl_flags & FLG_OF_NOLDYNSYM) && + ((ofl->ofl_dynlocscnt + ofl->ofl_dynscopecnt) > 0)) + cnt += 2; + if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) == FLG_OF_VERDEF) cnt += 2; /* DT_VERDEF & DT_VERDEFNUM */ @@ -790,7 +975,7 @@ make_dynamic(Ofl_desc *ofl) cnt += 3; /* - * Allocate one DT_REGISTER entry for ever register symbol. + * Allocate one DT_REGISTER entry for every register symbol. */ cnt += ofl->ofl_regsymcnt; @@ -856,36 +1041,16 @@ ld_make_got(Ofl_desc *ofl) size_t size = (size_t)ofl->ofl_gotcnt * M_GOT_ENTSIZE; size_t rsize = (size_t)ofl->ofl_relocgotsz; - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_GOT), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_BYTE; + data->d_size = size; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = SHT_PROGBITS; - shdr->sh_flags = SHF_ALLOC | SHF_WRITE; + shdr->sh_flags |= SHF_WRITE; shdr->sh_size = (Xword)size; - shdr->sh_addralign = M_WORD_ALIGN; shdr->sh_entsize = M_GOT_ENTSIZE; - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_GOT); - isec->is_shdr = shdr; - isec->is_indata = data; - if ((ofl->ofl_osgot = ld_place_section(ofl, isec, M_ID_GOT, 0)) == (Os_desc *)S_ERROR) return (S_ERROR); @@ -940,32 +1105,13 @@ make_interp(Ofl_desc *ofl) size = strlen(iname) + 1; - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_INTERP), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_size = size; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = SHT_PROGBITS; - shdr->sh_flags = SHF_ALLOC; + data->d_size = size; shdr->sh_size = (Xword)size; - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_INTERP); - isec->is_shdr = shdr; - isec->is_indata = data; + data->d_align = shdr->sh_addralign = 1; ofl->ofl_osinterp = ld_place_section(ofl, isec, M_ID_INTERP, 0); return ((uintptr_t)ofl->ofl_osinterp); @@ -995,46 +1141,11 @@ make_cap(Ofl_desc *ofl) return (1); size++; /* Add CA_SUNW_NULL */ - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_SUNW_cap, MSG_ORIG(MSG_SCN_SUNWCAP), size, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_CAP; - data->d_version = ofl->ofl_dehdr->e_version; - data->d_align = M_WORD_ALIGN; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = SHT_SUNW_cap; - shdr->sh_flags = SHF_ALLOC; - shdr->sh_addralign = M_WORD_ALIGN; - if ((shdr->sh_entsize = (Xword)elf_fsize(ELF_T_CAP, 1, - ofl->ofl_dehdr->e_version)) == 0) { - eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_FSIZE), - ofl->ofl_name); - return (S_ERROR); - } - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_SUNWCAP); - isec->is_shdr = shdr; - isec->is_indata = data; - - /* - * Determine the size of the section, and create the data. - */ - size = size * (size_t)shdr->sh_entsize; - shdr->sh_size = (Xword)size; - data->d_size = size; - if ((data->d_buf = libld_malloc(size)) == 0) + if ((data->d_buf = libld_malloc(shdr->sh_size)) == 0) return (S_ERROR); cap = (Cap *)data->d_buf; @@ -1053,7 +1164,7 @@ make_cap(Ofl_desc *ofl) /* * If we're not creating a relocatable object, save the output section - * to trigger the creation of an associated a program header. + * to trigger the creation of an associated program header. */ osec = ld_place_section(ofl, isec, M_ID_CAP, 0); if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) @@ -1083,36 +1194,18 @@ make_plt(Ofl_desc *ofl) size += sizeof (Word); #endif - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_PLT), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_BYTE; + data->d_size = size; data->d_align = M_PLT_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = SHT_PROGBITS; shdr->sh_flags = M_PLT_SHF_FLAGS; shdr->sh_size = (Xword)size; shdr->sh_addralign = M_PLT_ALIGN; shdr->sh_entsize = M_PLT_ENTSIZE; - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == (Is_desc *)0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_PLT); - isec->is_shdr = shdr; - isec->is_indata = data; - if ((ofl->ofl_osplt = ld_place_section(ofl, isec, M_ID_PLT, 0)) == (Os_desc *)S_ERROR) return (S_ERROR); @@ -1138,37 +1231,12 @@ make_hash(Ofl_desc *ofl) size_t cnt; /* - * Allocate and initialize the Elf_Data structure. + * Allocate section header structures. We set entcnt to 0 + * because it's going to change after we place this section. */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_HASH, MSG_ORIG(MSG_SCN_HASH), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_WORD; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = SHT_HASH; - shdr->sh_flags = SHF_ALLOC; - shdr->sh_addralign = M_WORD_ALIGN; - if ((shdr->sh_entsize = (Xword)elf_fsize(ELF_T_WORD, 1, - ofl->ofl_dehdr->e_version)) == 0) { - eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_FSIZE), - ofl->ofl_name); - return (S_ERROR); - } - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_HASH); - isec->is_shdr = shdr; - isec->is_indata = data; /* * Place the section first since it will affect the local symbol @@ -1221,36 +1289,12 @@ make_symtab(Ofl_desc *ofl) Word symcnt; /* - * Allocate and initialize the Elf_Data structure. + * Create the section headers. Note that we supply an ent_cnt + * of 0. We won't know the count until the section has been placed. */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_SYMTAB, MSG_ORIG(MSG_SCN_SYMTAB), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_SYM; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = SHT_SYMTAB; - shdr->sh_addralign = M_WORD_ALIGN; - if ((shdr->sh_entsize = (Xword)elf_fsize(ELF_T_SYM, 1, - ofl->ofl_dehdr->e_version)) == 0) { - eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_FSIZE), - ofl->ofl_name); - return (S_ERROR); - } - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_SYMTAB); - isec->is_shdr = shdr; - isec->is_indata = data; /* * Place the section first since it will affect the local symbol @@ -1269,21 +1313,11 @@ make_symtab(Ofl_desc *ofl) Shdr *xshdr; Elf_Data *xdata; - if ((xdata = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_SYMTAB_SHNDX, + MSG_ORIG(MSG_SCN_SYMTAB_SHNDX), 0, &xisec, + &xshdr, &xdata) == S_ERROR) return (S_ERROR); - xdata->d_type = ELF_T_WORD; - xdata->d_align = M_WORD_ALIGN; - xdata->d_version = ofl->ofl_dehdr->e_version; - if ((xshdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - xshdr->sh_type = SHT_SYMTAB_SHNDX; - xshdr->sh_addralign = M_WORD_ALIGN; - xshdr->sh_entsize = sizeof (Word); - if ((xisec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - xisec->is_name = MSG_ORIG(MSG_SCN_SYMTAB_SHNDX); - xisec->is_shdr = xshdr; - xisec->is_indata = xdata; + if ((ofl->ofl_ossymshndx = ld_place_section(ofl, xisec, M_ID_SYMTAB_NDX, 0)) == (Os_desc *)S_ERROR) return (S_ERROR); @@ -1323,51 +1357,38 @@ make_symtab(Ofl_desc *ofl) static uintptr_t make_dynsym(Ofl_desc *ofl) { - Shdr *shdr; - Elf_Data *data; - Is_desc *isec; + Shdr *shdr, *lshdr; + Elf_Data *data, *ldata; + Is_desc *isec, *lisec; size_t size; Xword cnt; + int need_ldynsym; - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) - return (S_ERROR); - data->d_type = ELF_T_SYM; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; + need_ldynsym = !(ofl->ofl_flags & FLG_OF_NOLDYNSYM) && + ((ofl->ofl_dynlocscnt + ofl->ofl_dynscopecnt) > 0); /* - * Allocate and initialize the Shdr structure. + * Create the section headers. Note that we supply an ent_cnt + * of 0. We won't know the count until the section has been placed. */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) + if (need_ldynsym && new_section(ofl, SHT_SUNW_LDYNSYM, + MSG_ORIG(MSG_SCN_LDYNSYM), 0, &lisec, &lshdr, &ldata) == S_ERROR) return (S_ERROR); - shdr->sh_type = SHT_DYNSYM; - shdr->sh_flags = SHF_ALLOC; - shdr->sh_addralign = M_WORD_ALIGN; - if ((shdr->sh_entsize = (Xword)elf_fsize(ELF_T_SYM, 1, - ofl->ofl_dehdr->e_version)) == 0) { - eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_FSIZE), - ofl->ofl_name); - return (S_ERROR); - } - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) + if (new_section(ofl, SHT_DYNSYM, MSG_ORIG(MSG_SCN_DYNSYM), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_DYNSYM); - isec->is_shdr = shdr; - isec->is_indata = data; /* - * Place the section first since it will affect the local symbol + * Place the section(s) first since it will affect the local symbol * count. */ - if ((ofl->ofl_osdynsym = ld_place_section(ofl, isec, M_ID_DYNSYM, 0)) == - (Os_desc *)S_ERROR) + if (need_ldynsym && + ((ofl->ofl_osldynsym = ld_place_section(ofl, lisec, + M_ID_LDYNSYM, 0)) == (Os_desc *)S_ERROR)) + return (S_ERROR); + if ((ofl->ofl_osdynsym = ld_place_section(ofl, isec, M_ID_DYNSYM, 0)) + == (Os_desc *)S_ERROR) return (S_ERROR); /* @@ -1382,58 +1403,76 @@ make_dynsym(Ofl_desc *ofl) data->d_size = size; shdr->sh_size = (Xword)size; + /* + * An ldynsym contains local function symbols. It is not + * used for linking, but if present, serves to allow better + * stack traces to be generated in contexts where the symtab + * is not available. (dladdr(), or stripped executable/library files). + */ + if (need_ldynsym) { + cnt = 1 + ofl->ofl_dynlocscnt + ofl->ofl_dynscopecnt; + size = (size_t)cnt * shdr->sh_entsize; + + ldata->d_size = size; + lshdr->sh_size = (Xword)size; + } + return (1); } /* - * Build a SHT_SYMTAB_SHNDX for the .dynsym + * Helper routine for make_dynsym_shndx. Builds a + * a SHT_SYMTAB_SHNDX for dynsym or ldynsym, without knowing + * which one it is. */ static uintptr_t -make_dynsym_shndx(Ofl_desc *ofl) +make_dyn_shndx(Ofl_desc *ofl, const char *shname, Os_desc *symtab, + Os_desc **ret_os) { Is_desc *isec; Is_desc *dynsymisp; Shdr *shdr, *dynshdr; Elf_Data *data; - /* - * Allocate the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + dynsymisp = (Is_desc *)symtab->os_isdescs.head->data; + dynshdr = dynsymisp->is_shdr; + + if (new_section(ofl, SHT_SYMTAB_SHNDX, shname, + (dynshdr->sh_size / dynshdr->sh_entsize), + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_WORD; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) + if ((*ret_os = ld_place_section(ofl, isec, + M_ID_DYNSYM_NDX, 0)) == (Os_desc *)S_ERROR) return (S_ERROR); - shdr->sh_type = SHT_SYMTAB_SHNDX; - shdr->sh_addralign = M_WORD_ALIGN; - shdr->sh_entsize = sizeof (Word); + assert(*ret_os); + + return (1); +} + +/* + * Build a SHT_SYMTAB_SHNDX for the .dynsym, and .SUNW_ldynsym + */ +static uintptr_t +make_dynsym_shndx(Ofl_desc *ofl) +{ /* - * Allocate the Is_desc structure. + * If there is an ldynsym, generate a section for its extended + * index section as well. */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_DYNSYM_SHNDX); - isec->is_shdr = shdr; - isec->is_indata = data; + if (!(ofl->ofl_flags & FLG_OF_NOLDYNSYM) && + ((ofl->ofl_dynlocscnt + ofl->ofl_dynscopecnt) > 0)) { + if (make_dyn_shndx(ofl, MSG_ORIG(MSG_SCN_LDYNSYM_SHNDX), + ofl->ofl_osldynsym, &ofl->ofl_osldynshndx) == S_ERROR) + return (S_ERROR); + } - if ((ofl->ofl_osdynshndx = ld_place_section(ofl, isec, - M_ID_DYNSYM_NDX, 0)) == (Os_desc *)S_ERROR) + /* The Generate a section for the dynsym */ + if (make_dyn_shndx(ofl, MSG_ORIG(MSG_SCN_DYNSYM_SHNDX), + ofl->ofl_osdynsym, &ofl->ofl_osdynshndx) == S_ERROR) return (S_ERROR); - assert(ofl->ofl_osdynsym); - dynsymisp = (Is_desc *)ofl->ofl_osdynsym->os_isdescs.head->data; - dynshdr = dynsymisp->is_shdr; - shdr->sh_size = (Xword)((dynshdr->sh_size / dynshdr->sh_entsize) * - sizeof (Word)); - data->d_size = shdr->sh_size; - return (1); } @@ -1449,32 +1488,9 @@ make_shstrtab(Ofl_desc *ofl) Is_desc *isec; size_t size; - /* - * Allocate the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) - return (S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_align = 1; - data->d_version = ofl->ofl_dehdr->e_version; - - /* - * Allocate the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) + if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_SHSTRTAB), + 0, &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - shdr->sh_type = SHT_STRTAB; - shdr->sh_flags |= SHF_STRINGS; - shdr->sh_addralign = 1; - - /* - * Allocate the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_SHSTRTAB); - isec->is_shdr = shdr; - isec->is_indata = data; /* * Place the section first, as it may effect the number of section @@ -1515,34 +1531,13 @@ make_strtab(Ofl_desc *ofl) size = st_getstrtab_sz(ofl->ofl_strtab); assert(size > 0); - /* - * Allocate the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_STRTAB), + 0, &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_size = size; - data->d_type = ELF_T_BYTE; - data->d_align = 1; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); + /* Set the size of the data area */ + data->d_size = size; shdr->sh_size = (Xword)size; - shdr->sh_addralign = 1; - shdr->sh_type = SHT_STRTAB; - shdr->sh_flags |= SHF_STRINGS; - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_STRTAB); - isec->is_shdr = shdr; - isec->is_indata = data; ofl->ofl_osstrtab = ld_place_section(ofl, isec, M_ID_STRTAB, 0); return ((uintptr_t)ofl->ofl_osstrtab); @@ -1560,6 +1555,18 @@ make_dynstr(Ofl_desc *ofl) size_t size; /* + * If this dynstr is to contain local symbols, and if we + * have scope reduced global symbols to put there, then + * account for the STT_FILE symbol that precedes those symbols. + */ + if (!(ofl->ofl_flags & FLG_OF_NOLDYNSYM) && ofl->ofl_dynscopecnt) { + if (st_insert(ofl->ofl_dynstrtab, ofl->ofl_name) == -1) + return (S_ERROR); + ofl->ofl_dynscopecnt++; + } + + + /* * Account for any local, named register symbols. These locals are * required for reference from DT_REGISTER .dynamic entries. */ @@ -1599,37 +1606,17 @@ make_dynstr(Ofl_desc *ofl) size = st_getstrtab_sz(ofl->ofl_dynstrtab); assert(size > 0); - /* - * Allocate the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_DYNSTR), + 0, &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_size = size; - data->d_align = 1; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); + /* Make it allocable if necessary */ if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) - shdr->sh_flags = SHF_ALLOC; + shdr->sh_flags |= SHF_ALLOC; - shdr->sh_type = SHT_STRTAB; - shdr->sh_flags |= SHF_STRINGS; + /* Set the size of the data area */ + data->d_size = size; shdr->sh_size = (Xword)size; - shdr->sh_addralign = 1; - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_DYNSTR); - isec->is_shdr = shdr; - isec->is_indata = data; ofl->ofl_osdynstr = ld_place_section(ofl, isec, M_ID_DYNSTR, 0); return ((uintptr_t)ofl->ofl_osdynstr); @@ -1691,29 +1678,14 @@ make_reloc(Ofl_desc *ofl, Os_desc *osp) /* LINTED */ ofl->ofl_relocsz += (Xword)size; - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, M_REL_SHT_TYPE, sectname, 0, &isec, &shdr, &data) + == S_ERROR) return (S_ERROR); - data->d_type = M_REL_ELF_TYPE; + data->d_size = size; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = M_REL_SHT_TYPE; shdr->sh_size = (Xword)size; - shdr->sh_addralign = M_WORD_ALIGN; - shdr->sh_entsize = relsize; - - if ((ofl->ofl_flags & FLG_OF_DYNAMIC) && - !(ofl->ofl_flags & FLG_OF_RELOBJ) && - (sh_flags & SHF_ALLOC)) + if (OFL_ALLOW_DYNSYM(ofl) && (sh_flags & SHF_ALLOC)) shdr->sh_flags = SHF_ALLOC; if (osp) { @@ -1724,17 +1696,6 @@ make_reloc(Ofl_desc *ofl, Os_desc *osp) shdr->sh_flags |= SHF_INFO_LINK; } - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_shdr = shdr; - isec->is_indata = data; - isec->is_name = sectname; - - /* * Associate this relocation section to the section its going to * relocate. @@ -1791,36 +1752,18 @@ make_verneed(Ofl_desc *ofl) Shdr *shdr; Elf_Data *data; Is_desc *isec; - size_t size = ofl->ofl_verneedsz; /* - * Allocate and initialize the Elf_Data structure. + * verneed sections do not have a constant element size, so the + * value of ent_cnt specified here (0) is meaningless. */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_SUNW_verneed, MSG_ORIG(MSG_SCN_SUNWVERSION), + 0, &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_size = size; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = (Word)SHT_SUNW_verneed; - shdr->sh_flags = SHF_ALLOC; - shdr->sh_size = (Xword)size; - shdr->sh_addralign = M_WORD_ALIGN; - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_SUNWVERSION); - isec->is_shdr = shdr; - isec->is_indata = data; + /* During version processing we calculated the total size. */ + data->d_size = ofl->ofl_verneedsz; + shdr->sh_size = (Xword)ofl->ofl_verneedsz; ofl->ofl_osverneed = ld_place_section(ofl, isec, M_ID_VERSION, 0); return ((uintptr_t)ofl->ofl_osverneed); @@ -1839,7 +1782,6 @@ make_verdef(Ofl_desc *ofl) Elf_Data *data; Is_desc *isec; Ver_desc *vdp; - size_t size; /* * Reserve a string table entry for the base version dependency (other @@ -1847,7 +1789,6 @@ make_verdef(Ofl_desc *ofl) * accounted for during symbol processing). */ vdp = (Ver_desc *)ofl->ofl_verdesc.head->data; - size = strlen(vdp->vd_name) + 1; if (ofl->ofl_flags & FLG_OF_DYNAMIC) { if (st_insert(ofl->ofl_dynstrtab, vdp->vd_name) == -1) @@ -1858,36 +1799,16 @@ make_verdef(Ofl_desc *ofl) } /* - * During version processing we calculated the total number of entries. - * Allocate and initialize the Elf_Data structure. + * verdef sections do not have a constant element size, so the + * value of ent_cnt specified here (0) is meaningless. */ - size = ofl->ofl_verdefsz; - - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_SUNW_verdef, MSG_ORIG(MSG_SCN_SUNWVERSION), + 0, &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_size = size; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = (Word)SHT_SUNW_verdef; - shdr->sh_flags = SHF_ALLOC; - shdr->sh_size = (Xword)size; - shdr->sh_addralign = M_WORD_ALIGN; - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_SUNWVERSION); - isec->is_shdr = shdr; - isec->is_indata = data; + /* During version processing we calculated the total size. */ + data->d_size = ofl->ofl_verdefsz; + shdr->sh_size = (Xword)ofl->ofl_verdefsz; ofl->ofl_osverdef = ld_place_section(ofl, isec, M_ID_VERSION, 0); return ((uintptr_t)ofl->ofl_osverdef); @@ -1899,49 +1820,19 @@ make_verdef(Ofl_desc *ofl) * provides additional symbol information. */ static Os_desc * -make_sym_sec(Ofl_desc *ofl, const char *sectname, Word entsize, - Word stype, int ident) +make_sym_sec(Ofl_desc *ofl, const char *sectname, Word stype, int ident) { Shdr *shdr; Elf_Data *data; Is_desc *isec; /* - * Allocate and initialize the Elf_Data structures for the symbol index - * array. + * We don't know the size of this section yet, so set it to 0. + * It gets filled in after the dynsym is sized. */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, stype, sectname, 0, &isec, &shdr, &data) == + S_ERROR) return ((Os_desc *)S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return ((Os_desc *)S_ERROR); - shdr->sh_type = (Word)stype; - shdr->sh_flags = SHF_ALLOC; - shdr->sh_addralign = M_WORD_ALIGN; - shdr->sh_entsize = entsize; - - if (stype == SHT_SUNW_syminfo) { - /* - * The sh_info field of the SHT_*_syminfo section points - * to the header index of the associated .dynamic section. - */ - shdr->sh_flags |= SHF_INFO_LINK; - } - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return ((Os_desc *)S_ERROR); - isec->is_name = sectname; - isec->is_shdr = shdr; - isec->is_indata = data; return (ld_place_section(ofl, isec, ident, 0)); } @@ -1957,35 +1848,21 @@ ld_make_sunwbss(Ofl_desc *ofl, size_t size, Xword align) Is_desc *isec; /* - * Allocate and initialize the Elf_Data structure. + * Allocate header structs. We will set the name ourselves below, + * and there is no entcnt for a BSS. So, the shname and entcnt + * arguments are 0. */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_NOBITS, MSG_ORIG(MSG_SCN_SUNWBSS), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_type = ELF_T_BYTE; + data->d_size = size; data->d_align = align; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = SHT_NOBITS; - shdr->sh_flags = SHF_ALLOC | SHF_WRITE; shdr->sh_size = (Xword)size; shdr->sh_addralign = align; /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) - return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_SUNWBSS); - isec->is_shdr = shdr; - isec->is_indata = data; - - /* * Retain this .sunwbss input section as this will be where global * symbol references are added. */ @@ -2007,39 +1884,20 @@ ld_make_sunwdata(Ofl_desc *ofl, size_t size, Xword align) Is_desc *isec; Os_desc *osp; - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) - return (S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_size = size; - if ((data->d_buf = libld_calloc(size, 1)) == 0) + if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_SUNWDATA1), 0, + &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - data->d_align = (size_t)M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return (S_ERROR); - shdr->sh_type = SHT_PROGBITS; - shdr->sh_flags = SHF_ALLOC | SHF_WRITE; + shdr->sh_flags |= SHF_WRITE; + data->d_size = size; shdr->sh_size = (Xword)size; - if (align == 0) - shdr->sh_addralign = M_WORD_ALIGN; - else + if (align != 0) { + data->d_align = align; shdr->sh_addralign = align; + } - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) + if ((data->d_buf = libld_calloc(size, 1)) == 0) return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_SUNWDATA1); - isec->is_shdr = shdr; - isec->is_indata = data; /* * Retain this .sunwdata1 input section as this will @@ -2067,50 +1925,17 @@ ld_make_sunwmove(Ofl_desc *ofl, int mv_nums) Shdr *shdr; Elf_Data *data; Is_desc *isec; - size_t size; Listnode *lnp1; Psym_info *psym; int cnt = 1; - /* - * Generate the move input sections and output sections - */ - size = mv_nums * sizeof (Move); - - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) - return (S_ERROR); - data->d_type = ELF_T_BYTE; - if ((data->d_buf = libld_calloc(size, 1)) == 0) - return (S_ERROR); - data->d_size = size; - data->d_align = sizeof (Lword); - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) + if (new_section(ofl, SHT_SUNW_move, MSG_ORIG(MSG_SCN_SUNWMOVE), + mv_nums, &isec, &shdr, &data) == S_ERROR) return (S_ERROR); - shdr->sh_link = 0; - shdr->sh_info = 0; - shdr->sh_type = SHT_SUNW_move; - shdr->sh_size = (Xword)size; - shdr->sh_flags = SHF_ALLOC | SHF_WRITE; - shdr->sh_addralign = sizeof (Lword); - shdr->sh_entsize = sizeof (Move); - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == 0) + if ((data->d_buf = libld_calloc(data->d_size, 1)) == 0) return (S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_SUNWMOVE); - isec->is_shdr = shdr; - isec->is_indata = data; - isec->is_file = 0; /* * Copy move entries @@ -2206,18 +2031,18 @@ ld_make_sections(Ofl_desc *ofl) if (make_verdef(ofl) == S_ERROR) return (S_ERROR); if ((ofl->ofl_osversym = make_sym_sec(ofl, - MSG_ORIG(MSG_SCN_SUNWVERSYM), sizeof (Versym), - SHT_SUNW_versym, M_ID_VERSION)) == (Os_desc*)S_ERROR) + MSG_ORIG(MSG_SCN_SUNWVERSYM), SHT_SUNW_versym, + M_ID_VERSION)) == (Os_desc*)S_ERROR) return (S_ERROR); } /* - * Create a syminfo section is necessary. + * Create a syminfo section if necessary. */ if (ofl->ofl_flags & FLG_OF_SYMINFO) { if ((ofl->ofl_ossyminfo = make_sym_sec(ofl, - MSG_ORIG(MSG_SCN_SUNWSYMINFO), sizeof (Syminfo), - SHT_SUNW_syminfo, M_ID_SYMINFO)) == (Os_desc *)S_ERROR) + MSG_ORIG(MSG_SCN_SUNWSYMINFO), SHT_SUNW_syminfo, + M_ID_SYMINFO)) == (Os_desc *)S_ERROR) return (S_ERROR); } @@ -2342,13 +2167,14 @@ ld_make_sections(Ofl_desc *ofl) size_t size; ulong_t cnt; - if ((flags & FLG_OF_RELOBJ) || (flags & FLG_OF_STATIC)) + if (flags & (FLG_OF_RELOBJ | FLG_OF_STATIC)) { isec = (Is_desc *)ofl->ofl_ossymtab-> os_isdescs.head->data; - else + } else { isec = (Is_desc *)ofl->ofl_osdynsym-> os_isdescs.head->data; - cnt = isec->is_shdr->sh_size / isec->is_shdr->sh_entsize; + } + cnt = (isec->is_shdr->sh_size / isec->is_shdr->sh_entsize); if (ofl->ofl_osversym) { isec = (Is_desc *)ofl->ofl_osversym->os_isdescs. @@ -2384,34 +2210,13 @@ ld_make_data(Ofl_desc *ofl, size_t size) Elf_Data *data; Is_desc *isec; - /* - * Allocate and initialize the Elf_Data structure. - */ - if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) + if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_DATA), 0, + &isec, &shdr, &data) == S_ERROR) return ((Is_desc *)S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_size = size; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return ((Is_desc *)S_ERROR); - shdr->sh_type = SHT_PROGBITS; - shdr->sh_flags = SHF_ALLOC | SHF_WRITE; + data->d_size = size; shdr->sh_size = (Xword)size; - shdr->sh_addralign = M_WORD_ALIGN; - - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == (Is_desc *)0) - return ((Is_desc *)S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_DATA); - isec->is_shdr = shdr; - isec->is_indata = data; + shdr->sh_flags |= SHF_WRITE; if (ld_place_section(ofl, isec, M_ID_DATA, 0) == (Os_desc *)S_ERROR) return ((Is_desc *)S_ERROR); @@ -2473,38 +2278,18 @@ ld_make_text(Ofl_desc *ofl, size_t size) if (size < sizeof (ret_template)) size = sizeof (ret_template); - /* - * Allocate and initialize the Elf_Data structure. Fill the buffer - * with the appropriate return instruction. - */ - if (((data = libld_calloc(sizeof (Elf_Data), 1)) == 0) || - ((data->d_buf = libld_calloc(size, 1)) == 0)) + if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_TEXT), 0, + &isec, &shdr, &data) == S_ERROR) return ((Is_desc *)S_ERROR); - data->d_type = ELF_T_BYTE; - data->d_size = size; - data->d_align = M_WORD_ALIGN; - data->d_version = ofl->ofl_dehdr->e_version; - - (void) memcpy(data->d_buf, ret_template, sizeof (ret_template)); - /* - * Allocate and initialize the Shdr structure. - */ - if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0) - return ((Is_desc *)S_ERROR); - shdr->sh_type = SHT_PROGBITS; - shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR; + data->d_size = size; shdr->sh_size = (Xword)size; - shdr->sh_addralign = M_WORD_ALIGN; + shdr->sh_flags |= SHF_EXECINSTR; - /* - * Allocate and initialize the Is_desc structure. - */ - if ((isec = libld_calloc(1, sizeof (Is_desc))) == (Is_desc *)0) + /* Fill the buffer with the appropriate return instruction. */ + if ((data->d_buf = libld_calloc(size, 1)) == 0) return ((Is_desc *)S_ERROR); - isec->is_name = MSG_ORIG(MSG_SCN_TEXT); - isec->is_shdr = shdr; - isec->is_indata = data; + (void) memcpy(data->d_buf, ret_template, sizeof (ret_template)); if (ld_place_section(ofl, isec, M_ID_TEXT, 0) == (Os_desc *)S_ERROR) return ((Is_desc *)S_ERROR); diff --git a/usr/src/cmd/sgs/libld/common/syms.c b/usr/src/cmd/sgs/libld/common/syms.c index b12e7f99ed..76438303ce 100644 --- a/usr/src/cmd/sgs/libld/common/syms.c +++ b/usr/src/cmd/sgs/libld/common/syms.c @@ -466,7 +466,7 @@ ld_sym_enter(const char *name, Sym *osym, Word hash, Ifl_desc *ifl, * implicit shared object. */ if (ifl->ifl_vercnt) { - Ver_index * vip; + Ver_index *vip; Half vndx = ifl->ifl_versym[ndx]; sap->sa_dverndx = vndx; @@ -745,9 +745,7 @@ sym_undef_entry(Ofl_desc *ofl, Sym_desc *sdp, Type type) uintptr_t ld_sym_spec(Ofl_desc *ofl) { - Word flags = ofl->ofl_flags; - - if (!(flags & FLG_OF_RELOBJ)) { + if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) { DBG_CALL(Dbg_syms_spec_title(ofl->ofl_lml)); @@ -781,8 +779,7 @@ ld_sym_spec(Ofl_desc *ofl) FLG_SY1_GLOB, ofl) == S_ERROR) return (S_ERROR); - if ((flags & (FLG_OF_DYNAMIC | FLG_OF_RELOBJ)) == - FLG_OF_DYNAMIC) + if (OFL_ALLOW_DYNSYM(ofl)) if (sym_add_spec(MSG_ORIG(MSG_SYM_PLKTBL), MSG_ORIG(MSG_SYM_PLKTBL_U), SDAUX_ID_PLT, FLG_SY1_GLOB, ofl) == S_ERROR) @@ -958,6 +955,7 @@ ld_sym_validate(Ofl_desc *ofl) Xword lbssalign = 0, lbsssize = 0; #endif int ret; + int allow_ldynsym; /* * If a symbol is undefined and this link-edit calls for no undefined @@ -992,6 +990,7 @@ ld_sym_validate(Ofl_desc *ofl) if ((oflags & FLG_OF_VERDEF) && (ofl->ofl_vercnt > VER_NDX_GLOBAL)) verdesc = FLG_OF_FATAL; + allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl); /* * Collect and validate the globals from the internal symbol table. */ @@ -1319,6 +1318,13 @@ ld_sym_validate(Ofl_desc *ofl) sym->st_name) && (st_insert(ofl->ofl_strtab, sdp->sd_name) == -1)) return (S_ERROR); + if (allow_ldynsym && sym->st_name && + (ELF_ST_TYPE(sym->st_info) == STT_FUNC)) { + ofl->ofl_dynscopecnt++; + if (st_insert(ofl->ofl_dynstrtab, + sdp->sd_name) == -1) + return (S_ERROR); + } } } else { ofl->ofl_globcnt++; @@ -1636,6 +1642,7 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) * index array. */ if (local) { + int allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl); for (sym++, ndx = 1; ndx < local; sym++, ndx++) { Word shndx, sdflags = FLG_SY_CLEAN; const char *name; @@ -1827,6 +1834,15 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) sym->st_name) && (st_insert(ofl->ofl_strtab, sdp->sd_name) == -1)) return (S_ERROR); + + if (allow_ldynsym && sym->st_name && + ((type == STT_FUNC) || + (type == STT_FILE))) { + ofl->ofl_dynlocscnt++; + if (st_insert(ofl->ofl_dynstrtab, + sdp->sd_name) == -1) + return (S_ERROR); + } } } } diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c index 61507002a9..74e98c13a3 100644 --- a/usr/src/cmd/sgs/libld/common/update.c +++ b/usr/src/cmd/sgs/libld/common/update.c @@ -41,7 +41,7 @@ #include "_libld.h" /* - * Comparison routine used by qsort() for sorting of the global yymbol list + * Comparison routine used by qsort() for sorting of the global symbol list * based off of the hashbuckets the symbol will eventually be deposited in. */ static int @@ -77,13 +77,17 @@ update_osym(Ofl_desc *ofl) Addr tlsbssaddr = 0; Addr sunwbssaddr = 0, sunwdata1addr; int start_set = 0; - Sym _sym = {0}, *sym, *symtab = 0, *dynsym = 0; + Sym _sym = {0}, *sym, *symtab = 0; + Sym *dynsym = 0, *ldynsym = 0; Word symtab_ndx = 0; /* index into .symtab */ - Word dynsym_ndx = 0; /* index into .dynsym */ + Word ldynsym_ndx = 0; /* index into .SUNW_ldynsym */ + Word dynsym_ndx = 0; /* index into .dynsym */ Word scopesym_ndx = 0; /* index into scoped symbols */ - Word *symndx = 0; /* Symbol index (for relocation use) */ + Word ldynscopesym_ndx = 0; /* index to ldynsym scoped syms */ + Word *symndx; /* Symbol index (for relocation use) */ Word *symshndx = 0; /* .symtab_shndx table */ Word *dynshndx = 0; /* .dynsym_shndx table */ + Word *ldynshndx = 0; /* .SUNW_ldynsym_shndx table */ Str_tbl *shstrtab; Str_tbl *strtab; Str_tbl *dynstr; @@ -118,10 +122,19 @@ update_osym(Ofl_desc *ofl) if (ofl->ofl_ossymshndx) symshndx = (Word *)ofl->ofl_ossymshndx->os_outdata->d_buf; } - if ((flags & FLG_OF_DYNAMIC) && !(flags & FLG_OF_RELOBJ)) { + if (OFL_ALLOW_DYNSYM(ofl)) { dynsym = (Sym *)ofl->ofl_osdynsym->os_outdata->d_buf; dynsym[dynsym_ndx++] = _sym; /* + * If we are also constructing a .SUNW_ldynsym section + * to contain local function symbols, then set it up too. + */ + if (ofl->ofl_osldynsym) { + ldynsym = (Sym *)ofl->ofl_osldynsym->os_outdata->d_buf; + ldynsym[ldynsym_ndx++] = _sym; + } + + /* * Initialize the hash table. */ hashtab = (Word *)(ofl->ofl_oshash->os_outdata->d_buf); @@ -132,6 +145,8 @@ update_osym(Ofl_desc *ofl) ofl->ofl_lregsymcnt + 1; if (ofl->ofl_osdynshndx) dynshndx = (Word *)ofl->ofl_osdynshndx->os_outdata->d_buf; + if (ofl->ofl_osldynshndx) + ldynshndx = (Word *)ofl->ofl_osldynshndx->os_outdata->d_buf; } /* @@ -173,7 +188,7 @@ update_osym(Ofl_desc *ofl) DBG_CALL(Dbg_syms_sec_title(ofl->ofl_lml)); /* - * Add the output file name to the first .symtab symbol. + * Put output file name to the first .symtab and .SUNW_ldynsym symbol. */ if (symtab) { (void) st_setstring(strtab, ofl->ofl_name, &stoff); @@ -189,6 +204,21 @@ update_osym(Ofl_desc *ofl) if (versym && !dynsym) versym[1] = 0; } + if (ldynsym && ofl->ofl_dynscopecnt) { + (void) st_setstring(dynstr, ofl->ofl_name, &stoff); + sym = &ldynsym[ldynsym_ndx]; + /* LINTED */ + sym->st_name = stoff; + sym->st_value = 0; + sym->st_size = 0; + sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE); + sym->st_other = 0; + sym->st_shndx = SHN_ABS; + + /* Scoped symbols get filled in global loop below */ + ldynscopesym_ndx = ldynsym_ndx + 1; + ldynsym_ndx += ofl->ofl_dynscopecnt; + } /* * If we are to display GOT summary information, then allocate @@ -474,6 +504,8 @@ update_osym(Ofl_desc *ofl) Gotndx *gnp; unsigned char type; Word *_symshndx; + int enter_in_symtab, enter_in_ldynsym; + int update_done; sdp = ifl->ifl_oldndx[lndx]; sym = sdp->sd_sym; @@ -524,13 +556,16 @@ update_osym(Ofl_desc *ofl) * we still need to update any local symbols that are * used during relocation. */ + enter_in_symtab = symtab && + (!(ofl->ofl_flags1 & FLG_OF1_REDLSYM) || + (sdp->sd_psyminfo)); + enter_in_ldynsym = ldynsym && sdp->sd_name && + ((type == STT_FUNC) || (type == STT_FILE)); _symshndx = 0; - if (symtab && (!(ofl->ofl_flags1 & FLG_OF1_REDLSYM) || - (sdp->sd_psyminfo))) { + if (enter_in_symtab) { if (!dynsym) sdp->sd_symndx = *symndx; symtab[symtab_ndx] = *sym; - /* * Provided this isn't an unnamed register * symbol, update its name. @@ -547,9 +582,24 @@ update_osym(Ofl_desc *ofl) sdp->sd_sym = sym = &symtab[symtab_ndx++]; if ((sdp->sd_flags & FLG_SY_SPECSEC) && - (sym->st_shndx == SHN_ABS)) + (sym->st_shndx == SHN_ABS) && + !enter_in_ldynsym) continue; - } else { + } else if (enter_in_ldynsym) { + /* + * Not using symtab, but we do have ldynsym + * available. + */ + ldynsym[ldynsym_ndx] = *sym; + (void) st_setstring(dynstr, sdp->sd_name, + &stoff); + ldynsym[ldynsym_ndx].st_name = stoff; + + sdp->sd_flags &= ~FLG_SY_CLEAN; + if (ldynshndx) + _symshndx = &ldynshndx[ldynsym_ndx]; + sdp->sd_sym = sym = &ldynsym[ldynsym_ndx++]; + } else { /* Not using symtab or ldynsym */ /* * If this symbol requires modifying to provide * for a relocation or move table update, make @@ -570,10 +620,11 @@ update_osym(Ofl_desc *ofl) /* * Update the symbols contents if necessary. */ + update_done = 0; if (type == STT_FILE) { sdp->sd_shndx = sym->st_shndx = SHN_ABS; sdp->sd_flags |= FLG_SY_SPECSEC; - continue; + update_done = 1; } /* @@ -581,14 +632,14 @@ update_osym(Ofl_desc *ofl) * initialized symbols, then update the address here. */ if (ofl->ofl_issunwdata1 && - (sdp->sd_flags & FLG_SY_PAREXPN)) { + (sdp->sd_flags & FLG_SY_PAREXPN) && !update_done) { static Addr laddr = 0; sym->st_shndx = sunwdata1ndx; sdp->sd_isc = ofl->ofl_issunwdata1; - if (ofl->ofl_flags & FLG_OF_RELOBJ) + if (ofl->ofl_flags & FLG_OF_RELOBJ) { sym->st_value = sunwdata1addr; - else { + } else { sym->st_value = laddr; laddr += sym->st_size; } @@ -599,7 +650,7 @@ update_osym(Ofl_desc *ofl) * If this isn't an UNDEF symbol (ie. an input section * is associated), update the symbols value and index. */ - if ((isc = sdp->sd_isc) != 0) { + if (((isc = sdp->sd_isc) != 0) && !update_done) { Word sectndx; osp = isc->is_osdesc; @@ -613,9 +664,10 @@ update_osym(Ofl_desc *ofl) * the TLS segment. */ if ((ELF_ST_TYPE(sym->st_info) == - STT_TLS) && (ofl->ofl_tlsphdr)) + STT_TLS) && (ofl->ofl_tlsphdr)) { sym->st_value -= ofl->ofl_tlsphdr->p_vaddr; + } } /* LINTED */ if ((sdp->sd_shndx = sectndx = @@ -629,6 +681,25 @@ update_osym(Ofl_desc *ofl) sym->st_shndx = sectndx; } } + + /* + * If entering the symbol in both the symtab and the + * ldynsym, then the one in symtab needs to be + * copied to ldynsym. If it is only in the ldynsym, + * then the code above already set it up and we have + * nothing more to do here. + */ + if (enter_in_symtab && enter_in_ldynsym) { + ldynsym[ldynsym_ndx] = *sym; + (void) st_setstring(dynstr, sdp->sd_name, + &stoff); + ldynsym[ldynsym_ndx].st_name = stoff; + + if (_symshndx && ldynshndx) + ldynshndx[ldynsym_ndx] = *_symshndx; + + ldynsym_ndx++; + } } } @@ -897,7 +968,7 @@ update_osym(Ofl_desc *ofl) Sym *sym; Sym_aux *sap; Half spec; - int local = 0, enter_in_symtab; + int local = 0, dynlocal = 0, enter_in_symtab; Listnode *lnp2; Gotndx *gnp; Word sectndx; @@ -953,10 +1024,15 @@ update_osym(Ofl_desc *ofl) else sdp->sd_symndx = 0; - if (sdp->sd_flags1 & FLG_SY1_ELIM) + if (sdp->sd_flags1 & FLG_SY1_ELIM) { enter_in_symtab = 0; - } else + } else if (ldynsym && sdp->sd_sym->st_name && + (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_FUNC)) { + dynlocal = 1; + } + } else { sdp->sd_symndx = *symndx; + } /* * Copy basic symbol and string information. @@ -1146,7 +1222,7 @@ update_osym(Ofl_desc *ofl) * first, followed by the .dynsym, thus the `sym' value will * remain as the .dynsym value when the .dynsym is present. * This ensures that any versioning symbols st_name value will - * be appropriate for the string table used to by version + * be appropriate for the string table used by version * entries. */ if (enter_in_symtab) { @@ -1156,42 +1232,45 @@ update_osym(Ofl_desc *ofl) _symndx = scopesym_ndx; else _symndx = symtab_ndx; + symtab[_symndx] = *sdp->sd_sym; sdp->sd_sym = sym = &symtab[_symndx]; (void) st_setstring(strtab, name, &stoff); sym->st_name = stoff; } + if (dynlocal) { + ldynsym[ldynscopesym_ndx] = *sdp->sd_sym; + sdp->sd_sym = sym = &ldynsym[ldynscopesym_ndx]; + (void) st_setstring(dynstr, name, &stoff); + ldynsym[ldynscopesym_ndx].st_name = stoff; + } if (dynsym && !local) { dynsym[dynsym_ndx] = *sdp->sd_sym; - /* * Provided this isn't an unnamed register symbol, * update its name and hash value. */ if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) || dynsym[dynsym_ndx].st_name) { - (void) st_setstring(dynstr, name, &stoff); - dynsym[dynsym_ndx].st_name = stoff; - if (stoff) { - Word _hashndx; - hashval = - sap->sa_hash % ofl->ofl_hashbkts; - /* LINTED */ - if (_hashndx = hashbkt[hashval]) { - while (hashchain[_hashndx]) - _hashndx = - hashchain[_hashndx]; - hashchain[_hashndx] = - sdp->sd_symndx; - } else - hashbkt[hashval] = - sdp->sd_symndx; + (void) st_setstring(dynstr, name, &stoff); + dynsym[dynsym_ndx].st_name = stoff; + if (stoff) { + Word _hashndx; + hashval = sap->sa_hash % ofl->ofl_hashbkts; + /* LINTED */ + if (_hashndx = hashbkt[hashval]) { + while (hashchain[_hashndx]) + _hashndx = hashchain[_hashndx]; + hashchain[_hashndx] = sdp->sd_symndx; + } else { + hashbkt[hashval] = sdp->sd_symndx; } + } } sdp->sd_sym = sym = &dynsym[dynsym_ndx]; } - if (!enter_in_symtab && (!dynsym || local)) { + if (!enter_in_symtab && (!dynsym || (local && !dynlocal))) { if (!(sdp->sd_flags & FLG_SY_UPREQD)) continue; sym = sdp->sd_sym; @@ -1219,15 +1298,23 @@ update_osym(Ofl_desc *ofl) libld_calloc(sizeof (Wk_desc), 1)) == 0) return ((Addr)S_ERROR); - if (enter_in_symtab) + if (enter_in_symtab) { if (local) wkp->wk_symtab = &symtab[scopesym_ndx]; else wkp->wk_symtab = &symtab[symtab_ndx]; - if (dynsym && !local) - wkp->wk_dynsym = &dynsym[dynsym_ndx]; + } + if (dynsym) { + if (!local) { + wkp->wk_dynsym = + &dynsym[dynsym_ndx]; + } else if (dynlocal) { + wkp->wk_dynsym = + &ldynsym[ldynscopesym_ndx]; + } + } wkp->wk_weak = sdp; wkp->wk_alias = _sdp; @@ -1239,8 +1326,13 @@ update_osym(Ofl_desc *ofl) scopesym_ndx++; else symtab_ndx++; - if (dynsym && !local) - dynsym_ndx++; + if (dynsym) { + if (!local) { + dynsym_ndx++; + } else if (dynlocal) { + ldynscopesym_ndx++; + } + } continue; } } @@ -1446,11 +1538,13 @@ update_osym(Ofl_desc *ofl) * .symtab entry. */ sdp->sd_shndx = sectndx; - if (enter_in_symtab && dynsym && !local) { - symtab[symtab_ndx].st_value = sym->st_value; - symtab[symtab_ndx].st_size = sym->st_size; - symtab[symtab_ndx].st_info = sym->st_info; - symtab[symtab_ndx].st_other = sym->st_other; + if (enter_in_symtab && dynsym && (!local || dynlocal)) { + Word _symndx = dynlocal ? scopesym_ndx : symtab_ndx; + + symtab[_symndx].st_value = sym->st_value; + symtab[_symndx].st_size = sym->st_size; + symtab[_symndx].st_info = sym->st_info; + symtab[_symndx].st_other = sym->st_other; } @@ -1472,17 +1566,34 @@ update_osym(Ofl_desc *ofl) } } - if (dynsym && !local) { + if (dynsym && (!local || dynlocal)) { + /* + * dynsym and ldynsym are distinct tables, so + * we use indirection to access the right one + * and the related extended section index array. + */ + Word _symndx; + Sym *_dynsym; + Word *_dynshndx; + + if (!local) { + _symndx = dynsym_ndx++; + _dynsym = dynsym; + _dynshndx = dynshndx; + } else { + _symndx = ldynscopesym_ndx++; + _dynsym = ldynsym; + _dynshndx = ldynshndx; + } if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) && (sectndx >= SHN_LORESERVE)) { - assert(dynshndx != 0); - dynshndx[dynsym_ndx] = sectndx; - dynsym[dynsym_ndx].st_shndx = SHN_XINDEX; + assert(_dynshndx != 0); + _dynshndx[_symndx] = sectndx; + _dynsym[_symndx].st_shndx = SHN_XINDEX; } else { /* LINTED */ - dynsym[dynsym_ndx].st_shndx = (Half)sectndx; + _dynsym[_symndx].st_shndx = (Half)sectndx; } - dynsym_ndx++; } DBG_CALL(Dbg_syms_new(ofl, sym, sdp)); @@ -1551,7 +1662,11 @@ update_osym(Ofl_desc *ofl) DBG_CALL(Dbg_got_display(ofl, 0, 0)); /* - * Update the section headers information. + * Update the section headers information. sh_info is + * supposed to contain the offset at which the first + * global symbol resides in the symbol table, while + * sh_link contains the section index of the associated + * string table. */ if (symtab) { Shdr * shdr = ofl->ofl_ossymtab->os_shdr; @@ -1569,7 +1684,7 @@ update_osym(Ofl_desc *ofl) if (dynsym) { Shdr * shdr = ofl->ofl_osdynsym->os_shdr; - shdr->sh_info = ofl->ofl_dynshdrcnt + ofl->ofl_lregsymcnt + 1; + shdr->sh_info = 1 + ofl->ofl_dynshdrcnt + ofl->ofl_lregsymcnt; /* LINTED */ shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn); @@ -1582,6 +1697,39 @@ update_osym(Ofl_desc *ofl) (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn); } } + if (ldynsym) { + Shdr * shdr = ofl->ofl_osldynsym->os_shdr; + + /* ldynsym has no globals, so give index one past the end */ + shdr->sh_info = ldynsym_ndx; + + /* + * The ldynsym and dynsym must be adjacent. The + * idea is that rtld should be able to start with + * the ldynsym and march straight through the end + * of dynsym, seeing them as a single symbol table, + * despite the fact that they are in distinct sections. + * Ensure that this happened correctly. + * + * Note that I use ldynsym_ndx here instead of the + * computation I used to set the section size + * (1 + ofl->ofl_dynlocscnt + ofl->ofl_dynscopecnt). + * The two will agree, unless we somehow miscounted symbols + * or failed to insert them all. Using ldynsym_ndx here + * catches that error in addition to checking for adjacency. + */ + assert(dynsym == (ldynsym + ldynsym_ndx)); + + + /* LINTED */ + shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn); + + if (ldynshndx) { + shdr = ofl->ofl_osldynshndx->os_shdr; + shdr->sh_link = + (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn); + } + } /* * Used by ld.so.1 only. @@ -1745,6 +1893,26 @@ update_odynamic(Ofl_desc *ofl) dyn->d_un.d_ptr = shdr->sh_entsize; dyn++; + if (ofl->ofl_osldynsym) { + /* + * We have arranged for the .SUNW_ldynsym data to be + * immediately in front of the .dynsym data. + * This means that you could start at the top + * of .SUNW_ldynsym and see the data for both tables + * without a break. This is the view we want to + * provide for DT_SUNW_SYMTAB, which is why we + * add the lengths together. + */ + Shdr *lshdr = ofl->ofl_osldynsym->os_shdr; + dyn->d_tag = DT_SUNW_SYMTAB; + dyn->d_un.d_ptr = lshdr->sh_addr; + dyn++; + + dyn->d_tag = DT_SUNW_SYMSZ; + dyn->d_un.d_val = lshdr->sh_size + shdr->sh_size; + dyn++; + } + /* * Reserve the DT_CHECKSUM entry. Its value will be filled in * after the complete image is built. @@ -2432,7 +2600,7 @@ update_move(Ofl_desc *ofl) * Determine the index of the symbol table that will be referenced by * the relocation entries. */ - if ((flags & (FLG_OF_DYNAMIC|FLG_OF_RELOBJ)) == FLG_OF_DYNAMIC) + if (OFL_ALLOW_DYNSYM(ofl)) /* LINTED */ ndx = (Word) elf_ndxscn(ofl->ofl_osdynsym->os_scn); else if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ)) @@ -2807,8 +2975,7 @@ ld_update_outfile(Ofl_desc *ofl) * figured out by now. */ if (phdr->p_type == PT_DYNAMIC) { - if ((flags & (FLG_OF_DYNAMIC | FLG_OF_RELOBJ)) == - FLG_OF_DYNAMIC) { + if (OFL_ALLOW_DYNSYM(ofl)) { Shdr * shdr = ofl->ofl_osdynamic->os_shdr; phdr->p_vaddr = shdr->sh_addr; diff --git a/usr/src/cmd/sgs/librtld/common/dynamic.c b/usr/src/cmd/sgs/librtld/common/dynamic.c index 1fc6d5bc6f..cda26668bc 100644 --- a/usr/src/cmd/sgs/librtld/common/dynamic.c +++ b/usr/src/cmd/sgs/librtld/common/dynamic.c @@ -111,11 +111,13 @@ update_dynamic(Cache *cache, Cache *_cache, Rt_map *lmp, int flags, case DT_CONFIG: case DT_DEPAUDIT: case DT_AUDIT: + case DT_SUNW_SYMSZ: break; case DT_PLTGOT: case DT_HASH: case DT_STRTAB: case DT_SYMTAB: + case DT_SUNW_SYMTAB: case DT_INIT: case DT_FINI: case DT_VERSYM: diff --git a/usr/src/cmd/sgs/librtld_db/rdb_demo/common/ps.c b/usr/src/cmd/sgs/librtld_db/rdb_demo/common/ps.c index 407148993b..ad11766ad0 100644 --- a/usr/src/cmd/sgs/librtld_db/rdb_demo/common/ps.c +++ b/usr/src/cmd/sgs/librtld_db/rdb_demo/common/ps.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2000 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -53,7 +52,7 @@ #if !defined(_LP64) static void -gelf_sym_to_elf32(GElf_Sym * src, Elf32_Sym * dst) +gelf_sym_to_elf32(GElf_Sym *src, Elf32_Sym *dst) { dst->st_name = src->st_name; /* LINTED */ @@ -68,14 +67,13 @@ gelf_sym_to_elf32(GElf_Sym * src, Elf32_Sym * dst) #endif static void -get_ldbase(struct ps_prochandle * procp) +get_ldbase(struct ps_prochandle *procp) { int pauxvfd; char pname[MAXPATHLEN]; struct stat stbuf; - void * auxvptr; - void * auxvtail; - auxv_t * auxvp; + void *auxvptr, *auxvtail; + auxv_t *auxvp; uint_t entsize; (void) snprintf(pname, MAXPATHLEN, "/proc/%d/auxv", procp->pp_pid); @@ -127,7 +125,7 @@ get_ldbase(struct ps_prochandle * procp) } retc_t -ps_init(int pctlfd, int pstatusfd, pid_t pid, struct ps_prochandle * procp) +ps_init(int pctlfd, int pstatusfd, pid_t pid, struct ps_prochandle *procp) { rd_notify_t rd_notify; char procname[MAXPATHLEN]; @@ -228,7 +226,7 @@ ps_init(int pctlfd, int pstatusfd, pid_t pid, struct ps_prochandle * procp) retc_t -ps_close(struct ps_prochandle * ph) +ps_close(struct ps_prochandle *ph) { delete_all_breakpoints(ph); if (ph->pp_auxvp) @@ -239,7 +237,7 @@ ps_close(struct ps_prochandle * ph) ps_err_e -ps_pauxv(struct ps_prochandle * ph, const auxv_t ** auxvp) +ps_pauxv(struct ps_prochandle *ph, const auxv_t **auxvp) { *auxvp = ph->pp_auxvp; return (PS_OK); @@ -247,7 +245,7 @@ ps_pauxv(struct ps_prochandle * ph, const auxv_t ** auxvp) ps_err_e -ps_pdmodel(struct ps_prochandle * ph, int * dm) +ps_pdmodel(struct ps_prochandle *ph, int *dm) { pstatus_t pstatus; @@ -260,8 +258,7 @@ ps_pdmodel(struct ps_prochandle * ph, int * dm) ps_err_e -ps_pread(struct ps_prochandle * ph, psaddr_t addr, void * buf, - size_t size) +ps_pread(struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t size) { /* LINTED */ if (pread(ph->pp_asfd, buf, size, (off_t)addr) != size) @@ -272,8 +269,7 @@ ps_pread(struct ps_prochandle * ph, psaddr_t addr, void * buf, ps_err_e -ps_pwrite(struct ps_prochandle * ph, psaddr_t addr, const void * buf, - size_t size) +ps_pwrite(struct ps_prochandle *ph, psaddr_t addr, const void *buf, size_t size) { /* LINTED */ if (pwrite(ph->pp_asfd, buf, size, (off_t)addr) != size) @@ -284,11 +280,10 @@ ps_pwrite(struct ps_prochandle * ph, psaddr_t addr, const void * buf, ps_err_e -ps_pglobal_sym(struct ps_prochandle * ph, - const char * object_name, const char * sym_name, - ps_sym_t * symp) +ps_pglobal_sym(struct ps_prochandle *ph, const char *object_name, + const char *sym_name, ps_sym_t *symp) { - map_info_t * mip; + map_info_t *mip; GElf_Sym gsym; if ((mip = str_to_map(ph, object_name)) == 0) @@ -308,12 +303,11 @@ ps_pglobal_sym(struct ps_prochandle * ph, ps_err_e -ps_pglobal_lookup(struct ps_prochandle * ph, - const char * object_name, const char * sym_name, - ulong_t * sym_addr) +ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name, + const char *sym_name, ulong_t *sym_addr) { GElf_Sym sym; - map_info_t * mip; + map_info_t *mip; if ((mip = str_to_map(ph, object_name)) == 0) return (PS_ERR); @@ -328,8 +322,7 @@ ps_pglobal_lookup(struct ps_prochandle * ph, ps_err_e -ps_lgetregs(struct ps_prochandle * ph, lwpid_t lid, - prgregset_t gregset) +ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) { char procname[MAXPATHLEN]; int lwpfd; @@ -352,10 +345,10 @@ ps_lgetregs(struct ps_prochandle * ph, lwpid_t lid, void -ps_plog(const char * fmt, ...) +ps_plog(const char *fmt, ...) { va_list args; - static FILE * log_fp = 0; + static FILE *log_fp = 0; if (log_fp == 0) { char log_fname[256]; @@ -377,3 +370,9 @@ ps_plog(const char * fmt, ...) fputc('\n', log_fp); fflush(log_fp); } + +ps_err_e +ps_pbrandname(struct ps_prochandle *P, char *buf, size_t len) +{ + return (PS_ERR); +} diff --git a/usr/src/cmd/sgs/pvs/common/pvs.c b/usr/src/cmd/sgs/pvs/common/pvs.c index 76d1848766..cc8cb42a8d 100644 --- a/usr/src/cmd/sgs/pvs/common/pvs.c +++ b/usr/src/cmd/sgs/pvs/common/pvs.c @@ -806,14 +806,24 @@ main(int argc, char **argv, char **envp) /* * Remember the version sections and symbol table. */ - if ((shdr.sh_type == SHT_SUNW_verdef) && dflag) - _cache_def = _cache; - else if ((shdr.sh_type == SHT_SUNW_verneed) && rflag) - _cache_need = _cache; - else if ((shdr.sh_type == SHT_SUNW_versym) && sflag) - _cache_sym = _cache; - else if ((shdr.sh_type == SHT_SYMTAB) && lflag) - _cache_loc = _cache; + switch (shdr.sh_type) { + case SHT_SUNW_verdef: + if (dflag) + _cache_def = _cache; + break; + case SHT_SUNW_verneed: + if (rflag) + _cache_need = _cache; + break; + case SHT_SUNW_versym: + if (sflag) + _cache_sym = _cache; + break; + case SHT_SYMTAB: + if (lflag) + _cache_loc = _cache; + break; + } } /* diff --git a/usr/src/cmd/sgs/rtld/common/_elf.h b/usr/src/cmd/sgs/rtld/common/_elf.h index bf30ef9c8a..7f687c86c7 100644 --- a/usr/src/cmd/sgs/rtld/common/_elf.h +++ b/usr/src/cmd/sgs/rtld/common/_elf.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -24,7 +23,7 @@ * All Rights Reserved * * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -87,6 +86,7 @@ typedef struct pltpadinfo { */ typedef struct _rt_elf_private { void *e_symtab; /* symbol table */ + void *e_sunwsymtab; /* symtab augmented with local fcns */ uint_t *e_hash; /* hash table */ char *e_strtab; /* string table */ void *e_reloc; /* relocation table */ @@ -94,6 +94,7 @@ typedef struct _rt_elf_private { void *e_pltreserve; /* ia64: DT_IA_64_PLTRESERVE */ void *e_dynplt; /* dynamic plt table - used by prof */ void *e_jmprel; /* plt relocations */ + ulong_t e_sunwsymsz; /* size of w_sunwsymtab */ ulong_t e_pltrelsize; /* size of PLT relocation entries */ ulong_t e_relsz; /* size of relocs */ ulong_t e_relent; /* size of base reloc entry */ @@ -120,6 +121,7 @@ typedef struct _rt_elf_private { */ #define ELFPRV(X) ((X)->rt_priv) #define SYMTAB(X) (((Rt_elfp *)(X)->rt_priv)->e_symtab) +#define SUNWSYMTAB(X) (((Rt_elfp *)(X)->rt_priv)->e_sunwsymtab) #define HASH(X) (((Rt_elfp *)(X)->rt_priv)->e_hash) #define STRTAB(X) (((Rt_elfp *)(X)->rt_priv)->e_strtab) #define REL(X) (((Rt_elfp *)(X)->rt_priv)->e_reloc) @@ -129,6 +131,7 @@ typedef struct _rt_elf_private { #define MOVETAB(X) (((Rt_elfp *)(X)->rt_priv)->e_movetab) #define DYNPLT(X) (((Rt_elfp *)(X)->rt_priv)->e_dynplt) #define JMPREL(X) (((Rt_elfp *)(X)->rt_priv)->e_jmprel) +#define SUNWSYMSZ(X) (((Rt_elfp *)(X)->rt_priv)->e_sunwsymsz) #define PTTLS(X) (((Rt_elfp *)(X)->rt_priv)->e_pttls) #define PTUNWIND(X) (((Rt_elfp *)(X)->rt_priv)->e_ptunwind) #define TLSSTATOFF(X) (((Rt_elfp *)(X)->rt_priv)->e_tlsstatoff) diff --git a/usr/src/cmd/sgs/rtld/common/elf.c b/usr/src/cmd/sgs/rtld/common/elf.c index 54be0c2aa9..fba212bf3d 100644 --- a/usr/src/cmd/sgs/rtld/common/elf.c +++ b/usr/src/cmd/sgs/rtld/common/elf.c @@ -1926,8 +1926,7 @@ elf_find_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo) * symbol binding information. */ if ((sip = SYMINFO(ilmp)) != 0) - /* LINTED */ - sip = (Syminfo *)((char *)sip + (ndx * SYMINENT(ilmp))); + sip += ndx; /* * If this is a direct binding request, but the symbol definition has @@ -2085,6 +2084,13 @@ elf_new_lm(Lm_list *lml, const char *pname, const char *oname, Dyn *ld, case DT_SYMTAB: SYMTAB(lmp) = (void *)(ld->d_un.d_ptr + base); break; + case DT_SUNW_SYMTAB: + SUNWSYMTAB(lmp) = + (void *)(ld->d_un.d_ptr + base); + break; + case DT_SUNW_SYMSZ: + SUNWSYMSZ(lmp) = ld->d_un.d_val; + break; case DT_STRTAB: STRTAB(lmp) = (void *)(ld->d_un.d_ptr + base); break; @@ -2379,6 +2385,37 @@ elf_new_lm(Lm_list *lml, const char *pname, const char *oname, Dyn *ld, } /* + * A dynsym contains only global functions. We want to have + * a version of it that also includes local functions, so that + * dladdr() will be able to report names for local functions + * when used to generate a stack trace for a stripped file. + * This version of the dynsym is provided via DT_SUNW_SYMTAB. + * + * In producing DT_SUNW_SYMTAB, ld uses a non-obvious trick + * in order to avoid having to have two copies of the global + * symbols held in DT_SYMTAB: The local symbols are placed in + * a separate section than the globals in the dynsym, but the + * linker conspires to put the data for these two sections adjacent + * to each other. DT_SUNW_SYMTAB points at the top of the local + * symbols, and DT_SUNW_SYMSZ is the combined length of both tables. + * + * If the two sections are not adjacent, then something went wrong + * at link time. We use ASSERT to kill the process if this is + * a debug build. In a production build, we will silently ignore + * the presence of the .ldynsym and proceed. We can detect this + * situation by checking to see that DT_SYMTAB lies in + * the range given by DT_SUNW_SYMTAB/DT_SUNW_SYMSZ. + */ + if ((SUNWSYMTAB(lmp) != NULL) && + (((char *)SYMTAB(lmp) <= (char *)SUNWSYMTAB(lmp)) || + (((char *)SYMTAB(lmp) >= + (SUNWSYMSZ(lmp) + (char *)SUNWSYMTAB(lmp)))))) { + ASSERT(0); + SUNWSYMTAB(lmp) = NULL; + SUNWSYMSZ(lmp) = 0; + } + + /* * If configuration file use hasn't been disabled, and a configuration * file hasn't already been set via an environment variable, see if any * application specific configuration file is specified. An LD_CONFIG @@ -2929,14 +2966,32 @@ elf_dladdr(ulong_t addr, Rt_map *lmp, Dl_info *dlip, void **info, int flags) int _flags; /* - * If we don't have a .hash table there are no symbols to look at. + * If SUNWSYMTAB() is non-NULL, then it sees a special version of + * the dynsym that starts with any local function symbols that exist in + * the library and then moves to the data held in SYMTAB(). In this + * case, SUNWSYMSZ tells us how long the symbol table is. The + * availability of local function symbols will enhance the results + * we can provide. + * + * If SUNWSYMTAB() is NULL, then SYMTAB() references a dynsym that + * contains only global symbols. In that case, the length of + * the symbol table comes from the nchain field of the related + * symbol lookup hash table. */ - if (HASH(lmp) == 0) - return; - - cnt = HASH(lmp)[1]; str = STRTAB(lmp); - sym = SYMTAB(lmp); + if (SUNWSYMSZ(lmp) == NULL) { + sym = SYMTAB(lmp); + /* + * If we don't have a .hash table there are no symbols + * to look at. + */ + if (HASH(lmp) == 0) + return; + cnt = HASH(lmp)[1]; + } else { + sym = SUNWSYMTAB(lmp); + cnt = SUNWSYMSZ(lmp) / SYMENT(lmp); + } if (FLAGS(lmp) & FLG_RT_FIXED) base = 0; @@ -2946,7 +3001,19 @@ elf_dladdr(ulong_t addr, Rt_map *lmp, Dl_info *dlip, void **info, int flags) for (_sym = 0, _value = 0, sym++, ndx = 1; ndx < cnt; ndx++, sym++) { ulong_t value; - if (sym->st_shndx == SHN_UNDEF) + /* + * Skip expected symbol types that are not functions + * or data: + * - A symbol table starts with an undefined symbol + * in slot 0. If we are using SUNWSYMTAB(), + * there will be a second undefined symbol + * right before the globals. + * - The local part of SUNWSYMTAB() contains a + * series of function symbols. Each section + * starts with an initial STT_FILE symbol. + */ + if ((sym->st_shndx == SHN_UNDEF) || + (ELF_ST_TYPE(sym->st_info) == STT_FILE)) continue; value = sym->st_value + base; diff --git a/usr/src/cmd/sgs/rtld/common/object.c b/usr/src/cmd/sgs/rtld/common/object.c index 309940d552..94398c08ea 100644 --- a/usr/src/cmd/sgs/rtld/common/object.c +++ b/usr/src/cmd/sgs/rtld/common/object.c @@ -68,8 +68,8 @@ elf_obj_init(Lm_list *lml, Aliste lmco, const char *name) ofl->ofl_dehdr = &dehdr; ofl->ofl_flags = - (FLG_OF_DYNAMIC | FLG_OF_SHAROBJ | FLG_OF_STRIP | FLG_OF_MEMORY); - ofl->ofl_flags1 = FLG_OF1_RELDYN | FLG_OF1_TEXTOFF; + (FLG_OF_DYNAMIC | FLG_OF_SHAROBJ | FLG_OF_STRIP); + ofl->ofl_flags1 = FLG_OF1_RELDYN | FLG_OF1_TEXTOFF | FLG_OF1_MEMORY; ofl->ofl_lml = lml; /* diff --git a/usr/src/cmd/sgs/rtld/i386/_setup.c b/usr/src/cmd/sgs/rtld/i386/_setup.c index 6761a0d9e9..bc010977a5 100644 --- a/usr/src/cmd/sgs/rtld/i386/_setup.c +++ b/usr/src/cmd/sgs/rtld/i386/_setup.c @@ -83,7 +83,6 @@ _setup(Boot * ebp, Dyn * ld_dyn) uid_t uid = -1, euid = -1; gid_t gid = -1, egid = -1; char *_platform = 0, *_execname = 0, *_emulator = 0; - int _branded = 0; int auxflags = -1; /* * Scan the bootstrap structure to pick up the basics. @@ -179,7 +178,6 @@ _setup(Boot * ebp, Dyn * ld_dyn) case AT_SUN_EMULATOR: /* name of emulation library, if any */ _emulator = auxv->a_un.a_ptr; - _branded = 1; break; #endif } diff --git a/usr/src/uts/common/sys/elf.h b/usr/src/uts/common/sys/elf.h index 10b4df023c..3e93d63b1a 100644 --- a/usr/src/uts/common/sys/elf.h +++ b/usr/src/uts/common/sys/elf.h @@ -401,7 +401,8 @@ typedef struct { #define SHT_NUM 19 #define SHT_LOOS 0x60000000 /* OS specific range */ -#define SHT_LOSUNW 0x6ffffff4 +#define SHT_LOSUNW 0x6ffffff3 +#define SHT_SUNW_LDYNSYM 0x6ffffff3 #define SHT_SUNW_dof 0x6ffffff4 #define SHT_SUNW_cap 0x6ffffff5 #define SHT_SUNW_SIGNATURE 0x6ffffff6 diff --git a/usr/src/uts/common/sys/link.h b/usr/src/uts/common/sys/link.h index 80ce240cf2..43edf601c5 100644 --- a/usr/src/uts/common/sys/link.h +++ b/usr/src/uts/common/sys/link.h @@ -117,6 +117,10 @@ typedef struct { #define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ #define DT_SUNW_CAP 0x60000010 /* hardware/software */ /* capabilities */ +#define DT_SUNW_SYMTAB 0x60000011 /* symtab with local fcn */ + /* symbols immediately */ + /* preceding DT_SYMTAB */ +#define DT_SUNW_SYMSZ 0x60000012 /* Size of SUNW_SYMTAB table */ #define DT_HIOS 0x6ffff000 /* |