--- old/usr/src/cmd/sgs/elfdump/common/_elfdump.h	2012-10-11 22:38:17.251396003 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/_elfdump.h	2012-10-11 22:38:17.268357129 -0400
@@ -224,7 +224,7 @@
 
 extern	corenote_ret_t	corenote(Half, int, Word, const char *, Word);
 extern	void	dump_eh_frame(uchar_t *, size_t, uint64_t, Half e_machine,
-		    uchar_t *e_ident);
+		    uchar_t *e_ident, uint64_t gotaddr);
 extern	void	dump_hex_bytes(const void *, size_t, int, int, int);
 
 extern	int	fake_shdr_cache32(const char *, int, Elf *, Elf32_Ehdr *,
--- old/usr/src/cmd/sgs/elfdump/common/dwarf.c	2012-10-11 22:38:17.846136310 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/dwarf.c	2012-10-11 22:38:17.857886786 -0400
@@ -49,6 +49,7 @@
 	uint64_t	ciecalign;	/* CIE code align factor */
 	int64_t		ciedalign;	/* CIE data align factor */
 	uint64_t	fdeinitloc;	/* FDE initial location */
+	uint64_t	gotaddr;	/* Address of the GOT */
 } dump_cfi_state_t;
 
 
@@ -301,8 +302,8 @@
 
 		case 0x01:		/* v2: DW_CFA_set_loc, address */
 			cur_pc = dwarf_ehe_extract(&data[off], ndx,
-			    state->cieRflag, state->e_ident,
-			    state->sh_addr, off + *ndx);
+			    state->cieRflag, state->e_ident, B_FALSE,
+			    state->sh_addr, off + *ndx, state->gotaddr);
 			dbg_print(0, MSG_ORIG(MSG_CFA_CFASET), PREFIX,
 			    EC_XWORD(cur_pc));
 			break;
@@ -465,7 +466,7 @@
 
 void
 dump_eh_frame(uchar_t *data, size_t datasize, uint64_t sh_addr,
-    Half e_machine, uchar_t *e_ident)
+    Half e_machine, uchar_t *e_ident, uint64_t gotaddr)
 {
 	Conv_dwarf_ehe_buf_t	dwarf_ehe_buf;
 	dump_cfi_state_t	cfi_state;
@@ -479,6 +480,7 @@
 	cfi_state.e_ident = e_ident;
 	cfi_state.sh_addr = sh_addr;
 	cfi_state.do_swap = _elf_sys_encoding() != e_ident[EI_DATA];
+	cfi_state.gotaddr = gotaddr;
 
 	off = 0;
 	while (off < datasize) {
@@ -568,8 +570,8 @@
 					ndx += 1;
 
 					persVal = dwarf_ehe_extract(&data[off],
-					    &ndx, ciePflag, e_ident,
-					    sh_addr, off + ndx);
+					    &ndx, ciePflag, e_ident, B_FALSE,
+					    sh_addr, off + ndx, gotaddr);
 					dbg_print(0,
 					    MSG_ORIG(MSG_UNW_CIEAXPERS));
 					dbg_print(0,
@@ -633,11 +635,11 @@
 			    fdelength, fdecieptr);
 
 			cfi_state.fdeinitloc = dwarf_ehe_extract(&data[off],
-			    &ndx, cfi_state.cieRflag, e_ident,
-			    sh_addr, off + ndx);
+			    &ndx, cfi_state.cieRflag, e_ident, B_FALSE,
+			    sh_addr, off + ndx, gotaddr);
 			fdeaddrrange = dwarf_ehe_extract(&data[off], &ndx,
 			    (cfi_state.cieRflag & ~DW_EH_PE_pcrel),
-			    e_ident, sh_addr, off + ndx);
+			    e_ident, B_FALSE, sh_addr, off + ndx, gotaddr);
 
 			dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
 			    EC_XWORD(cfi_state.fdeinitloc),
@@ -660,7 +662,8 @@
 
 					lsda = dwarf_ehe_extract(&data[off],
 					    &lndx, cieLflag, e_ident,
-					    sh_addr, off + lndx);
+					    B_FALSE, sh_addr, off + lndx,
+					    gotaddr);
 					dbg_print(0,
 					    MSG_ORIG(MSG_UNW_FDEAXLSDA),
 					    EC_XWORD(lsda));
--- old/usr/src/cmd/sgs/elfdump/common/elfdump.c	2012-10-11 22:38:18.290283689 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/elfdump.c	2012-10-11 22:38:18.302755464 -0400
@@ -532,7 +532,7 @@
  *	flags - Command line option flags
  */
 static void
-unwind_eh_frame(Cache *cache, Word shndx, Phdr *uphdr, Ehdr *ehdr,
+unwind_eh_frame(Cache *cache, Word shndx, Word shnum, Phdr *uphdr, Ehdr *ehdr,
     gnu_eh_state_t *eh_state, uchar_t osabi, const char *file, uint_t flags)
 {
 #if	defined(_ELF64)
@@ -551,7 +551,16 @@
 	uint64_t		ndx, frame_ptr, fde_cnt, tabndx;
 	uint_t			vers, frame_ptr_enc, fde_cnt_enc, table_enc;
 	uint64_t		initloc, initloc0;
+	uint64_t		gotaddr = 0;
+	int			cnt;
 
+	for (cnt = 1; cnt < shnum; cnt++) {
+		if (strncmp(cache[cnt].c_name, MSG_ORIG(MSG_ELF_GOT),
+		    MSG_ELF_GOT_SIZE) == 0) {
+			gotaddr = cache[cnt].c_shdr->sh_addr;
+			break;
+		}
+	}
 
 	/*
 	 * Is this a .eh_frame_hdr?
@@ -578,7 +587,7 @@
 		dbg_print(0, MSG_ORIG(MSG_UNW_FRMVERS), vers);
 
 		frame_ptr = dwarf_ehe_extract(data, &ndx, frame_ptr_enc,
-		    ehdr->e_ident, shdr->sh_addr, ndx);
+		    ehdr->e_ident, B_TRUE, shdr->sh_addr, ndx, gotaddr);
 		if (eh_state->hdr_cnt == 1) {
 			eh_state->hdr_ndx = shndx;
 			eh_state->frame_ptr = frame_ptr;
@@ -589,7 +598,7 @@
 		    EC_XWORD(frame_ptr));
 
 		fde_cnt = dwarf_ehe_extract(data, &ndx, fde_cnt_enc,
-		    ehdr->e_ident, shdr->sh_addr, ndx);
+		    ehdr->e_ident, B_TRUE, shdr->sh_addr, ndx, gotaddr);
 
 		dbg_print(0, MSG_ORIG(MSG_UNW_FDCNENC),
 		    conv_dwarf_ehe(fde_cnt_enc, &dwarf_ehe_buf),
@@ -601,7 +610,7 @@
 
 		for (tabndx = 0; tabndx < fde_cnt; tabndx++) {
 			initloc = dwarf_ehe_extract(data, &ndx, table_enc,
-			    ehdr->e_ident, shdr->sh_addr, ndx);
+			    ehdr->e_ident, B_TRUE, shdr->sh_addr, ndx, gotaddr);
 			/*LINTED:E_VAR_USED_BEFORE_SET*/
 			if ((tabndx != 0) && (initloc0 > initloc))
 				(void) fprintf(stderr,
@@ -610,8 +619,8 @@
 			dbg_print(0, MSG_ORIG(MSG_UNW_BINSRTABENT),
 			    EC_XWORD(initloc),
 			    EC_XWORD(dwarf_ehe_extract(data, &ndx,
-			    table_enc, ehdr->e_ident, shdr->sh_addr,
-			    ndx)));
+			    table_enc, ehdr->e_ident, B_TRUE, shdr->sh_addr,
+			    ndx, gotaddr)));
 			initloc0 = initloc;
 		}
 	} else {		/* Display the .eh_frame section */
@@ -628,7 +637,7 @@
 			    conv_ehdr_type(osabi, ehdr->e_type, 0, &inv_buf));
 		}
 		dump_eh_frame(data, datasize, shdr->sh_addr,
-		    ehdr->e_machine, ehdr->e_ident);
+		    ehdr->e_machine, ehdr->e_ident, gotaddr);
 	}
 
 	/*
@@ -875,8 +884,8 @@
 			unwind_exception_ranges(_cache, file,
 			    _elf_sys_encoding() != ehdr->e_ident[EI_DATA]);
 		else
-			unwind_eh_frame(cache, cnt, uphdr, ehdr, &eh_state,
-			    osabi, file, flags);
+			unwind_eh_frame(cache, cnt, shnum, uphdr, ehdr,
+			    &eh_state, osabi, file, flags);
 	}
 }
 
--- old/usr/src/cmd/sgs/include/dwarf.h	2012-10-11 22:38:19.045336914 -0400
+++ new/usr/src/cmd/sgs/include/dwarf.h	2012-10-11 22:38:19.058013475 -0400
@@ -232,6 +232,8 @@
 #define	DW_EH_PE_datarel	0x30	/* Value is reletive to the beginning */
 					/*  of the eh_frame_hdr segment */
 					/*  ( segment type PT_AMD64_UNWIND ) */
+					/*  when within that segment, or to */
+					/*  the GOT when without. */
 #define	DW_EH_PE_funcrel	0x40
 #define	DW_EH_PE_aligned	0x50	/* value is an aligned void* */
 #define	DW_EH_PE_indirect	0x80	/* bit to signal indirection after */
@@ -251,7 +253,8 @@
 extern	uint64_t	uleb_extract(unsigned char *, uint64_t *);
 extern	int64_t		sleb_extract(unsigned char *, uint64_t *);
 extern	uint64_t	dwarf_ehe_extract(unsigned char *, uint64_t *,
-			    uint_t, unsigned char *, uint64_t, uint64_t);
+			    uint_t, unsigned char *, boolean_t, uint64_t,
+			    uint64_t, uint64_t);
 
 #ifdef	__cplusplus
 }
--- old/usr/src/cmd/sgs/libld/common/unwind.c	2012-10-11 22:38:19.457202684 -0400
+++ new/usr/src/cmd/sgs/libld/common/unwind.c	2012-10-11 22:38:19.469780013 -0400
@@ -639,8 +639,8 @@
 					    (void) dwarf_ehe_extract(
 						&data[off + ndx],
 						&ndx, ciePflag,
-						ofl->ofl_dehdr->e_ident,
-						shdr->sh_addr, off + ndx);
+						ofl->ofl_dehdr->e_ident, B_FALSE,
+						shdr->sh_addr, off + ndx, 0);
 					    break;
 					case 'R':
 					    /* code encoding */
@@ -658,10 +658,17 @@
 				uint_t	    bintabndx;
 				uint64_t    initloc;
 				uint64_t    fdeaddr;
+				uint64_t    gotaddr = 0;
+
+				if (ofl->ofl_osgot != NULL)
+					gotaddr =
+					    ofl->ofl_osgot->os_shdr->sh_addr;
 
 				initloc = dwarf_ehe_extract(&data[off],
 				    &ndx, cieRflag, ofl->ofl_dehdr->e_ident,
-				    shdr->sh_addr, off + ndx);
+				    B_FALSE,
+				    shdr->sh_addr, off + ndx,
+				    gotaddr);
 
 				/*
 				 * Ignore FDEs with initloc set to 0.
--- old/usr/src/cmd/sgs/packages/common/SUNWonld-README	2012-10-11 22:38:19.901607198 -0400
+++ new/usr/src/cmd/sgs/packages/common/SUNWonld-README	2012-10-11 22:38:19.914236222 -0400
@@ -1631,3 +1631,4 @@
 ================================================================================
 
 308     ld may misalign sections only preceded by empty sections
+3265	link-editor builds bogus .eh_frame_hdr on ia32
--- old/usr/src/cmd/sgs/tools/common/leb128.c	2012-10-11 22:38:20.423160716 -0400
+++ new/usr/src/cmd/sgs/tools/common/leb128.c	2012-10-11 22:38:20.434487672 -0400
@@ -195,7 +195,8 @@
  */
 uint64_t
 dwarf_ehe_extract(unsigned char *data, uint64_t *dotp, uint_t ehe_flags,
-    unsigned char *eident, uint64_t sh_base, uint64_t sh_offset)
+    unsigned char *eident, boolean_t frame_hdr, uint64_t sh_base,
+    uint64_t sh_offset, uint64_t dbase)
 {
 	uint64_t    dot = *dotp;
 	uint_t	    lsb;
@@ -281,17 +282,27 @@
 	/*
 	 * If value is relative to a base address, adjust it
 	 */
-	if (result) {
-		switch (ehe_flags & 0xf0) {
-		case DW_EH_PE_pcrel:
-			result += sh_base + sh_offset;
-			break;
+	switch (ehe_flags & 0xf0) {
+	case DW_EH_PE_pcrel:
+		result += sh_base + sh_offset;
+		break;
 
-		case DW_EH_PE_datarel:
+	/*
+	 * datarel is relative to .eh_frame_hdr if within .eh_frame,
+	 * but GOT if not.
+	 */
+	case DW_EH_PE_datarel:
+		if (frame_hdr)
 			result += sh_base;
-			break;
-		}
+		else
+			result += dbase;
+		break;
 	}
+
+	/* Truncate the result to its specified size */
+	result = (result << ((sizeof (uint64_t) - fsize) * 8)) >>
+	    ((sizeof (uint64_t) - fsize) * 8);
+
 	*dotp = dot;
 	return (result);
 }
--- old/usr/src/head/link.h	2012-10-11 22:38:20.910809202 -0400
+++ new/usr/src/head/link.h	2012-10-11 22:38:20.922349311 -0400
@@ -28,7 +28,7 @@
 #include <sys/link.h>
 
 #ifndef _ASM
-#include <libelf.h>
+#include <elf.h>
 #include <sys/types.h>
 #include <dlfcn.h>
 #endif
@@ -39,9 +39,14 @@
 
 #ifndef _ASM
 /*
- * ld support library calls
+ * ld support library calls.
+ *
+ * These cannot be used in a 32bit large file capable environment,
+ * thanks to the use of libelf.
  */
+#if !defined(_ILP32) || _FILE_OFFSET_BITS != 64
 #ifdef __STDC__
+#include <libelf.h>
 extern uint_t	ld_version(uint_t);
 extern void	ld_input_done(uint_t *);
 
@@ -88,6 +93,7 @@
 
 #endif /* (defined(_LP64) || defined(_LONGLONG_TYPE) */
 #endif /* __STDC__ */
+#endif /* !defined(_ILP32) || _FILE_OFFSET_BITS != 64 */
 
 /*
  * ld_version() version values.
