summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/sgs/dump/common/dump.c2
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.c3
-rw-r--r--usr/src/cmd/sgs/include/i386/machdep.h15
-rw-r--r--usr/src/cmd/sgs/include/libld.h26
-rw-r--r--usr/src/cmd/sgs/include/sparc/machdep.h9
-rw-r--r--usr/src/cmd/sgs/libconv/common/dynamic.c4
-rw-r--r--usr/src/cmd/sgs/libconv/common/dynamic.msg2
-rw-r--r--usr/src/cmd/sgs/libconv/common/sections.c28
-rw-r--r--usr/src/cmd/sgs/libconv/common/sections.msg2
-rw-r--r--usr/src/cmd/sgs/libld/common/args.c16
-rw-r--r--usr/src/cmd/sgs/libld/common/libld.msg6
-rw-r--r--usr/src/cmd/sgs/libld/common/outfile.c7
-rw-r--r--usr/src/cmd/sgs/libld/common/sections.c1147
-rw-r--r--usr/src/cmd/sgs/libld/common/syms.c28
-rw-r--r--usr/src/cmd/sgs/libld/common/update.c287
-rw-r--r--usr/src/cmd/sgs/librtld/common/dynamic.c2
-rw-r--r--usr/src/cmd/sgs/librtld_db/rdb_demo/common/ps.c57
-rw-r--r--usr/src/cmd/sgs/pvs/common/pvs.c26
-rw-r--r--usr/src/cmd/sgs/rtld/common/_elf.h11
-rw-r--r--usr/src/cmd/sgs/rtld/common/elf.c85
-rw-r--r--usr/src/cmd/sgs/rtld/common/object.c4
-rw-r--r--usr/src/cmd/sgs/rtld/i386/_setup.c2
-rw-r--r--usr/src/uts/common/sys/elf.h3
-rw-r--r--usr/src/uts/common/sys/link.h4
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
/*