--- a/usr/src/cmd/sgs/libld/common/sections.c Tue Sep 19 15:34:23 2006 -0700
+++ b/usr/src/cmd/sgs/libld/common/sections.c Tue Sep 19 15:38:37 2006 -0700
@@ -62,6 +62,9 @@
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 @@
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 @@
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 @@
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,6 +291,238 @@
}
/*
+ * 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().
+ */
+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;
+ 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 = sec_info->d_type;
+ data->d_size = size;
+ data->d_align = sec_info->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 = shtype;
+ shdr->sh_size = size;
+ 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
@@ -280,34 +541,20 @@
Xword rsize = (Xword)ofl->ofl_relocbsssz;
/*
- * 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, NULL, 0,
+ &isec, &shdr, &data) == S_ERROR)
return (S_ERROR);
- data->d_type = ELF_T_BYTE;
+
data->d_size = (size_t)size;
data->d_align = (size_t)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 = 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_shdr = shdr;
- isec->is_indata = data;
-
if (which == MAKE_TLS) {
isec->is_name = MSG_ORIG(MSG_SCN_TBSS);
ident = M_ID_TLSBSS;
@@ -383,37 +630,12 @@
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 @@
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 @@
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 @@
*/
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 @@
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,35 +1041,15 @@
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)
- 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)
+ if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_GOT), 0,
+ &isec, &shdr, &data) == S_ERROR)
return (S_ERROR);
- shdr->sh_type = SHT_PROGBITS;
- shdr->sh_flags = SHF_ALLOC | SHF_WRITE;
- shdr->sh_size = (Xword)size;
- shdr->sh_addralign = M_WORD_ALIGN;
- shdr->sh_entsize = M_GOT_ENTSIZE;
+
+ data->d_size = 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_GOT);
- isec->is_shdr = shdr;
- isec->is_indata = data;
+ shdr->sh_flags |= SHF_WRITE;
+ shdr->sh_size = (Xword)size;
+ shdr->sh_entsize = M_GOT_ENTSIZE;
if ((ofl->ofl_osgot = ld_place_section(ofl, isec, M_ID_GOT, 0)) ==
(Os_desc *)S_ERROR)
@@ -940,32 +1105,13 @@
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 @@
return (1);
size++; /* Add CA_SUNW_NULL */
- /*
- * Allocate and initialize the Elf_Data structure.
- */
- if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0)
- 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)
+ if (new_section(ofl, SHT_SUNW_cap, MSG_ORIG(MSG_SCN_SUNWCAP), size,
+ &isec, &shdr, &data) == S_ERROR)
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 @@
/*
* 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 @@
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 @@
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)
- 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)
+ if (new_section(ofl, SHT_HASH, MSG_ORIG(MSG_SCN_HASH), 0,
+ &isec, &shdr, &data) == S_ERROR)
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 @@
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)
- 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)
+ if (new_section(ofl, SHT_SYMTAB, MSG_ORIG(MSG_SCN_SYMTAB), 0,
+ &isec, &shdr, &data) == S_ERROR)
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 @@
Shdr *xshdr;
Elf_Data *xdata;
- if ((xdata = libld_calloc(sizeof (Elf_Data), 1)) == 0)
- 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)
+ if (new_section(ofl, SHT_SYMTAB_SHNDX,
+ MSG_ORIG(MSG_SCN_SYMTAB_SHNDX), 0, &xisec,
+ &xshdr, &xdata) == S_ERROR)
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 @@
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);
+
+ if (new_section(ofl, SHT_DYNSYM, MSG_ORIG(MSG_SCN_DYNSYM), 0,
+ &isec, &shdr, &data) == S_ERROR)
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_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,57 +1403,75 @@
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)
- return (S_ERROR);
- data->d_type = ELF_T_WORD;
- data->d_align = M_WORD_ALIGN;
- data->d_version = ofl->ofl_dehdr->e_version;
+ dynsymisp = (Is_desc *)symtab->os_isdescs.head->data;
+ dynshdr = dynsymisp->is_shdr;
- /*
- * Allocate the Shdr structure.
- */
- if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0)
+ if (new_section(ofl, SHT_SYMTAB_SHNDX, shname,
+ (dynshdr->sh_size / dynshdr->sh_entsize),
+ &isec, &shdr, &data) == S_ERROR)
return (S_ERROR);
- shdr->sh_type = SHT_SYMTAB_SHNDX;
- shdr->sh_addralign = M_WORD_ALIGN;
- shdr->sh_entsize = sizeof (Word);
- /*
- * Allocate the Is_desc structure.
- */
- 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_osdynshndx = ld_place_section(ofl, isec,
+ if ((*ret_os = ld_place_section(ofl, isec,
M_ID_DYNSYM_NDX, 0)) == (Os_desc *)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;
+ 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)
+{
+ /*
+ * If there is an ldynsym, generate a section for its extended
+ * index section as well.
+ */
+ 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);
+ }
+
+ /* 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);
return (1);
}
@@ -1449,32 +1488,9 @@
Is_desc *isec;
size_t size;
- /*
- * Allocate the Elf_Data structure.
- */
- if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0)
+ if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_SHSTRTAB),
+ 0, &isec, &shdr, &data) == S_ERROR)
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)
- 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 @@
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 @@
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 @@
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_type = SHT_STRTAB;
- shdr->sh_flags |= SHF_STRINGS;
- shdr->sh_size = (Xword)size;
- shdr->sh_addralign = 1;
+ shdr->sh_flags |= SHF_ALLOC;
- /*
- * 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;
+ /* Set the size of the data area */
+ data->d_size = size;
+ shdr->sh_size = (Xword)size;
ofl->ofl_osdynstr = ld_place_section(ofl, isec, M_ID_DYNSTR, 0);
return ((uintptr_t)ofl->ofl_osdynstr);
@@ -1691,29 +1678,14 @@
/* 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;
+ data->d_size = size;
+
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 @@
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 @@
Shdr *shdr;
Elf_Data *data;
Is_desc *isec;
- size_t size = ofl->ofl_verneedsz;
-
- /*
- * 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;
- data->d_align = M_WORD_ALIGN;
- data->d_version = ofl->ofl_dehdr->e_version;
/*
- * Allocate and initialize the Shdr structure.
+ * verneed sections do not have a constant element size, so the
+ * value of ent_cnt specified here (0) is meaningless.
*/
- if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0)
+ if (new_section(ofl, SHT_SUNW_verneed, MSG_ORIG(MSG_SCN_SUNWVERSION),
+ 0, &isec, &shdr, &data) == S_ERROR)
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 @@
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 @@
* 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 @@
}
/*
- * During version processing we calculated the total number of entries.
- * Allocate and initialize the Elf_Data structure.
- */
- size = ofl->ofl_verdefsz;
-
- if ((data = libld_calloc(sizeof (Elf_Data), 1)) == 0)
- 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.
+ * verdef sections do not have a constant element size, so the
+ * value of ent_cnt specified here (0) is meaningless.
*/
- if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0)
+ if (new_section(ofl, SHT_SUNW_verdef, MSG_ORIG(MSG_SCN_SUNWVERSION),
+ 0, &isec, &shdr, &data) == S_ERROR)
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 @@
* 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)
- 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)
+ if (new_section(ofl, stype, sectname, 0, &isec, &shdr, &data) ==
+ S_ERROR)
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 @@
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 @@
Is_desc *isec;
Os_desc *osp;
- /*
- * 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_SUNWDATA1), 0,
+ &isec, &shdr, &data) == S_ERROR)
return (S_ERROR);
- data->d_type = ELF_T_BYTE;
+
+ shdr->sh_flags |= SHF_WRITE;
data->d_size = size;
+ shdr->sh_size = (Xword)size;
+ if (align != 0) {
+ data->d_align = align;
+ shdr->sh_addralign = align;
+ }
+
if ((data->d_buf = libld_calloc(size, 1)) == 0)
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_size = (Xword)size;
- if (align == 0)
- shdr->sh_addralign = M_WORD_ALIGN;
- else
- 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_SUNWDATA1);
- isec->is_shdr = shdr;
- isec->is_indata = data;
/*
* Retain this .sunwdata1 input section as this will
@@ -2067,50 +1925,17 @@
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 @@
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 @@
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 @@
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 @@
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);
--- a/usr/src/cmd/sgs/libld/common/update.c Tue Sep 19 15:34:23 2006 -0700
+++ b/usr/src/cmd/sgs/libld/common/update.c Tue Sep 19 15:38:37 2006 -0700
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 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 @@
* 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 @@
* 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 @@
* 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 @@
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 @@
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 @@
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 @@
* 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 @@
_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 @@
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 @@
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 @@
* .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 @@
}
}
- 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 @@
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 @@
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 @@
(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 @@
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 @@
* 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 @@
* 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;