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