changeset 13830:8a85b2c3d89b

3210 ld should tolerate SHT_PROGBITS for .eh_frame sections on amd64 Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Bryan Cantrill <bryan@joyent.com>
date Thu, 20 Sep 2012 15:05:02 +0000
parents f77936ab6455
children df991d875843
files usr/src/cmd/sgs/libld/common/files.c usr/src/cmd/sgs/libld/common/libld.msg usr/src/cmd/sgs/libld/common/place.c usr/src/uts/common/sys/elf_amd64.h
diffstat 4 files changed, 42 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- 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)) {
--- 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
--- 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;
--- 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