diff options
author | Ali Bahrami <Ali.Bahrami@Sun.COM> | 2009-03-18 13:28:28 -0600 |
---|---|---|
committer | Ali Bahrami <Ali.Bahrami@Sun.COM> | 2009-03-18 13:28:28 -0600 |
commit | 7e16fca05dfbcfd32c2ebc9e4d1abdac1cd8657c (patch) | |
tree | 5033ac748bcd6544a0981e069919df2d213acead /usr/src/cmd/sgs/libld/common | |
parent | c13e065d8ffc8eafc02caf1091e66e146a2b2ce4 (diff) | |
download | illumos-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.XLINK | 7 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/_libld.h | 39 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/entry.c | 11 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/files.c | 177 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/globals.c | 8 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/ldmain.c | 7 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/machrel.amd.c | 10 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/machrel.intel.c | 9 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/machrel.sparc.c | 11 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/outfile.c | 5 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/sections.c | 5 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libld/common/unwind.amd.h | 49 | ||||
-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.c | 16 |
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 |