# HG changeset patch # User Bryan Cantrill # Date 1348153502 0 # Node ID 8a85b2c3d89b8d32f68ff1110532baa58d1d1c8b # Parent f77936ab6455b14d5dd060fb4429024db48a0a0c 3210 ld should tolerate SHT_PROGBITS for .eh_frame sections on amd64 Reviewed by: Robert Mustacchi Reviewed by: Garrett D'Amore Reviewed by: Eric Schrock Reviewed by: Igor Kozhukhov Approved by: Richard Lowe diff -r f77936ab6455 -r 8a85b2c3d89b usr/src/cmd/sgs/libld/common/files.c --- a/usr/src/cmd/sgs/libld/common/files.c Mon Sep 03 21:55:26 2012 -0500 +++ b/usr/src/cmd/sgs/libld/common/files.c Thu Sep 20 15:05:02 2012 +0000 @@ -24,6 +24,7 @@ * All Rights Reserved * * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ /* @@ -1428,6 +1429,7 @@ * are updated as necessary to reflect the changes. Returns TRUE * for success, FALSE for failure. */ +/*ARGSUSED*/ inline static Boolean process_progbits_alloc(const char *name, Ifl_desc *ifl, Shdr *shdr, Word ndx, int *ident, Ofl_desc *ofl, Boolean is_stab_index, @@ -1436,8 +1438,6 @@ Boolean done = FALSE; if (name[0] == '.') { - Conv_inv_buf_t inv_buf1, inv_buf2; - switch (name[1]) { case 'e': if (!is_name_cmp(name, MSG_ORIG(MSG_SCN_EHFRAME), @@ -1449,21 +1449,32 @@ done = TRUE; /* - * Only accept a progbits .eh_frame on a platform - * for which this is the expected type. + * Historically, the section containing the logic to + * unwind stack frames -- the .eh_frame section -- was + * of type SHT_PROGBITS. Apparently the most + * aesthetically galling aspect of this was not the + * .eh_frame section's dubious purpose or its filthy + * implementation, but rather its section type; with the + * introduction of the AMD64 ABI, a new section header + * type (SHT_AMD64_UNWIND) was introduced for (and + * dedicated to) this section. When both the Sun + * compilers and the GNU compilers had been modified to + * generate this new section type, the linker became + * much more pedantic about .eh_frame: it refused to + * link an AMD64 object that contained a .eh_frame with + * the legacy SHT_PROGBITS. That this was too fussy is + * evidenced by searching the net for the error message + * that it generated ("section type is SHT_PROGBITS: + * expected SHT_AMD64_UNWIND"), which reveals a myriad + * of problems, including legacy objects, hand-coded + * assembly and otherwise cross-platform objects + * created on other platforms (the GNU toolchain was + * only modified to create the new section type on + * Solaris and derivatives). We therefore always accept + * a .eh_frame of SHT_PROGBITS -- regardless of + * m_sht_unwind. */ - if (ld_targ.t_m.m_sht_unwind == SHT_PROGBITS) - break; - ld_eprintf(ofl, ERR_FATAL, - MSG_INTL(MSG_FIL_EXEHFRMTYP), ifl->ifl_name, - EC_WORD(ndx), name, - conv_sec_type(ifl->ifl_ehdr->e_ident[EI_OSABI], - ifl->ifl_ehdr->e_machine, shdr->sh_type, - CONV_FMT_ALT_CF, &inv_buf1), - conv_sec_type(ifl->ifl_ehdr->e_ident[EI_OSABI], - ifl->ifl_ehdr->e_machine, ld_targ.t_m.m_sht_unwind, - CONV_FMT_ALT_CF, &inv_buf2)); - return (FALSE); + break; case 'g': if (is_name_cmp(name, MSG_ORIG(MSG_SCN_GOT), MSG_SCN_GOT_SIZE)) { diff -r f77936ab6455 -r 8a85b2c3d89b usr/src/cmd/sgs/libld/common/libld.msg --- a/usr/src/cmd/sgs/libld/common/libld.msg Mon Sep 03 21:55:26 2012 -0500 +++ b/usr/src/cmd/sgs/libld/common/libld.msg Thu Sep 20 15:05:02 2012 +0000 @@ -419,8 +419,6 @@ @ MSG_FIL_BADORDREF "file %s: section [%u]%s: contains illegal reference \ to discarded section: [%u]%s" -@ MSG_FIL_EXEHFRMTYP "file %s: section [%u]%s: section type is %s: \ - expected %s" # Recording name conflicts diff -r f77936ab6455 -r 8a85b2c3d89b usr/src/cmd/sgs/libld/common/place.c --- a/usr/src/cmd/sgs/libld/common/place.c Mon Sep 03 21:55:26 2012 -0500 +++ b/usr/src/cmd/sgs/libld/common/place.c Thu Sep 20 15:05:02 2012 +0000 @@ -24,6 +24,7 @@ * All Rights Reserved * * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ /* @@ -978,6 +979,7 @@ * Section types are considered to match if any one of * the following are true: * - The type codes are the same + * - Both are .eh_frame sections (regardless of type code) * - The input section is COMDAT, and the output section * is SHT_PROGBITS. */ @@ -987,6 +989,7 @@ (shdr->sh_type != SHT_GROUP) && (shdr->sh_type != SHT_SUNW_dof) && ((shdr->sh_type == os_shdr->sh_type) || + (is_ehframe && (osp->os_flags & FLG_OS_EHFRAME)) || ((shdr->sh_type == SHT_SUNW_COMDAT) && (os_shdr->sh_type == SHT_PROGBITS))) && ((shflags & ~shflagmask) == @@ -1132,9 +1135,19 @@ return ((Os_desc *)S_ERROR); } ofl->ofl_flags |= FLG_OF_EHFRAME; + + /* + * For .eh_frame sections, we always set the type to be the + * type specified by the ABI. This allows .eh_frame sections + * of type SHT_PROGBITS to be correctly merged with .eh_frame + * sections of the ABI-defined type (e.g. SHT_AMD64_UNWIND), + * with the output being of the ABI-defined type. + */ + osp->os_shdr->sh_type = ld_targ.t_m.m_sht_unwind; + } else { + osp->os_shdr->sh_type = shdr->sh_type; } - 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 = oname; diff -r f77936ab6455 -r 8a85b2c3d89b usr/src/uts/common/sys/elf_amd64.h --- a/usr/src/uts/common/sys/elf_amd64.h Mon Sep 03 21:55:26 2012 -0500 +++ b/usr/src/uts/common/sys/elf_amd64.h Thu Sep 20 15:05:02 2012 +0000 @@ -118,7 +118,7 @@ * processor specific section types */ #define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ - +#define SHT_X86_64_UNWIND SHT_AMD64_UNWIND /* * NOTE: PT_SUNW_UNWIND is defined in the OS specific range