Skip to content

Commit

Permalink
OS-1551 ld should tolerate SHT_PROGBITS for .eh_frame sections on amd64
Browse files Browse the repository at this point in the history
  • Loading branch information
bcantrill committed Sep 20, 2012
1 parent e1c569f commit 204e460
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 18 deletions.
40 changes: 26 additions & 14 deletions usr/src/cmd/sgs/libld/common/files.c
Expand Up @@ -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.
*/

/*
Expand Down Expand Up @@ -1449,21 +1450,32 @@ process_progbits_alloc(const char *name, Ifl_desc *ifl, Shdr *shdr,
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)) {
Expand Down
2 changes: 0 additions & 2 deletions usr/src/cmd/sgs/libld/common/libld.msg
Expand Up @@ -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
Expand Down
15 changes: 14 additions & 1 deletion usr/src/cmd/sgs/libld/common/place.c
Expand Up @@ -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.
*/

/*
Expand Down Expand Up @@ -978,6 +979,7 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, Place_path_info *path_info,
* 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.
*/
Expand All @@ -987,6 +989,7 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, Place_path_info *path_info,
(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) ==
Expand Down Expand Up @@ -1132,9 +1135,19 @@ ld_place_section(Ofl_desc *ofl, Is_desc *isp, Place_path_info *path_info,
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;
Expand Down
2 changes: 1 addition & 1 deletion usr/src/uts/common/sys/elf_amd64.h
Expand Up @@ -118,7 +118,7 @@ extern "C" {
* 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
Expand Down

0 comments on commit 204e460

Please sign in to comment.