summaryrefslogtreecommitdiff
path: root/usr/src/cmd/sgs/libld/common
diff options
context:
space:
mode:
authorAli Bahrami <Ali.Bahrami@Sun.COM>2009-03-18 13:28:28 -0600
committerAli Bahrami <Ali.Bahrami@Sun.COM>2009-03-18 13:28:28 -0600
commit7e16fca05dfbcfd32c2ebc9e4d1abdac1cd8657c (patch)
tree5033ac748bcd6544a0981e069919df2d213acead /usr/src/cmd/sgs/libld/common
parentc13e065d8ffc8eafc02caf1091e66e146a2b2ce4 (diff)
downloadillumos-gate-7e16fca05dfbcfd32c2ebc9e4d1abdac1cd8657c.tar.gz
6813909 generalize eh_frame support to non-amd64 platforms
--HG-- rename : usr/src/cmd/sgs/libld/common/unwind.amd.c => usr/src/cmd/sgs/libld/common/unwind.c
Diffstat (limited to 'usr/src/cmd/sgs/libld/common')
-rw-r--r--usr/src/cmd/sgs/libld/common/README.XLINK7
-rw-r--r--usr/src/cmd/sgs/libld/common/_libld.h39
-rw-r--r--usr/src/cmd/sgs/libld/common/entry.c11
-rw-r--r--usr/src/cmd/sgs/libld/common/files.c177
-rw-r--r--usr/src/cmd/sgs/libld/common/globals.c8
-rw-r--r--usr/src/cmd/sgs/libld/common/ldmain.c7
-rw-r--r--usr/src/cmd/sgs/libld/common/machrel.amd.c10
-rw-r--r--usr/src/cmd/sgs/libld/common/machrel.intel.c9
-rw-r--r--usr/src/cmd/sgs/libld/common/machrel.sparc.c11
-rw-r--r--usr/src/cmd/sgs/libld/common/outfile.c5
-rw-r--r--usr/src/cmd/sgs/libld/common/sections.c5
-rw-r--r--usr/src/cmd/sgs/libld/common/unwind.amd.h49
-rw-r--r--usr/src/cmd/sgs/libld/common/unwind.c (renamed from usr/src/cmd/sgs/libld/common/unwind.amd.c)108
-rw-r--r--usr/src/cmd/sgs/libld/common/update.c16
14 files changed, 247 insertions, 215 deletions
diff --git a/usr/src/cmd/sgs/libld/common/README.XLINK b/usr/src/cmd/sgs/libld/common/README.XLINK
index 2eebe59ee2..5eba8e52f4 100644
--- a/usr/src/cmd/sgs/libld/common/README.XLINK
+++ b/usr/src/cmd/sgs/libld/common/README.XLINK
@@ -20,10 +20,9 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
@@ -72,8 +71,8 @@ In addition, the target-specific files usually include the target
in their name (i.e. machrel.sparc.c).
Although the target dependent and independent (common) code is well separated,
-they are interdependent. For example, the common code is aware of
-the target-specific section types that can occur only for some targets
+they are interdependent. The common code is explicitly aware of
+target-specific section types that can occur only for some targets
(i.e. SHT_AMD64_UNWIND). This is not an architecture that allows
for arbitrary target support to be dynamically plugged into an unchanged
platform independent core. Rather, it is an organization that allows
diff --git a/usr/src/cmd/sgs/libld/common/_libld.h b/usr/src/cmd/sgs/libld/common/_libld.h
index 42a1dc82da..61d09a73a0 100644
--- a/usr/src/cmd/sgs/libld/common/_libld.h
+++ b/usr/src/cmd/sgs/libld/common/_libld.h
@@ -98,6 +98,9 @@ typedef struct {
Word m_plt_reservsz;
Word m_plt_shf_flags;
+ /* Section type of .eh_frame/.eh_frame_hdr sections */
+ Word m_sht_unwind;
+
Word m_dt_register;
} Target_mach;
@@ -134,6 +137,7 @@ typedef struct {
Word id_tlsbss;
Word id_unknown;
Word id_unwind;
+ Word id_unwindhdr;
Word id_user;
Word id_version;
} Target_machid;
@@ -218,26 +222,12 @@ typedef struct {
int (* ms_reg_enter)(Sym_desc *, Ofl_desc *);
} Target_machsym;
-/*
- * amd64 unwind header support
- *
- * These fields are allowed to be NULL for targets that do not support
- * amd64 unwind headers. If any of these fields are non-NULL, all of them are
- * required to be present (use empty stub routines if necessary).
- */
-typedef struct {
- uintptr_t (* uw_make_unwindhdr)(Ofl_desc *);
- uintptr_t (* uw_populate_unwindhdr)(Ofl_desc *);
- uintptr_t (* uw_append_unwind)(Os_desc *, Ofl_desc *);
-} Target_unwind;
-
typedef struct {
Target_mach t_m;
Target_machid t_id;
Target_nullfunc t_nf;
Target_machrel t_mr;
Target_machsym t_ms;
- Target_unwind t_uw;
} Target;
@@ -330,16 +320,17 @@ typedef struct {
/*
* Define Alist initialization sizes.
*/
-#define AL_CNT_IFL_GROUPS 20 /* ifl_groups initial alist count */
-#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_IFL_GROUPS 20 /* ifl_groups */
+#define AL_CNT_OFL_DTSFLTRS 4 /* ofl_dtsfltrs */
+#define AL_CNT_OFL_SYMFLTRS 20 /* ofl_symfltrs */
#define AL_CNT_OS_MSTRISDESCS 10 /* os_mstrisdescs */
#define AL_CNT_OS_RELISDESCS 100 /* os_relisdescs */
#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_SG_OSDESC 40 /* sg_osdescs */
+#define AL_CNT_SG_SECORDER 40 /* sg_secorder */
#define AL_CNT_STRMRGREL 500 /* ld_make_strmerge() reloc alist cnt */
#define AL_CNT_STRMRGSYM 20 /* ld_make_strmerge() sym alist cnt */
+#define AL_CNT_UNWIND 1 /* ofl_unwind */
/*
* Return codes for {tls|got}_fixups() routines
@@ -590,6 +581,9 @@ extern Sdf_desc *sdf_find(const char *, List *);
#define ld_targ ld64_targ
#define ld_targ_init_sparc ld64_targ_init_sparc
#define ld_targ_init_x86 ld64_targ_init_x86
+#define ld_unwind_make_hdr ld64_unwind_make_hdr
+#define ld_unwind_populate_hdr ld64_unwind_populate_hdr
+#define ld_unwind_register ld64_unwind_register
#define ld_vers_base ld64_vers_base
#define ld_vers_check_defs ld64_vers_check_defs
#define ld_vers_check_need ld64_vers_check_need
@@ -673,6 +667,9 @@ extern Sdf_desc *sdf_find(const char *, List *);
#define ld_targ ld32_targ
#define ld_targ_init_sparc ld32_targ_init_sparc
#define ld_targ_init_x86 ld32_targ_init_x86
+#define ld_unwind_make_hdr ld32_unwind_make_hdr
+#define ld_unwind_populate_hdr ld32_unwind_populate_hdr
+#define ld_unwind_register ld32_unwind_register
#define ld_vers_base ld32_vers_base
#define ld_vers_check_defs ld32_vers_check_defs
#define ld_vers_check_need ld32_vers_check_need
@@ -792,6 +789,10 @@ extern Target ld_targ;
extern const Target *ld_targ_init_sparc(void);
extern const Target *ld_targ_init_x86(void);
+extern uintptr_t ld_unwind_make_hdr(Ofl_desc *);
+extern uintptr_t ld_unwind_populate_hdr(Ofl_desc *);
+extern uintptr_t ld_unwind_register(Os_desc *, Ofl_desc *);
+
extern Ver_desc *ld_vers_base(Ofl_desc *);
extern uintptr_t ld_vers_check_defs(Ofl_desc *);
extern uintptr_t ld_vers_check_need(Ofl_desc *);
diff --git a/usr/src/cmd/sgs/libld/common/entry.c b/usr/src/cmd/sgs/libld/common/entry.c
index d06df73030..175b0ac342 100644
--- a/usr/src/cmd/sgs/libld/common/entry.c
+++ b/usr/src/cmd/sgs/libld/common/entry.c
@@ -23,7 +23,7 @@
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -53,9 +53,7 @@ typedef enum {
LD_DYN,
LD_DTRACE,
LD_TLS,
-#if defined(_ELF64)
- LD_UNWIND, /* (amd64-only) */
-#endif
+ LD_UNWIND,
LD_NOTE,
LD_EXTRA,
LD_NUM
@@ -138,11 +136,9 @@ static const Sg_desc sg_desc[LD_NUM] = {
SG_DESC_INIT(PT_TLS, PF_R, MSG_ORIG(MSG_ENT_TLS),
(FLG_SG_TYPE | FLG_SG_FLAGS)),
-#if defined(_ELF64)
- /* LD_UNWIND (amd64-only) */
+ /* LD_UNWIND */
SG_DESC_INIT(PT_SUNW_UNWIND, PF_R, MSG_ORIG(MSG_ENT_UNWIND),
(FLG_SG_TYPE | FLG_SG_FLAGS)),
-#endif
/* LD_NOTE */
SG_DESC_INIT(PT_NOTE, 0, MSG_ORIG(MSG_ENT_NOTE), FLG_SG_TYPE),
@@ -297,7 +293,6 @@ ld_ent_setup(Ofl_desc *ofl, Xword segalign)
switch (idx) {
case LD_LRODATA:
case LD_LDATA:
- case LD_UNWIND:
if ((ld_targ.t_m.m_mach != EM_AMD64))
continue;
}
diff --git a/usr/src/cmd/sgs/libld/common/files.c b/usr/src/cmd/sgs/libld/common/files.c
index 26700a1fed..63b3d565f0 100644
--- a/usr/src/cmd/sgs/libld/common/files.c
+++ b/usr/src/cmd/sgs/libld/common/files.c
@@ -555,7 +555,9 @@ static uintptr_t
process_progbits(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn,
Word ndx, int ident, Ofl_desc *ofl)
{
- int stab_index = 0;
+ int stab_index = 0;
+ Word is_flags = 0;
+ uintptr_t r;
/*
* Never include .stab.excl sections in any output file.
@@ -587,37 +589,93 @@ process_progbits(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn,
* our own version, so don't allow any input sections of these types to
* be added to the output section list (why a relocatable object would
* have a .plt or .got is a mystery, but stranger things have occurred).
+ *
+ * If there are any unwind sections, and this is a platform that uses
+ * SHT_PROGBITS for unwind sections, then set their ident to reflect
+ * that.
*/
if (ident) {
- if (shdr->sh_flags & SHF_TLS)
+ if (shdr->sh_flags & SHF_TLS) {
ident = ld_targ.t_id.id_tls;
- else if ((shdr->sh_flags & ~ALL_SHF_IGNORE) ==
- (SHF_ALLOC | SHF_EXECINSTR))
+ } else if ((shdr->sh_flags & ~ALL_SHF_IGNORE) ==
+ (SHF_ALLOC | SHF_EXECINSTR)) {
ident = ld_targ.t_id.id_text;
- else if (shdr->sh_flags & SHF_ALLOC) {
- if ((strcmp(name, MSG_ORIG(MSG_SCN_PLT)) == 0) ||
- (strcmp(name, MSG_ORIG(MSG_SCN_GOT)) == 0))
- ident = ld_targ.t_id.id_null;
- else if (stab_index) {
- /*
- * This is a work-around for x86 compilers that
- * have set SHF_ALLOC for the .stab.index
- * section.
- *
- * Because of this, make sure that the
- * .stab.index does not end up as the last
- * section in the text segment. Older linkers
- * can produce segmentation violations when they
- * strip (ld -s) against a shared object whose
- * last section in the text segment is a .stab.
- */
- ident = ld_targ.t_id.id_interp;
- } else
- ident = ld_targ.t_id.id_data;
+ } else if (shdr->sh_flags & SHF_ALLOC) {
+ int done = 0;
+
+ if (name[0] == '.') {
+ switch (name[1]) {
+ case 'e':
+ if ((ld_targ.t_m.m_sht_unwind ==
+ SHT_PROGBITS) &&
+ (strcmp(name,
+ MSG_ORIG(MSG_SCN_EHFRAME)) == 0)) {
+ ident = ld_targ.t_id.id_unwind;
+ is_flags = FLG_IS_EHFRAME;
+ done = 1;
+ }
+ break;
+ case 'g':
+ if (strcmp(name,
+ MSG_ORIG(MSG_SCN_GOT)) == 0) {
+ ident = ld_targ.t_id.id_null;
+ done = 1;
+ break;
+ }
+ if ((ld_targ.t_m.m_sht_unwind ==
+ SHT_PROGBITS)&&
+ (strcmp(name,
+ MSG_ORIG(MSG_SCN_GCC_X_TBL)) ==
+ 0)) {
+ ident = ld_targ.t_id.id_unwind;
+ done = 1;
+ break;
+ }
+ break;
+ case 'p':
+ if (strcmp(name,
+ MSG_ORIG(MSG_SCN_PLT)) == 0) {
+ ident = ld_targ.t_id.id_null;
+ done = 1;
+ }
+ break;
+ }
+ }
+ if (!done) {
+ if (stab_index) {
+ /*
+ * This is a work-around for x86
+ * compilers that have set SHF_ALLOC
+ * for the .stab.index section.
+ *
+ * Because of this, make sure that the
+ * .stab.index does not end up as the
+ * last section in the text segment.
+ * Older linkers can produce
+ * segmentation violations when they
+ * strip (ld -s) against a shared
+ * object whose last section in the
+ * text segment is a .stab.
+ */
+ ident = ld_targ.t_id.id_interp;
+ } else {
+ ident = ld_targ.t_id.id_data;
+ }
+ }
} else
ident = ld_targ.t_id.id_note;
}
- return (process_section(name, ifl, shdr, scn, ndx, ident, ofl));
+
+ r = process_section(name, ifl, shdr, scn, ndx, ident, ofl);
+
+ /*
+ * On success, process_section() creates an input section descriptor.
+ * Now that it exists, we can add any pending input section flags.
+ */
+ if ((is_flags != 0) && (r == 1))
+ ifl->ifl_isdesc[ndx]->is_flags |= is_flags;
+
+ return (r);
}
/*
@@ -1277,6 +1335,21 @@ process_dynamic(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
}
/*
+ * Process a progbits section from a relocatable object (ET_REL).
+ * This is used on non-amd64 objects to recognize .eh_frame sections.
+ */
+/*ARGSUSED1*/
+static uintptr_t
+process_progbits_final(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
+{
+ if (isc->is_osdesc && (isc->is_flags & FLG_IS_EHFRAME) &&
+ (ld_unwind_register(isc->is_osdesc, ofl) == S_ERROR))
+ return (S_ERROR);
+
+ return (1);
+}
+
+/*
* Process a group section.
*/
static uintptr_t
@@ -1415,8 +1488,10 @@ process_exclude(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn,
* procedure (ie. things that can only be done when all required sections
* have been collected).
*/
-static uintptr_t (*Initial[SHT_NUM][2])() = {
+typedef uintptr_t (* initial_func_t)(const char *, Ifl_desc *, Shdr *,
+ Elf_Scn *, Word, int, Ofl_desc *);
+static initial_func_t Initial[SHT_NUM][2] = {
/* ET_REL ET_DYN */
/* SHT_NULL */ invalid_section, invalid_section,
@@ -1440,10 +1515,13 @@ static uintptr_t (*Initial[SHT_NUM][2])() = {
/* SHT_SYMTAB_SHNDX */ process_sym_shndx, NULL
};
-static uintptr_t (*Final[SHT_NUM][2])() = {
+typedef uintptr_t (* final_func_t)(Is_desc *, Ifl_desc *, Ofl_desc *);
+
+static final_func_t Final[SHT_NUM][2] = {
+/* ET_REL ET_DYN */
/* SHT_NULL */ NULL, NULL,
-/* SHT_PROGBITS */ NULL, NULL,
+/* SHT_PROGBITS */ process_progbits_final, NULL,
/* SHT_SYMTAB */ ld_sym_process, ld_sym_process,
/* SHT_STRTAB */ NULL, NULL,
/* SHT_RELA */ rel_process, NULL,
@@ -1643,8 +1721,8 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
return (S_ERROR);
break;
case SHT_SUNW_cap:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
capisp = ifl->ifl_isdesc[ndx];
break;
@@ -1655,13 +1733,13 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
return (S_ERROR);
break;
case SHT_SUNW_move:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
break;
case SHT_SUNW_syminfo:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
sifisp = ifl->ifl_isdesc[ndx];
break;
@@ -1677,20 +1755,20 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
ifl->ifl_isdesc[ndx]->is_flags |= FLG_IS_COMDAT;
break;
case SHT_SUNW_verdef:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
vdfisp = ifl->ifl_isdesc[ndx];
break;
case SHT_SUNW_verneed:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
vndisp = ifl->ifl_isdesc[ndx];
break;
case SHT_SUNW_versym:
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_null, ofl) == S_ERROR)
return (S_ERROR);
vsyisp = ifl->ifl_isdesc[ndx];
break;
@@ -1704,9 +1782,8 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
if (ld_targ.t_m.m_mach !=
LD_TARG_BYCLASS(EM_SPARC, EM_SPARCV9))
goto do_default;
- if (process_section(name, ifl, shdr, scn,
- ndx, ld_targ.t_id.id_gotdata, ofl) ==
- S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ld_targ.t_id.id_gotdata, ofl) == S_ERROR)
return (S_ERROR);
break;
#if defined(_ELF64)
@@ -1732,15 +1809,17 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
scn, ndx, ld_targ.t_id.id_unwind,
ofl) == S_ERROR)
return (S_ERROR);
+ ifl->ifl_isdesc[ndx]->is_flags |=
+ FLG_IS_EHFRAME;
}
break;
#endif
default:
do_default:
- if (ident != ld_targ.t_id.id_null)
- ident = ld_targ.t_id.id_user;
- if (process_section(name, ifl, shdr, scn,
- ndx, ident, ofl) == S_ERROR)
+ if (process_section(name, ifl, shdr, scn, ndx,
+ ((ident == ld_targ.t_id.id_null) ?
+ ident : ld_targ.t_id.id_user), ofl) ==
+ S_ERROR)
return (S_ERROR);
break;
}
@@ -1935,9 +2014,7 @@ process_elf(Ifl_desc *ifl, Elf *elf, Ofl_desc *ofl)
* 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))
+ (ld_unwind_register(osp, ofl) == S_ERROR))
return (S_ERROR);
#endif
}
diff --git a/usr/src/cmd/sgs/libld/common/globals.c b/usr/src/cmd/sgs/libld/common/globals.c
index 51e81ad867..b1dd5ed72e 100644
--- a/usr/src/cmd/sgs/libld/common/globals.c
+++ b/usr/src/cmd/sgs/libld/common/globals.c
@@ -90,7 +90,7 @@ ldynsym_symtype[] = {
1, /* STT_FILE */
0, /* STT_COMMON */
0, /* STT_TLS */
- 0, /* 7 */
+ 0, /* STT_IFUNC */
0, /* 8 */
0, /* 9 */
0, /* 10 */
@@ -100,7 +100,7 @@ ldynsym_symtype[] = {
0, /* 14 */
0, /* 15 */
};
-#if STT_NUM != (STT_TLS + 1)
+#if STT_NUM != (STT_IFUNC + 1)
#error "STT_NUM has grown. Update ldynsym_symtype[]."
#endif
@@ -117,7 +117,7 @@ dynsymsort_symtype[] = {
0, /* STT_FILE */
1, /* STT_COMMON */
0, /* STT_TLS */
- 0, /* 7 */
+ 0, /* STT_IFUNC */
0, /* 8 */
0, /* 9 */
0, /* 10 */
@@ -127,6 +127,6 @@ dynsymsort_symtype[] = {
0, /* 14 */
0, /* 15 */
};
-#if STT_NUM != (STT_TLS + 1)
+#if STT_NUM != (STT_IFUNC + 1)
#error "STT_NUM has grown. Update dynsymsort_symtype[]."
#endif
diff --git a/usr/src/cmd/sgs/libld/common/ldmain.c b/usr/src/cmd/sgs/libld/common/ldmain.c
index 0f35378b11..e4f8fb731f 100644
--- a/usr/src/cmd/sgs/libld/common/ldmain.c
+++ b/usr/src/cmd/sgs/libld/common/ldmain.c
@@ -348,14 +348,11 @@ ld_main(int argc, char **argv, Half mach)
if (ld_reloc_process(ofl) == S_ERROR)
return (ld_exit(ofl));
-#if defined(_ELF64)
/*
- * Fill in contents for Unwind Header
+ * Fill in contents for unwind header (.eh_frame_hdr)
*/
- if ((ld_targ.t_uw.uw_populate_unwindhdr != NULL) &&
- ((*ld_targ.t_uw.uw_populate_unwindhdr)(ofl) == S_ERROR))
+ if (ld_unwind_populate_hdr(ofl) == S_ERROR)
return (ld_exit(ofl));
-#endif
/*
* Finally create the files elf checksum.
diff --git a/usr/src/cmd/sgs/libld/common/machrel.amd.c b/usr/src/cmd/sgs/libld/common/machrel.amd.c
index 151c29f9d3..a654c30c96 100644
--- a/usr/src/cmd/sgs/libld/common/machrel.amd.c
+++ b/usr/src/cmd/sgs/libld/common/machrel.amd.c
@@ -36,7 +36,6 @@
#include <i386/machdep_x86.h>
#include "msg.h"
#include "_libld.h"
-#include "unwind.amd.h"
/* Forward declarations */
@@ -1595,6 +1594,9 @@ ld_targ_init_x86(void)
M_PLT_RESERVSZ, /* m_plt_reservsz */
M_PLT_SHF_FLAGS, /* m_plt_shf_flags */
+ /* Section type of .eh_frame/.eh_frame_hdr sections */
+ SHT_AMD64_UNWIND, /* m_sht_unwind */
+
M_DT_REGISTER, /* m_dt_register */
},
{ /* Target_machid */
@@ -1626,6 +1628,7 @@ ld_targ_init_x86(void)
M_ID_TLSBSS, /* id_tlsbss */
M_ID_UNKNOWN, /* id_unknown */
M_ID_UNWIND, /* id_unwind */
+ M_ID_UNWINDHDR, /* id_unwindhdr */
M_ID_USER, /* id_user */
M_ID_VERSION, /* id_version */
},
@@ -1662,11 +1665,6 @@ ld_targ_init_x86(void)
NULL, /* ms_is_regsym */
NULL, /* ms_reg_find */
NULL /* ms_reg_enter */
- },
- { /* Target_unwind */
- make_amd64_unwindhdr, /* uw_make_unwindhdr */
- populate_amd64_unwindhdr, /* uw_populate_unwindhdr */
- append_amd64_unwind, /* uw_append_unwind */
}
};
diff --git a/usr/src/cmd/sgs/libld/common/machrel.intel.c b/usr/src/cmd/sgs/libld/common/machrel.intel.c
index 9de8c80fca..65f7c35c86 100644
--- a/usr/src/cmd/sgs/libld/common/machrel.intel.c
+++ b/usr/src/cmd/sgs/libld/common/machrel.intel.c
@@ -1670,6 +1670,9 @@ ld_targ_init_x86(void)
M_PLT_RESERVSZ, /* m_plt_reservsz */
M_PLT_SHF_FLAGS, /* m_plt_shf_flags */
+ /* Section type of .eh_frame/.eh_frame_hdr sections */
+ SHT_PROGBITS, /* m_sht_unwind */
+
M_DT_REGISTER, /* m_dt_register */
},
{ /* Target_machid */
@@ -1701,6 +1704,7 @@ ld_targ_init_x86(void)
M_ID_TLSBSS, /* id_tlsbss */
M_ID_UNKNOWN, /* id_unknown */
M_ID_UNWIND, /* id_unwind */
+ M_ID_UNWINDHDR, /* id_unwindhdr */
M_ID_USER, /* id_user */
M_ID_VERSION, /* id_version */
},
@@ -1737,11 +1741,6 @@ ld_targ_init_x86(void)
NULL, /* ms_is_regsym */
NULL, /* ms_reg_find */
NULL /* ms_reg_enter */
- },
- { /* Target_unwind */
- NULL, /* uw_make_unwindhdr */
- NULL, /* uw_populate_unwindhdr */
- NULL, /* uw_append_unwind */
}
};
diff --git a/usr/src/cmd/sgs/libld/common/machrel.sparc.c b/usr/src/cmd/sgs/libld/common/machrel.sparc.c
index 0d2774af8d..6f83983425 100644
--- a/usr/src/cmd/sgs/libld/common/machrel.sparc.c
+++ b/usr/src/cmd/sgs/libld/common/machrel.sparc.c
@@ -2247,6 +2247,9 @@ ld_targ_init_sparc(void)
M_PLT_RESERVSZ, /* m_plt_reservsz */
M_PLT_SHF_FLAGS, /* m_plt_shf_flags */
+ /* Section type of .eh_frame/.eh_frame_hdr sections */
+ SHT_PROGBITS, /* m_sht_unwind */
+
M_DT_REGISTER, /* m_dt_register */
},
{ /* Target_machid */
@@ -2277,7 +2280,8 @@ ld_targ_init_sparc(void)
M_ID_TLS, /* id_tls */
M_ID_TLSBSS, /* id_tlsbss */
M_ID_UNKNOWN, /* id_unknown */
- M_ID_UNKNOWN, /* id_unwind (unused) */
+ M_ID_UNWIND, /* id_unwind */
+ M_ID_UNWINDHDR, /* id_unwindhdr */
M_ID_USER, /* id_user */
M_ID_VERSION, /* id_version */
},
@@ -2314,11 +2318,6 @@ ld_targ_init_sparc(void)
ld_is_regsym_sparc, /* ms_is_regsym */
ld_reg_find_sparc, /* ms_reg_find */
ld_reg_enter_sparc /* ms_reg_enter */
- },
- { /* Target_unwind */
- NULL, /* uw_make_unwindhdr */
- NULL, /* uw_populate_unwindhdr */
- NULL, /* uw_append_unwind */
}
};
diff --git a/usr/src/cmd/sgs/libld/common/outfile.c b/usr/src/cmd/sgs/libld/common/outfile.c
index d3d735f3fa..6b52f0febc 100644
--- a/usr/src/cmd/sgs/libld/common/outfile.c
+++ b/usr/src/cmd/sgs/libld/common/outfile.c
@@ -456,12 +456,9 @@ ld_create_outfile(Ofl_desc *ofl)
} else if (ptype == PT_TLS) {
if (flags & FLG_OF_TLSPHDR)
nseg++;
-#if defined(_ELF64)
- } else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
- (ptype == PT_SUNW_UNWIND)) {
+ } else if (ptype == PT_SUNW_UNWIND) {
if (ofl->ofl_unwindhdr)
nseg++;
-#endif
} else if (ptype == PT_SUNWDTRACE) {
if (ofl->ofl_dtracesym)
nseg++;
diff --git a/usr/src/cmd/sgs/libld/common/sections.c b/usr/src/cmd/sgs/libld/common/sections.c
index a4cd691c3b..a8119ecb61 100644
--- a/usr/src/cmd/sgs/libld/common/sections.c
+++ b/usr/src/cmd/sgs/libld/common/sections.c
@@ -2771,11 +2771,8 @@ ld_make_sections(Ofl_desc *ofl)
return (S_ERROR);
if (make_dynsym(ofl) == S_ERROR)
return (S_ERROR);
-#if defined(_ELF64)
- if ((ld_targ.t_uw.uw_make_unwindhdr != NULL) &&
- ((*ld_targ.t_uw.uw_make_unwindhdr)(ofl) == S_ERROR))
+ if (ld_unwind_make_hdr(ofl) == S_ERROR)
return (S_ERROR);
-#endif
if (make_dynsort(ofl) == S_ERROR)
return (S_ERROR);
}
diff --git a/usr/src/cmd/sgs/libld/common/unwind.amd.h b/usr/src/cmd/sgs/libld/common/unwind.amd.h
deleted file mode 100644
index eeebb52182..0000000000
--- a/usr/src/cmd/sgs/libld/common/unwind.amd.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * amd64 unwind functionality
- */
-
-#ifndef _UNWIND_DOT_AMD_DOT_H
-#define _UNWIND_DOT_AMD_DOT_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern uintptr_t append_amd64_unwind(Os_desc *, Ofl_desc *);
-extern uintptr_t make_amd64_unwindhdr(Ofl_desc *);
-extern uintptr_t populate_amd64_unwindhdr(Ofl_desc *);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _UNWIND_DOT_AMD_DOT_H */
diff --git a/usr/src/cmd/sgs/libld/common/unwind.amd.c b/usr/src/cmd/sgs/libld/common/unwind.c
index 14bcd12245..b2263e1e55 100644
--- a/usr/src/cmd/sgs/libld/common/unwind.amd.c
+++ b/usr/src/cmd/sgs/libld/common/unwind.c
@@ -24,18 +24,14 @@
* Use is subject to license terms.
*/
-#define ELF_TARGET_AMD64
-
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sgs.h>
#include <debug.h>
-#include <i386/machdep_x86.h>
#include <_libld.h>
#include <dwarf.h>
#include <stdlib.h>
-#include "unwind.amd.h"
/*
* A EH_FRAME_HDR consists of the following:
@@ -112,16 +108,16 @@
* =================
*
* The call frame information needed for unwinding the stack is output in
- * an ELF section(s) of type SHT_AMD64_UNWIND. In the simplest case there
- * will be one such section per object file and it will be named
- * ".eh_frame". An .eh_frame section consists of one or more
+ * an ELF section(s) of type SHT_AMD64_UNWIND (amd64) or SHT_PROGBITS (other).
+ * In the simplest case there will be one such section per object file and it
+ * will be named ".eh_frame". An .eh_frame section consists of one or more
* subsections. Each subsection contains a CIE (Common Information Entry)
* followed by varying number of FDEs (Frame Descriptor Entry). A FDE
* corresponds to an explicit or compiler generated function in a
* compilation unit, all FDEs can access the CIE that begins their
* subsection for data.
*
- * If an object file contains C++ template instantiations there shall be
+ * If an object file contains C++ template instantiations, there shall be
* a separate CIE immediately preceding each FDE corresponding to an
* instantiation.
*
@@ -287,10 +283,28 @@
+static uint_t
+extract_uint(const uchar_t *data, uint64_t *ndx, int do_swap)
+{
+ uint_t r;
+ uchar_t *p = (uchar_t *)&r;
+
+ data += *ndx;
+ if (do_swap)
+ UL_ASSIGN_BSWAP_WORD(p, data);
+ else
+ UL_ASSIGN_WORD(p, data);
+
+ (*ndx) += 4;
+ return (r);
+}
+
/*
- * The job of this function is to determine how much space
- * will be required for the final table. We'll build
- * it later.
+ * Create an unwind header (.eh_frame_hdr) output section.
+ * The section is created and space reserved, but the data
+ * is not copied into place. That is done by a later call
+ * to ld_unwind_populate(), after active relocations have been
+ * processed.
*
* When GNU linkonce processing is in effect, we can end up in a situation
* where the FDEs related to discarded sections remain in the eh_frame
@@ -303,21 +317,22 @@
* where all FDEs are valid.
*/
uintptr_t
-make_amd64_unwindhdr(Ofl_desc *ofl)
+ld_unwind_make_hdr(Ofl_desc *ofl)
{
+ int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
Shdr *shdr;
Elf_Data *elfdata;
Is_desc *isp;
size_t size;
Xword fde_cnt;
- Listnode *lnp;
+ Aliste idx;
Os_desc *osp;
/*
* we only build a unwind header if we have
* some unwind information in the file.
*/
- if (ofl->ofl_unwind.head == NULL)
+ if (aplist_nitems(ofl->ofl_unwind) == 0)
return (1);
/*
@@ -326,7 +341,7 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
if ((elfdata = libld_calloc(sizeof (Elf_Data), 1)) == 0)
return (S_ERROR);
elfdata->d_type = ELF_T_BYTE;
- elfdata->d_align = M_WORD_ALIGN;
+ elfdata->d_align = ld_targ.t_m.m_word_align;
elfdata->d_version = ofl->ofl_dehdr->e_version;
/*
@@ -334,9 +349,9 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
*/
if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0)
return (S_ERROR);
- shdr->sh_type = SHT_AMD64_UNWIND;
+ shdr->sh_type = ld_targ.t_m.m_sht_unwind;
shdr->sh_flags = SHF_ALLOC;
- shdr->sh_addralign = M_WORD_ALIGN;
+ shdr->sh_addralign = ld_targ.t_m.m_word_align;
shdr->sh_entsize = 0;
/*
@@ -349,7 +364,7 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
isp->is_indata = elfdata;
if ((ofl->ofl_unwindhdr = ld_place_section(ofl, isp,
- M_ID_UNWINDHDR, 0)) == (Os_desc *)S_ERROR)
+ ld_targ.t_id.id_unwindhdr, 0)) == (Os_desc *)S_ERROR)
return (S_ERROR);
/*
@@ -358,7 +373,7 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
* in the binary search table.
*/
fde_cnt = 0;
- for (LIST_TRAVERSE(&ofl->ofl_unwind, lnp, osp)) {
+ for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, osp)) {
Listnode *_lnp;
for (LIST_TRAVERSE(&osp->os_isdescs, _lnp, isp)) {
@@ -370,7 +385,7 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
while (off < size) {
uint_t length, id;
- uint64_t ndx;
+ uint64_t ndx = 0;
/*
* Extract length in lsb format. A zero length
@@ -378,15 +393,14 @@ make_amd64_unwindhdr(Ofl_desc *ofl)
* that processing for unwind information is
* complete.
*/
- if ((length = LSB32EXTRACT(data + off)) == 0)
+ length = extract_uint(data + off, &ndx, bswap);
+ if (length == 0)
break;
/*
* Extract CIE id in lsb format.
*/
- ndx = 4;
- id = LSB32EXTRACT(data + off + ndx);
- ndx += 4;
+ id = extract_uint(data + off, &ndx, bswap);
/*
* A CIE record has a id of '0', otherwise
@@ -470,12 +484,12 @@ bintabcompare(const void *p1, const void *p2)
}
uintptr_t
-populate_amd64_unwindhdr(Ofl_desc *ofl)
+ld_unwind_populate_hdr(Ofl_desc *ofl)
{
uchar_t *hdrdata;
uint_t *binarytable;
uint_t hdroff;
- Listnode *lnp;
+ Aliste idx;
Addr hdraddr;
Os_desc *hdrosp;
Os_desc *osp;
@@ -524,7 +538,7 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
first_unwind = 0;
fde_count = 0;
- for (LIST_TRAVERSE(&ofl->ofl_unwind, lnp, osp)) {
+ for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, osp)) {
uchar_t *data;
size_t size;
uint64_t off = 0;
@@ -544,22 +558,21 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
while (off < size) {
uint_t length, id;
- uint64_t ndx;
+ uint64_t ndx = 0;
/*
* Extract length in lsb format. A zero length
* indicates that this CIE is a terminator and that
* processing of unwind information is complete.
*/
- if ((length = LSB32EXTRACT(data + off)) == 0)
+ length = extract_uint(data + off, &ndx, bswap);
+ if (length == 0)
goto done;
/*
* Extract CIE id in lsb format.
*/
- ndx = 4;
- id = LSB32EXTRACT(data + off + ndx);
- ndx += 4;
+ id = extract_uint(data + off, &ndx, bswap);
/*
* A CIE record has a id of '0'; otherwise
@@ -627,7 +640,7 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
&data[off + ndx],
&ndx, ciePflag,
ofl->ofl_dehdr->e_ident,
- shdr->sh_addr + off + ndx);
+ shdr->sh_addr, off + ndx);
break;
case 'R':
/* code encoding */
@@ -648,7 +661,7 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
initloc = dwarf_ehe_extract(&data[off],
&ndx, cieRflag, ofl->ofl_dehdr->e_ident,
- shdr->sh_addr + off + ndx);
+ shdr->sh_addr, off + ndx);
/*
* Ignore FDEs with initloc set to 0.
@@ -686,7 +699,7 @@ populate_amd64_unwindhdr(Ofl_desc *ofl)
done:
/*
- * Do a quick sort on the binary table. If this is a cross
+ * Do a quicksort on the binary table. If this is a cross
* link from a system with the opposite byte order, xlate
* the resulting values into LSB order.
*/
@@ -710,7 +723,7 @@ done:
/* LINTED */
uint_ptr = (uint_t *)(&hdrdata[hdroff]);
*uint_ptr = first_unwind->os_shdr->sh_addr -
- hdrosp->os_shdr->sh_addr + hdroff;
+ (hdrosp->os_shdr->sh_addr + hdroff);
if (bswap)
*uint_ptr = ld_bswap_Word(*uint_ptr);
@@ -724,7 +737,7 @@ done:
/*
* If relaxed relocations are active, then there is a chance
* that we didn't use all the space reserved for this section.
- * For details, see the note at head of make_amd64_unwindhdr() above.
+ * For details, see the note at head of ld_unwind_make_hdr() above.
*
* Find the PT_SUNW_UNWIND program header, and change the size values
* to the size of the subset of the section that was actually used.
@@ -745,23 +758,34 @@ done:
return (1);
}
+/*
+ * Append an .eh_frame section to our output list if not already present.
+ *
+ * Usually, there is a single .eh_frame output section. However, there can
+ * be more if there are incompatible section flags on incoming sections.
+ * If this does happen, the frame_ptr field of the eh_frame_hdr section
+ * will point at the base of the first output section, and the other
+ * sections will not be accessible via frame_ptr. However, the .eh_frame_hdr
+ * will be able to access all the data in the different .eh_frame sections,
+ * because the entries in sorted table are all encoded as DW_EH_PE_datarel.
+ */
uintptr_t
-append_amd64_unwind(Os_desc *osp, Ofl_desc * ofl)
+ld_unwind_register(Os_desc *osp, Ofl_desc * ofl)
{
- Listnode *lnp;
- Os_desc *_osp;
+ Aliste idx;
+ Os_desc *_osp;
/*
* Check to see if this output section is already
* on the list.
*/
- for (LIST_TRAVERSE(&ofl->ofl_unwind, lnp, _osp))
+ for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, _osp))
if (osp == _osp)
return (1);
/*
* Append output section to unwind list
*/
- if (list_appendc(&ofl->ofl_unwind, osp) == 0)
+ if (aplist_append(&ofl->ofl_unwind, osp, AL_CNT_UNWIND) == NULL)
return (S_ERROR);
return (1);
}
diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c
index 63dda77127..7ee234fbf6 100644
--- a/usr/src/cmd/sgs/libld/common/update.c
+++ b/usr/src/cmd/sgs/libld/common/update.c
@@ -3383,17 +3383,15 @@ ld_update_outfile(Ofl_desc *ofl)
}
/*
- * As the AMD unwind program header occurs after the loadable
- * headers in the segment descriptor table, all the address
- * information for the .eh_frame output section will have been
- * figured out by now.
+ * As the unwind (.eh_frame_hdr) program header occurs after
+ * the loadable headers in the segment descriptor table, all
+ * the address information for the .eh_frame output section
+ * will have been figured out by now.
*/
-#if defined(_ELF64)
- if ((ld_targ.t_m.m_mach == EM_AMD64) &&
- (phdr->p_type == PT_SUNW_UNWIND)) {
+ if (phdr->p_type == PT_SUNW_UNWIND) {
Shdr *shdr;
- if (ofl->ofl_unwindhdr == 0)
+ if (ofl->ofl_unwindhdr == NULL)
continue;
shdr = ofl->ofl_unwindhdr->os_shdr;
@@ -3408,7 +3406,7 @@ ld_update_outfile(Ofl_desc *ofl)
ofl->ofl_phdr[phdrndx++] = *phdr;
continue;
}
-#endif
+
/*
* As the TLS program header occurs after the loadable
* headers in the segment descriptor table, all the address