changeset 6206:6b0ed502a8e7

PSARC 2008/179 cross link-editor 6671255 link-editor should support cross linking
author ab196087
date Tue, 18 Mar 2008 09:17:00 -0700
parents 3c724f3b4616
children d65deea051cd
files deleted_files/usr/src/cmd/sgs/libld/common/libld.chk.msg deleted_files/usr/src/cmd/sgs/libld/common/machsym.intel.c deleted_files/usr/src/uts/intel/amd64/krtld/relmach.h deleted_files/usr/src/uts/intel/ia32/krtld/relmach.h deleted_files/usr/src/uts/sparc/krtld/relmach.h deleted_files/usr/src/uts/sparc/sys/machelf.h usr/src/cmd/sgs/crle/common/lintsup.c usr/src/cmd/sgs/crle/inc.flg usr/src/cmd/sgs/dump/common/dump.c usr/src/cmd/sgs/elfdump/common/_elfdump.h usr/src/cmd/sgs/elfdump/common/elfdump.c usr/src/cmd/sgs/elfdump/common/elfdump.msg usr/src/cmd/sgs/elfdump/common/fake_shdr.c usr/src/cmd/sgs/elfedit/common/elfconst.c usr/src/cmd/sgs/elfedit/common/elfedit.msg usr/src/cmd/sgs/elfedit/common/elfedit_machelf.c usr/src/cmd/sgs/elfedit/common/sys.c usr/src/cmd/sgs/elfedit/common/util_machelf.c usr/src/cmd/sgs/elfedit/modules/common/cap.c usr/src/cmd/sgs/elfedit/modules/common/dyn.c usr/src/cmd/sgs/elfedit/modules/common/dyn.msg usr/src/cmd/sgs/elfedit/modules/common/ehdr.c usr/src/cmd/sgs/elfedit/modules/common/phdr.c usr/src/cmd/sgs/elfedit/modules/common/shdr.c usr/src/cmd/sgs/elfedit/modules/common/str.c usr/src/cmd/sgs/elfedit/modules/common/sym.c usr/src/cmd/sgs/elfedit/modules/common/syminfo.c usr/src/cmd/sgs/include/_libelf.h usr/src/cmd/sgs/include/_machelf.h usr/src/cmd/sgs/include/conv.h usr/src/cmd/sgs/include/debug.h usr/src/cmd/sgs/include/i386/machdep.h usr/src/cmd/sgs/include/i386/machdep_x86.h usr/src/cmd/sgs/include/libld.h usr/src/cmd/sgs/include/machdep.h usr/src/cmd/sgs/include/rtld.h usr/src/cmd/sgs/include/sparc/machdep.h usr/src/cmd/sgs/include/sparc/machdep_sparc.h usr/src/cmd/sgs/ld/common/ld.c usr/src/cmd/sgs/ld/common/ld.msg usr/src/cmd/sgs/libconv/common/cap.c usr/src/cmd/sgs/libconv/common/dynamic.c usr/src/cmd/sgs/libconv/common/dynamic.msg usr/src/cmd/sgs/libconv/common/elf.c usr/src/cmd/sgs/libconv/common/globals.c usr/src/cmd/sgs/libconv/common/llib-lconv usr/src/cmd/sgs/libconv/common/symbols.c usr/src/cmd/sgs/libconv/common/syminfo.c usr/src/cmd/sgs/libelf/common/decl.h usr/src/cmd/sgs/libelf/common/llib-lelf usr/src/cmd/sgs/libelf/common/mapfile-common usr/src/cmd/sgs/libelf/common/update.c usr/src/cmd/sgs/libld/Makefile.com usr/src/cmd/sgs/libld/Makefile.targ usr/src/cmd/sgs/libld/amd64/Makefile usr/src/cmd/sgs/libld/common/README.XLINK usr/src/cmd/sgs/libld/common/_libld.h usr/src/cmd/sgs/libld/common/args.c usr/src/cmd/sgs/libld/common/entry.c usr/src/cmd/sgs/libld/common/files.c usr/src/cmd/sgs/libld/common/ldlibs.c usr/src/cmd/sgs/libld/common/ldmachdep.c usr/src/cmd/sgs/libld/common/ldmain.c usr/src/cmd/sgs/libld/common/libld.chk.msg usr/src/cmd/sgs/libld/common/libld.intel.msg usr/src/cmd/sgs/libld/common/libld.msg usr/src/cmd/sgs/libld/common/libld.sparc.msg usr/src/cmd/sgs/libld/common/libs.c usr/src/cmd/sgs/libld/common/llib-lld usr/src/cmd/sgs/libld/common/machrel.amd.c usr/src/cmd/sgs/libld/common/machrel.intel.c usr/src/cmd/sgs/libld/common/machrel.sparc.c usr/src/cmd/sgs/libld/common/machsym.intel.c usr/src/cmd/sgs/libld/common/machsym.sparc.c usr/src/cmd/sgs/libld/common/machsym.sparc.h usr/src/cmd/sgs/libld/common/map.c usr/src/cmd/sgs/libld/common/mapfile-vers usr/src/cmd/sgs/libld/common/outfile.c usr/src/cmd/sgs/libld/common/place.c usr/src/cmd/sgs/libld/common/relocate.c usr/src/cmd/sgs/libld/common/resolve.c usr/src/cmd/sgs/libld/common/sections.c usr/src/cmd/sgs/libld/common/syms.c usr/src/cmd/sgs/libld/common/unwind.amd.c usr/src/cmd/sgs/libld/common/unwind.amd.h usr/src/cmd/sgs/libld/common/update.c usr/src/cmd/sgs/libld/i386/Makefile usr/src/cmd/sgs/libld/sparc/Makefile usr/src/cmd/sgs/libld/sparcv9/Makefile usr/src/cmd/sgs/liblddbg/common/files.c usr/src/cmd/sgs/liblddbg/common/got.c usr/src/cmd/sgs/liblddbg/common/llib-llddbg usr/src/cmd/sgs/liblddbg/common/relocate.c usr/src/cmd/sgs/librtld/amd64/_relocate.c usr/src/cmd/sgs/librtld/common/relocate.c usr/src/cmd/sgs/librtld/i386/_relocate.c usr/src/cmd/sgs/librtld/sparc/_relocate.c usr/src/cmd/sgs/librtld/sparcv9/_relocate.c usr/src/cmd/sgs/packages/Makefile usr/src/cmd/sgs/packages/common/SUNWonld-README usr/src/cmd/sgs/packages/inc.flg usr/src/cmd/sgs/rtld/amd64/amd64_elf.c usr/src/cmd/sgs/rtld/common/analyze.c usr/src/cmd/sgs/rtld/common/cap.c usr/src/cmd/sgs/rtld/common/object.c usr/src/cmd/sgs/rtld/common/rtld.sparc.msg usr/src/cmd/sgs/rtld/common/setup.c usr/src/cmd/sgs/rtld/i386/i386_elf.c usr/src/cmd/sgs/rtld/sparc/common_sparc.c usr/src/cmd/sgs/rtld/sparc/sparc_elf.c usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c usr/src/uts/common/krtld/kobj.c usr/src/uts/common/krtld/reloc.h usr/src/uts/common/krtld/reloc_defs.h usr/src/uts/common/sys/Makefile usr/src/uts/common/sys/link.h usr/src/uts/common/sys/machelf.h usr/src/uts/intel/amd64/krtld/doreloc.c usr/src/uts/intel/amd64/krtld/relmach.h usr/src/uts/intel/ia32/krtld/doreloc.c usr/src/uts/intel/ia32/krtld/relmach.h usr/src/uts/intel/sys/Makefile usr/src/uts/intel/sys/machelf.h usr/src/uts/sparc/krtld/doreloc.c usr/src/uts/sparc/krtld/relmach.h usr/src/uts/sparc/sys/Makefile usr/src/uts/sparc/sys/machelf.h
diffstat 127 files changed, 5376 insertions(+), 2943 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/sgs/libld/common/libld.chk.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,42 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+@ _START_
+
+# Messages to satisfy chkmsg target.  Numerous messages within common code
+# (reloc.h) aren't required for each target, but chkmsg has no way of dealing
+# with ifdefs, thus this file exists to satisfy common code messages.
+
+@ MSG_REL_UNIMPL	"relocation error: file %s:  symbol %s: \
+			 unimplemented relocation type: %d"
+@ MSG_REL_UNNOBITS	"relocation error: %s: file %s: symbol %s: \
+			 unsupported number of bits: %d"
+@ MSG_REL_LOSEBITS	"relocation error: %s: file %s: symbol %s: \
+			 value 0x%llx loses %d bits at offset 0x%llx"
+
+@ _END_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/sgs/libld/common/machsym.intel.c	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,73 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include	<stdio.h>
+#include	<debug.h>
+#include	"_libld.h"
+
+
+/*
+ * This file contains stub routines since currently register symbols
+ * are not relevant to the i386 architecture.  But - having these
+ * stub routines avoids #ifdefs in common codes - and I hate that.
+ */
+/* ARGSUSED */
+int
+ld_reg_check(Sym_desc *sdp, Sym *nsym, const char *nname, Ifl_desc *ifl,
+    Ofl_desc * ofl)
+{
+	return (1);
+}
+
+/* ARGSUSED */
+int
+ld_mach_sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl)
+{
+	return (0);
+}
+
+/* ARGSUSED */
+const char *
+ld_is_regsym(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs,
+    int symndx, Word shndx, const char *symsecname, Word * flags)
+{
+	return (0);
+}
+
+/* ARGSUSED */
+Sym_desc *
+ld_reg_find(Sym * sym, Ofl_desc * ofl)
+{
+	return (0);
+}
+
+/* ARGSUSED */
+int
+ld_reg_enter(Sym_desc * sdp, Ofl_desc * ofl)
+{
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/intel/amd64/krtld/relmach.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_RELMACH_H
+#define	_RELMACH_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Architecture specific flags presented in a architecture neutral format
+ */
+#define	SHF_NEUT_SHORT	0
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _RELMACH_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/intel/ia32/krtld/relmach.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1998-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef	_RELMACH_H
+#define	_RELMACH_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Architecture specific flags presented in a architecture neutral format
+ */
+#define	SHF_NEUT_SHORT	0
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _RELMACH_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/sparc/krtld/relmach.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 (c) 1998-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef	_RELMACH_H
+#define	_RELMACH_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Architecture specific flags presented in a architecture nutral format
+ */
+#define	SHF_NEUT_SHORT	0
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _RELMACH_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/sparc/sys/machelf.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,190 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_SYS_MACHELF_H
+#define	_SYS_MACHELF_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <sys/elf_SPARC.h>
+#ifndef	_ASM
+#include <sys/types.h>
+#include <sys/elf.h>
+#include <sys/link.h>	/* for Elf*_Dyn */
+#endif	/* _ASM */
+
+/*
+ * Make machine class dependent data types transparent to the common code
+ */
+#if defined(_ELF64) && !defined(_ELF32_COMPAT)
+
+#ifndef	_ASM
+typedef	Elf64_Xword	Xword;
+typedef	Elf64_Lword	Lword;
+typedef	Elf64_Sxword	Sxword;
+typedef	Elf64_Word	Word;
+typedef	Elf64_Sword	Sword;
+typedef	Elf64_Half	Half;
+typedef	Elf64_Addr	Addr;
+typedef	Elf64_Off	Off;
+typedef	uchar_t		Byte;
+#endif	/* _ASM */
+
+#if defined(_KERNEL)
+#define	ELF_R_TYPE	ELF64_R_TYPE
+#define	ELF_R_SYM	ELF64_R_SYM
+#define	ELF_R_TYPE_DATA ELF64_R_TYPE_DATA
+#define	ELF_R_INFO	ELF64_R_INFO
+#define	ELF_ST_BIND	ELF64_ST_BIND
+#define	ELF_ST_TYPE	ELF64_ST_TYPE
+#define	ELF_M_SYM	ELF64_M_SYM
+#define	ELF_M_SIZE	ELF64_M_SIZE
+#endif
+
+#ifndef	_ASM
+typedef	Elf64_Ehdr	Ehdr;
+typedef	Elf64_Shdr	Shdr;
+typedef	Elf64_Sym	Sym;
+typedef	Elf64_Syminfo	Syminfo;
+typedef	Elf64_Rela	Rela;
+typedef	Elf64_Rel	Rel;
+typedef	Elf64_Nhdr	Nhdr;
+typedef	Elf64_Phdr	Phdr;
+typedef	Elf64_Dyn	Dyn;
+typedef	Elf64_Boot	Boot;
+typedef	Elf64_Verdef	Verdef;
+typedef	Elf64_Verdaux	Verdaux;
+typedef	Elf64_Verneed	Verneed;
+typedef	Elf64_Vernaux	Vernaux;
+typedef	Elf64_Versym	Versym;
+typedef	Elf64_Move	Move;
+typedef	Elf64_Cap	Cap;
+#endif	/* _ASM */
+
+#else	/* _ILP32 */
+
+#ifndef	_ASM
+typedef	Elf32_Word	Xword;	/* Xword/Sxword are 32-bits in Elf32 */
+typedef	Elf32_Lword	Lword;
+typedef	Elf32_Sword	Sxword;
+typedef	Elf32_Word	Word;
+typedef	Elf32_Sword	Sword;
+typedef	Elf32_Half	Half;
+typedef	Elf32_Addr	Addr;
+typedef	Elf32_Off	Off;
+typedef	uchar_t		Byte;
+#endif	/* _ASM */
+
+#if defined(_KERNEL)
+#define	ELF_R_TYPE	ELF32_R_TYPE
+#define	ELF_R_SYM	ELF32_R_SYM
+#define	ELF_R_INFO	ELF32_R_INFO
+#define	ELF_R_TYPE_DATA(x)	(0)
+#define	ELF_ST_BIND	ELF32_ST_BIND
+#define	ELF_ST_TYPE	ELF32_ST_TYPE
+#define	ELF_M_SYM	ELF32_M_SYM
+#define	ELF_M_SIZE	ELF32_M_SIZE
+#endif
+
+#ifndef	_ASM
+typedef	Elf32_Ehdr	Ehdr;
+typedef	Elf32_Shdr	Shdr;
+typedef	Elf32_Sym	Sym;
+typedef	Elf32_Syminfo	Syminfo;
+typedef	Elf32_Rela	Rela;
+typedef	Elf32_Rel	Rel;
+typedef	Elf32_Nhdr	Nhdr;
+typedef	Elf32_Phdr	Phdr;
+typedef	Elf32_Dyn	Dyn;
+typedef	Elf32_Boot	Boot;
+typedef	Elf32_Verdef	Verdef;
+typedef	Elf32_Verdaux	Verdaux;
+typedef	Elf32_Verneed	Verneed;
+typedef	Elf32_Vernaux	Vernaux;
+typedef	Elf32_Versym	Versym;
+typedef	Elf32_Move	Move;
+typedef	Elf32_Cap	Cap;
+#endif	/* _ASM */
+
+#endif	/* _ILP32 */
+
+/*
+ * Elf `printf' type-cast macros.  These force arguments to be a fixed size
+ * so that Elf32 and Elf64 can share common format strings.
+ */
+#ifndef	__lint
+#define	EC_ADDR(a)	((Elf64_Addr)(a))		/* "ull" */
+#define	EC_OFF(a)	((Elf64_Off)(a))		/* "ull"  */
+#define	EC_HALF(a)	((Elf64_Half)(a))		/* "d"   */
+#define	EC_WORD(a)	((Elf64_Word)(a))		/* "u"   */
+#define	EC_SWORD(a)	((Elf64_Sword)(a))		/* "d"   */
+#define	EC_XWORD(a)	((Elf64_Xword)(a))		/* "ull" */
+#define	EC_SXWORD(a)	((Elf64_Sxword)(a))		/* "ll"  */
+#define	EC_LWORD(a)	((Elf64_Lword)(a))		/* "ull" */
+
+/*
+ * A native pointer is special.  Although it can be convenient to display
+ * these from a common format (ull), compilers may flag the cast of a pointer
+ * to an integer as illegal.  Casting these pointers to the native pointer
+ * size, suppresses any compiler errors.
+ */
+#define	EC_NATPTR(a)	((Elf64_Xword)(uintptr_t)(a))	/* "ull" */
+#else
+#define	EC_ADDR(a)	((u_longlong_t)(a))
+#define	EC_OFF(a)	((u_longlong_t)(a))
+#define	EC_HALF(a)	((ushort_t)(a))
+#define	EC_WORD(a)	((uint_t)(a))
+#define	EC_SWORD(a)	((int)(a))
+#define	EC_XWORD(a)	((u_longlong_t)(a))
+#define	EC_SXWORD(a)	((longlong_t)(a))
+#define	EC_LWORD(a)	((u_longlong_t)(a))
+
+#define	EC_NATPTR(a)	((u_longlong_t)(a))
+#endif
+
+#ifndef	_ASM
+/*
+ * Structure used to build the reloc_table[]
+ */
+typedef struct {
+	Xword		re_mask;	/* mask to apply to reloc */
+	Word		re_flags;	/* relocation attributes */
+	uchar_t		re_fsize;	/* field size (in bytes) */
+	uchar_t		re_bshift;	/* number of bits to shift */
+	uchar_t		re_sigbits;	/* number of significant bits */
+} Rel_entry;
+
+#endif	/* _ASM */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_MACHELF_H */
--- a/usr/src/cmd/sgs/crle/common/lintsup.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/crle/common/lintsup.c	Tue Mar 18 09:17:00 2008 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -23,8 +22,8 @@
 /* PROTOLIB1 */
 
 /*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -33,6 +32,8 @@
  * Supplimental Pseudo-code to get lint to consider
  * these symbols used.
  */
+#include <link.h>
+#include <_libelf.h>
 #include "msg.h"
 
 void
--- a/usr/src/cmd/sgs/crle/inc.flg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/crle/inc.flg	Tue Mar 18 09:17:00 2008 -0700
@@ -3,9 +3,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# 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.
@@ -23,7 +22,7 @@
 #
 # ident	"%Z%%M%	%I%	%E% SMI" 
 #
-# Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # A combination of requirements and instructions for building crle and
@@ -38,13 +37,11 @@
 
 echo_file usr/src/cmd/sgs/packages/common/SUNWonld-README
 
-echo_file usr/src/uts/intel/sys/machelf.h
+echo_file usr/src/uts/common/sys/machelf.h
 echo_file usr/src/uts/intel/sys/Makefile
-echo_file usr/src/uts/sparc/sys/machelf.h
 echo_file usr/src/uts/sparc/sys/Makefile
 echo_file usr/src/uts/common/krtld/reloc.h
-echo_file usr/src/uts/intel/ia32/krtld/relmach.h
-echo_file usr/src/uts/sparc/krtld/relmach.h
+echo_file usr/src/uts/common/krtld/reloc_defs.h
 
 echo_file usr/src/cmd/sgs/rtld/common/_elf.h
 echo_file usr/src/cmd/sgs/rtld/common/_rtld.h
@@ -71,12 +68,6 @@
 #
 #	(cd $SRC/cmd/sgs/tools ; NATIVECC=cc make -e)
 #
-# The following is needed to install system headers:
-#
-#	mkdir -p $ROOT/usr/include/sys
-#	(cd $SRC/uts/$MACH/sys ; make $ROOT/usr/include/sys/machelf.h), or
-#	(cd $SRC/uts/intel/sys ; make $ROOT/usr/include/sys/machelf.h)
-#
 # The following is required to build libconv.a:
 #
 #	(cd $SRC/cmd/sgs/libconv ; make install lint)
--- a/usr/src/cmd/sgs/dump/common/dump.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/dump/common/dump.c	Tue Mar 18 09:17:00 2008 -0700
@@ -23,7 +23,7 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -37,7 +37,7 @@
 #include <locale.h>
 #include <unistd.h>
 #include <libelf.h>
-#include <link.h>
+#include <sys/link.h>
 #include <sys/elf.h>
 #include <sys/machelf.h>
 #include <fcntl.h>
@@ -1232,12 +1232,14 @@
 				break;
 
 			/*
-			 * Items that are bitmasks
+			 * Integer items that are bitmasks, or which
+			 * can be otherwise formatted in symbolic form.
 			 */
 			case DT_FLAGS:
 			case DT_FEATURE_1:
 			case DT_POSFLAG_1:
 			case DT_FLAGS_1:
+			case DT_SUNW_LDMACH:
 				str = NULL;
 				if (v_flag) {
 					switch (p_dyn.d_tag) {
@@ -1264,6 +1266,11 @@
 						    p_dyn.d_un.d_val, 0,
 						    &conv_buf.dyn_flag1);
 						break;
+					case DT_SUNW_LDMACH:
+						str = conv_ehdr_mach(
+						    p_dyn.d_un.d_val, 0,
+						    &conv_buf.inv);
+						break;
 					}
 				}
 				if (str) {	/* Show as string */
--- a/usr/src/cmd/sgs/elfdump/common/_elfdump.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfdump/common/_elfdump.h	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,7 +29,7 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#include	<machelf.h>
+#include	<_machelf.h>
 #include	<debug.h>
 
 /*
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -28,10 +28,10 @@
 /*
  * Dump an elf file.
  */
-#include	<machdep.h>
 #include	<sys/elf_386.h>
 #include	<sys/elf_amd64.h>
 #include	<sys/elf_SPARC.h>
+#include	<_libelf.h>
 #include	<dwarf.h>
 #include	<stdio.h>
 #include	<unistd.h>
@@ -1523,8 +1523,8 @@
 	    (sym->st_shndx >= state->shnum)) {
 		(void) fprintf(stderr,
 		    MSG_INTL(MSG_ERR_BADSYM5), state->file,
-		    state->secname, demangle(symname, state->flags),
-		    sym->st_shndx);
+		    state->secname, EC_WORD(symndx),
+		    demangle(symname, state->flags), sym->st_shndx);
 	}
 
 	/*
@@ -1574,13 +1574,15 @@
 		    ((tshdr->sh_flags & SHF_TLS) == 0)) {
 			(void) fprintf(stderr,
 			    MSG_INTL(MSG_ERR_BADSYM3), state->file,
-			    state->secname, demangle(symname, state->flags));
+			    state->secname, EC_WORD(symndx),
+			    demangle(symname, state->flags));
 		}
 	} else if ((type != STT_SECTION) && sym->st_size &&
 	    tshdr && (tshdr->sh_flags & SHF_TLS)) {
 		(void) fprintf(stderr,
 		    MSG_INTL(MSG_ERR_BADSYM4), state->file,
-		    state->secname, demangle(symname, state->flags));
+		    state->secname, EC_WORD(symndx),
+		    demangle(symname, state->flags));
 	}
 
 	/*
@@ -1608,7 +1610,8 @@
 		if (((v + sym->st_size) > tshdr->sh_size)) {
 			(void) fprintf(stderr,
 			    MSG_INTL(MSG_ERR_BADSYM6), state->file,
-			    state->secname, demangle(symname, state->flags),
+			    state->secname, EC_WORD(symndx),
+			    demangle(symname, state->flags),
 			    EC_WORD(shndx), EC_XWORD(tshdr->sh_size),
 			    EC_XWORD(sym->st_value), EC_XWORD(sym->st_size));
 		}
@@ -1629,8 +1632,8 @@
 		if ((symndx < info) && (bind != STB_LOCAL)) {
 			(void) fprintf(stderr,
 			    MSG_INTL(MSG_ERR_BADSYM7), state->file,
-			    state->secname, demangle(symname, state->flags),
-			    EC_XWORD(info));
+			    state->secname, EC_WORD(symndx),
+			    demangle(symname, state->flags), EC_XWORD(info));
 
 		} else if ((symndx >= info) && (bind == STB_LOCAL) &&
 		    ((sym->st_shndx != SHN_UNDEF) ||
@@ -1638,8 +1641,8 @@
 		    (sym->st_size != 0) || (sym->st_value != 0))) {
 			(void) fprintf(stderr,
 			    MSG_INTL(MSG_ERR_BADSYM8), state->file,
-			    state->secname, demangle(symname, state->flags),
-			    EC_XWORD(info));
+			    state->secname, EC_WORD(symndx),
+			    demangle(symname, state->flags), EC_XWORD(info));
 		}
 	}
 
@@ -1897,6 +1900,7 @@
 
 		for (relndx = 0; relndx < relnum; relndx++,
 		    rels = (void *)((char *)rels + relsize)) {
+			Half		mach = ehdr->e_machine;
 			char		section[BUFSIZ];
 			const char	*symname;
 			Word		symndx, reltype;
@@ -1910,11 +1914,11 @@
 			if (type == SHT_RELA) {
 				rela = (Rela *)rels;
 				symndx = ELF_R_SYM(rela->r_info);
-				reltype = ELF_R_TYPE(rela->r_info);
+				reltype = ELF_R_TYPE(rela->r_info, mach);
 			} else {
 				rel = (Rel *)rels;
 				symndx = ELF_R_SYM(rel->r_info);
-				reltype = ELF_R_TYPE(rel->r_info);
+				reltype = ELF_R_TYPE(rel->r_info, mach);
 			}
 
 			symname = relsymname(cache, _cache, strsec, symndx,
@@ -1926,7 +1930,6 @@
 			 * relocations.
 			 */
 			if (symndx == 0) {
-				Half	mach = ehdr->e_machine;
 				int	badrel = 0;
 
 				if ((mach == EM_SPARC) ||
@@ -2250,6 +2253,7 @@
 
 		for (ndx = 0; ndx < numdyn; dyn++, ndx++) {
 			union {
+				Conv_inv_buf_t		inv;
 				Conv_dyn_flag_buf_t	flag;
 				Conv_dyn_flag1_buf_t	flag1;
 				Conv_dyn_posflag1_buf_t	posflag1;
@@ -2348,6 +2352,11 @@
 				name = MSG_INTL(MSG_STR_DEPRECATED);
 				break;
 
+			case DT_SUNW_LDMACH:
+				name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0,
+				    &c_buf.inv);
+				break;
+
 			/*
 			 * Cases below this point are strictly sanity checking,
 			 * and do not generate a name string. The TEST_ macros
@@ -2626,7 +2635,8 @@
 			    (cache[shndx].c_shdr)->sh_type == SHT_NOBITS))) {
 				(void) fprintf(stderr,
 				    MSG_INTL(MSG_ERR_BADSYM2), file,
-				    _cache->c_name, demangle(symname, flags));
+				    _cache->c_name, EC_WORD(symndx),
+				    demangle(symname, flags));
 			}
 
 			(void) snprintf(index, MAXNDXSIZE,
@@ -3111,6 +3121,7 @@
 	char		*gotdata;
 	Sym		*gotsym;
 	Xword		gotsymaddr;
+	uint_t		sys_encoding;
 
 	/*
 	 * First, find the got.
@@ -3247,12 +3258,14 @@
 			if (type == SHT_RELA) {
 				rela = (Rela *)rels;
 				symndx = ELF_R_SYM(rela->r_info);
-				reltype = ELF_R_TYPE(rela->r_info);
+				reltype = ELF_R_TYPE(rela->r_info,
+				    ehdr->e_machine);
 				offset = rela->r_offset;
 			} else {
 				rel = (Rel *)rels;
 				symndx = ELF_R_SYM(rel->r_info);
-				reltype = ELF_R_TYPE(rel->r_info);
+				reltype = ELF_R_TYPE(rel->r_info,
+				    ehdr->e_machine);
 				offset = rel->r_offset;
 			}
 
@@ -3293,6 +3306,7 @@
 	dbg_print(0, MSG_INTL(MSG_ELF_SCN_GOT), gotcache->c_name);
 	Elf_got_title(0);
 
+	sys_encoding = _elf_sys_encoding();
 	for (gotndx = 0; gotndx < gotents; gotndx++) {
 		Got_info	*gip;
 		Sword		gindex;
@@ -3312,6 +3326,7 @@
 			gotentry = *((Xword *)(gotdata) + gotndx);
 
 		Elf_got_entry(0, gindex, gaddr, gotentry, ehdr->e_machine,
+		    ehdr->e_ident[EI_DATA], sys_encoding,
 		    gip->g_reltype, gip->g_rel, gip->g_symname);
 	}
 	free(gottable);
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -92,19 +92,20 @@
 @ MSG_ERR_BADSHINFO	"%s: %s: invalid sh_info: %d\n"
 @ MSG_ERR_BADSHTYPE	"%s: %s: invalid sh_type: %d\n"
 @ MSG_ERR_BADALIGN	"%s: %s: bad sh_offset alignment\n"
-@ MSG_ERR_BADSYM2	"%s: %s: bad symbol entry: %s: must be SHN_COMMON or \
+@ MSG_ERR_BADSYM2	"%s: %s: index[%d]: bad symbol entry: %s: must be SHN_COMMON or \
 			 defined in SHT_NOBITS section\n"
-@ MSG_ERR_BADSYM3	"%s: %s: bad symbol entry: %s: must be defined in \
+@ MSG_ERR_BADSYM3	"%s: %s: index[%d]: bad symbol entry: %s: must be defined in \
 			 a SHF_TLS section\n"
-@ MSG_ERR_BADSYM4	"%s: %s: bad symbol entry: %s: must be defined in \
+@ MSG_ERR_BADSYM4	"%s: %s: index[%d]: bad symbol entry: %s: must be defined in \
 			 a non-SHF_TLS section\n"
-@ MSG_ERR_BADSYM5	"%s: %s: bad symbol entry: %s: invalid shndx: %d\n"
-@ MSG_ERR_BADSYM6	"%s: %s: bad symbol entry: %s: section[%d] \
+@ MSG_ERR_BADSYM5	"%s: %s: index[%d]: bad symbol entry: %s: \
+			 invalid shndx: %d\n"
+@ MSG_ERR_BADSYM6	"%s: %s: index[%d]: bad symbol entry: %s: section[%d] \
 			 size: %#llx: symbol (address %#llx, size %#llx) \
 			 lies outside of containing section\n"
-@ MSG_ERR_BADSYM7	"%s: %s: suspicious global symbol entry: %s: lies \
+@ MSG_ERR_BADSYM7	"%s: %s: index[%d]: suspicious global symbol entry: %s: lies \
 			 within local symbol range (index < %lld)\n"
-@ MSG_ERR_BADSYM8	"%s: %s: suspicious local symbol entry: %s: lies \
+@ MSG_ERR_BADSYM8	"%s: %s: index[%d]: suspicious local symbol entry: %s: lies \
 			 within global symbol range (index >= %lld)\n"
 
 @ MSG_ERR_RELBADSYMNDX	"%s: bad symbol reference %d: from relocation \
--- a/usr/src/cmd/sgs/elfdump/common/fake_shdr.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfdump/common/fake_shdr.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -61,7 +61,6 @@
 
 
 
-#include	<machdep.h>
 #include	<sys/elf_amd64.h>
 #include	<stdio.h>
 #include	<unistd.h>
@@ -156,13 +155,28 @@
 	Elf_Type	libelf_type;
 } SINFO_DATA;
 
+/*
+ * Many of these sections use an alignment given by M_WORD_ALIGN, a
+ * value that varies depending on the object target machine. Since we
+ * don't know that value at compile time, we settle for a value of
+ * 4 for ELFCLASS32 objects, and 8 for ELFCLASS64. This matches the
+ * platforms we current support (sparc and x86), and is good enough for
+ * a fake section header in any event, as the resulting object is only
+ * analyzed, and is not executed.
+ */
+#ifdef _ELF64
+#define	FAKE_M_WORD_ALIGN 8
+#else
+#define	FAKE_M_WORD_ALIGN 4
+#endif
+
 static SINFO_DATA sinfo_data[SINFO_T_NUM] = {
 	/* SINFO_T_NULL */
 	{ 0 },
 
 	/* SINFO_T_DYN */
 	{ MSG_ORIG(MSG_PHDRNAM_DYN), SHT_DYNAMIC, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Dyn), ELF_T_DYN },
+	    FAKE_M_WORD_ALIGN, sizeof (Dyn), ELF_T_DYN },
 
 	/* SINFO_T_DYNSTR */
 	{ MSG_ORIG(MSG_PHDRNAM_DYNSTR), SHT_STRTAB, SHF_ALLOC,
@@ -170,39 +184,39 @@
 
 	/* SINFO_T_DYNSYM */
 	{ MSG_ORIG(MSG_PHDRNAM_DYNSYM), SHT_DYNSYM, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Sym), ELF_T_SYM },
+	    FAKE_M_WORD_ALIGN, sizeof (Sym), ELF_T_SYM },
 
 	/* SINFO_T_LDYNSYM */
 	{ MSG_ORIG(MSG_PHDRNAM_LDYNSYM), SHT_SUNW_LDYNSYM, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Sym), ELF_T_SYM },
+	    FAKE_M_WORD_ALIGN, sizeof (Sym), ELF_T_SYM },
 
 	/* SINFO_T_HASH */
 	{ MSG_ORIG(MSG_PHDRNAM_HASH), SHT_HASH, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
+	    FAKE_M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
 
 	/* SINFO_T_SYMINFO */
 	{ MSG_ORIG(MSG_PHDRNAM_SYMINFO),  SHT_SUNW_syminfo, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Syminfo), ELF_T_SYMINFO },
+	    FAKE_M_WORD_ALIGN, sizeof (Syminfo), ELF_T_SYMINFO },
 
 	/* SINFO_T_SYMSORT */
 	{ MSG_ORIG(MSG_PHDRNAM_SYMSORT), SHT_SUNW_symsort, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
+	    FAKE_M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
 
 	/* SINFO_T_TLSSORT */
 	{ MSG_ORIG(MSG_PHDRNAM_TLSSORT), SHT_SUNW_tlssort, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
+	    FAKE_M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
 
 	/* SINFO_T_VERNEED */
 	{ MSG_ORIG(MSG_PHDRNAM_VER), SHT_SUNW_verneed, SHF_ALLOC,
-	    M_WORD_ALIGN, 1, ELF_T_VNEED },
+	    FAKE_M_WORD_ALIGN, 1, ELF_T_VNEED },
 
 	/* SINFO_T_VERDEF */
 	{ MSG_ORIG(MSG_PHDRNAM_VER), SHT_SUNW_verdef, SHF_ALLOC,
-	    M_WORD_ALIGN, 1, ELF_T_VDEF },
+	    FAKE_M_WORD_ALIGN, 1, ELF_T_VDEF },
 
 	/* SINFO_T_VERSYM */
 	{ MSG_ORIG(MSG_PHDRNAM_VER), SHT_SUNW_versym, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Versym), ELF_T_HALF },
+	    FAKE_M_WORD_ALIGN, sizeof (Versym), ELF_T_HALF },
 
 	/* SINFO_T_INTERP */
 	{ MSG_ORIG(MSG_PHDRNAM_INTERP), SHT_PROGBITS, SHF_ALLOC,
@@ -222,11 +236,11 @@
 
 	/* SINFO_T_REL */
 	{ MSG_ORIG(MSG_PHDRNAM_REL), SHT_REL, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Rel), ELF_T_REL },
+	    FAKE_M_WORD_ALIGN, sizeof (Rel), ELF_T_REL },
 
 	/* SINFO_T_RELA */
 	{ MSG_ORIG(MSG_PHDRNAM_RELA), SHT_RELA, SHF_ALLOC,
-	    M_WORD_ALIGN, sizeof (Rela), ELF_T_RELA },
+	    FAKE_M_WORD_ALIGN, sizeof (Rela), ELF_T_RELA },
 
 	/* SINFO_T_PREINITARR */
 	{ MSG_ORIG(MSG_PHDRNAM_PREINITARR), SHT_PREINIT_ARRAY, SHF_ALLOC,
@@ -242,7 +256,7 @@
 
 	/* SINFO_T_NOTE */
 	{ MSG_ORIG(MSG_PHDRNAM_NOTE), SHT_NOTE, 0,
-	    M_WORD_ALIGN, 1, ELF_T_NOTE }
+	    FAKE_M_WORD_ALIGN, 1, ELF_T_NOTE }
 };
 
 
--- a/usr/src/cmd/sgs/elfedit/common/elfconst.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/common/elfconst.c	Tue Mar 18 09:17:00 2008 -0700
@@ -436,6 +436,9 @@
 	{ MSG_ORIG(MSG_DT_SUNW_STRPAD),		DT_SUNW_STRPAD },
 	{ MSG_ORIG(MSG_DT_SUNW_STRPAD_ALT1),	DT_SUNW_STRPAD },
 
+	{ MSG_ORIG(MSG_DT_SUNW_LDMACH),		DT_SUNW_LDMACH },
+	{ MSG_ORIG(MSG_DT_SUNW_LDMACH_ALT1),	DT_SUNW_LDMACH },
+
 	{ MSG_ORIG(MSG_DT_SPARC_REGISTER),	DT_SPARC_REGISTER },
 	{ MSG_ORIG(MSG_DT_SPARC_REGISTER_ALT1),	DT_SPARC_REGISTER },
 
--- a/usr/src/cmd/sgs/elfedit/common/elfedit.msg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/common/elfedit.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -790,6 +790,8 @@
 @ MSG_DT_SUNW_TLSSORTSZ_ALT1	"sunw_tlssortsz"
 @ MSG_DT_SUNW_STRPAD		"DT_SUNW_STRPAD"	# 0x60000019
 @ MSG_DT_SUNW_STRPAD_ALT1	"sunw_strpad"
+@ MSG_DT_SUNW_LDMACH		"DT_SUNW_ldmach"	# 0x6000001b
+@ MSG_DT_SUNW_LDMACH_ALT1	"sunw_ldmach"
 @ MSG_DT_SPARC_REGISTER		"DT_SPARC_REGISTER"	# 0x70000001
 @ MSG_DT_SPARC_REGISTER_ALT1	"sparc_register"
 @ MSG_DT_DEPRECATED_SPARC_REGISTER "DT_DEPRECATED_SPARC_REGISTER" # 0x7000001
--- a/usr/src/cmd/sgs/elfedit/common/elfedit_machelf.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/common/elfedit_machelf.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -31,7 +31,7 @@
 #include	<stdlib.h>
 #include	<stdio.h>
 #include	<unistd.h>
-#include	<machdep.h>
+#include	<_machelf.h>
 #include	<libelf.h>
 #include	<strings.h>
 #include	<sgs.h>
--- a/usr/src/cmd/sgs/elfedit/common/sys.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/common/sys.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -45,8 +45,8 @@
  *		as a sharable object.
  *	- It must be avaialble before the ELFCLASS of the object
  *		is known, so it is not ELFCLASS specific. We don't build
- *		it twice with machdep.h, as we do for the loadable modules.
- *		This means that commands need to test for the type
+ *		it twice with <sys/machelf.h>, as we do for the loadable
+ *		modules. This means that commands need to test for the type
  *		of their obj_state argument at runtime.
  *	- The init function signature is different. We build an entire
  *		module definition statically.
--- a/usr/src/cmd/sgs/elfedit/common/util_machelf.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/common/util_machelf.c	Tue Mar 18 09:17:00 2008 -0700
@@ -29,7 +29,7 @@
 #include	<stdio.h>
 #include	<unistd.h>
 #include	<libintl.h>
-#include	<machdep.h>
+#include	<_machelf.h>
 #include	<libelf.h>
 #include	<link.h>
 #include	<strings.h>
--- a/usr/src/cmd/sgs/elfedit/modules/common/cap.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/modules/common/cap.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,13 +20,12 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include	<ctype.h>
-#include	<machdep.h>
 #include	<elfedit.h>
 #include	<sys/elf_SPARC.h>
 #include	<strings.h>
--- a/usr/src/cmd/sgs/elfedit/modules/common/dyn.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/modules/common/dyn.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,13 +20,12 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include	<ctype.h>
-#include	<machdep.h>
 #include	<elfedit.h>
 #include	<sys/elf_SPARC.h>
 #include	<strings.h>
@@ -63,7 +62,8 @@
 	DYN_CMD_T_FLAGS =	7,	/* dyn:flags */
 	DYN_CMD_T_FLAGS1 =	8,	/* dyn:flags1 */
 	DYN_CMD_T_FEATURE1 =	9,	/* dyn:feature1 */
-	DYN_CMD_T_CHECKSUM =	10	/* dyn:checksum */
+	DYN_CMD_T_CHECKSUM =	10,	/* dyn:checksum */
+	DYN_CMD_T_SUNW_LDMACH =	11	/* dyn:sunw_ldmach */
 } DYN_CMD_T;
 
 
@@ -320,6 +320,7 @@
 	dyn = &argstate->dyn.data[ndx];
 	for (; cnt--; dyn++, ndx++) {
 		union {
+			Conv_inv_buf_t		inv;
 			Conv_dyn_flag_buf_t	flag;
 			Conv_dyn_flag1_buf_t	flag1;
 			Conv_dyn_posflag1_buf_t	posflag1;
@@ -415,6 +416,10 @@
 		case DT_DEPRECATED_SPARC_REGISTER:
 			name = MSG_INTL(MSG_STR_DEPRECATED);
 			break;
+		case DT_SUNW_LDMACH:
+			name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0,
+			    &c_buf.inv);
+			break;
 		}
 
 		if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
@@ -1045,6 +1050,15 @@
 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
 		break;
 
+	case DYN_CMD_T_SUNW_LDMACH:
+		if (argstate.argc > 1)
+			elfedit_command_usage();
+		print_only = (argstate.argc == 0);
+		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
+		    ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1),
+		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
+		break;
+
 	default:
 		/* Note expected: All commands should have been caught above */
 		elfedit_command_usage();
@@ -1318,6 +1332,36 @@
 			}
 
 		}
+		break;
+
+	case DYN_CMD_T_SUNW_LDMACH:
+		{
+			Conv_inv_buf_t buf1, buf2;
+			Half ldmach;
+
+			ldmach = (Half) elfedit_atoconst(argstate.argv[0],
+			    ELFEDIT_CONST_EM);
+
+			/* Set the value */
+			if (dyn[ndx].d_un.d_val == ldmach) {
+				elfedit_msg(ELFEDIT_MSG_DEBUG,
+				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
+				    dyn_name, EC_WORD(ndx),
+				    conv_ehdr_mach(dyn[ndx].d_un.d_val, 0,
+				    &buf1));
+			} else {
+				elfedit_msg(ELFEDIT_MSG_DEBUG,
+				    MSG_INTL(MSG_DEBUG_S_CHG),
+				    dyn_ndx, dyn_name, EC_WORD(ndx),
+				    conv_ehdr_mach(dyn[ndx].d_un.d_val, 0,
+				    &buf1),
+				    conv_ehdr_mach(ldmach, 0, &buf2));
+				ret = ELFEDIT_CMDRET_MOD;
+				dyn[ndx].d_un.d_val = ldmach;
+			}
+		}
+		break;
+
 	}
 
 	/*
@@ -1454,6 +1498,22 @@
 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1);
 }
 
+/*ARGSUSED*/
+static void
+cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
+    const char *argv[], int num_opt)
+{
+	/*
+	 * This command doesn't accept options, so num_opt should be
+	 * 0. This is a defensive measure, in case that should change.
+	 */
+	argc -= num_opt;
+	argv += num_opt;
+
+	if (argc == 1)
+		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM);
+}
+
 
 /*
  * Implementation functions for the commands
@@ -1524,6 +1584,12 @@
 	return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv));
 }
 
+static elfedit_cmdret_t
+cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
+{
+	return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv));
+}
+
 
 
 /*ARGSUSED*/
@@ -1718,6 +1784,17 @@
 	static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM),
 	    NULL };
 
+	/* dyn:sunw_ldmach */
+	static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH),
+	    NULL };
+	static elfedit_cmd_optarg_t arg_sunw_ldmach[] = {
+		{ MSG_ORIG(MSG_STR_VALUE),
+		    /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */
+		    ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE),
+		    ELFEDIT_CMDOA_F_OPT },
+		{ NULL }
+	};
+
 
 
 	static elfedit_cmd_t cmds[] = {
@@ -1809,6 +1886,14 @@
 		    ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM),
 		    NULL, NULL },
 
+		/* dyn:sunw_ldmach */
+		{ cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach,
+		    /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */
+		    ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH),
+		    /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */
+		    ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH),
+		    opt_ostyle, arg_sunw_ldmach },
+
 		{ NULL }
 	};
 
--- a/usr/src/cmd/sgs/elfedit/modules/common/dyn.msg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/modules/common/dyn.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -91,6 +91,7 @@
 @ MSG_DESC_FLAGS1	"DT_FLAGS_1 bit values"
 @ MSG_DESC_FEATURE1	"DT_FEATURE_1 bit values"
 @ MSG_DESC_CHECKSUM	"Recompute DT_CHECKSUM"
+@ MSG_DESC_SUNW_LDMACH	"Linker machine type"
 
 
 # Commmand option description strings
@@ -189,6 +190,11 @@
    the DTF_1_ symbolic constants defined in\n\
    /usr/include/sys/link.h\n"
 
+@ MSG_A1_SUNW_LDMACH_VALUE	"\
+   Machine type of link-editor that built the object being edited.\n\
+   This can be an integer value, or any of the EM_ symbolic\n\
+   constants defined in /usr/include/elf.h\n"
+
 
 # Help strings
 
@@ -386,6 +392,22 @@
    DT_CHECKSUM element, and room for it exists at the end\n\
    of the section, a new one is inserted.\n"
 
+@ MSG_HELP_SUNW_LDMACH	"   \
+   The dyn:sunw_ldmach command is used to display or alter the\n\
+   DT_SUNW_LDMACH dynamic element of the ELF object. This dynamic\n\
+   element records the ELF machine type of the link-editor that produced\n\
+   the object. This is of special interest if the object was built\n\
+   by a cross link-editor instead of being linked on a machine of the\n\
+   same type as the object.\n\
+   \n\
+   If dyn:sunw_ldmach is called without arguments, the current\n\
+   value is shown. If called with the value argument, the\n\
+   DT_SUNW_LDMACH dynamic element is set to the specified machine type.\n\
+   \n\
+   If the current dynamic section does not have a current\n\
+   DT_SUNW_LDMACH element, and room for it exists at the end\n\
+   of the section, a new one is inserted.\n"
+
 @ _END_
 
 
@@ -429,3 +451,4 @@
 @ MSG_CMD_FLAGS1	"flags1"
 @ MSG_CMD_FEATURE1	"feature1"
 @ MSG_CMD_CHECKSUM	"checksum"
+@ MSG_CMD_SUNW_LDMACH	"sunw_ldmach"
--- a/usr/src/cmd/sgs/elfedit/modules/common/ehdr.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/modules/common/ehdr.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,14 +20,13 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include	<stdio.h>
 #include	<ctype.h>
-#include	<machdep.h>
 #include	<elfedit.h>
 #include	<sys/elf_SPARC.h>
 #include	<sys/elf_amd64.h>
--- a/usr/src/cmd/sgs/elfedit/modules/common/phdr.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/modules/common/phdr.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,12 +20,11 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#include	<machdep.h>
 #include	<elfedit.h>
 #include	<strings.h>
 #include	<conv.h>
--- a/usr/src/cmd/sgs/elfedit/modules/common/shdr.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/modules/common/shdr.c	Tue Mar 18 09:17:00 2008 -0700
@@ -27,7 +27,6 @@
 
 #include	<stdio.h>
 #include	<unistd.h>
-#include	<machdep.h>
 #include	<elfedit.h>
 #include	<sys/elf_SPARC.h>
 #include	<sys/elf_amd64.h>
--- a/usr/src/cmd/sgs/elfedit/modules/common/str.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/modules/common/str.c	Tue Mar 18 09:17:00 2008 -0700
@@ -28,7 +28,6 @@
 #include	<stdio.h>
 #include	<ctype.h>
 #include	<unistd.h>
-#include	<machdep.h>
 #include	<elfedit.h>
 #include	<strings.h>
 #include	<debug.h>
--- a/usr/src/cmd/sgs/elfedit/modules/common/sym.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/modules/common/sym.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -29,7 +29,6 @@
 
 #include	<stdio.h>
 #include	<unistd.h>
-#include	<machdep.h>
 #include	<elfedit.h>
 #include	<strings.h>
 #include	<debug.h>
--- a/usr/src/cmd/sgs/elfedit/modules/common/syminfo.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/elfedit/modules/common/syminfo.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,14 +20,13 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include	<stdio.h>
 #include	<unistd.h>
-#include	<machdep.h>
 #include	<elfedit.h>
 #include	<strings.h>
 #include	<debug.h>
--- a/usr/src/cmd/sgs/include/_libelf.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/include/_libelf.h	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -44,6 +44,7 @@
 
 extern Elf64_Off	_elf_getxoff(Elf_Data *);
 extern GElf_Xword	_gelf_getdyndtflags_1(Elf *elf);
+extern int		_elf_swap_wrimage(Elf *elf);
 extern uint_t		_elf_sys_encoding(void);
 
 #ifdef	__cplusplus
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/include/_machelf.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ *
+ * Wrapper around the <sys/machelf.h> header that adds
+ * definitions used by SGS.
+ */
+
+#ifndef	_MACHELF_H
+#define	_MACHELF_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/machelf.h>
+#include <string.h>		/* memcpy() */
+
+/*
+ * Make machine class dependent functions transparent to the common code
+ */
+
+/*
+ * Note on ELF_R_TYPE: 64-bit sparc relocations require the use of
+ * ELF64_R_TYPE_ID instead of the ELF64_R_TYPE macro used for all
+ * other platforms. So our ELF_R_TYPE macro requires the caller to
+ * supply the machine type.
+ */
+
+
+#if	defined(_ELF64)
+#define	ELF_R_TYPE(_info, _mach)  \
+	(((_mach) == EM_SPARCV9) ? ELF64_R_TYPE_ID(_info) : ELF64_R_TYPE(_info))
+#define	ELF_R_INFO			ELF64_R_INFO
+#define	ELF_R_SYM			ELF64_R_SYM
+#define	ELF_R_TYPE_DATA(x)		ELF64_R_TYPE_DATA(x)
+#define	ELF_R_TYPE_INFO(xoff, type)	ELF64_R_TYPE_INFO(xoff, type)
+#define	ELF_ST_BIND			ELF64_ST_BIND
+#define	ELF_ST_TYPE			ELF64_ST_TYPE
+#define	ELF_ST_INFO			ELF64_ST_INFO
+#define	ELF_ST_VISIBILITY		ELF64_ST_VISIBILITY
+#define	ELF_M_SYM			ELF64_M_SYM
+#define	ELF_M_SIZE			ELF64_M_SIZE
+#define	ELF_M_INFO			ELF64_M_INFO
+#define	elf_checksum			elf64_checksum
+#define	elf_fsize			elf64_fsize
+#define	elf_getehdr			elf64_getehdr
+#define	elf_getphdr			elf64_getphdr
+#define	elf_newehdr			elf64_newehdr
+#define	elf_newphdr			elf64_newphdr
+#define	elf_getshdr			elf64_getshdr
+#define	elf_xlatetof			elf64_xlatetof
+#define	elf_xlatetom			elf64_xlatetom
+#else /* _ELF64 */
+#define	ELF_R_TYPE(_info, _mach)	ELF32_R_TYPE(_info)
+#define	ELF_R_INFO			ELF32_R_INFO
+#define	ELF_R_SYM			ELF32_R_SYM
+/* Elf64 can hide extra offset in r_info */
+#define	ELF_R_TYPE_DATA(x)		(0)
+#define	ELF_R_TYPE_INFO(xoff, type)	(type)
+#define	ELF_ST_BIND			ELF32_ST_BIND
+#define	ELF_ST_TYPE			ELF32_ST_TYPE
+#define	ELF_ST_INFO			ELF32_ST_INFO
+#define	ELF_ST_VISIBILITY		ELF32_ST_VISIBILITY
+#define	ELF_M_SYM			ELF32_M_SYM
+#define	ELF_M_SIZE			ELF32_M_SIZE
+#define	ELF_M_INFO			ELF32_M_INFO
+#define	elf_checksum			elf32_checksum
+#define	elf_fsize			elf32_fsize
+#define	elf_getehdr			elf32_getehdr
+#define	elf_getphdr			elf32_getphdr
+#define	elf_newehdr			elf32_newehdr
+#define	elf_newphdr			elf32_newphdr
+#define	elf_getshdr			elf32_getshdr
+#define	elf_xlatetof			elf32_xlatetof
+#define	elf_xlatetom			elf32_xlatetom
+#endif	/* _ELF32 */
+
+
+/*
+ * Macros for swapping bytes. The type of the argument must
+ * match the type given in the macro name.
+ */
+#define	BSWAP_HALF(_half) \
+	(((_half) << 8) | ((_half) >> 8))
+
+#define	BSWAP_WORD(_word) \
+	((((_word) << 24) | (((_word) & 0xff00) << 8) | \
+	(((_word) >> 8) & 0xff00) | ((_word) >> 24)))
+
+#if	defined(_ELF64)
+#define	BSWAP_XWORD(_xword) \
+	(((_xword) << 56) | \
+	(((_xword) & 0x0000ff00) << 40) | \
+	(((_xword) & 0x00ff0000) << 24) | \
+	(((_xword) & 0xff000000) << 8) | \
+	(((_xword) >> 8)  & 0xff000000) | \
+	(((_xword) >> 24) & 0x00ff0000) | \
+	(((_xword) >> 40) & 0x0000ff00) | \
+	((_xword) >> 56))	/* Xword is unsigned - 0 bits enter from left */
+#else
+#define	BSWAP_XWORD(_xword) BSWAP_WORD(_xword)
+#endif
+
+/*
+ * Macros for assigning Half/Word/Xword items from one location to
+ * another that are safe no matter what the data alignment rules of the
+ * running platform are. Variants exist to swap the data byteorder
+ * at the same time, or not.
+ *
+ * These macros are useful for code that accesses data that is aligned
+ * for a different system architecture, as occurs in cross linking.
+ *
+ * All of these macros assume the arguments are passed as pointers to
+ * bytes (signed or unsigned).
+ */
+
+#define	UL_ASSIGN_HALF(_dst, _src) (void) \
+	((_dst)[0] = (_src)[0],	(_dst)[1] = (_src)[1])
+#define	UL_ASSIGN_WORD(_dst, _src) (void) \
+	((_dst)[0] = (_src)[0],	(_dst)[1] = (_src)[1], \
+	(_dst)[2] = (_src)[2], 	(_dst)[3] = (_src)[3])
+#if	defined(_ELF64)
+#define	UL_ASSIGN_XWORD(_dst, _src) (void) memcpy(_dst, (_src), sizeof (Xword))
+#else
+#define	UL_ASSIGN_XWORD(_xword) UL_ASSIGN_WORD(_xword)
+#endif
+
+#define	UL_ASSIGN_BSWAP_HALF(_dst, _src) (void) \
+	((_dst)[0] = (_src)[1],	(_dst)[1] = (_src)[0])
+#define	UL_ASSIGN_BSWAP_WORD(_dst, _src) (void) \
+	((_dst)[0] = (_src)[3],	(_dst)[1] = (_src)[2], \
+	(_dst)[2] = (_src)[1],	(_dst)[3] = (_src)[0])
+#if	defined(_ELF64)
+#define	UL_ASSIGN_BSWAP_XWORD(_dst, _src) (void) \
+	((_dst)[0] = (_src)[7],	(_dst)[1] = (_src)[6], \
+	(_dst)[2] = (_src)[5],	(_dst)[3] = (_src)[4], \
+	(_dst)[4] = (_src)[3],	(_dst)[5] = (_src)[2], \
+	(_dst)[6] = (_src)[1],	(_dst)[7] = (_src)[0])
+#else
+#define	UL_ASSIGN_BSWAP_XWORD(_dst, _src) UL_ASSIGN_BSWAP_WORD(_dst, _src)
+#endif
+
+
+#endif /* _MACHELF_H */
--- a/usr/src/cmd/sgs/include/conv.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/include/conv.h	Tue Mar 18 09:17:00 2008 -0700
@@ -23,7 +23,7 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -41,7 +41,6 @@
 #include <dlfcn.h>
 #include <libld.h>
 #include <sgs.h>
-#include <machdep.h>
 
 #ifdef	__cplusplus
 extern "C" {
@@ -785,7 +784,8 @@
 			    Conv_phdr_flags_buf_t *);
 extern	const char	*conv_phdr_type(Half, Word, Conv_fmt_flags_t,
 			    Conv_inv_buf_t *);
-extern	const char	*conv_reject_desc(Rej_desc *, Conv_reject_desc_buf_t *);
+extern	const char	*conv_reject_desc(Rej_desc *, Conv_reject_desc_buf_t *,
+			    Half mach);
 extern	const char	*conv_reloc_type(Half, Word, Conv_fmt_flags_t,
 			    Conv_inv_buf_t *);
 extern	const char	*conv_reloc_type_static(Half, Word, Conv_fmt_flags_t);
--- a/usr/src/cmd/sgs/include/debug.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/include/debug.h	Tue Mar 18 09:17:00 2008 -0700
@@ -696,11 +696,11 @@
 extern	void	Dbg_file_output(Ofl_desc *);
 extern	void	Dbg_file_preload(Lm_list *, const char *);
 extern	void	Dbg_file_prot(Rt_map *, int);
-extern	void	Dbg_file_rejected(Lm_list *, Rej_desc *);
+extern	void	Dbg_file_rejected(Lm_list *, Rej_desc *, Half mach);
 extern	void	Dbg_file_reuse(Lm_list *, const char *, const char *);
 extern	void	Dbg_file_skip(Lm_list *, const char *, const char *);
 
-extern	void	Dbg_got_display(Ofl_desc *, Off, int);
+extern	void	Dbg_got_display(Ofl_desc *, Off, int, Word, size_t);
 
 extern	void	Dbg_libs_audit(Lm_list *, const char *, const char *);
 extern	void	Dbg_libs_find(Lm_list *, const char *);
@@ -973,8 +973,8 @@
 
 extern	void	Elf_ehdr(Lm_list *, Ehdr *, Shdr *);
 
-extern	void	Elf_got_entry(Lm_list *, Sword, Addr, Xword, Half, Word, void *,
-		    const char *);
+extern	void	Elf_got_entry(Lm_list *, Sword, Addr, Xword, Half,
+		    uchar_t, uchar_t, Word, void *, const char *);
 extern	void	Elf_got_title(Lm_list *);
 
 extern	void	Elf_phdr(Lm_list *, Half, Phdr *);
--- a/usr/src/cmd/sgs/include/i386/machdep.h	Tue Mar 18 08:44:14 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +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 (c) 1988 AT&T
- *	  All Rights Reserved
- *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- *
- * Global include file for all sgs ia32 based machine dependent macros,
- * constants and declarations.
- */
-
-#ifndef	_MACHDEP_H
-#define	_MACHDEP_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <link.h>
-#include <sys/machelf.h>
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Elf header information.
- */
-#ifdef _ELF64
-#define	M_MACH			EM_AMD64
-#define	M_CLASS			ELFCLASS64
-#else
-#define	M_MACH			EM_386
-#define	M_CLASS			ELFCLASS32
-#endif
-
-#define	M_MACHPLUS		M_MACH
-#define	M_DATA			ELFDATA2LSB
-#define	M_FLAGSPLUS		0
-
-/*
- * Page boundary Macros: truncate to previous page boundary and round to
- * next page boundary (refer to generic macros in ../sgs.h also).
- */
-#define	M_PTRUNC(X)	((X) & ~(syspagsz - 1))
-#define	M_PROUND(X)	(((X) + syspagsz - 1) & ~(syspagsz - 1))
-
-/*
- * Segment boundary macros: truncate to previous segment boundary and round
- * to next page boundary.
- */
-#if	defined(_ELF64)
-#define	M_SEGSIZE	ELF_AMD64_MAXPGSZ
-#else
-#define	M_SEGSIZE	ELF_386_MAXPGSZ
-#endif
-
-#define	M_STRUNC(X)	((X) & ~(M_SEGSIZE - 1))
-#define	M_SROUND(X)	(((X) + M_SEGSIZE - 1) & ~(M_SEGSIZE - 1))
-
-/*
- * TLS static segments must be rounded to the following requirements,
- * due to libthread stack allocation.
- */
-#if	defined(_ELF64)
-#define	M_TLSSTATALIGN	0x10
-#else
-#define	M_TLSSTATALIGN	0x08
-#endif
-
-
-/*
- * Other machine dependent entities
- */
-#if	defined(_ELF64)
-#define	M_SEGM_ALIGN	0x00010000
-#else
-#define	M_SEGM_ALIGN	ELF_386_MAXPGSZ
-#endif
-
-/*
- * Values for IA32 objects
- */
-
-/*
- * Instruction encodings.
- */
-#define	M_INST_JMP		0xe9
-#define	M_INST_PUSHL		0x68
-#define	M_SPECIAL_INST		0xff
-#define	M_PUSHL_DISP		0x35
-#define	M_PUSHL_REG_DISP	0xb3
-#define	M_JMP_DISP_IND		0x25
-#define	M_JMP_REG_DISP_IND	0xa3
-#define	M_NOP			0x90
-
-#define	M_BIND_ADJ	1		/* adjustment for end of */
-					/*	elf_rtbndr() address */
-#ifdef _ELF64
-#define	M_WORD_ALIGN	8
-#define	M_SEGM_ORIGIN	(Addr)0x00400000  /* default first segment offset */
-#else
-
-#define	M_WORD_ALIGN	4
-
-#define	M_STACK_GAP	(0x08000000)
-#define	M_STACK_PGS	(0x00048000)
-#define	M_SEGM_ORIGIN	(Addr)(M_STACK_GAP + M_STACK_PGS)
-#endif
-
-
-/*
- * Plt and Got information; the first few .got and .plt entries are reserved
- *	PLT[0]	jump to dynamic linker
- *	GOT[0]	address of _DYNAMIC
- */
-#define	M_PLT_ENTSIZE	16		/* plt entry size in bytes */
-#define	M_PLT_ALIGN	M_WORD_ALIGN	/* alignment of .plt section */
-#define	M_PLT_INSSIZE	6		/* single plt instruction size */
-#define	M_PLT_RESERVSZ	M_PLT_ENTSIZE	/* PLT[0] reserved */
-
-#define	M_GOT_XDYNAMIC	0		/* got index for _DYNAMIC */
-#define	M_GOT_XLINKMAP	1		/* got index for link map */
-#define	M_GOT_XRTLD	2		/* got index for rtbinder */
-#define	M_GOT_XNumber	3		/* reserved no. of got entries */
-
-#ifdef	_ELF64
-#define	M_GOT_ENTSIZE	8		/* got entry size in bytes */
-#else /* ELF32 */
-#define	M_GOT_ENTSIZE	4		/* got entry size in bytes */
-#endif
-
-/*
- * Make machine class dependent functions transparent to the common code
- */
-#if	defined(_ELF64)
-#define	ELF_R_TYPE		ELF64_R_TYPE
-#define	ELF_R_INFO		ELF64_R_INFO
-#define	ELF_R_SYM		ELF64_R_SYM
-#define	ELF_ST_BIND		ELF64_ST_BIND
-#define	ELF_ST_TYPE		ELF64_ST_TYPE
-#define	ELF_ST_INFO		ELF64_ST_INFO
-#define	ELF_ST_VISIBILITY	ELF64_ST_VISIBILITY
-#define	ELF_M_SYM		ELF64_M_SYM
-#define	ELF_M_SIZE		ELF64_M_SIZE
-#define	ELF_M_INFO		ELF64_M_INFO
-#define	elf_checksum		elf64_checksum
-#define	elf_fsize		elf64_fsize
-#define	elf_getehdr		elf64_getehdr
-#define	elf_getphdr		elf64_getphdr
-#define	elf_newehdr		elf64_newehdr
-#define	elf_newphdr		elf64_newphdr
-#define	elf_getshdr		elf64_getshdr
-#define	elf_xlatetof		elf64_xlatetof
-#define	elf_xlatetom		elf64_xlatetom
-#else /* _ELF64 */
-#define	ELF_R_TYPE		ELF32_R_TYPE
-#define	ELF_R_INFO		ELF32_R_INFO
-#define	ELF_R_SYM		ELF32_R_SYM
-#define	ELF_ST_BIND		ELF32_ST_BIND
-#define	ELF_ST_TYPE		ELF32_ST_TYPE
-#define	ELF_ST_INFO		ELF32_ST_INFO
-#define	ELF_ST_VISIBILITY	ELF32_ST_VISIBILITY
-#define	ELF_M_SYM		ELF32_M_SYM
-#define	ELF_M_SIZE		ELF32_M_SIZE
-#define	ELF_M_INFO		ELF32_M_INFO
-#define	elf_checksum		elf32_checksum
-#define	elf_fsize		elf32_fsize
-#define	elf_getehdr		elf32_getehdr
-#define	elf_getphdr		elf32_getphdr
-#define	elf_newehdr		elf32_newehdr
-#define	elf_newphdr		elf32_newphdr
-#define	elf_getshdr		elf32_getshdr
-#define	elf_xlatetof		elf32_xlatetof
-#define	elf_xlatetom		elf32_xlatetom
-#endif	/* _ELF32 */
-
-
-/*
- * Make common relocation information transparent to the common code
- */
-#if	defined(_ELF64)
-#define	M_REL_DT_TYPE	DT_RELA		/* .dynamic entry */
-#define	M_REL_DT_SIZE	DT_RELASZ	/* .dynamic entry */
-#define	M_REL_DT_ENT	DT_RELAENT	/* .dynamic entry */
-#define	M_REL_DT_COUNT	DT_RELACOUNT	/* .dynamic entry */
-#define	M_REL_SHT_TYPE	SHT_RELA	/* section header type */
-#define	M_REL_ELF_TYPE	ELF_T_RELA	/* data buffer type */
-
-#else /* _ELF32 */
-#define	M_REL_DT_TYPE	DT_REL		/* .dynamic entry */
-#define	M_REL_DT_SIZE	DT_RELSZ	/* .dynamic entry */
-#define	M_REL_DT_ENT	DT_RELENT	/* .dynamic entry */
-#define	M_REL_DT_COUNT	DT_RELCOUNT	/* .dynamic entry */
-#define	M_REL_SHT_TYPE	SHT_REL		/* section header type */
-#define	M_REL_ELF_TYPE	ELF_T_REL	/* data buffer type */
-
-#endif /* ELF32 */
-
-/*
- * Make common relocation types transparent to the common code
- */
-#if	defined(_ELF64)
-#define	M_R_NONE	R_AMD64_NONE
-#define	M_R_GLOB_DAT	R_AMD64_GLOB_DAT
-#define	M_R_COPY	R_AMD64_COPY
-#define	M_R_RELATIVE	R_AMD64_RELATIVE
-#define	M_R_JMP_SLOT	R_AMD64_JUMP_SLOT
-#define	M_R_FPTR	R_AMD64_NONE
-#define	M_R_ARRAYADDR	R_AMD64_GLOB_DAT
-#define	M_R_NUM		R_AMD64_NUM
-#else
-#define	M_R_NONE	R_386_NONE
-#define	M_R_GLOB_DAT	R_386_GLOB_DAT
-#define	M_R_COPY	R_386_COPY
-#define	M_R_RELATIVE	R_386_RELATIVE
-#define	M_R_JMP_SLOT	R_386_JMP_SLOT
-#define	M_R_FPTR	R_386_NONE
-#define	M_R_ARRAYADDR	R_386_GLOB_DAT
-#define	M_R_NUM		R_386_NUM
-#endif
-
-/*
- * The following are defined as M_R_NONE so that checks
- * for these relocations can be performed in common code - although
- * the checks are really only relevant to SPARC.
- */
-#define	M_R_REGISTER	M_R_NONE
-
-/*
- * DT_REGISTER is not valid on i386 or amd64
- */
-#define	M_DT_REGISTER	0xffffffff
-#define	M_DT_PLTRESERVE	0xfffffffe
-
-/*
- * Make plt section information transparent to the common code.
- */
-#define	M_PLT_SHF_FLAGS	(SHF_ALLOC | SHF_EXECINSTR)
-
-
-/*
- * Make data segment information transparent to the common code.
- */
-#ifdef _ELF64
-#define	M_DATASEG_PERM	(PF_R | PF_W)
-#else
-#define	M_DATASEG_PERM	(PF_R | PF_W | PF_X)
-#endif
-
-/*
- * Define a set of identifies for special sections.  These allow the sections
- * to be ordered within the output file image.  These values should be
- * maintained consistently, where appropriate, in each platform specific header
- * file.
- *
- *  o	null identifies that this section does not need to be added to the
- *	output image (ie. shared object sections or sections we're going to
- *	recreate (sym tables, string tables, relocations, etc.)).
- *
- *  o	any user defined section will be first in the associated segment.
- *
- *  o	interp and capabilities sections are next, as these are accessed
- *	immediately the first page of the image is mapped.
- *
- *  o	the syminfo, hash, dynsym, dynstr and rel's are grouped together as
- *	these will all be accessed first by ld.so.1 to perform relocations.
- *
- *  o	the got and dynamic are grouped together as these may also be
- *	accessed first by ld.so.1 to perform relocations, fill in DT_DEBUG
- *	(executables only), and .got[0].
- *
- *  o	unknown sections (stabs, comments, etc.) go at the end.
- *
- * Note that .tlsbss/.bss are given the largest identifiers.  This insures that
- * if any unknown sections become associated to the same segment as the .bss,
- * the .bss sections are always the last section in the segment.
- */
-#define	M_ID_NULL	0x00
-#define	M_ID_USER	0x01
-
-#define	M_ID_INTERP	0x03			/* SHF_ALLOC */
-#define	M_ID_CAP	0x04
-#define	M_ID_UNWINDHDR	0x05
-#define	M_ID_UNWIND	0x06
-#define	M_ID_SYMINFO	0x07
-#define	M_ID_HASH	0x08
-#define	M_ID_LDYNSYM	0x09			/* always right before DYNSYM */
-#define	M_ID_DYNSYM	0x0a
-#define	M_ID_DYNSTR	0x0b
-#define	M_ID_VERSION	0x0c
-#define	M_ID_DYNSORT	0x0d
-#define	M_ID_REL	0x0e
-#define	M_ID_PLT	0x0f			/* SHF_ALLOC + SHF_EXECISNTR */
-#define	M_ID_TEXT	0x10
-#define	M_ID_DATA	0x20
-
-/*	M_ID_USER	0x02			dual entry - listed above */
-#define	M_ID_GOT	0x03			/* SHF_ALLOC + SHF_WRITE */
-#define	M_ID_DYNAMIC	0x05
-#define	M_ID_ARRAY	0x06
-
-#define	M_ID_UNKNOWN	0xfb			/* just before TLS */
-
-#define	M_ID_TLS	0xfc			/* just before bss */
-#define	M_ID_TLSBSS	0xfd
-#define	M_ID_BSS	0xfe
-#define	M_ID_LBSS	0xff
-
-#define	M_ID_SYMTAB_NDX	0x02			/* ! SHF_ALLOC */
-#define	M_ID_SYMTAB	0x03
-#define	M_ID_STRTAB	0x04
-#define	M_ID_DYNSYM_NDX	0x05
-#define	M_ID_NOTE	0x06
-
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif /* _MACHDEP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/include/i386/machdep_x86.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,297 @@
+/*
+ * 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 (c) 1988 AT&T
+ *	  All Rights Reserved
+ *
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Global include file for all sgs ia32 based machine dependent macros,
+ * constants and declarations.
+ */
+
+#ifndef	_MACHDEP_X86_H
+#define	_MACHDEP_X86_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <link.h>
+#include <sys/machelf.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Elf header information.
+ */
+#define	M_MACH_32		EM_386
+#define	M_MACH_64		EM_AMD64
+
+#ifdef _ELF64
+#define	M_MACH			EM_AMD64
+#define	M_CLASS			ELFCLASS64
+#else
+#define	M_MACH			EM_386
+#define	M_CLASS			ELFCLASS32
+#endif
+
+#define	M_MACHPLUS		M_MACH
+#define	M_DATA			ELFDATA2LSB
+#define	M_FLAGSPLUS		0
+
+/*
+ * Page boundary Macros: truncate to previous page boundary and round to
+ * next page boundary (refer to generic macros in ../sgs.h also).
+ */
+#define	M_PTRUNC(X)	((X) & ~(syspagsz - 1))
+#define	M_PROUND(X)	(((X) + syspagsz - 1) & ~(syspagsz - 1))
+
+/*
+ * Segment boundary macros: truncate to previous segment boundary and round
+ * to next page boundary.
+ */
+#if	defined(_ELF64)
+#define	M_SEGSIZE	ELF_AMD64_MAXPGSZ
+#else
+#define	M_SEGSIZE	ELF_386_MAXPGSZ
+#endif
+
+#define	M_STRUNC(X)	((X) & ~(M_SEGSIZE - 1))
+#define	M_SROUND(X)	(((X) + M_SEGSIZE - 1) & ~(M_SEGSIZE - 1))
+
+/*
+ * TLS static segments must be rounded to the following requirements,
+ * due to libthread stack allocation.
+ */
+#if	defined(_ELF64)
+#define	M_TLSSTATALIGN	0x10
+#else
+#define	M_TLSSTATALIGN	0x08
+#endif
+
+
+/*
+ * Other machine dependent entities
+ */
+#if	defined(_ELF64)
+#define	M_SEGM_ALIGN	0x00010000
+#else
+#define	M_SEGM_ALIGN	ELF_386_MAXPGSZ
+#endif
+
+/*
+ * Values for IA32 objects
+ */
+
+/*
+ * Instruction encodings.
+ */
+#define	M_INST_JMP		0xe9
+#define	M_INST_PUSHL		0x68
+#define	M_SPECIAL_INST		0xff
+#define	M_PUSHL_DISP		0x35
+#define	M_PUSHL_REG_DISP	0xb3
+#define	M_JMP_DISP_IND		0x25
+#define	M_JMP_REG_DISP_IND	0xa3
+#define	M_NOP			0x90
+
+#define	M_BIND_ADJ	1		/* adjustment for end of */
+					/*	elf_rtbndr() address */
+#ifdef _ELF64
+#define	M_WORD_ALIGN	8
+#define	M_SEGM_ORIGIN	(Addr)0x00400000  /* default first segment offset */
+#else
+
+#define	M_WORD_ALIGN	4
+
+#define	M_STACK_GAP	(0x08000000)
+#define	M_STACK_PGS	(0x00048000)
+#define	M_SEGM_ORIGIN	(Addr)(M_STACK_GAP + M_STACK_PGS)
+#endif
+
+
+/*
+ * Plt and Got information; the first few .got and .plt entries are reserved
+ *	PLT[0]	jump to dynamic linker
+ *	GOT[0]	address of _DYNAMIC
+ */
+#define	M_PLT_ENTSIZE	16		/* plt entry size in bytes */
+#define	M_PLT_ALIGN	M_WORD_ALIGN	/* alignment of .plt section */
+#define	M_PLT_INSSIZE	6		/* single plt instruction size */
+#define	M_PLT_RESERVSZ	M_PLT_ENTSIZE	/* PLT[0] reserved */
+
+#define	M_GOT_XDYNAMIC	0		/* got index for _DYNAMIC */
+#define	M_GOT_XLINKMAP	1		/* got index for link map */
+#define	M_GOT_XRTLD	2		/* got index for rtbinder */
+#define	M_GOT_XNumber	3		/* reserved no. of got entries */
+
+#ifdef	_ELF64
+#define	M_GOT_ENTSIZE	8		/* got entry size in bytes */
+#else /* ELF32 */
+#define	M_GOT_ENTSIZE	4		/* got entry size in bytes */
+#endif
+
+/*
+ * Make common relocation information transparent to the common code
+ */
+#if	defined(_ELF64)
+#define	M_REL_DT_TYPE	DT_RELA		/* .dynamic entry */
+#define	M_REL_DT_SIZE	DT_RELASZ	/* .dynamic entry */
+#define	M_REL_DT_ENT	DT_RELAENT	/* .dynamic entry */
+#define	M_REL_DT_COUNT	DT_RELACOUNT	/* .dynamic entry */
+#define	M_REL_SHT_TYPE	SHT_RELA	/* section header type */
+#define	M_REL_ELF_TYPE	ELF_T_RELA	/* data buffer type */
+
+#else /* _ELF32 */
+#define	M_REL_DT_TYPE	DT_REL		/* .dynamic entry */
+#define	M_REL_DT_SIZE	DT_RELSZ	/* .dynamic entry */
+#define	M_REL_DT_ENT	DT_RELENT	/* .dynamic entry */
+#define	M_REL_DT_COUNT	DT_RELCOUNT	/* .dynamic entry */
+#define	M_REL_SHT_TYPE	SHT_REL		/* section header type */
+#define	M_REL_ELF_TYPE	ELF_T_REL	/* data buffer type */
+
+#endif /* ELF32 */
+
+/*
+ * Make common relocation types transparent to the common code
+ */
+#if	defined(_ELF64)
+#define	M_R_NONE	R_AMD64_NONE
+#define	M_R_GLOB_DAT	R_AMD64_GLOB_DAT
+#define	M_R_COPY	R_AMD64_COPY
+#define	M_R_RELATIVE	R_AMD64_RELATIVE
+#define	M_R_JMP_SLOT	R_AMD64_JUMP_SLOT
+#define	M_R_FPTR	R_AMD64_NONE
+#define	M_R_ARRAYADDR	R_AMD64_GLOB_DAT
+#define	M_R_NUM		R_AMD64_NUM
+#else
+#define	M_R_NONE	R_386_NONE
+#define	M_R_GLOB_DAT	R_386_GLOB_DAT
+#define	M_R_COPY	R_386_COPY
+#define	M_R_RELATIVE	R_386_RELATIVE
+#define	M_R_JMP_SLOT	R_386_JMP_SLOT
+#define	M_R_FPTR	R_386_NONE
+#define	M_R_ARRAYADDR	R_386_GLOB_DAT
+#define	M_R_NUM		R_386_NUM
+#endif
+
+/*
+ * The following are defined as M_R_NONE so that checks
+ * for these relocations can be performed in common code - although
+ * the checks are really only relevant to SPARC.
+ */
+#define	M_R_REGISTER	M_R_NONE
+
+/*
+ * DT_REGISTER is not valid on i386 or amd64
+ */
+#define	M_DT_REGISTER	0xffffffff
+#define	M_DT_PLTRESERVE	0xfffffffe
+
+/*
+ * Make plt section information transparent to the common code.
+ */
+#define	M_PLT_SHF_FLAGS	(SHF_ALLOC | SHF_EXECINSTR)
+
+
+/*
+ * Make data segment information transparent to the common code.
+ */
+#ifdef _ELF64
+#define	M_DATASEG_PERM	(PF_R | PF_W)
+#else
+#define	M_DATASEG_PERM	(PF_R | PF_W | PF_X)
+#endif
+
+/*
+ * Define a set of identifies for special sections.  These allow the sections
+ * to be ordered within the output file image.  These values should be
+ * maintained consistently, where appropriate, in each platform specific header
+ * file.
+ *
+ *  o	null identifies that this section does not need to be added to the
+ *	output image (ie. shared object sections or sections we're going to
+ *	recreate (sym tables, string tables, relocations, etc.)).
+ *
+ *  o	any user defined section will be first in the associated segment.
+ *
+ *  o	interp and capabilities sections are next, as these are accessed
+ *	immediately the first page of the image is mapped.
+ *
+ *  o	the syminfo, hash, dynsym, dynstr and rel's are grouped together as
+ *	these will all be accessed first by ld.so.1 to perform relocations.
+ *
+ *  o	the got and dynamic are grouped together as these may also be
+ *	accessed first by ld.so.1 to perform relocations, fill in DT_DEBUG
+ *	(executables only), and .got[0].
+ *
+ *  o	unknown sections (stabs, comments, etc.) go at the end.
+ *
+ * Note that .tlsbss/.bss are given the largest identifiers.  This insures that
+ * if any unknown sections become associated to the same segment as the .bss,
+ * the .bss sections are always the last section in the segment.
+ */
+#define	M_ID_NULL	0x00
+#define	M_ID_USER	0x01
+
+#define	M_ID_INTERP	0x03			/* SHF_ALLOC */
+#define	M_ID_CAP	0x04
+#define	M_ID_UNWINDHDR	0x05
+#define	M_ID_UNWIND	0x06
+#define	M_ID_SYMINFO	0x07
+#define	M_ID_HASH	0x08
+#define	M_ID_LDYNSYM	0x09			/* always right before DYNSYM */
+#define	M_ID_DYNSYM	0x0a
+#define	M_ID_DYNSTR	0x0b
+#define	M_ID_VERSION	0x0c
+#define	M_ID_DYNSORT	0x0d
+#define	M_ID_REL	0x0e
+#define	M_ID_PLT	0x0f			/* SHF_ALLOC + SHF_EXECISNTR */
+#define	M_ID_TEXT	0x10
+#define	M_ID_DATA	0x20
+
+/*	M_ID_USER	0x02			dual entry - listed above */
+#define	M_ID_GOT	0x03			/* SHF_ALLOC + SHF_WRITE */
+#define	M_ID_DYNAMIC	0x05
+#define	M_ID_ARRAY	0x06
+
+#define	M_ID_UNKNOWN	0xfb			/* just before TLS */
+
+#define	M_ID_TLS	0xfc			/* just before bss */
+#define	M_ID_TLSBSS	0xfd
+#define	M_ID_BSS	0xfe
+#define	M_ID_LBSS	0xff
+
+#define	M_ID_SYMTAB_NDX	0x02			/* ! SHF_ALLOC */
+#define	M_ID_SYMTAB	0x03
+#define	M_ID_STRTAB	0x04
+#define	M_ID_DYNSYM_NDX	0x05
+#define	M_ID_NOTE	0x06
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _MACHDEP_X86_H */
--- a/usr/src/cmd/sgs/include/libld.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/include/libld.h	Tue Mar 18 09:17:00 2008 -0700
@@ -35,7 +35,7 @@
 #include <stdlib.h>
 #include <libelf.h>
 #include <sgs.h>
-#include <machdep.h>
+#include <_machelf.h>
 #include <string_table.h>
 #include <sys/avl.h>
 #include <alist.h>
@@ -177,7 +177,7 @@
 	List		ofl_rtldinfo;	/* list of rtldinfo syms */
 	List		ofl_osgroups;	/* list of output GROUP sections */
 	List		ofl_ostlsseg;	/* pointer to sections in TLS segment */
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)			/* for amd64 target only */
 	List		ofl_unwind;	/* list of unwind output sections */
 	Os_desc		*ofl_unwindhdr;	/* Unwind hdr */
 #endif
@@ -400,14 +400,6 @@
 	!((_ofl)->ofl_dtflags_1 & DF_1_NORELOC))
 
 /*
- * Determine whether relocation processing needs to swap the
- * data being relocated.
- */
-#define	OFL_SWAP_RELOC_DATA(_ofl, _rel) \
-	((((_ofl)->ofl_flags1 & FLG_OF1_ENCDIFF) != 0) && \
-	((_rel)->rel_osdesc->os_shdr->sh_type == SHT_PROGBITS))
-
-/*
  * Relocation (active & output) processing structure - transparent to common
  * code.
  *
@@ -1093,6 +1085,7 @@
 #define	ld_create_outfile	ld64_create_outfile
 #define	ld_ent_setup		ld64_ent_setup
 #define	ld_init_strings		ld64_init_strings
+#define	ld_init_target		ld64_init_target
 #define	ld_make_sections	ld64_make_sections
 #define	ld_main			ld64_main
 #define	ld_ofl_cleanup		ld64_ofl_cleanup
@@ -1107,6 +1100,7 @@
 #define	ld_create_outfile	ld32_create_outfile
 #define	ld_ent_setup		ld32_ent_setup
 #define	ld_init_strings		ld32_init_strings
+#define	ld_init_target		ld32_init_target
 #define	ld_make_sections	ld32_make_sections
 #define	ld_main			ld32_main
 #define	ld_ofl_cleanup		ld32_ofl_cleanup
@@ -1118,12 +1112,13 @@
 
 #endif
 
-extern int		ld32_main(int, char **);
-extern int		ld64_main(int, char **);
+extern int		ld32_main(int, char **, Half);
+extern int		ld64_main(int, char **, Half);
 
 extern uintptr_t	ld_create_outfile(Ofl_desc *);
 extern uintptr_t	ld_ent_setup(Ofl_desc *, Xword);
 extern uintptr_t	ld_init_strings(Ofl_desc *);
+extern int		ld_init_target(Lm_list *, Half mach);
 extern uintptr_t	ld_make_sections(Ofl_desc *);
 extern void		ld_ofl_cleanup(Ofl_desc *);
 extern Ifl_desc		*ld_process_open(const char *, const char *, int *,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/include/machdep.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * Global include file for all sgs machine dependent macros, constants
+ * and declarations applicable to the current system. This header is
+ * to be used for code that supports the native system only. Code that
+ * needs to support non-native targets should avoid it, and use the
+ * target-specific versions found in the subdirectories below the include
+ * directory holding this file.
+ */
+
+#ifndef	_MACHDEP_H
+#define	_MACHDEP_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#if defined(__sparc)
+
+#include <sparc/machdep_sparc.h>
+
+#elif defined(__i386) || defined(__amd64)
+
+#include <i386/machdep_x86.h>
+
+#else
+
+#error "machdep.h does not understand current machine"
+
+#endif
+
+#endif /* _MACHDEP_H */
--- a/usr/src/cmd/sgs/include/rtld.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/include/rtld.h	Tue Mar 18 09:17:00 2008 -0700
@@ -36,7 +36,7 @@
 #include <sgs.h>
 #include <thread.h>
 #include <synch.h>
-#include <machdep.h>
+#include <link.h>
 #include <sys/avl.h>
 #include <alist.h>
 #include <libc_int.h>
--- a/usr/src/cmd/sgs/include/sparc/machdep.h	Tue Mar 18 08:44:14 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +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 (c) 1988 AT&T
- *	  All Rights Reserved
- *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- *
- * Global include file for all sgs SPARC machine dependent macros, constants
- * and declarations.
- */
-
-#ifndef	_MACHDEP_H
-#define	_MACHDEP_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <link.h>
-#include <sys/machelf.h>
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Elf header information.
- */
-#ifdef _ELF64
-#define	M_MACH			EM_SPARCV9
-#define	M_CLASS			ELFCLASS64
-#else
-#define	M_MACH			EM_SPARC
-#define	M_CLASS			ELFCLASS32
-#endif
-#define	M_MACHPLUS		EM_SPARC32PLUS
-#define	M_DATA			ELFDATA2MSB
-#define	M_FLAGSPLUS		EF_SPARC_32PLUS
-
-/*
- * Page boundary Macros: truncate to previous page boundary and round to
- * next page boundary (refer to generic macros in ../sgs.h also).
- */
-#define	M_PTRUNC(X)	((X) & ~(syspagsz - 1))
-#define	M_PROUND(X)	(((X) + syspagsz - 1) & ~(syspagsz - 1))
-
-/*
- * Segment boundary macros: truncate to previous segment boundary and round
- * to next page boundary.
- */
-#ifndef	M_SEGSIZE
-#define	M_SEGSIZE	ELF_SPARC_MAXPGSZ
-#endif
-#define	M_STRUNC(X)	((X) & ~(M_SEGSIZE - 1))
-#define	M_SROUND(X)	(((X) + M_SEGSIZE - 1) & ~(M_SEGSIZE - 1))
-
-
-/*
- * TLS static segments must be rounded to the following requirements,
- * due to libthread stack allocation.
- */
-#if	defined(_ELF64)
-#define	M_TLSSTATALIGN	0x10
-#else
-#define	M_TLSSTATALIGN	0x08
-#endif
-
-
-/*
- * Instruction encodings.
- */
-#define	M_SAVESP64	0x9de3bfc0	/* save %sp, -64, %sp */
-#define	M_CALL		0x40000000
-#define	M_JMPL		0x81c06000	/* jmpl %g1 + simm13, %g0 */
-#define	M_SETHIG0	0x01000000	/* sethi %hi(val), %g0 */
-#define	M_SETHIG1	0x03000000	/* sethi %hi(val), %g1 */
-#define	M_STO7G1IM	0xde206000	/* st	 %o7,[%g1 + %lo(val)] */
-#define	M_SUBFPSPG1	0x8227800e	/* sub	%fp,%sp,%g1 */
-#define	M_NOP		0x01000000	/* sethi 0, %o0 (nop) */
-#define	M_BA_A		0x30800000	/* ba,a */
-#define	M_BA_A_PT	0x30480000	/* ba,a %icc, <dst> */
-#define	M_MOVO7TOG1	0x8210000f	/* mov %o7, %g1 */
-#define	M_MOVO7TOG5	0x8a10000f	/* mov %o7, %g5 */
-#define	M_MOVI7TOG1	0x8210001f	/* mov %i7, %g1 */
-#define	M_BA_A_XCC	0x30680000	/* ba,a %xcc */
-#define	M_JMPL_G5G0	0x81c16000	/* jmpl %g5 + 0, %g0 */
-#define	M_XNOR_G5G1	0x82396000	/* xnor	%g5, 0, %g1 */
-
-
-#define	M_BIND_ADJ	4		/* adjustment for end of */
-					/*	elf_rtbndr() address */
-
-
-/*
- * Plt and Got information; the first few .got and .plt entries are reserved
- *	PLT[0]	jump to dynamic linker
- *	GOT[0]	address of _DYNAMIC
- */
-#define	M_PLT_INSSIZE	4		/* single plt instruction size */
-#define	M_GOT_XDYNAMIC	0		/* got index for _DYNAMIC */
-#define	M_GOT_XNumber	1		/* reserved no. of got entries */
-
-/*
- * ELF32 bit PLT constants
- */
-#define	M32_PLT_ENTSIZE		12	/* 32bit plt entry size in bytes */
-
-/*
- * ELF64 bit PLT constants
- */
-#define	M64_PLT_NEARPLTS	0x8000	/* # of NEAR PLTS we can have */
-#define	M64_PLT_ENTSIZE		32	/* plt entry size in bytes */
-#define	M64_PLT_FENTSIZE	24	/* size of far plt is 6 instructions */
-					/*	x 4bytes */
-#define	M64_PLT_PSIZE		8		/* size of PLTP pointer */
-#define	M64_PLT_FBLKCNTS	160	/* # of plts in far PLT blocks */
-#define	M64_PLT_FBLOCKSZ	(M64_PLT_FBLKCNTS *\
-				M64_PLT_ENTSIZE) /* size of far PLT block */
-
-
-#ifdef _ELF64
-#define	M_PLT_ENTSIZE	M64_PLT_ENTSIZE	/* plt entry size in bytes */
-#define	M_PLT_XNumber	4		/* reserved no. of plt entries */
-#define	M_PLT_ALIGN	256		/* alignment of .plt section */
-#define	M_PLT_RESERVSZ	(M_PLT_XNumber * \
-			M_PLT_ENTSIZE)	/* first 4 plt's reserved */
-#define	M_GOT_ENTSIZE	8		/* got entry size in bytes */
-#define	M_GOT_MAXSMALL	1024		/* maximum no. of small gots */
-#else /* Elf32 */
-#define	M_PLT_ENTSIZE	M32_PLT_ENTSIZE	/* plt entry size in bytes */
-#define	M_PLT_XNumber	4		/* reserved no. of plt entries */
-#define	M_PLT_ALIGN	M_WORD_ALIGN	/* alignment of .plt section */
-#define	M_PLT_RESERVSZ	(M_PLT_XNumber * \
-			M_PLT_ENTSIZE)	/* first 4 plt's reserved */
-#define	M_GOT_ENTSIZE	4		/* got entry size in bytes */
-#define	M_GOT_MAXSMALL	2048		/* maximum no. of small gots */
-#endif /* _ELF64 */
-					/* transition flags for got sizing */
-#define	M_GOT_LARGE	(Sword)(-M_GOT_MAXSMALL - 1)
-#define	M_GOT_SMALL	(Sword)(-M_GOT_MAXSMALL - 2)
-#define	M_GOT_MIXED	(Sword)(-M_GOT_MAXSMALL - 3)
-
-
-/*
- * Other machine dependent entities
- */
-#ifdef _ELF64
-#define	M_SEGM_ALIGN	ELF_SPARCV9_MAXPGSZ
-/*
- * Put 64-bit programs above 4 gigabytes to help insure correctness,
- * so any 64-bit programs that truncate pointers will fault now instead of
- * corrupting itself and dying mysteriously.
- */
-#define	M_SEGM_ORIGIN	(Addr)0x100000000ULL  /* default first segment offset */
-#define	M_WORD_ALIGN	8
-#else
-#define	M_SEGM_ALIGN	ELF_SPARC_MAXPGSZ
-#define	M_SEGM_ORIGIN	(Addr)0x10000	/* default first segment offset */
-#define	M_WORD_ALIGN	4
-#endif
-
-/*
- * Make machine class dependent functions transparent to the common code
- */
-#ifdef _ELF64
-#define	ELF_R_TYPE		ELF64_R_TYPE_ID
-#define	ELF_R_INFO		ELF64_R_INFO
-#define	ELF_R_SYM		ELF64_R_SYM
-#define	ELF_R_TYPE_DATA		ELF64_R_TYPE_DATA
-#define	ELF_R_TYPE_INFO		ELF64_R_TYPE_INFO
-#define	ELF_ST_BIND		ELF64_ST_BIND
-#define	ELF_ST_TYPE		ELF64_ST_TYPE
-#define	ELF_ST_INFO		ELF64_ST_INFO
-#define	ELF_ST_VISIBILITY	ELF64_ST_VISIBILITY
-#define	ELF_M_SYM		ELF64_M_SYM
-#define	ELF_M_SIZE		ELF64_M_SIZE
-#define	ELF_M_INFO		ELF64_M_INFO
-#define	elf_checksum		elf64_checksum
-#define	elf_fsize		elf64_fsize
-#define	elf_getehdr		elf64_getehdr
-#define	elf_getphdr		elf64_getphdr
-#define	elf_newehdr		elf64_newehdr
-#define	elf_newphdr		elf64_newphdr
-#define	elf_getshdr		elf64_getshdr
-#define	elf_xlatetom		elf64_xlatetom
-#else	/* Elf32 */
-#define	ELF_R_TYPE		ELF32_R_TYPE
-#define	ELF_R_INFO		ELF32_R_INFO
-#define	ELF_R_SYM		ELF32_R_SYM
-#define	ELF_M_SYM		ELF32_M_SYM
-#define	ELF_M_SIZE		ELF32_M_SIZE
-#define	ELF_M_INFO		ELF32_M_INFO
-/* Elf64 can hide extra offset in r_info */
-#define	ELF_R_TYPE_DATA(x)	(0)
-#define	ELF_R_TYPE_INFO(xoff, type)	(type)
-#define	ELF_ST_BIND		ELF32_ST_BIND
-#define	ELF_ST_TYPE		ELF32_ST_TYPE
-#define	ELF_ST_INFO		ELF32_ST_INFO
-#define	ELF_ST_VISIBILITY	ELF32_ST_VISIBILITY
-#define	elf_checksum		elf32_checksum
-#define	elf_fsize		elf32_fsize
-#define	elf_getehdr		elf32_getehdr
-#define	elf_getphdr		elf32_getphdr
-#define	elf_newehdr		elf32_newehdr
-#define	elf_newphdr		elf32_newphdr
-#define	elf_getshdr		elf32_getshdr
-#define	elf_xlatetom		elf32_xlatetom
-#endif	/* Elf32 */
-
-/*
- * Make common relocation information transparent to the common code
- */
-#define	M_REL_DT_TYPE	DT_RELA		/* .dynamic entry */
-#define	M_REL_DT_SIZE	DT_RELASZ	/* .dynamic entry */
-#define	M_REL_DT_ENT	DT_RELAENT	/* .dynamic entry */
-#define	M_REL_DT_COUNT	DT_RELACOUNT	/* .dynamic entry */
-#define	M_REL_SHT_TYPE	SHT_RELA	/* section header type */
-#define	M_REL_ELF_TYPE	ELF_T_RELA	/* data buffer type */
-
-/*
- * Make common relocation types transparent to the common code
- */
-#define	M_R_NONE	R_SPARC_NONE
-#define	M_R_GLOB_DAT	R_SPARC_GLOB_DAT
-#define	M_R_COPY	R_SPARC_COPY
-#define	M_R_RELATIVE	R_SPARC_RELATIVE
-#define	M_R_JMP_SLOT	R_SPARC_JMP_SLOT
-#define	M_R_REGISTER	R_SPARC_REGISTER
-#define	M_R_FPTR	R_SPARC_NONE
-#define	M_R_NUM		R_SPARC_NUM
-
-#ifdef	_ELF64
-#define	M_R_ARRAYADDR	R_SPARC_64
-#define	M_R_DTPMOD	R_SPARC_TLS_DTPMOD64
-#define	M_R_DTPOFF	R_SPARC_TLS_DTPOFF64
-#define	M_R_TPOFF	R_SPARC_TLS_TPOFF64
-#else	/* _ELF32 */
-#define	M_R_ARRAYADDR	R_SPARC_32
-#define	M_R_DTPMOD	R_SPARC_TLS_DTPMOD32
-#define	M_R_DTPOFF	R_SPARC_TLS_DTPOFF32
-#define	M_R_TPOFF	R_SPARC_TLS_TPOFF32
-#endif	/* _ELF64 */
-
-
-/*
- * Make register symbols transparent to common code
- */
-#define	M_DT_REGISTER	DT_SPARC_REGISTER
-
-/*
- * PLTRESERVE is not relevant on sparc
- */
-#define	M_DT_PLTRESERVE	0xffffffff
-
-
-/*
- * Make plt section information transparent to the common code.
- */
-#define	M_PLT_SHF_FLAGS	(SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR)
-
-/*
- * Make data segment information transparent to the common code.
- */
-#define	M_DATASEG_PERM	(PF_R | PF_W | PF_X)
-
-/*
- * Define a set of identifies for special sections.  These allow the sections
- * to be ordered within the output file image.  These values should be
- * maintained consistently, where appropriate, in each platform specific header
- * file.
- *
- *  o	null identifies that this section does not need to be added to the
- *	output image (ie. shared object sections or sections we're going to
- *	recreate (sym tables, string tables, relocations, etc.)).
- *
- *  o	any user defined section will be first in the associated segment.
- *
- *  o	interp and capabilities sections are next, as these are accessed
- *	immediately the first page of the image is mapped.
- *
- *  o	the syminfo, hash, dynsym, dynstr and rel's are grouped together as
- *	these will all be accessed first by ld.so.1 to perform relocations.
- *
- *  o	the got, dynamic, and plt are grouped together as these may also be
- *	accessed first by ld.so.1 to perform relocations, fill in DT_DEBUG
- *	(executables only), and .plt[0].
- *
- *  o	unknown sections (stabs, comments etc.) go at the end.
- *
- * Note that .tlsbss/.bss are given the largest identifiers.  This insures that
- * if any unknown sections become associated to the same segment as the .bss,
- * the .bss sections are always the last section in the segment.
- */
-#define	M_ID_NULL	0x00
-#define	M_ID_USER	0x01
-
-#define	M_ID_INTERP	0x02			/* SHF_ALLOC */
-#define	M_ID_CAP	0x03
-#define	M_ID_SYMINFO	0x04
-#define	M_ID_HASH	0x05
-#define	M_ID_LDYNSYM	0x06			/* always right before DYNSYM */
-#define	M_ID_DYNSYM	0x07
-#define	M_ID_DYNSTR	0x08
-#define	M_ID_VERSION	0x09
-#define	M_ID_DYNSORT	0x0a
-#define	M_ID_REL	0x0b
-#define	M_ID_TEXT	0x0c			/* SHF_ALLOC + SHF_EXECINSTR */
-#define	M_ID_DATA	0x0d
-
-/*	M_ID_USER	0x01			dual entry - listed above */
-#define	M_ID_GOTDATA	0x02			/* SHF_ALLOC + SHF_WRITE */
-#define	M_ID_GOT	0x03
-#define	M_ID_PLT	0x04
-#define	M_ID_DYNAMIC	0x05
-#define	M_ID_ARRAY	0x06
-
-#define	M_ID_UNKNOWN	0xfc			/* just before TLS */
-
-#define	M_ID_TLS	0xfd			/* just before bss */
-#define	M_ID_TLSBSS	0xfe
-#define	M_ID_BSS	0xff
-
-#define	M_ID_SYMTAB_NDX	0x02			/* ! SHF_ALLOC */
-#define	M_ID_SYMTAB	0x03
-#define	M_ID_STRTAB	0x04
-#define	M_ID_DYNSYM_NDX	0x05
-#define	M_ID_NOTE	0x06
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif /* _MACHDEP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/include/sparc/machdep_sparc.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,308 @@
+/*
+ * 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 (c) 1988 AT&T
+ *	  All Rights Reserved
+ *
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Global include file for all sgs SPARC machine dependent macros, constants
+ * and declarations.
+ */
+
+#ifndef	_MACHDEP_SPARC_H
+#define	_MACHDEP_SPARC_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <link.h>
+#include <sys/machelf.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Elf header information.
+ */
+#define	M_MACH_32		EM_SPARC
+#define	M_MACH_64		EM_SPARCV9
+
+#ifdef _ELF64
+#define	M_MACH			EM_SPARCV9
+#define	M_CLASS			ELFCLASS64
+#else
+#define	M_MACH			EM_SPARC
+#define	M_CLASS			ELFCLASS32
+#endif
+#define	M_MACHPLUS		EM_SPARC32PLUS
+#define	M_DATA			ELFDATA2MSB
+#define	M_FLAGSPLUS		EF_SPARC_32PLUS
+
+/*
+ * Page boundary Macros: truncate to previous page boundary and round to
+ * next page boundary (refer to generic macros in ../sgs.h also).
+ */
+#define	M_PTRUNC(X)	((X) & ~(syspagsz - 1))
+#define	M_PROUND(X)	(((X) + syspagsz - 1) & ~(syspagsz - 1))
+
+/*
+ * Segment boundary macros: truncate to previous segment boundary and round
+ * to next page boundary.
+ */
+#ifndef	M_SEGSIZE
+#define	M_SEGSIZE	ELF_SPARC_MAXPGSZ
+#endif
+#define	M_STRUNC(X)	((X) & ~(M_SEGSIZE - 1))
+#define	M_SROUND(X)	(((X) + M_SEGSIZE - 1) & ~(M_SEGSIZE - 1))
+
+
+/*
+ * TLS static segments must be rounded to the following requirements,
+ * due to libthread stack allocation.
+ */
+#if	defined(_ELF64)
+#define	M_TLSSTATALIGN	0x10
+#else
+#define	M_TLSSTATALIGN	0x08
+#endif
+
+
+/*
+ * Instruction encodings.
+ */
+#define	M_SAVESP64	0x9de3bfc0	/* save %sp, -64, %sp */
+#define	M_CALL		0x40000000
+#define	M_JMPL		0x81c06000	/* jmpl %g1 + simm13, %g0 */
+#define	M_SETHIG0	0x01000000	/* sethi %hi(val), %g0 */
+#define	M_SETHIG1	0x03000000	/* sethi %hi(val), %g1 */
+#define	M_STO7G1IM	0xde206000	/* st	 %o7,[%g1 + %lo(val)] */
+#define	M_SUBFPSPG1	0x8227800e	/* sub	%fp,%sp,%g1 */
+#define	M_NOP		0x01000000	/* sethi 0, %o0 (nop) */
+#define	M_BA_A		0x30800000	/* ba,a */
+#define	M_BA_A_PT	0x30480000	/* ba,a %icc, <dst> */
+#define	M_MOVO7TOG1	0x8210000f	/* mov %o7, %g1 */
+#define	M_MOVO7TOG5	0x8a10000f	/* mov %o7, %g5 */
+#define	M_MOVI7TOG1	0x8210001f	/* mov %i7, %g1 */
+#define	M_BA_A_XCC	0x30680000	/* ba,a %xcc */
+#define	M_JMPL_G5G0	0x81c16000	/* jmpl %g5 + 0, %g0 */
+#define	M_XNOR_G5G1	0x82396000	/* xnor	%g5, 0, %g1 */
+
+
+#define	M_BIND_ADJ	4		/* adjustment for end of */
+					/*	elf_rtbndr() address */
+
+
+/*
+ * Plt and Got information; the first few .got and .plt entries are reserved
+ *	PLT[0]	jump to dynamic linker
+ *	GOT[0]	address of _DYNAMIC
+ */
+#define	M_PLT_INSSIZE	4		/* single plt instruction size */
+#define	M_GOT_XDYNAMIC	0		/* got index for _DYNAMIC */
+#define	M_GOT_XNumber	1		/* reserved no. of got entries */
+
+/*
+ * ELF32 bit PLT constants
+ */
+#define	M32_PLT_ENTSIZE		12	/* 32bit plt entry size in bytes */
+
+/*
+ * ELF64 bit PLT constants
+ */
+#define	M64_PLT_NEARPLTS	0x8000	/* # of NEAR PLTS we can have */
+#define	M64_PLT_ENTSIZE		32	/* plt entry size in bytes */
+#define	M64_PLT_FENTSIZE	24	/* size of far plt is 6 instructions */
+					/*	x 4bytes */
+#define	M64_PLT_PSIZE		8		/* size of PLTP pointer */
+#define	M64_PLT_FBLKCNTS	160	/* # of plts in far PLT blocks */
+#define	M64_PLT_FBLOCKSZ	(M64_PLT_FBLKCNTS *\
+				M64_PLT_ENTSIZE) /* size of far PLT block */
+
+
+#ifdef _ELF64
+#define	M_PLT_ENTSIZE	M64_PLT_ENTSIZE	/* plt entry size in bytes */
+#define	M_PLT_XNumber	4		/* reserved no. of plt entries */
+#define	M_PLT_ALIGN	256		/* alignment of .plt section */
+#define	M_PLT_RESERVSZ	(M_PLT_XNumber * \
+			M_PLT_ENTSIZE)	/* first 4 plt's reserved */
+#define	M_GOT_ENTSIZE	8		/* got entry size in bytes */
+#define	M_GOT_MAXSMALL	1024		/* maximum no. of small gots */
+#else /* Elf32 */
+#define	M_PLT_ENTSIZE	M32_PLT_ENTSIZE	/* plt entry size in bytes */
+#define	M_PLT_XNumber	4		/* reserved no. of plt entries */
+#define	M_PLT_ALIGN	M_WORD_ALIGN	/* alignment of .plt section */
+#define	M_PLT_RESERVSZ	(M_PLT_XNumber * \
+			M_PLT_ENTSIZE)	/* first 4 plt's reserved */
+#define	M_GOT_ENTSIZE	4		/* got entry size in bytes */
+#define	M_GOT_MAXSMALL	2048		/* maximum no. of small gots */
+#endif /* _ELF64 */
+					/* transition flags for got sizing */
+#define	M_GOT_LARGE	(Sword)(-M_GOT_MAXSMALL - 1)
+#define	M_GOT_SMALL	(Sword)(-M_GOT_MAXSMALL - 2)
+#define	M_GOT_MIXED	(Sword)(-M_GOT_MAXSMALL - 3)
+
+
+/*
+ * Other machine dependent entities
+ */
+#ifdef _ELF64
+#define	M_SEGM_ALIGN	ELF_SPARCV9_MAXPGSZ
+/*
+ * Put 64-bit programs above 4 gigabytes to help insure correctness,
+ * so any 64-bit programs that truncate pointers will fault now instead of
+ * corrupting itself and dying mysteriously.
+ */
+#define	M_SEGM_ORIGIN	(Addr)0x100000000ULL  /* default first segment offset */
+#define	M_WORD_ALIGN	8
+#else
+#define	M_SEGM_ALIGN	ELF_SPARC_MAXPGSZ
+#define	M_SEGM_ORIGIN	(Addr)0x10000	/* default first segment offset */
+#define	M_WORD_ALIGN	4
+#endif
+
+/*
+ * Make common relocation information transparent to the common code
+ */
+#define	M_REL_DT_TYPE	DT_RELA		/* .dynamic entry */
+#define	M_REL_DT_SIZE	DT_RELASZ	/* .dynamic entry */
+#define	M_REL_DT_ENT	DT_RELAENT	/* .dynamic entry */
+#define	M_REL_DT_COUNT	DT_RELACOUNT	/* .dynamic entry */
+#define	M_REL_SHT_TYPE	SHT_RELA	/* section header type */
+#define	M_REL_ELF_TYPE	ELF_T_RELA	/* data buffer type */
+
+/*
+ * Make common relocation types transparent to the common code
+ */
+#define	M_R_NONE	R_SPARC_NONE
+#define	M_R_GLOB_DAT	R_SPARC_GLOB_DAT
+#define	M_R_COPY	R_SPARC_COPY
+#define	M_R_RELATIVE	R_SPARC_RELATIVE
+#define	M_R_JMP_SLOT	R_SPARC_JMP_SLOT
+#define	M_R_REGISTER	R_SPARC_REGISTER
+#define	M_R_FPTR	R_SPARC_NONE
+#define	M_R_NUM		R_SPARC_NUM
+
+#ifdef	_ELF64
+#define	M_R_ARRAYADDR	R_SPARC_64
+#define	M_R_DTPMOD	R_SPARC_TLS_DTPMOD64
+#define	M_R_DTPOFF	R_SPARC_TLS_DTPOFF64
+#define	M_R_TPOFF	R_SPARC_TLS_TPOFF64
+#else	/* _ELF32 */
+#define	M_R_ARRAYADDR	R_SPARC_32
+#define	M_R_DTPMOD	R_SPARC_TLS_DTPMOD32
+#define	M_R_DTPOFF	R_SPARC_TLS_DTPOFF32
+#define	M_R_TPOFF	R_SPARC_TLS_TPOFF32
+#endif	/* _ELF64 */
+
+
+/*
+ * Make register symbols transparent to common code
+ */
+#define	M_DT_REGISTER	DT_SPARC_REGISTER
+
+/*
+ * PLTRESERVE is not relevant on sparc
+ */
+#define	M_DT_PLTRESERVE	0xffffffff
+
+
+/*
+ * Make plt section information transparent to the common code.
+ */
+#define	M_PLT_SHF_FLAGS	(SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR)
+
+/*
+ * Make data segment information transparent to the common code.
+ */
+#define	M_DATASEG_PERM	(PF_R | PF_W | PF_X)
+
+/*
+ * Define a set of identifies for special sections.  These allow the sections
+ * to be ordered within the output file image.  These values should be
+ * maintained consistently, where appropriate, in each platform specific header
+ * file.
+ *
+ *  o	null identifies that this section does not need to be added to the
+ *	output image (ie. shared object sections or sections we're going to
+ *	recreate (sym tables, string tables, relocations, etc.)).
+ *
+ *  o	any user defined section will be first in the associated segment.
+ *
+ *  o	interp and capabilities sections are next, as these are accessed
+ *	immediately the first page of the image is mapped.
+ *
+ *  o	the syminfo, hash, dynsym, dynstr and rel's are grouped together as
+ *	these will all be accessed first by ld.so.1 to perform relocations.
+ *
+ *  o	the got, dynamic, and plt are grouped together as these may also be
+ *	accessed first by ld.so.1 to perform relocations, fill in DT_DEBUG
+ *	(executables only), and .plt[0].
+ *
+ *  o	unknown sections (stabs, comments etc.) go at the end.
+ *
+ * Note that .tlsbss/.bss are given the largest identifiers.  This insures that
+ * if any unknown sections become associated to the same segment as the .bss,
+ * the .bss sections are always the last section in the segment.
+ */
+#define	M_ID_NULL	0x00
+#define	M_ID_USER	0x01
+
+#define	M_ID_INTERP	0x02			/* SHF_ALLOC */
+#define	M_ID_CAP	0x03
+#define	M_ID_SYMINFO	0x04
+#define	M_ID_HASH	0x05
+#define	M_ID_LDYNSYM	0x06			/* always right before DYNSYM */
+#define	M_ID_DYNSYM	0x07
+#define	M_ID_DYNSTR	0x08
+#define	M_ID_VERSION	0x09
+#define	M_ID_DYNSORT	0x0a
+#define	M_ID_REL	0x0b
+#define	M_ID_TEXT	0x0c			/* SHF_ALLOC + SHF_EXECINSTR */
+#define	M_ID_DATA	0x0d
+
+/*	M_ID_USER	0x01			dual entry - listed above */
+#define	M_ID_GOTDATA	0x02			/* SHF_ALLOC + SHF_WRITE */
+#define	M_ID_GOT	0x03
+#define	M_ID_PLT	0x04
+#define	M_ID_DYNAMIC	0x05
+#define	M_ID_ARRAY	0x06
+
+#define	M_ID_UNKNOWN	0xfc			/* just before TLS */
+
+#define	M_ID_TLS	0xfd			/* just before bss */
+#define	M_ID_TLSBSS	0xfe
+#define	M_ID_BSS	0xff
+
+#define	M_ID_SYMTAB_NDX	0x02			/* ! SHF_ALLOC */
+#define	M_ID_SYMTAB	0x03
+#define	M_ID_STRTAB	0x04
+#define	M_ID_DYNSYM_NDX	0x05
+#define	M_ID_NOTE	0x06
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _MACHDEP_SPARC_H */
--- a/usr/src/cmd/sgs/ld/common/ld.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/ld/common/ld.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -31,6 +31,7 @@
 #include	<unistd.h>
 #include	<stdarg.h>
 #include	<string.h>
+#include	<strings.h>
 #include	<errno.h>
 #include	<fcntl.h>
 #include	<libintl.h>
@@ -38,6 +39,7 @@
 #include	<fcntl.h>
 #include	"conv.h"
 #include	"libld.h"
+#include	"machdep.h"
 #include	"msg.h"
 
 /*
@@ -68,13 +70,14 @@
 	if (error > ERR_NONE) {
 		if (error == ERR_WARNING) {
 			if (strings[ERR_WARNING] == 0)
-			    strings[ERR_WARNING] = MSG_INTL(MSG_ERR_WARNING);
+				strings[ERR_WARNING] =
+				    MSG_INTL(MSG_ERR_WARNING);
 		} else if (error == ERR_FATAL) {
 			if (strings[ERR_FATAL] == 0)
-			    strings[ERR_FATAL] = MSG_INTL(MSG_ERR_FATAL);
+				strings[ERR_FATAL] = MSG_INTL(MSG_ERR_FATAL);
 		} else if (error == ERR_ELF) {
 			if (strings[ERR_ELF] == 0)
-			    strings[ERR_ELF] = MSG_INTL(MSG_ERR_ELF);
+				strings[ERR_ELF] = MSG_INTL(MSG_ERR_ELF);
 		}
 		(void) fputs(MSG_ORIG(MSG_STR_LDDIAG), stderr);
 	}
@@ -96,26 +99,45 @@
 
 
 /*
- * Determine whether we need the Elf32 or Elf64 libld.
+ * Determine:
+ *	- ELFCLASS of resulting object (aoutclass)
+ *	- Whether we need the 32 or 64-bit libld (ldclass)
+ *	- ELF machine type of resulting object (m_mach)
  */
 static int
-determine_class(int argc, char **argv, uchar_t *aoutclass, uchar_t *ldclass)
+process_args(int argc, char **argv, uchar_t *aoutclass, uchar_t *ldclass,
+    Half *mach)
 {
-#if	defined(__sparcv9) || defined(__amd64)
-	uchar_t aclass = 0, lclass = ELFCLASS64;
+#if	defined(_LP64)
+	uchar_t lclass = ELFCLASS64;
 #else
-	uchar_t	aclass = 0, lclass = 0;
+	uchar_t	lclass = ELFCLASSNONE;
 #endif
+	uchar_t	aclass = ELFCLASSNONE;
+	Half	mach32 = EM_NONE, mach64 = EM_NONE;
 	int	c;
 
 getmore:
 	/*
-	 * Skip options.
+	 * In general, libld.so is responsible for processing the
+	 * command line options. The exception to this are those options
+	 * that contain information about which linker to run and the
+	 * class/machine of the output object. We examine the options
+	 * here looking for the following:
+	 *
+	 *	-64
+	 *		Produce an ELFCLASS64 object. Use the 64-bit linker.
 	 *
-	 * The only options we're interested in is -64 or -altzexec64.  The -64
-	 * option is used when the only input to ld() is a mapfile or archive,
-	 * and a 64-bit a.out is required.  The -zaltexec64 option requests the
-	 * 64-bit version of ld() is used regardless of the required a.out.
+	 *	-zaltexec64
+	 *		Use the 64-bit linker regardless of the class
+	 *		of the output object.
+	 *
+	 *	-z target=platform
+	 *		Produce output object for the specified platform.
+	 *
+	 * The -64 and -ztarget options are used when the only input to
+	 * ld() is a mapfile or archive, and a 64-bit or non-native output
+	 * object is required.
 	 *
 	 * If we've already processed a 32-bit object and we find -64, we have
 	 * an error condition, but let this fall through to libld to obtain the
@@ -129,13 +151,40 @@
 				    MSG_ARG_FOUR_SIZE) == 0)
 					aclass = ELFCLASS64;
 				break;
-#if	!defined(__sparcv9) && !defined(__amd64)
+
 			case 'z':
+#if	!defined(_LP64)
+				/* -z altexec64 */
 				if (strncmp(optarg, MSG_ORIG(MSG_ARG_ALTEXEC64),
-				    MSG_ARG_ALTEXEC64_SIZE) == 0)
+				    MSG_ARG_ALTEXEC64_SIZE) == 0) {
 					lclass = ELFCLASS64;
+					break;
+				}
+#endif
+
+				/* -z target=platform */
+				if (strncmp(optarg, MSG_ORIG(MSG_ARG_TARGET),
+				    MSG_ARG_TARGET_SIZE) == 0) {
+					char *pstr =
+					    optarg + MSG_ARG_TARGET_SIZE;
+
+					if (strcasecmp(pstr,
+					    MSG_ORIG(MSG_TARG_SPARC)) == 0) {
+						mach32 = EM_SPARC;
+						mach64 = EM_SPARCV9;
+					} else if (strcasecmp(pstr,
+					    MSG_ORIG(MSG_TARG_X86)) == 0) {
+						mach32 = EM_386;
+						mach64 = EM_AMD64;
+					} else {
+						eprintf(0, ERR_FATAL,
+						    MSG_INTL(MSG_ERR_BADTARG),
+						    pstr);
+						return (1);
+					}
+				}
 				break;
-#endif
+
 			default:
 				break;
 		}
@@ -147,7 +196,7 @@
 	 */
 	for (; optind < argc; optind++) {
 		int		fd;
-		unsigned char	ident[EI_NIDENT];
+		Elf32_Ehdr	ehdr32;
 
 		/*
 		 * If we detect some more options return to getopt().
@@ -162,11 +211,15 @@
 		}
 
 		/*
-		 * If we've already determined the object class, continue.
-		 * We're only interested in skipping all files to check for
-		 * more options, and specifically if the -64 option is set.
+		 * If we've already determined the object class and
+		 * machine type, continue to the next argument. Only
+		 * the first object contributes to this decision, and
+		 * there's no value to opening or examing the subsequent
+		 * ones. We do need to keep going though, because there
+		 * may be additional options that might affect our
+		 * class/machine decision.
 		 */
-		if (aclass)
+		if ((aclass != ELFCLASSNONE) && (mach32 != EM_NONE))
 			continue;
 
 		/*
@@ -180,28 +233,82 @@
 			return (1);
 		}
 
-		if ((read(fd, ident, EI_NIDENT) == EI_NIDENT) &&
-		    (ident[EI_MAG0] == ELFMAG0) &&
-		    (ident[EI_MAG1] == ELFMAG1) &&
-		    (ident[EI_MAG2] == ELFMAG2) &&
-		    (ident[EI_MAG3] == ELFMAG3)) {
-			if (((aclass = ident[EI_CLASS]) != ELFCLASS32) &&
-			    (aclass != ELFCLASS64))
-				aclass = 0;
+		/*
+		 * Note that we read an entire 32-bit ELF header struct
+		 * here, even though we have yet to determine that the
+		 * file is an ELF object or that it is ELFCLASS32. We
+		 * do this because:
+		 *	- Any valid ELF object of any class must
+		 *		have at least this number of bytes in it,
+		 *		since an ELF header is manditory, and since
+		 *		a 32-bit header is smaller than a 64-bit one.
+		 *	- The 32 and 64-bit ELF headers are identical
+		 *		up through the e_version field, so we can
+		 *		obtain the e_machine value of a 64-bit
+		 *		object via the e_machine value we read into
+		 *		the 32-bit version. This cannot change, because
+		 *		the layout of an ELF header is fixed by the ABI.
+		 *
+		 * Note however that we do have to worry about the byte
+		 * order difference between the object and the system
+		 * running this program when we read the e_machine value,
+		 * since it is a multi-byte value;
+		 */
+		if ((read(fd, &ehdr32, sizeof (ehdr32)) == sizeof (ehdr32)) &&
+		    (ehdr32.e_ident[EI_MAG0] == ELFMAG0) &&
+		    (ehdr32.e_ident[EI_MAG1] == ELFMAG1) &&
+		    (ehdr32.e_ident[EI_MAG2] == ELFMAG2) &&
+		    (ehdr32.e_ident[EI_MAG3] == ELFMAG3)) {
+			if (aclass == ELFCLASSNONE) {
+				aclass = ehdr32.e_ident[EI_CLASS];
+				if ((aclass != ELFCLASS32) &&
+				    (aclass != ELFCLASS64))
+					aclass = ELFCLASSNONE;
+			}
+
+			if (mach32 == EM_NONE) {
+				int	one = 1;
+				uchar_t	*one_p = (uchar_t *)&one;
+				int	ld_elfdata;
+
+				ld_elfdata = (one_p[0] == 1) ?
+				    ELFDATA2LSB : ELFDATA2MSB;
+				/*
+				 * Both the 32 and 64-bit versions get the
+				 * type from the object. If the user has
+				 * asked for an inconsistant class/machine
+				 * combination, libld will catch it.
+				 */
+				mach32 = mach64 =
+				    (ld_elfdata == ehdr32.e_ident[EI_DATA]) ?
+				    ehdr32.e_machine :
+				    BSWAP_HALF(ehdr32.e_machine);
+			}
 		}
+
 		(void) close(fd);
 	}
 
 	/*
-	 * If we couldn't establish a class default to 32-bit.
+	 * If we couldn't establish a class, default to 32-bit.
 	 */
-	if (aclass == 0)
+	if (aclass == ELFCLASSNONE)
 		aclass = ELFCLASS32;
-	if (lclass == 0)
+	*aoutclass = aclass;
+
+	if (lclass == ELFCLASSNONE)
 		lclass = ELFCLASS32;
+	*ldclass = lclass;
 
-	*aoutclass = aclass;
-	*ldclass = lclass;
+	/*
+	 * Use the machine type that goes with the class we've determined.
+	 * If we didn't find a usable machine type, use the native
+	 * machine.
+	 */
+	*mach = (aclass == ELFCLASS64) ? mach64 : mach32;
+	if (*mach == EM_NONE)
+		*mach = (aclass == ELFCLASS64) ? M_MACH_64 : M_MACH_32;
+
 	return (0);
 }
 
@@ -356,6 +463,7 @@
 {
 	char		*ld_options, **oargv = argv;
 	uchar_t 	aoutclass, ldclass, checkclass;
+	Half		mach;
 
 	/*
 	 * XX64 -- Strip "-Wl," from the head of each argument.  This is to
@@ -400,9 +508,12 @@
 	}
 
 	/*
-	 * Determine the object class, and link-editor class required.
+	 * Examine the command arguments to determine:
+	 *	- object class
+	 *	- link-editor class
+	 *	- target machine
 	 */
-	if (determine_class(argc, argv, &aoutclass, &ldclass))
+	if (process_args(argc, argv, &aoutclass, &ldclass, &mach))
 		return (1);
 
 	/*
@@ -425,9 +536,9 @@
 	 */
 	optind = opterr = 1;
 	if (aoutclass == ELFCLASS64)
-		return (ld64_main(argc, argv));
+		return (ld64_main(argc, argv, mach));
 	else
-		return (ld32_main(argc, argv));
+		return (ld32_main(argc, argv, mach));
 }
 
 /*
--- a/usr/src/cmd/sgs/ld/common/ld.msg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/ld/common/ld.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -39,6 +39,8 @@
 @ MSG_SYS_ALLOC		"alloc failed: %s"
 @ MSG_SYS_64		"unable to execute 64-bit version of ld"
 
+@ MSG_ERR_BADTARG	"unknown target platform: %s"
+
 # Generic error diagnostic labels
 
 @ MSG_ERR_WARNING	"warning: "
@@ -49,7 +51,7 @@
 
 
 # The following strings represent reserved words, files, pathnames and symbols.
-# Reference to this strings is via the MSG_ORIG() macro, and thus no message
+# Reference to these strings is via the MSG_ORIG() macro, and thus no message
 # translation is required.
 
 @ MSG_STR_EMPTY		""
@@ -62,8 +64,13 @@
 
 @ MSG_ARG_FOUR		"4"
 @ MSG_ARG_ALTEXEC64	"altexec64"
+@ MSG_ARG_TARGET	"target="
 
 @ MSG_LD_OPTIONS	"LD_OPTIONS"
 @ MSG_LD_ALTEXEC	"LD_ALTEXEC="
 
 @ MSG_SUNW_OST_SGS	"SUNW_OST_SGS"
+
+@ MSG_TARG_SPARC	"sparc"
+@ MSG_TARG_X86		"x86"
+
--- a/usr/src/cmd/sgs/libconv/common/cap.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libconv/common/cap.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -30,7 +30,7 @@
  */
 #include	<strings.h>
 #include	<stdio.h>
-#include	<sys/machelf.h>
+#include	<_machelf.h>
 #include	<elfcap.h>
 #include	"cap_msg.h"
 #include	"_conv.h"
--- a/usr/src/cmd/sgs/libconv/common/dynamic.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libconv/common/dynamic.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -359,8 +359,9 @@
 	};
 
 	/*
-	 * SUNW: DT_LOOS -> DT_HIOS range. Note hole between DT_SUNW_TLSSORTSZ
-	 * and DT_SUNW_STRPAD. We handle DT_SUNW_STRPAD as a single value below.
+	 * SUNW: DT_LOOS -> DT_HIOS range. Note hole between DT_SUNW_TLSSORTSZ,
+	 * DT_SUNW_STRPAD, and DT_SUNW_LDMACH. We handle the outliers
+	 * separately below as single values.
 	 */
 	static const Msg	tags_sunw_auxiliary[] = {
 		MSG_DYN_SUNW_AUXILIARY,	MSG_DYN_SUNW_RTLDINF,
@@ -425,6 +426,8 @@
 	DYN_RANGE(DT_SUNW_AUXILIARY, tags_sunw_auxiliary);
 	if (tag == DT_SUNW_STRPAD)
 		return (MSG_ORIG(MSG_DYN_SUNW_STRPAD));
+	if (tag == DT_SUNW_LDMACH)
+		return (MSG_ORIG(MSG_DYN_SUNW_LDMACH));
 	DYN_RANGE(DT_CHECKSUM, tags_checksum);
 	DYN_RANGE(DT_CONFIG, tags_config);
 	if (tag == DT_VERSYM)
--- a/usr/src/cmd/sgs/libconv/common/dynamic.msg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libconv/common/dynamic.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -101,6 +101,7 @@
 @ MSG_DYN_SUNW_TLSSORT		"SUNW_TLSSORT"
 @ MSG_DYN_SUNW_TLSSORTSZ	"SUNW_TLSSORTSZ"
 @ MSG_DYN_SUNW_STRPAD		"SUNW_STRPAD"
+@ MSG_DYN_SUNW_LDMACH		"SUNW_LDMACH"
 
 @ MSG_DF_ORIGIN		"ORIGIN"
 @ MSG_DF_SYMBOLIC	"SYMBOLIC"
--- a/usr/src/cmd/sgs/libconv/common/elf.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libconv/common/elf.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -392,7 +392,8 @@
  * terms of a string.
  */
 const char *
-conv_reject_desc(Rej_desc * rej, Conv_reject_desc_buf_t *reject_desc_buf)
+conv_reject_desc(Rej_desc * rej, Conv_reject_desc_buf_t *reject_desc_buf,
+    Half mach)
 {
 	ushort_t	type = rej->rej_type;
 	uint_t		info = rej->rej_info;
@@ -415,10 +416,7 @@
 		    &reject_desc_buf->inv_buf));
 	else if ((type == SGS_REJ_BADFLAG) || (type == SGS_REJ_MISFLAG) ||
 	    (type == SGS_REJ_HAL) || (type == SGS_REJ_US3))
-		/*
-		 * Only called from ld.so.1, thus M_MACH is hardcoded.
-		 */
-		return (conv_ehdr_flags(M_MACH, (Word)info, 0,
+		return (conv_ehdr_flags(mach, (Word)info, 0,
 		    &reject_desc_buf->flags_buf));
 	else if (type == SGS_REJ_UNKFILE)
 		return ((const char *)0);
--- a/usr/src/cmd/sgs/libconv/common/globals.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libconv/common/globals.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,14 +20,14 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include	<stdio.h>
 #include	<strings.h>
-#include	<sys/machelf.h>
+#include	<_machelf.h>
 #include	"_conv.h"
 #include	"globals_msg.h"
 
--- a/usr/src/cmd/sgs/libconv/common/llib-lconv	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libconv/common/llib-lconv	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /* LINTLIBRARY */
@@ -30,7 +30,7 @@
 
 #include	<stdlib.h>
 #include	<libelf.h>
-#include	<sys/machelf.h>
+#include	<_machelf.h>
 #include	<sgs.h>
 #include	<libld.h>
 #include	<conv.h>
@@ -122,8 +122,10 @@
 		    Conv64_phdr_flags_buf_t *);
 const char	*conv32_phdr_type(Elf32_Half, Word, int, Conv32_inv_buf_t *);
 const char	*conv64_phdr_type(Elf64_Half, Word, int, Conv64_inv_buf_t *);
-const char	*conv32_reject_desc(Rej_desc *, Conv32_reject_desc_buf_t *);
-const char	*conv64_reject_desc(Rej_desc *, Conv64_reject_desc_buf_t *);
+const char	*conv32_reject_desc(Rej_desc *, Conv32_reject_desc_buf_t *,
+		    Elf32_Half);
+const char	*conv64_reject_desc(Rej_desc *, Conv64_reject_desc_buf_t *,
+		    Elf64_Half);
 const char	*conv32_reloc_type(Half, Word, int, Conv32_inv_buf_t *);
 const char	*conv64_reloc_type(Half, Word, int, Conv64_inv_buf_t *);
 const char	*conv32_reloc_type_static(Half, Word, int);
--- a/usr/src/cmd/sgs/libconv/common/symbols.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libconv/common/symbols.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -29,7 +29,7 @@
  * String conversion routines for symbol attributes.
  */
 #include	<stdio.h>
-#include	<sys/machelf.h>
+#include	<_machelf.h>
 #include	<sys/elf_SPARC.h>
 #include	<sys/elf_amd64.h>
 #include	"_conv.h"
--- a/usr/src/cmd/sgs/libconv/common/syminfo.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libconv/common/syminfo.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -29,7 +29,7 @@
  * String conversion routines for syminfo attributes.
  */
 #include	<stdio.h>
-#include	<sys/machelf.h>
+#include	<_machelf.h>
 #include	"_conv.h"
 #include	"syminfo_msg.h"
 
--- a/usr/src/cmd/sgs/libelf/common/decl.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libelf/common/decl.h	Tue Mar 18 09:17:00 2008 -0700
@@ -23,7 +23,7 @@
 
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -486,6 +486,7 @@
 extern unsigned		_elf_work;
 extern mutex_t		_elf_globals_mutex;
 extern off_t		_elf64_update(Elf * elf, Elf_Cmd cmd);
+extern int		_elf64_swap_wrimage(Elf *elf);
 
 /* CSTYLED */
 NOTE(MUTEX_PROTECTS_DATA(_elf_globals_mutex, \
--- a/usr/src/cmd/sgs/libelf/common/llib-lelf	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libelf/common/llib-lelf	Tue Mar 18 09:17:00 2008 -0700
@@ -22,7 +22,7 @@
 /* PROTOLIB1 */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved. 
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved. 
  * Use is subject to license terms.
  */ 
 
@@ -185,4 +185,5 @@
  * Private Symbols
  */
 Elf64_Off	_elf_getxoff(Elf_Data *);
+int		_elf_swap_wrimage(Elf *);
 uint_t		_elf_sys_encoding(void);
--- a/usr/src/cmd/sgs/libelf/common/mapfile-common	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libelf/common/mapfile-common	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -180,6 +180,7 @@
 	_elf_rawdata =		NODYNSORT;
 	_elf_rawfile =		NODYNSORT;
 	_elf_strptr =		NODYNSORT;
+	_elf_swap_wrimage;
 	_elf_update =		NODYNSORT;
 	_elf32_fsize =		NODYNSORT;
 	_elf32_xlatetof =	NODYNSORT;
--- a/usr/src/cmd/sgs/libelf/common/update.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libelf/common/update.c	Tue Mar 18 09:17:00 2008 -0700
@@ -24,7 +24,7 @@
  *	  All Rights Reserved
  *
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -66,6 +66,7 @@
 #define	wrt		wrt64
 #define	elf_xlatetof	elf64_xlatetof
 #define	_elfxx_update	_elf64_update
+#define	_elfxx_swap_wrimage	_elf64_swap_wrimage
 
 #else	/* ELF32 */
 
@@ -81,6 +82,7 @@
 #define	wrt		wrt32
 #define	elf_xlatetof	elf32_xlatetof
 #define	_elfxx_update	_elf32_update
+#define	_elfxx_swap_wrimage	_elf32_swap_wrimage
 
 #endif /* ELF64 */
 
@@ -358,7 +360,7 @@
 			d->db_osz = (size_t)fsz;
 
 			if ((sh->sh_type != SHT_NOBITS) &&
-			((j = (Xword)(d->db_data.d_off + d->db_osz)) > sz))
+			    ((j = (Xword)(d->db_data.d_off + d->db_osz)) > sz))
 				sz = j;
 		}
 		if (sh->sh_size < sz) {
@@ -404,10 +406,24 @@
 	Elf_Scn		*s;
 	Ehdr		*eh = elf->ed_ehdr;
 	unsigned	ver = eh->e_version;
-	unsigned	encode = eh->e_ident[EI_DATA];
+	unsigned	encode;
 	int		byte;
 
 	/*
+	 * If this is an ELF_C_WRIMAGE write, then we encode into the
+	 * byte order of the system we are running on rather than that of
+	 * of the object. For ld.so.1, this is the same order, but
+	 * for 'ld', it might not be in the case where we are cross
+	 * linking an object for a different target. In this later case,
+	 * the linker-host byte order is necessary so that the linker can
+	 * manipulate the resulting  image. It is expected that the linker
+	 * will call elf_swap_wrimage() if necessary to convert the image
+	 * to the target byte order.
+	 */
+	encode = (update_cmd == ELF_C_WRIMAGE) ? _elf_sys_encoding() :
+	    eh->e_ident[EI_DATA];
+
+	/*
 	 * Two issues can cause trouble for the output file.
 	 * First, begin() with ELF_C_RDWR opens a file for both
 	 * read and write.  On the write update(), the library
@@ -695,8 +711,8 @@
 				return ((off_t)sz);
 			}
 			sz = _elf_outsync(elf->ed_fd, elf->ed_wrimage,
-				elf->ed_wrimagesz,
-				(elf->ed_myflags & EDF_IMALLOC ? 0 : 1));
+			    elf->ed_wrimagesz,
+			    (elf->ed_myflags & EDF_IMALLOC ? 0 : 1));
 			elf->ed_myflags &= ~EDF_IMALLOC;
 			elf->ed_wrimage = 0;
 			elf->ed_wrimagesz = 0;
@@ -756,6 +772,105 @@
 }
 
 
+/*
+ * When wrt() processes an ELF_C_WRIMAGE request, the resulting image
+ * gets the byte order (encoding) of the platform running the linker
+ * rather than that of the target host. This allows the linker to modify
+ * the image, prior to flushing it to the output file. This routine
+ * is used to re-translate such an image into the byte order of the
+ * target host.
+ */
+int
+_elfxx_swap_wrimage(Elf * elf)
+{
+	NOTE(ASSUMING_PROTECTED(*elf))
+	Elf_Data	dst, src;
+	Elf_Scn		*s;
+	Ehdr		*eh = elf->ed_ehdr;
+	Half		e_phnum = eh->e_phnum;
+	unsigned	ver = eh->e_version;
+	unsigned	encode = eh->e_ident[EI_DATA];
+
+	/*
+	 * Ehdr first
+	 */
+
+	src.d_buf = dst.d_buf = (Elf_Void *)eh;
+	src.d_type = dst.d_type = ELF_T_EHDR;
+	src.d_size = dst.d_size = sizeof (Ehdr);
+	src.d_version = dst.d_version = ver;
+	if (elf_xlatetof(&dst, &src, encode) == 0)
+		return (1);
+
+	/*
+	 * Phdr table if one exists
+	 */
+
+	if (e_phnum != 0) {
+		unsigned	work;
+		/*
+		 * Unlike other library data, phdr table is
+		 * in the user version.
+		 */
+
+		src.d_buf = dst.d_buf = (Elf_Void *)elf->ed_phdr;
+		src.d_type = dst.d_type = ELF_T_PHDR;
+		src.d_size = dst.d_size = elf->ed_phdrsz;
+		ELFACCESSDATA(work, _elf_work)
+		src.d_version = dst.d_version = work;
+		if (elf_xlatetof(&dst, &src, encode) == 0) {
+			return (1);
+		}
+	}
+
+	/*
+	 * Loop through sections
+	 */
+
+	for (s = elf->ed_hdscn; s != 0; s = s->s_next) {
+		register Dnode	*d, *prevd;
+		Shdr		*sh = s->s_shdr;
+
+		if ((sh->sh_type == SHT_NOBITS) || (sh->sh_type == SHT_NULL))
+			continue;
+
+		for (d = s->s_hdnode, prevd = 0;
+		    d != 0; prevd = d, d = d->db_next) {
+
+			if ((d->db_myflags & DBF_READY) == 0) {
+				SCNLOCK(s);
+				if (_elf_locked_getdata(s, &prevd->db_data) !=
+				    &d->db_data) {
+					SCNUNLOCK(s);
+					return (1);
+				}
+				SCNUNLOCK(s);
+			}
+
+			dst = d->db_data;
+			if (elf_xlatetof(&dst, &d->db_data, encode) == 0)
+				return (1);
+		}
+	}
+
+	/*
+	 * Shdr table
+	 */
+
+	src.d_type = dst.d_type = ELF_T_SHDR;
+	src.d_version = dst.d_version = ver;
+	for (s = elf->ed_hdscn; s != 0; s = s->s_next) {
+		src.d_buf = dst.d_buf = s->s_shdr;
+		src.d_size = dst.d_size = sizeof (Shdr);
+		if (elf_xlatetof(&dst, &src, encode) == 0)
+			return (1);
+	}
+
+	return (0);
+}
+
+
+
 #ifndef _ELF64
 /* class-independent, only needs to be compiled once */
 
@@ -775,6 +890,22 @@
 	return (-1);
 }
 
+int
+_elf_swap_wrimage(Elf *elf)
+{
+	if (elf == 0)
+		return (0);
+
+	if (elf->ed_class == ELFCLASS32)
+		return (_elf32_swap_wrimage(elf));
+
+	if (elf->ed_class == ELFCLASS64)
+		return (_elf64_swap_wrimage(elf));
+
+	_elf_seterr(EREQ_CLASS, 0);
+	return (0);
+}
+
 /*
  * 4106312, 4106398, This is an ad-hoc means for the 32-bit
  * Elf64 version of libld.so.3 to get around the limitation
--- a/usr/src/cmd/sgs/libld/Makefile.com	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/Makefile.com	Tue Mar 18 09:17:00 2008 -0700
@@ -31,25 +31,47 @@
 COMOBJS =	debug.o		globals.o	util.o
 
 COMOBJS32 =	args32.o	entry32.o	exit32.o	groups32.o \
-		ldentry32.o	ldlibs32.o	ldmain32.o	libs32.o \
-		files32.o	map32.o		order32.o	outfile32.o \
-		place32.o	relocate32.o	resolve32.o	sections32.o \
-		sunwmove32.o	support32.o	syms32.o	update32.o \
-		version32.o
+		ldentry32.o	ldlibs32.o	ldmachdep32.o	ldmain32.o \
+		libs32.o	files32.o	map32.o		order32.o \
+		outfile32.o	place32.o	relocate32.o	resolve32.o \
+		sections32.o	sunwmove32.o	support32.o	syms32.o \
+		update32.o	version32.o
 
 COMOBJS64 =	args64.o	entry64.o	exit64.o	groups64.o \
-		ldentry64.o	ldlibs64.o	ldmain64.o	libs64.o \
-		files64.o	map64.o		order64.o	outfile64.o \
-		place64.o	relocate64.o	resolve64.o	sections64.o \
-		sunwmove64.o	support64.o	syms64.o	update64.o \
-		version64.o
+		ldentry64.o	ldlibs64.o	ldmachdep64.o	ldmain64.o \
+		libs64.o	files64.o	map64.o		order64.o \
+		outfile64.o 	place64.o	relocate64.o	resolve64.o \
+		sections64.o	sunwmove64.o	support64.o	syms64.o \
+		update64.o	version64.o
 
 TOOLOBJS =	alist.o		assfail.o	findprime.o	string_table.o \
 		strhash.o
 AVLOBJ =	avl.o
 
-G_MACHOBJS32 =	doreloc32.o
-G_MACHOBJS64 =	doreloc64.o
+# Relocation engine objects. These are kept separate from the L_XXX_MACHOBJS
+# lists below in order to facilitate linting them.
+G_MACHOBJS32 =	doreloc_sparc_32.o doreloc_x86_32.o
+G_MACHOBJS64 =	doreloc_sparc_64.o doreloc_x86_64.o
+
+# Target specific objects (sparc/sparcv9)
+L_SPARC_MACHOBJS32 =	machrel.sparc32.o	machsym.sparc32.o
+L_SPARC_MACHOBJS64 =	machrel.sparc64.o	machsym.sparc64.o
+
+# Target specific objects (i386/amd64)
+E_X86_TOOLOBJS =	leb128.o
+L_X86_MACHOBJS32 =	machrel.intel32.o
+L_X86_MACHOBJS64 =	machrel.amd64.o		unwind.amd64.o
+
+
+# All target specific objects rolled together
+E_TOOLOBJS =	$(E_SPARC_TOOLOBJS) \
+	$(E_X86_TOOLOBJS)
+L_MACHOBJS32 =	$(L_SPARC_MACHOBJS32) \
+	$(L_X86_MACHOBJS32)
+L_MACHOBJS64 =	$(L_SPARC_MACHOBJS64) \
+	$(L_X86_MACHOBJS64)
+
+
 
 BLTOBJ =	msg.o
 ELFCAPOBJ =	elfcap.o
@@ -65,6 +87,14 @@
 SRCDIR =	../common
 ELFCAP=		$(SRC)/common/elfcap
 
+
+# Location of the shared relocation engines maintained under usr/src/uts.
+#
+KRTLD_I386 = $(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld
+KRTLD_AMD64 = $(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld
+KRTLD_SPARC = $(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld
+
+
 # Building SUNWonld results in a call to the `package' target.  Requirements
 # needed to run this application on older releases are established:
 #   dlopen/dlclose requires libdl.so.1 prior to 5.10
@@ -75,7 +105,7 @@
 CPPFLAGS +=	-DUSE_LIBLD_MALLOC -I$(SRCBASE)/lib/libc/inc \
 		    -I$(SRCBASE)/uts/common/krtld -I$(ELFCAP) \
 		    -I$(SRCBASE)/uts/sparc \
-		    $(VAR_LIBLD_CPPFLAGS) -DDO_RELOC_LIBLD
+		    $(VAR_LIBLD_CPPFLAGS)
 LDLIBS +=	$(CONVLIBDIR) $(CONV_LIB) $(LDDBGLIBDIR) $(LDDBG_LIB) \
 		    $(ELFLIBDIR) -lelf $(DLLIB) -lc
 
@@ -93,10 +123,14 @@
 
 BLTFILES =	$(BLTDEFS) $(BLTDATA) $(BLTMESG)
 
+# Due to cross linking support, every copy of libld contains every message.
+# However, we keep target specific messages in their own separate files for
+# organizational reasons.
+#
 SGSMSGCOM =	../common/libld.msg
 SGSMSGSPARC =	../common/libld.sparc.msg
 SGSMSGINTEL =	../common/libld.intel.msg
-SGSMSGTARG =	$(SGSMSGCOM)
+SGSMSGTARG =	$(SGSMSGCOM) $(SGSMSGSPARC) $(SGSMSGINTEL)
 SGSMSGALL =	$(SGSMSGCOM) $(SGSMSGSPARC) $(SGSMSGINTEL)
 
 SGSMSGFLAGS1 =	$(SGSMSGFLAGS) -m $(BLTMESG)
@@ -105,7 +139,10 @@
 CHKSRCS =	$(SRCBASE)/uts/common/krtld/reloc.h \
 		$(COMOBJS32:%32.o=../common/%.c) \
 		$(L_MACHOBJS32:%32.o=../common/%.c) \
-		$(L_MACHOBJS64:%64.o=../common/%.c)
+		$(L_MACHOBJS64:%64.o=../common/%.c) \
+		$(KRTLD_I386)/doreloc.c \
+		$(KRTLD_AMD64)/doreloc.c \
+		$(KRTLD_SPARC)/doreloc.c
 
 SRCS =		../common/llib-lld
 LIBSRCS =	$(TOOLOBJS:%.o=$(SGSTOOLS)/common/%.c) \
@@ -120,6 +157,19 @@
 LINTSRCS64 =	$(COMOBJS64:%64.o=../common/%.c) \
 		$(L_MACHOBJS64:%64.o=../common/%.c)
 
+# Add the shared relocation engine source files to the lint
+# sources and add the necessary command line options to lint them
+# correctly. Make can't derive the files since the source and object
+# names are not directly related
+$(LINTOUT32) :=	CPPFLAGS += -DDO_RELOC_LIBLD
+$(LINTOUT64) :=	CPPFLAGS += -DDO_RELOC_LIBLD -D_ELF64
+$(LINTLIB32) :=	CPPFLAGS += -DDO_RELOC_LIBLD
+$(LINTLIB64) :=	CPPFLAGS += -DDO_RELOC_LIBLD -D_ELF64
+LINTSRCS32 +=	$(KRTLD_I386)/doreloc.c	\
+		$(KRTLD_SPARC)/doreloc.c
+LINTSRCS64 +=	$(KRTLD_AMD64)/doreloc.c \
+		$(KRTLD_SPARC)/doreloc.c
+
 CLEANFILES +=	$(LINTOUTS) $(BLTFILES)
 CLOBBERFILES +=	$(DYNLIB) $(LINTLIBS) $(LIBLINKS)
 
--- a/usr/src/cmd/sgs/libld/Makefile.targ	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/Makefile.targ	Tue Mar 18 09:17:00 2008 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -30,19 +30,19 @@
 		$(POST_PROCESS_O)
 
 pics/%32.o:	../common/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET32) $<
+		$(COMPILE.c) -o $@ $<
 		$(POST_PROCESS_O)
 
 pics/%64.o:	../common/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET64) -D_ELF64 $<
+		$(COMPILE.c) -o $@ -D_ELF64 $<
 		$(POST_PROCESS_O)
 
 pics/%32.o:	%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET32) $<
+		$(COMPILE.c) -o $@ $<
 		$(POST_PROCESS_O)
 
 pics/%64.o:	%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET64) -D_ELF64 $<
+		$(COMPILE.c) -o $@ -D_ELF64 $<
 		$(POST_PROCESS_O)
 
 pics/%.o:	$(SGSTOOLS)/common/%.c
@@ -53,18 +53,40 @@
 		$(COMPILE.c) -o $@ $<
 		$(POST_PROCESS_O)
 
-#pics/%32.o:	$(SRCBASE)/uts/$(PLAT)/krtld/%.c
-#		$(COMPILE.c) -o $@ $(ELFTARGET32) $<
-#		$(POST_PROCESS_O)
 #
-#pics/%64.o:	$(SRCBASE)/uts/$(PLAT)/krtld/%.c
-#		$(COMPILE.c) -o $@ $(ELFTARGET64) -D_ELF64 $<
-#		$(POST_PROCESS_O)
-
+# We use the shared elfcap code under usr/src/common/elfcap
+#
 pics/elfcap.o:	$(ELFCAP)/elfcap.c
 		$(COMPILE.c) -o  $@ $(ELFCAP)/elfcap.c
 		$(POST_PROCESS_O)
 
+# Rules for compiling the shared relocation engines (doreloc.c) maintained
+# under usr/src/uts. To support cross linking, We compile and link
+# all of these into every copy of libld. Each one requires a separate rule:
+#	- The source files are in different subtrees under usr/src/uts
+#	- The output file needs to include the platform name to
+#		keep the object files from colliding
+# The DO_RELOC_LIBLD definition is needed to generate the libld version
+# of the doreloc code.
+#
+pics/%_x86_32.o: $(KRTLD_I386)/%.c
+		$(COMPILE.c) -o $@ -DDO_RELOC_LIBLD $<
+		$(POST_PROCESS_O)
+
+pics/%_x86_64.o: $(KRTLD_AMD64)/%.c
+		$(COMPILE.c) -o $@ -D_ELF64 -DDO_RELOC_LIBLD $<
+		$(POST_PROCESS_O)
+
+pics/%_sparc_32.o: $(KRTLD_SPARC)/%.c
+		$(COMPILE.c) -o $@ -DDO_RELOC_LIBLD $<
+		$(POST_PROCESS_O)
+
+pics/%_sparc_64.o: \
+		$(KRTLD_SPARC)/%.c
+		$(COMPILE.c) -o $@ -D_ELF64 -DDO_RELOC_LIBLD $<
+		$(POST_PROCESS_O)
+
+
 $(LIBLINKS):
 		$(RM) $@; $(SYMLINK) $(DYNLIB) $@
 
--- a/usr/src/cmd/sgs/libld/amd64/Makefile	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/amd64/Makefile	Tue Mar 18 09:17:00 2008 -0700
@@ -20,16 +20,12 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
 
-E_TOOLOBJS =	leb128.o
-L_MACHOBJS32 =	machrel.intel32.o	machsym.intel32.o
-L_MACHOBJS64 =	machrel.amd64.o		machsym.intel64.o	unwind.amd64.o
-
 include		../Makefile.com
 
 .KEEP_STATE:
@@ -40,16 +36,6 @@
 ROOTFS_DYNLIB64 = \
 		$(DYNLIB:%=$(ROOTFS_LIBDIR64)/%)
 
-SGSMSGCHK =	../common/libld.chk.msg
-SGSMSGTARG +=	$(SGSMSGINTEL)
-
-#
-# For cross-compilation, it is necessary to trigger the correct include files
-# (see sys/elf.h).
-#
-ELFTARGET64 =	-DELF_TARGET_AMD64
-ELFTARGET32 =	-DELF_TARGET_386
-
 ELFLIBDIR =	$(ELFLIBDIR64)
 LDDBGLIBDIR =	$(LDDBGLIBDIR64)
 CONVLIBDIR =	$(CONVLIBDIR64)
@@ -63,37 +49,3 @@
 
 include		../Makefile.targ
 include		../../Makefile.sub.64
-
-# Associate ELF32 and ELF64 objects to the appropriate headers.
-
-pics/%32.o :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld
-pics/%64.o :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld
-
-# Associate the various lint targets with the appropriate headers/files.
-
-$(LINTOUT32) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld \
-		    $(ELFTARGET32)
-$(LINTOUT64) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld \
-		    $(ELFTARGET64) -D_ELF64
-$(LINTLIB32) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld \
-		    $(ELFTARGET32)
-$(LINTLIB64) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld \
-		    $(ELFTARGET64) -D_ELF64
-
-LINTSRCS32 +=	$(G_MACHOBJS32:%32.o=$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld/%.c)
-LINTSRCS64 +=	$(G_MACHOBJS64:%64.o=$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld/%.c)
-
-# Compensate chkmsg with the doreloc family.
-
-CHKSRCS +=	$(G_MACHOBJS32:%32.o=$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld/%.c)
-CHKSRCS +=	$(G_MACHOBJS64:%64.o=$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld/%.c)
-
-pics/%32.o: \
-		$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET32) $<
-		$(POST_PROCESS_O)
-
-pics/%64.o: \
-		$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET64) -D_ELF64 $<
-		$(POST_PROCESS_O)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/libld/common/README.XLINK	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,373 @@
+#
+# 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.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+
+
+
+
+Notes On Cross Link-Editor Support in libld.so
+-----------------------------------------
+
+The Solaris link-editor is used in two contexts:
+
+	1) The standard ld command
+	2) Via the runtime linker (ld.so.1), when a program
+	   calls dlopen() on a relocatable object (ET_REL).
+
+To support both uses, it is packaged as a sharable library (libld.so).
+The ld command is therefore a simple wrapper that uses libld.
+
+libld.so is a cross linker. This means that it can link objects for
+a system other than the system running the link-editor (e.g. A link-editor
+running on an amd64 system processing sparc objects). This means that every
+instance of libld.so contains code for building objects for every supported
+target. This unlike GNU ld, where you build gld specifically for the
+platform you're targeting. This is possible because unlike gld, we only
+support Solaris, with a small number of platforms. 
+
+At initialization, the caller of libld.so specifies the type of objects
+being linked. By default, the ld command determines the machine type and
+class of the object being generated from the first ELF object processed
+from the command line. The -64 and -ztarget options exists to change this
+default, which is useful when creating an object entirely from an archive
+library or a mapfile. During initialization, the link-editor configures
+itself to build an output object of the specified type. This is done via
+indirection, using the global ld_targ structure to access code, data, and
+constants for the specified target.
+
+There are two types of source files used to build libld.so:
+
+	1) Common code used for all targets
+	2) Target specific code used only when linking for
+	  a given target.
+
+All of these files reside in usr/src/cmd/sgs/libld/common. However,
+it is easy to see which files belong in each category by examining
+the object lists maintained in usr/src/cmd/sgs/libld/Makefile.com.
+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
+(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
+a common core to support all the targets it knows about in a way that
+is understandable and maintainable. A truly pluggable architecture
+would be considerably more opaque and complex, and is neither necessary,
+nor desirable, given the wide commonality between modern computer
+architectures.
+
+It is possible to add support for new targets to libld.so. The process
+of doing so is largely a matter of examining the files for existing
+platforms, studying the ABI for the new target platform, and then
+filling in the missing pieces for the new target. The remainder of this
+file consists of sections that describe some of the issues and steps
+that you will encounter in adding a new target.
+
+-----------------------------------------------------------------------------
+The relocation code used by ld is shared by the runtime linker (ld.so.1)
+and by the kernel module loader (ktrld), and is therefore found under
+usr/src/uts. You must add code for a relocation engine to support the
+new target. To do so, examine the common header files:
+
+	usr/src/uts/common/krtld/reloc.h
+	usr/src/uts/common/krtld/reloc_defs.h
+
+   and the existing relocation engines:
+
+	usr/src/uts/intel/amd64/krtld/doreloc.c
+	usr/src/uts/intel/ia32/krtld/doreloc.c
+	usr/src/uts/sparc/krtld/doreloc.c
+
+The ABI for the target platform will be the primary information
+you require. If your new system has attributes not found in an existing
+target, you may have to add/modify fields in the Rel_entry struct typedef
+(reloc_defs.h), or you may have to add new flags. Either sort of change
+may require you to also modify the existing relocation engines, and
+undoubtedly the common code in libld.so as well.
+
+When compiled for use by libld, the relocation engine requires an
+argument named "bswap". Each relocation engine must be prepared to
+swap the data bytes it is operating on. This support allows a link-editor
+running on a platform with a different byte order than the target to
+build objects for that target. To see how this is implemented, and how
+to ifdef that support so it only exists in the libld version of
+the engine, examine the code for the existing engines.
+
+-----------------------------------------------------------------------------
+You must create a target subdirectory in usr/src/cmd/sgs/include,
+and construct a machdep_XXX.h file (where XXX is the name of the
+target). The machdep files for the current platforms can be helpful:
+
+	usr/src/cmd/sgs/include/sparc/machdep_sparc.h
+	usr/src/cmd/sgs/include/i386/machdep_x86.h
+
+Note that these files support both the 32 and 64-bit versions of
+a given platform, so there is only one subdirectory and machdep
+file for each platform (i.e. "sparc", instead of "sparc" and "sparcv9").
+
+Once you have created the target machdep_XXX.h file, you must edit:
+
+	usr/src/cmd/sgs/include/machdep.h
+
+and add a #include for your new file to it, surrounded by the
+appropriate #ifdef for the target platform.
+
+This two level structure allows us to #include machdep information
+in two different ways:
+
+	1) Code that wants support for the current platform,
+	   regardless of which platform that is, can include
+	   usr/src/cmd/sgs/include/machdep.h. The runtime linker
+	   (ld.so.1) is the primary consumer of this form.
+
+	2) Code that needs to support multiple targets must never
+	   include the generic machdep.h from (1) above. Instead,
+	   such code explicitly includes the machdep file for the target
+	   it is interested in. For example:
+
+		#include <sparc/machdep_sparc.h>
+
+	   libld.so uses this form to build non-native target
+	   code.
+
+You will find that most of the constants defined in the target
+machdep file end up as initialization for the information that
+libld.so accesses via the ld_targ global variable.
+
+-----------------------------------------------------------------------------
+Study the definition of the Target typedef in
+
+	usr/src/cmd/sgs/libld/common/_libld.h
+
+This is the type of the ld_targ global variable. Filling in a complete
+copy of this definition is the primary task involved in adding support
+for a new target to libld.so, so it will be helpful to be familiar with
+it before you dive deeper. libld follows two simple rules with regards
+to ld_targ, and the Target type:
+
+	1) The target-independent common code can only access
+	   target-dependent code or data via the ld_targ global
+	   variable.
+
+	2) The target-dependent code can access the common
+	   code or data freely.
+
+A given link-editor invocation is always for a single target. The choice
+of target is made at initialization, and does not change within a
+single link. Code for the other targets is present, but is not
+accessed.
+
+-----------------------------------------------------------------------------
+Files containing the target-specific code to support the new
+platform must be added to libld.so. Examine the object lists
+in usr/src/cmd/sgs/libld/Makefile.com to see the files for existing
+platforms, and read those files to get a sense of what is required.
+
+Among the other files, every platform will have a file named
+machrel.XXX.c. This file contains the relocation-related functions,
+and it also contains an init function for the target. This init function
+is responsible for initializing the ld_targ global variable so that
+the common code will use the code and definitions for your
+target.
+
+You should start by creating a machrel.XXX.c file for your new
+target. Add other files as needed. Be aware that any functions or
+variables you place in these target-dependent files must either
+be static, or must have names that will not collide with the names
+used by the rest of libld.so. The easiest way to do this is to
+add a target suffix to the end of all such non-local names
+(i.e. foo_sparc() instead of foo()).
+
+The existing code is the documentation for this phase of things: The
+best way to determine what a given function should do is to read the
+code for other platforms, taking into account the similarities and
+differences in the ABI for your new target and those existing ones.
+
+-----------------------------------------------------------------------------
+You may find that your new target requires support for new concepts
+not found in other targets. A common example of this might be
+a new target specific ELF section type (i.e. SHT_AMD64_UNWIND). Another
+might be details involving PIC code and PLT generation (as found for
+sparc). It may be necessary to add new fields to the ld_targ global
+variable, and to modify the libld.so common code to use these new
+fields.
+
+It is a standard convention that NULL function pointers are used to
+represent functionality not required by a given target. Although the
+common code can consult ld_targ.t_m.m_mach to determine the target it
+is linking for, and although there is some code that does this, it
+is generally undesirable and unnecessary. Instead, the common code
+should test for such pointers, as with this sparc-specific example
+from update.c:
+
+	/*
+	 * Assign a got offset if necessary.
+	 */
+	if ((ld_targ.t_mr.mr_assign_got != NULL) &&
+	    (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR)
+		return ((Addr)S_ERROR);
+
+It may be tempting to include information in the comment that explains
+the target specific nature of this, and that may even be appropriate.
+Consider however, that a new target may come along with the same feature
+later, and if that occurs, your comments will instantly be dated. In general,
+the use of ld_targ is a strong hint to the reader that they should go read
+the target-specific code referenced to understand what is going on. It is
+best to supply comments at the call site that describe the operation
+in generic terms (i.e. "assign a got if necessary") instead of in
+explicit target terms (i.e. "Assign a sparc got if necessary"). Of
+course, some features are extremely target-specific (like amd64 unwind
+sections), and it doesn't really help to be obscure in such cases.
+This is a judgement call.
+
+If you do add a new field to ld_targ that uses NULL to represent
+an option feature *YOU MUST DOCUMENT IT AS SUCH*. You will find
+comments in _libld.h for existing optional fields. It suffices to
+add a comment for your new field. In the absence of such a comment,
+the common code assumes that all function pointers are safe to call
+through (dereference) without first testing them.
+
+-----------------------------------------------------------------------------
+Byte swapping is a big issue in cross linking, as the system running
+the link-editor may have the opposite byte order from the target. It is
+important to know when, and when not, to swap bytes.
+
+If the build system and target have different byte orders, the
+FLG_OF1_ENCDIFF bit of the ofl_flags field of the output file
+descriptor will be set. If this bit is not set, the target and
+system byte orders are the same, and no byte swapping
+is required.
+
+libld uses libelf to read and write objects. libelf automatically
+swaps bytes for the sections it knows about, such as symbol tables,
+relocation records, and the usual ELF plumbing. It is therefore never
+necessary for your code to swap the bytes in this data. If you find that
+this is not the case, you have probably uncovered a bug in libelf that
+you should look into.
+
+The big exception to libelf transparently handling byte swapping is
+progbits sections (SHT_PROGBITS). libelf does not understand program
+code or data as anything other than a series of byte values, and as such,
+cannot do byte swapping for them. If your code examines or modifies
+such data, you are responsible for handling the byte swapping required.
+
+The OFL_SWAP_RELOC macros found in _libld.h can be helpful in making such
+determinations. You should use these macros instead of writing your own
+tests for this, as they have high documentation value. If you find they
+don't handle your target, add a new one that does.
+
+GOT and PLT sections are SHT_PROGBITS. You will probably find
+that the vast majority of byte swapping you have to handle
+concern the handling of these items.
+
+libld contains generic functions for byte swapping:
+
+	ld_bswap_Word();
+	ld_bswap_Xword();
+
+These functions are built on top of the of the BSWAP_ macros found
+in usr/src/cmd/sgs/include/_machelf.h:
+
+	BSWAP_HALF
+	BSWAP_WORD
+	BSWAP_XWORD
+
+When copying data from one address to another in a cross link environment,
+the source and/or destination addresses may not have adequate alignment for
+the data type being copied. For example, a sparc platform cannot access
+8-byte data types on 4-byte boundaries, but it might need to do so when
+linking X86 objects where the alignment of such data can be 4. The
+UL_ASSIGN macros can be used to copy potentially unaligned data:
+
+	UL_ASSIGN_HALF
+	UL_ASSIGN_WORD
+	UL_ASSIGN_XWORD
+
+The UL_ASSIGN_BSWAP macros do unaligned copies, and also perform
+byte swapping when the linker host and target byte orders are
+different:
+
+	UL_ASSIGN_BSWAP_HALF
+	UL_ASSIGN_BSWAP_WORD
+	UL_ASSIGN_BSWAP_XWORD
+
+If you are reading/writing to relocation data, the following
+routines understand relocation records and will get/set the
+proper amount of data while handling any needed swapping:
+
+	ld_reloc_targval_get()
+	ld_reloc_targval_set()
+
+Byte swapping is a fertile area for mistakes. If you're having trouble
+getting a successful link in a cross link situation, you should always
+do the experiment of doing the link on a platform with the same byte
+order as the target. If that link succeeds, then you are looking at
+a bug involving incorrect byte swapping.
+
+-----------------------------------------------------------------------------
+   As mentioned above, incorrect byte swapping is a common
+error when developing libld target specific code. In addition to
+trying a build machine with the same byte order as the target, elfdump
+can also be a powerful tool for debugging. The first step with
+elfdump is to simply dump everything and read it looking for obviously
+bad information:
+
+	% elfdump outobj 2>&1 | more
+
+elfdump tries to do sanity checking on the objects it
+displays. Hence, the following command is a a common
+idiom:
+
+	% elfdump outobj > /dev/null
+
+Any problems with the file that elfdump can detect will be
+written to stderr.
+
+-----------------------------------------------------------------------------
+Once you have the target-specific code in place, you must modify the
+libld initialization code so that it will know how to use it. This
+logic is found in
+
+	usr/src/cmd/sgs/libld/common/ldmain.c
+
+in the function ld_init_target().
+
+-----------------------------------------------------------------------------
+The ld front end program that uses libld must be modified so that
+the "-z target=platform" command line option recognizes your
+new target. This code is found in
+
+	usr/src/cmd/sgs/ld/common
+
+The change consists of adding an additional strcasecmp() to the
+command line processing for -ztarget.
+
+-----------------------------------------------------------------------------
+You probably changed things getting your target integrated.
+Please update this document to reflect your changes.
--- a/usr/src/cmd/sgs/libld/common/_libld.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/_libld.h	Tue Mar 18 09:17:00 2008 -0700
@@ -41,27 +41,206 @@
 #include <debug.h>
 #include <conv.h>
 #include <msg.h>
+#include <reloc_defs.h>
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
 /*
- * Types of segment index.
+ * In order to allow for cross linking, we need to be able to build
+ * libld with support for multiple targets within a single object.
+ * This is done using a global variable (ld_targ) of type Target to
+ * access target-specific code for the current target via indirection.
+ */
+
+/*
+ * Machine information for target
+ */
+typedef struct {
+	Half		m_mach;		/* ELF machine code for target */
+	Half		m_machplus;	/* Alt ELF machine code for target */
+					/*	Used for EM_SPARC32PLUS */
+	Word		m_flagsplus;	/* ELF header flags used to identify */
+					/*	a machplus object */
+	uchar_t		m_class;	/* Target ELFCLASS */
+	uchar_t		m_data;		/* Target byte order */
+
+	Xword		m_segm_align;	/* segment alignment */
+	Xword		m_segm_origin;	/* Default 1st segment offset */
+	Word		m_dataseg_perm;	/* data segment permission mask */
+	Word		m_word_align;	/* alignment to use for Word sections */
+	const char	*m_def_interp;	/* Def. interpreter for dyn objects */
+
+	/* Relocation type codes */
+	Word		m_r_arrayaddr;
+	Word		m_r_copy;
+	Word		m_r_glob_dat;
+	Word		m_r_jmp_slot;
+	Word		m_r_num;
+	Word		m_r_none;
+	Word		m_r_relative;
+	Word		m_r_register;
+
+	/* Relocation related constants */
+	Word		m_rel_dt_count;	/* Either DT_REL or DT_RELA */
+	Word		m_rel_dt_ent;	/* Either DT_RELENT or DT_RELAENT */
+	Word		m_rel_dt_size;	/* Either DT_RELSZ or DT_RELASZ */
+	Word		m_rel_dt_type;	/* Either DT_RELCOUNT or DT_RELACOUNT */
+	Word		m_rel_sht_type;	/* Either SHT_REL or SHT_RELA */
+
+	/* GOT related constants */
+	Word		m_got_entsize;
+	Word		m_got_xnumber;	/* reserved # of got ents */
+
+	/* PLT related constants */
+	Word		m_plt_align;
+	Word		m_plt_entsize;
+	Word		m_plt_reservsz;
+	Word		m_plt_shf_flags;
+
+	Word		m_dt_register;
+} Target_mach;
+
+
+/*
+ * Section identifiers, used to order sections in output object
  */
-typedef enum {
-	LD_PHDR,	LD_INTERP,	LD_SUNWCAP,	LD_TEXT,
-	LD_DATA,	LD_BSS,
-#if	defined(__x86) && defined(_ELF64)
-	LD_LRODATA,	LD_LDATA,
-#endif
-	LD_DYN,		LD_DTRACE,	 LD_SUNWBSS,	LD_TLS,
-#if	defined(__x86) && defined(_ELF64)
-	LD_UNWIND,
-#endif
-	LD_NOTE,	LD_EXTRA,
-	LD_NUM
-} Segment_ndx;
+typedef struct {
+	Word		id_array;
+	Word		id_bss;
+	Word		id_cap;
+	Word		id_data;
+	Word		id_dynamic;
+	Word		id_dynsort;
+	Word		id_dynstr;
+	Word		id_dynsym;
+	Word		id_dynsym_ndx;
+	Word		id_got;
+	Word		id_gotdata;
+	Word		id_hash;
+	Word		id_interp;
+	Word		id_lbss;
+	Word		id_ldynsym;
+	Word		id_note;
+	Word		id_null;
+	Word		id_plt;
+	Word		id_rel;
+	Word		id_strtab;
+	Word		id_syminfo;
+	Word		id_symtab;
+	Word		id_symtab_ndx;
+	Word		id_text;
+	Word		id_tls;
+	Word		id_tlsbss;
+	Word		id_unknown;
+	Word		id_unwind;
+	Word		id_user;
+	Word		id_version;
+} Target_machid;
+
+/*
+ * Target_nullfunc supplies machine code for generating a
+ *
+ *	void (*)(void)
+ *
+ * unnamed function. Such a function can be called, and returns
+ * immediately without doing any work. This is used to back FUNC
+ * symbol definitions added with a mapfile.
+ *
+ * The machine instructions are specified as an array of bytes rather
+ * than a larger integer type in order to avoid byte order issues that
+ * can otherwise occur in cross linking.
+ */
+typedef struct {
+	const uchar_t	*nf_template;	/* Array of machine inst. bytes */
+	size_t		nf_size;	/* # bytes in nf_template */
+} Target_nullfunc;
+
+/*
+ * Target_machrel holds pointers to the reloc_table and machrel functions
+ * for a given target machine.
+ *
+ * The following function pointers are allowed to be NULL, if the
+ * underlying target does not require the specified operation. All
+ * other functions must be supplied:
+ *
+ *	mr_assign_got
+ *	mr_reloc_register
+ *	mr_reloc_GOTOP
+ *	mr_allocate_got
+ */
+typedef struct {
+	const Rel_entry	*mr_reloc_table;
+
+	Word		(* mr_init_rel)(Rel_desc *, void *);
+	void 		(* mr_mach_eflags)(Ehdr *, Ofl_desc *);
+	void		(* mr_mach_make_dynamic)(Ofl_desc *, size_t *);
+	void		(* mr_mach_update_odynamic)(Ofl_desc *, Dyn **);
+	Xword		(* mr_calc_plt_addr)(Sym_desc *, Ofl_desc *);
+	uintptr_t	(* mr_perform_outreloc)(Rel_desc *, Ofl_desc *);
+	uintptr_t	(* mr_do_activerelocs)(Ofl_desc *);
+	uintptr_t	(* mr_add_outrel)(Word, Rel_desc *, Ofl_desc *);
+	uintptr_t	(* mr_reloc_register)(Rel_desc *, Is_desc *,
+			    Ofl_desc *);
+	uintptr_t	(* mr_reloc_local)(Rel_desc *, Ofl_desc *);
+	uintptr_t	(* mr_reloc_GOTOP)(Boolean, Rel_desc *, Ofl_desc *);
+	uintptr_t	(* mr_reloc_TLS)(Boolean, Rel_desc *, Ofl_desc *);
+	uintptr_t	(* mr_assign_got)(Ofl_desc *, Sym_desc *);
+
+	Gotndx *	(* mr_find_gotndx)(List *, Gotref, Ofl_desc *,
+			    Rel_desc *);
+	Xword		(* mr_calc_got_offset)(Rel_desc *, Ofl_desc *);
+	uintptr_t	(* mr_assign_got_ndx)(List *, Gotndx *, Gotref,
+			    Ofl_desc *, Rel_desc *, Sym_desc *);
+	void		(* mr_assign_plt_ndx)(Sym_desc *, Ofl_desc *);
+	uintptr_t	(* mr_allocate_got)(Ofl_desc *);
+	uintptr_t	(* mr_fillin_gotplt)(Ofl_desc *);
+} Target_machrel;
+
+
+/*
+ * Target_machsym holds pointers to the machsym functions
+ * for a given target machine.
+ *
+ * These fields are allowed to be NULL for targets that do not require
+ * special handling of register symbols. Register symbols are used by
+ * sparc targets. If any of these fields are non-NULL, all of them are
+ * required to be present (use empty stub routines if necessary).
+ */
+typedef struct {
+	int		(* ms_reg_check)(Sym_desc *, Sym *, const char *,
+			    Ifl_desc *, Ofl_desc *);
+	int		(* ms_mach_sym_typecheck)(Sym_desc *, Sym *,
+			    Ifl_desc *, Ofl_desc *);
+	const char	*(* ms_is_regsym)(Ofl_desc *, Ifl_desc *, Sym *,
+			    const char *, int, Word, const char *, Word *);
+	Sym_desc	*(* ms_reg_find)(Sym * sym, Ofl_desc * ofl);
+	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;
+
 
 /*
  * Types of bss sections
@@ -203,6 +382,7 @@
 extern const int	ldynsym_symtype[STT_NUM];
 extern const int	dynsymsort_symtype[STT_NUM];
 
+
 /*
  * Given a symbol of a type that is allowed within a .SUNW_dynsymsort or
  * .SUNW_dyntlssort section, examine the symbol attributes to determine
@@ -293,6 +473,18 @@
 
 
 /*
+ * The OFL_SWAP_RELOC macros are used to determine whether
+ * relocation processing needs to swap the data being relocated.
+ * It is an optimization to ld_swap_reloc_data(), as it avoids
+ * the function call in the case where the linker host and the
+ * target have the same byte order.
+ */
+
+#define	OFL_SWAP_RELOC_DATA(_ofl, _rel) \
+	(((_ofl)->ofl_flags1 & FLG_OF1_ENCDIFF) && \
+	ld_swap_reloc_data(_ofl, _rel))
+
+/*
  * For backward compatibility provide a /dev/zero file descriptor.
  */
 extern int		dz_fd;
@@ -321,40 +513,23 @@
 
 #define	ld_add_actrel		ld64_add_actrel
 #define	ld_add_libdir		ld64_add_libdir
-#define	ld_add_outrel		ld64_add_outrel
 #define	ld_adj_movereloc	ld64_adj_movereloc
-#if	defined(__sparc)
-#define	ld_allocate_got		ld64_allocate_got
-#endif
 #define	ld_am_I_partial		ld64_am_I_partial
 #define	ld_append_isp		ld64_append_isp
 #define	ld_ar_member		ld64_ar_member
 #define	ld_ar_setup		ld64_ar_setup
-#define	ld_assign_got		ld64_assign_got
-#define	ld_assign_got_ndx	ld64_assign_got_ndx
 #define	ld_assign_got_TLS	ld64_assign_got_TLS
-#define	ld_assign_plt_ndx	ld64_assign_plt_ndx
-#define	ld_byteswap_Xword	ld64_byteswap_Xword
-#define	ld_calc_got_offset	ld64_calc_got_offset
-#define	ld_calc_plt_addr	ld64_calc_plt_addr
+#define	ld_bswap_Word		ld64_bswap_Word
+#define	ld_bswap_Xword		ld64_bswap_Xword
 #define	ld_disp_errmsg		ld64_disp_errmsg
-#define	ld_do_activerelocs	ld64_do_activerelocs
 #define	ld_ent_check		ld64_ent_check
 #define	ld_exit			ld64_exit
-#define	ld_fillin_gotplt	ld64_fillin_gotplt
-#define	ld_find_gotndx		ld64_find_gotndx
 #define	ld_find_library		ld64_find_library
 #define	ld_finish_libs		ld64_finish_libs
 #define	ld_get_group		ld64_get_group
 #define	ld_lib_setup		ld64_lib_setup
 #define	ld_init			ld64_init
-#define	ld_init_rel		ld64_init_rel
-#define	ld_is_regsym		ld64_is_regsym
 #define	ld_lcm			ld64_lcm
-#define	ld_mach_update_odynamic	ld64_mach_update_odynamic
-#define	ld_mach_eflags		ld64_mach_eflags
-#define	ld_mach_make_dynamic	ld64_mach_make_dynamic
-#define	ld_mach_sym_typecheck	ld64_mach_sym_typecheck
 #define	ld_make_bss		ld64_make_bss
 #define	ld_make_data		ld64_make_data
 #define	ld_make_got		ld64_make_got
@@ -365,7 +540,6 @@
 #define	ld_map_out		ld64_map_out
 #define	ld_map_parse		ld64_map_parse
 #define	ld_open_outfile		ld64_open_outfile
-#define	ld_perform_outreloc	ld64_perform_outreloc
 #define	ld_place_section	ld64_place_section
 #define	ld_process_archive	ld64_process_archive
 #define	ld_process_files	ld64_process_files
@@ -373,22 +547,16 @@
 #define	ld_process_ifl		ld64_process_ifl
 #define	ld_process_ordered	ld64_process_ordered
 #define	ld_process_sym_reloc	ld64_process_sym_reloc
-#define	ld_reloc_local		ld64_reloc_local
 #define	ld_reloc_GOT_relative	ld64_reloc_GOT_relative
-#define	ld_reloc_GOTOP		ld64_reloc_GOTOP
 #define	ld_reloc_plt		ld64_reloc_plt
-#define	ld_reloc_register	ld64_reloc_register
 #define	ld_reloc_remain_entry	ld64_reloc_remain_entry
-#define	ld_reloc_TLS		ld64_reloc_TLS
 #define	ld_reloc_targval_get	ld64_reloc_targval_get
 #define	ld_reloc_targval_set	ld64_reloc_targval_set
-#define	ld_reg_check		ld64_reg_check
-#define	ld_reg_enter		ld64_reg_enter
-#define	ld_reg_find		ld64_reg_find
 #define	ld_sec_validate		ld64_sec_validate
 #define	ld_section_reld_name	ld64_section_reld_name
 #define	ld_sort_ordered		ld64_sort_ordered
 #define	ld_sort_seg_list	ld64_sort_seg_list
+#define	ld_sunw_ldmach		ld64_sunw_ldmach
 #define	ld_sunwmove_preprocess	ld64_sunwmove_preprocess
 #define	ld_sup_atexit		ld64_sup_atexit
 #define	ld_sup_open		ld64_sup_open
@@ -398,6 +566,7 @@
 #define	ld_sup_input_section	ld64_sup_input_section
 #define	ld_sup_section		ld64_sup_section
 #define	ld_sup_start		ld64_sup_start
+#define	ld_swap_reloc_data	ld64_swap_reloc_data
 #define	ld_sym_add_u		ld64_sym_add_u
 #define	ld_sym_adjust_vis	ld64_sym_adjust_vis
 #define	ld_sym_avl_comp		ld64_sym_avl_comp
@@ -408,6 +577,9 @@
 #define	ld_sym_process		ld64_sym_process
 #define	ld_sym_resolve		ld64_sym_resolve
 #define	ld_sym_spec		ld64_sym_spec
+#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_vers_base		ld64_vers_base
 #define	ld_vers_check_defs	ld64_vers_check_defs
 #define	ld_vers_check_need	ld64_vers_check_need
@@ -423,41 +595,24 @@
 
 #define	ld_add_actrel		ld32_add_actrel
 #define	ld_add_libdir		ld32_add_libdir
-#define	ld_add_outrel		ld32_add_outrel
 #define	ld_adj_movereloc	ld32_adj_movereloc
-#if	defined(__sparc)
-#define	ld_allocate_got		ld32_allocate_got
-#endif
 #define	ld_am_I_partial		ld32_am_I_partial
 #define	ld_append_isp		ld32_append_isp
 #define	ld_ar_member		ld32_ar_member
 #define	ld_ar_setup		ld32_ar_setup
-#define	ld_assign_got		ld32_assign_got
-#define	ld_assign_got_ndx	ld32_assign_got_ndx
 #define	ld_assign_got_TLS	ld32_assign_got_TLS
-#define	ld_assign_plt_ndx	ld32_assign_plt_ndx
-#define	ld_byteswap_Xword	ld32_byteswap_Xword
-#define	ld_calc_got_offset	ld32_calc_got_offset
-#define	ld_calc_plt_addr	ld32_calc_plt_addr
+#define	ld_bswap_Word		ld32_bswap_Word
+#define	ld_bswap_Xword		ld32_bswap_Xword
 #define	ld_disp_errmsg		ld32_disp_errmsg
-#define	ld_do_activerelocs	ld32_do_activerelocs
 #define	ld_ent_check		ld32_ent_check
 #define	ld_exit			ld32_exit
-#define	ld_fillin_gotplt	ld32_fillin_gotplt
-#define	ld_find_gotndx		ld32_find_gotndx
 #define	ld_find_library		ld32_find_library
 #define	ld_finish_libs		ld32_finish_libs
 #define	ld_section_reld_name	ld32_section_reld_name
 #define	ld_get_group		ld32_get_group
 #define	ld_lib_setup		ld32_lib_setup
 #define	ld_init			ld32_init
-#define	ld_init_rel		ld32_init_rel
-#define	ld_is_regsym		ld32_is_regsym
 #define	ld_lcm			ld32_lcm
-#define	ld_mach_update_odynamic	ld32_mach_update_odynamic
-#define	ld_mach_eflags		ld32_mach_eflags
-#define	ld_mach_make_dynamic	ld32_mach_make_dynamic
-#define	ld_mach_sym_typecheck	ld32_mach_sym_typecheck
 #define	ld_make_bss		ld32_make_bss
 #define	ld_make_data		ld32_make_data
 #define	ld_make_got		ld32_make_got
@@ -468,7 +623,6 @@
 #define	ld_map_out		ld32_map_out
 #define	ld_map_parse		ld32_map_parse
 #define	ld_open_outfile		ld32_open_outfile
-#define	ld_perform_outreloc	ld32_perform_outreloc
 #define	ld_place_section	ld32_place_section
 #define	ld_process_archive	ld32_process_archive
 #define	ld_process_files	ld32_process_files
@@ -476,21 +630,15 @@
 #define	ld_process_ifl		ld32_process_ifl
 #define	ld_process_ordered	ld32_process_ordered
 #define	ld_process_sym_reloc	ld32_process_sym_reloc
-#define	ld_reloc_local		ld32_reloc_local
 #define	ld_reloc_GOT_relative	ld32_reloc_GOT_relative
-#define	ld_reloc_GOTOP		ld32_reloc_GOTOP
 #define	ld_reloc_plt		ld32_reloc_plt
-#define	ld_reloc_register	ld32_reloc_register
 #define	ld_reloc_remain_entry	ld32_reloc_remain_entry
-#define	ld_reloc_TLS		ld32_reloc_TLS
 #define	ld_reloc_targval_get	ld32_reloc_targval_get
 #define	ld_reloc_targval_set	ld32_reloc_targval_set
-#define	ld_reg_check		ld32_reg_check
-#define	ld_reg_enter		ld32_reg_enter
-#define	ld_reg_find		ld32_reg_find
 #define	ld_sec_validate		ld32_sec_validate
 #define	ld_sort_ordered		ld32_sort_ordered
 #define	ld_sort_seg_list	ld32_sort_seg_list
+#define	ld_sunw_ldmach		ld32_sunw_ldmach
 #define	ld_sunwmove_preprocess	ld32_sunwmove_preprocess
 #define	ld_sup_atexit		ld32_sup_atexit
 #define	ld_sup_open		ld32_sup_open
@@ -500,6 +648,7 @@
 #define	ld_sup_input_section	ld32_sup_input_section
 #define	ld_sup_section		ld32_sup_section
 #define	ld_sup_start		ld32_sup_start
+#define	ld_swap_reloc_data	ld32_swap_reloc_data
 #define	ld_sym_add_u		ld32_sym_add_u
 #define	ld_sym_adjust_vis	ld32_sym_adjust_vis
 #define	ld_sym_avl_comp		ld32_sym_avl_comp
@@ -510,6 +659,9 @@
 #define	ld_sym_process		ld32_sym_process
 #define	ld_sym_resolve		ld32_sym_resolve
 #define	ld_sym_spec		ld32_sym_spec
+#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_vers_base		ld32_vers_base
 #define	ld_vers_check_defs	ld32_vers_check_defs
 #define	ld_vers_check_need	ld32_vers_check_need
@@ -527,36 +679,24 @@
 
 extern uintptr_t	ld_add_actrel(Word, Rel_desc *, Ofl_desc *);
 extern uintptr_t	ld_add_libdir(Ofl_desc *, const char *);
-extern uintptr_t	ld_add_outrel(Word, Rel_desc *, Ofl_desc *);
 extern void 		ld_adj_movereloc(Ofl_desc *, Rel_desc *);
 extern Sym_desc * 	ld_am_I_partial(Rel_desc *, Xword);
 extern int		ld_append_isp(Ofl_desc *, Os_desc *, Is_desc *, int);
 extern void		ld_ar_member(Ar_desc *, Elf_Arsym *, Ar_aux *,
 			    Ar_mem *);
 extern Ar_desc		*ld_ar_setup(const char *, Elf *, Ofl_desc *);
-#if	defined(__sparc)
-extern uintptr_t	ld_allocate_got(Ofl_desc *);
-#endif
-extern uintptr_t	ld_assign_got(Ofl_desc *, Sym_desc *);
-extern uintptr_t	ld_assign_got_ndx(List *, Gotndx *, Gotref, Ofl_desc *,
-			    Rel_desc *, Sym_desc *);
 extern uintptr_t	ld_assign_got_TLS(Boolean, Rel_desc *, Ofl_desc *,
 			    Sym_desc *, Gotndx *, Gotref, Word, Word,
 			    Word, Word);
-extern void		ld_assign_plt_ndx(Sym_desc *, Ofl_desc *);
 
-extern Xword		ld_byteswap_Xword(Xword);
-extern Xword		ld_calc_got_offset(Rel_desc *, Ofl_desc *);
-extern Xword		ld_calc_plt_addr(Sym_desc *, Ofl_desc *);
+extern Word		ld_bswap_Word(Word);
+extern Xword		ld_bswap_Xword(Xword);
 
 extern void		ld_disp_errmsg(const char *, Rel_desc *, Ofl_desc *);
-extern uintptr_t	ld_do_activerelocs(Ofl_desc *);
 
 extern void		ld_ent_check(Ofl_desc *);
 extern int		ld_exit(Ofl_desc *);
 
-extern uintptr_t	ld_fillin_gotplt(Ofl_desc *);
-extern Gotndx *		ld_find_gotndx(List *, Gotref, Ofl_desc *, Rel_desc *);
 extern uintptr_t	ld_find_library(const char *, Ofl_desc *);
 extern uintptr_t	ld_finish_libs(Ofl_desc *);
 
@@ -567,17 +707,9 @@
 extern uintptr_t	ld_lib_setup(Ofl_desc *);
 
 extern void		ld_init(Ofl_desc *);
-extern Word		ld_init_rel(Rel_desc *, void *);
-extern const char	*ld_is_regsym(Ofl_desc *, Ifl_desc *, Sym *,
-			    const char *, int, Word, const char *, Word *);
 
 extern Xword		ld_lcm(Xword, Xword);
 
-extern void		ld_mach_update_odynamic(Ofl_desc *, Dyn **);
-extern void		ld_mach_eflags(Ehdr *, Ofl_desc *);
-extern void		ld_mach_make_dynamic(Ofl_desc *, size_t *);
-extern int		ld_mach_sym_typecheck(Sym_desc *, Sym *, Ifl_desc *,
-			    Ofl_desc *);
 extern uintptr_t	ld_make_bss(Ofl_desc *, Xword, Xword, Bss_Type);
 extern Is_desc		*ld_make_data(Ofl_desc *, size_t);
 extern uintptr_t	ld_make_got(Ofl_desc *);
@@ -590,7 +722,6 @@
 
 extern uintptr_t	ld_open_outfile(Ofl_desc *);
 
-extern uintptr_t	ld_perform_outreloc(Rel_desc *, Ofl_desc *);
 extern Os_desc *	ld_place_section(Ofl_desc *, Is_desc *, int, Word);
 extern uintptr_t	ld_process_archive(const char *, int, Ar_desc *,
 			    Ofl_desc *);
@@ -602,26 +733,19 @@
 extern uintptr_t	ld_process_sym_reloc(Ofl_desc *, Rel_desc *, Rel *,
 			    Is_desc *, const char *);
 
-extern uintptr_t	ld_reloc_local(Rel_desc *, Ofl_desc *);
 extern uintptr_t	ld_reloc_GOT_relative(Boolean, Rel_desc *, Ofl_desc *);
-extern uintptr_t	ld_reloc_GOTOP(Boolean, Rel_desc *, Ofl_desc *);
 extern uintptr_t	ld_reloc_plt(Rel_desc *, Ofl_desc *);
-extern uintptr_t	ld_reloc_register(Rel_desc *, Is_desc *, Ofl_desc *);
 extern void		ld_reloc_remain_entry(Rel_desc *, Os_desc *,
 			    Ofl_desc *);
-extern uintptr_t	ld_reloc_TLS(Boolean, Rel_desc *, Ofl_desc *);
 extern int		ld_reloc_targval_get(Ofl_desc *, Rel_desc *,
 			    uchar_t *, Xword *);
 extern int		ld_reloc_targval_set(Ofl_desc *, Rel_desc *,
 			    uchar_t *, Xword);
-extern int		ld_reg_check(Sym_desc *, Sym *, const char *,
-			    Ifl_desc *, Ofl_desc *);
-extern int		ld_reg_enter(Sym_desc *, Ofl_desc *);
-extern Sym_desc *	ld_reg_find(Sym *, Ofl_desc *);
 
 extern void		ld_sec_validate(Ofl_desc *);
 extern uintptr_t	ld_sort_ordered(Ofl_desc *);
 extern uintptr_t	ld_sort_seg_list(Ofl_desc *);
+extern Half		ld_sunw_ldmach();
 extern uintptr_t	ld_sunwmove_preprocess(Ofl_desc *);
 extern void		ld_sup_atexit(Ofl_desc *, int);
 extern void		ld_sup_open(Ofl_desc *, const char **, const char **,
@@ -636,6 +760,7 @@
 extern uintptr_t	ld_sup_input_section(Ofl_desc*, Ifl_desc *,
 			    const char *, Shdr **, Word, Elf_Scn *, Elf *);
 extern void		ld_sup_start(Ofl_desc *, const Half, const char *);
+extern int		ld_swap_reloc_data(Ofl_desc *, Rel_desc *);
 extern Sym_desc		*ld_sym_add_u(const char *, Ofl_desc *, Msg);
 extern void		ld_sym_adjust_vis(Sym_desc *, Ofl_desc *);
 extern int		ld_sym_avl_comp(const void *, const void *);
@@ -650,6 +775,10 @@
 			    Ofl_desc *, int, Word, Word);
 extern uintptr_t	ld_sym_spec(Ofl_desc *);
 
+extern Target		ld_targ;
+extern const Target	*ld_targ_init_sparc(void);
+extern const Target	*ld_targ_init_x86(void);
+
 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 *);
@@ -667,12 +796,23 @@
 extern Xword		lcm(Xword, Xword);
 extern Listnode *	list_where(List *, Word);
 
-#if	defined(__x86) && defined(_ELF64)
-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 *);
+
+/*
+ * Most platforms have both a 32 and 64-bit variant (e.g. EM_SPARC and
+ * EM_SPARCV9). To support this, there many files in libld that are built
+ * twice, once for ELFCLASS64 (_ELF64), and once for ELFCLASS32. In these
+ * files, we sometimes want to supply one value for the ELFCLASS32 case
+ * and another for ELFCLASS64. The LD_TARG_BYCLASS macro is used to do
+ * this. It is called with both both alternatives, and yields the one
+ * that applies to the current compilation environment.
+ */
+#ifdef	_ELF64
+#define	LD_TARG_BYCLASS(_ec32, _ec64) (_ec64)
+#else
+#define	LD_TARG_BYCLASS(_ec32, _ec64) (_ec32)
 #endif
 
+
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/cmd/sgs/libld/common/args.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/args.c	Tue Mar 18 09:17:00 2008 -0700
@@ -185,6 +185,7 @@
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRL));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRREL));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRS));
+	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTARG));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZT));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTO));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTW));
@@ -539,7 +540,7 @@
 	 * it is only at this point we're sure what the output image will be
 	 * (static or dynamic).
 	 */
-	if (ld_ent_setup(ofl, M_SEGM_ALIGN) == S_ERROR)
+	if (ld_ent_setup(ofl, ld_targ.t_m.m_segm_align) == S_ERROR)
 		return (S_ERROR);
 
 	/*
@@ -548,7 +549,7 @@
 	 * If not, set FLG_OF1_ENCDIFF so relocation code will know
 	 * to check.
 	 */
-	if (_elf_sys_encoding() != M_DATA)
+	if (_elf_sys_encoding() != ld_targ.t_m.m_data)
 		ofl->ofl_flags1 |= FLG_OF1_ENCDIFF;
 
 	/*
@@ -740,11 +741,22 @@
 {
 	int	c;
 
+	/*
+	 * The -64 and -ztarget options are special, in that we validate
+	 * them, but otherwise ignore them. libld.so (this code) is called
+	 * from the ld front end program. ld has already examined the
+	 * arguments to determine the output class and machine type of the
+	 * output object, as reflected in the version (32/64) of ld_main()
+	 * that was called and the value of the 'mach' argument passed.
+	 * By time execution reaches this point, these options have already
+	 * been seen and acted on.
+	 */
+
 	while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
 		DBG_CALL(Dbg_args_flags(ofl->ofl_lml, (optind - 1), c));
 
 		switch (c) {
-		case '6':			/* Processed by ld to */
+		case '6':
 			/*
 			 * -64 is processed by ld to determine the output class.
 			 * Here we sanity check the option incase some other
@@ -1137,7 +1149,9 @@
 			    strcmp(optarg, MSG_ORIG(MSG_ARG_NOLAZYLOAD)) &&
 			    strcmp(optarg, MSG_ORIG(MSG_ARG_RECORD)) &&
 			    strcmp(optarg, MSG_ORIG(MSG_ARG_ALTEXEC64)) &&
-			    strcmp(optarg, MSG_ORIG(MSG_ARG_WEAKEXT))) {
+			    strcmp(optarg, MSG_ORIG(MSG_ARG_WEAKEXT)) &&
+			    strncmp(optarg, MSG_ORIG(MSG_ARG_TARGET),
+			    MSG_ARG_TARGET_SIZE)) {
 				eprintf(ofl->ofl_lml, ERR_FATAL,
 				    MSG_INTL(MSG_ARG_ILLEGAL),
 				    MSG_ORIG(MSG_ARG_Z), optarg);
@@ -1584,7 +1598,8 @@
 			    MSG_INTL(reject[rej.rej_type]),
 			    rej.rej_name ? rej.rej_name :
 			    MSG_INTL(MSG_STR_UNKNOWN),
-			    conv_reject_desc(&rej, &rej_buf));
+			    conv_reject_desc(&rej, &rej_buf,
+			    ld_targ.t_m.m_mach));
 			ofl->ofl_flags |= FLG_OF_FATAL;
 			return (1);
 		}
--- a/usr/src/cmd/sgs/libld/common/entry.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/entry.c	Tue Mar 18 09:17:00 2008 -0700
@@ -23,11 +23,13 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+#define	ELF_TARGET_AMD64
+
 #include	<stdio.h>
 #include	<memory.h>
 #include	<debug.h>
@@ -36,103 +38,124 @@
 
 
 /*
- * The loader uses a `segment descriptor' list to describe the output
- * segments it can potentially create.   Additional segments may be added
- * using a map file.
+ * Types of segment index.
  */
+typedef enum {
+	LD_PHDR,
+	LD_INTERP,
+	LD_SUNWCAP,
+	LD_TEXT,
+	LD_DATA,
+	LD_BSS,
+#if	defined(_ELF64)
+	LD_LRODATA,		/* (amd64-only) */
+	LD_LDATA,		/* (amd64-only) */
+#endif
+	LD_DYN,
+	LD_DTRACE,
+	LD_SUNWBSS,
+	LD_TLS,
 #if	defined(_ELF64)
-/* Phdr packing changes under Elf64 */
-static Sg_desc sg_desc[LD_NUM] = {
-	{{PT_PHDR, PF_R + PF_X, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_PHDR), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_INTERP, PF_R, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_INTERP), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_SUNWCAP, PF_R, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_SUNWCAP), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_LOAD, PF_R + PF_X, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_TEXT), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_LOAD, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_DATA), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_LOAD, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_BSS), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS | FLG_SG_DISABLED), NULL, 0, 0},
-#if	defined(__x86) && defined(_ELF64)
-	{{PT_LOAD, PF_R, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_LRODATA), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_LOAD, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_LDATA), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
+	LD_UNWIND,		/* (amd64-only) */
+#endif
+	LD_NOTE,
+	LD_EXTRA,
+	LD_NUM
+} Segment_ndx;
+
+/*
+ * The loader uses a `segment descriptor' list to describe the output
+ * segments it can potentially create. This list is initially seeded
+ * using the templates contained in the sg_desc[] array below. Additional
+ * segments may be added using a map file.
+ *
+ * The entries in sg_desc[] must be put in the order defined by the
+ * Segment_ndx enum, such that a given LD_XXX value can serve as
+ * an index into sg_desc[] for the corresponding descriptor.
+ *
+ * The entries in sg_desc[] are initialized using the SG_DESC_INIT macro
+ * for two reasons:
+ *
+ *	1) The first field of the Sg_desc struct is a program header
+ *		entry. ELF32_Phdr and ELF64_Phdr have the same fields,
+ *		but their order is different. Use of a macro allows us
+ *		to handle this transparently.
+ *	2) Most of the fields in the Sg_desc entries are set to 0.
+ *		Use of a macro allows us to hide the clutter.
+ */
+#ifdef _ELF64
+#define	SG_DESC_INIT(p_type, p_flags, sg_name, sg_flags) \
+	{ { p_type, p_flags, 0, 0, 0, 0, 0, 0}, \
+	    sg_name, 0, 0, NULL, NULL, sg_flags, NULL, 0, 0}
+#else
+#define	SG_DESC_INIT(p_type, p_flags, sg_name, sg_flags) \
+	{ { p_type, 0, 0, 0, 0, 0, p_flags, 0}, \
+	    sg_name, 0, 0, NULL, NULL, sg_flags, NULL, 0, 0}
 #endif
-	{{PT_DYNAMIC, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_DYNAMIC), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_SUNWDTRACE, M_DATASEG_PERM | PF_X, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_DTRACE), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_SUNWBSS, 0, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_SUNWBSS), 0, 0, NULL, NULL,
-		FLG_SG_TYPE, NULL, 0, 0},
-	{{PT_TLS, PF_R, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_TLS), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-#if	defined(__x86)
-	{{PT_SUNW_UNWIND, PF_R, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_UNWIND), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
+
+static const Sg_desc sg_desc[LD_NUM] = {
+	/* LD_PHDR */
+	SG_DESC_INIT(PT_PHDR, PF_R + PF_X, MSG_ORIG(MSG_ENT_PHDR),
+	    (FLG_SG_TYPE | FLG_SG_FLAGS)),
+
+	/* LD_INTERP */
+	SG_DESC_INIT(PT_INTERP, PF_R, MSG_ORIG(MSG_ENT_INTERP),
+	    (FLG_SG_TYPE | FLG_SG_FLAGS)),
+
+	/* LD_SUNWCAP */
+	SG_DESC_INIT(PT_SUNWCAP, PF_R, MSG_ORIG(MSG_ENT_SUNWCAP),
+	    (FLG_SG_TYPE | FLG_SG_FLAGS)),
+
+	/* LD_TEXT */
+	SG_DESC_INIT(PT_LOAD, PF_R + PF_X, MSG_ORIG(MSG_ENT_TEXT),
+	    (FLG_SG_TYPE | FLG_SG_FLAGS)),
+
+	/* LD_DATA */
+	SG_DESC_INIT(PT_LOAD, 0, MSG_ORIG(MSG_ENT_DATA),
+	    (FLG_SG_TYPE | FLG_SG_FLAGS)),
+
+	/* LD_BSS */
+	SG_DESC_INIT(PT_LOAD, 0, MSG_ORIG(MSG_ENT_BSS),
+	    (FLG_SG_TYPE | FLG_SG_FLAGS | FLG_SG_DISABLED)),
+
+#if	defined(_ELF64)
+	/* LD_LRODATA (amd64-only) */
+	SG_DESC_INIT(PT_LOAD, PF_R, MSG_ORIG(MSG_ENT_LRODATA),
+	    (FLG_SG_TYPE | FLG_SG_FLAGS)),
+
+	/* LD_LDATA (amd64-only) */
+	SG_DESC_INIT(PT_LOAD, 0, MSG_ORIG(MSG_ENT_LDATA),
+	    (FLG_SG_TYPE | FLG_SG_FLAGS)),
 #endif
-	{{PT_NOTE, 0, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_NOTE), 0, 0, NULL, NULL,
-		FLG_SG_TYPE, NULL, 0, 0},
-	{{PT_NULL, 0, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_STR_EMPTY), 0, 0, NULL, NULL,
-		FLG_SG_TYPE, NULL, 0, 0}
+
+	/* LD_DYN */
+	SG_DESC_INIT(PT_DYNAMIC, 0, MSG_ORIG(MSG_ENT_DYNAMIC),
+	    (FLG_SG_TYPE | FLG_SG_FLAGS)),
+
+	/* LD_DTRACE */
+	SG_DESC_INIT(PT_SUNWDTRACE, 0,
+		MSG_ORIG(MSG_ENT_DTRACE), (FLG_SG_TYPE | FLG_SG_FLAGS)),
+
+	/* LD_SUNWBSS */
+	SG_DESC_INIT(PT_SUNWBSS, 0, MSG_ORIG(MSG_ENT_SUNWBSS), FLG_SG_TYPE),
+
+	/* LD_TLS */
+	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) */
+	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),
+
+	/* LD_EXTRA */
+	SG_DESC_INIT(PT_NULL, 0, MSG_ORIG(MSG_STR_EMPTY), FLG_SG_TYPE)
 };
-#else  /* Elf32 */
-static Sg_desc sg_desc[LD_NUM] = {
-	{{PT_PHDR, 0, 0, 0, 0, 0, PF_R + PF_X, 0},
-		MSG_ORIG(MSG_ENT_PHDR), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_INTERP, 0, 0, 0, 0, 0, PF_R, 0},
-		MSG_ORIG(MSG_ENT_INTERP), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_SUNWCAP, 0, 0, 0, 0, 0, PF_R, 0},
-		MSG_ORIG(MSG_ENT_SUNWCAP), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_LOAD, 0, 0, 0, 0, 0, PF_R + PF_X, 0},
-		MSG_ORIG(MSG_ENT_TEXT), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_LOAD, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0},
-		MSG_ORIG(MSG_ENT_DATA), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_LOAD, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0},
-		MSG_ORIG(MSG_ENT_BSS), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS | FLG_SG_DISABLED), NULL, 0, 0},
-	{{PT_DYNAMIC, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0},
-		MSG_ORIG(MSG_ENT_DYNAMIC), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_SUNWDTRACE, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0},
-		MSG_ORIG(MSG_ENT_DTRACE), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_SUNWBSS, 0, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_SUNWBSS), 0, 0, NULL, NULL,
-		FLG_SG_TYPE, NULL, 0, 0},
-	{{PT_TLS, PF_R, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_TLS), 0, 0, NULL, NULL,
-		(FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0},
-	{{PT_NOTE, 0, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_ENT_NOTE), 0, 0, NULL, NULL,
-		FLG_SG_TYPE, NULL, 0, 0},
-	{{PT_NULL, 0, 0, 0, 0, 0, 0, 0},
-		MSG_ORIG(MSG_STR_EMPTY), 0, 0, NULL, NULL,
-		FLG_SG_TYPE, NULL, 0, 0}
-};
-#endif /* Elfxx */
+
 
 
 /*
@@ -142,37 +165,50 @@
  * modified further using a map file.  Each entrance criteria is associated
  * with a segment descriptor, thus a mapping of input sections to output
  * segments is maintained.
+ *
+ * Note the trick used for the ec_segment field, which is supposed to
+ * be a pointer to a segment descriptor. We initialize this with the
+ * index of the descriptor, and then turn it into an actual pointer
+ * at runtime, once memory has been allocated and the templates copied.
  */
 static const Ent_desc	ent_desc[] = {
 	{{NULL, NULL}, MSG_ORIG(MSG_SCN_SUNWBSS), NULL,
 		SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE,
 		(Sg_desc *)LD_SUNWBSS, 0, FALSE},
+
 	{{NULL, NULL}, NULL, SHT_NOTE, 0, 0,
 		(Sg_desc *)LD_NOTE, 0, FALSE},
-#if	defined(__x86) && defined(_ELF64)
+
+#if	defined(_ELF64)		/* (amd64-only) */
 	{{NULL, NULL}, MSG_ORIG(MSG_SCN_LRODATA), NULL,
 		SHF_ALLOC + SHF_AMD64_LARGE, SHF_ALLOC + SHF_AMD64_LARGE,
 		(Sg_desc *)LD_LRODATA, 0, FALSE},
 #endif
+
 	{{NULL, NULL}, NULL, NULL,
 		SHF_ALLOC + SHF_WRITE, SHF_ALLOC,
 		(Sg_desc *)LD_TEXT, 0, FALSE},
+
 	{{NULL, NULL}, NULL, SHT_NOBITS,
 		SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE,
 		(Sg_desc *)LD_BSS, 0, FALSE},
-#if	defined(__x86) && defined(_ELF64)
+
+#if	defined(_ELF64)		/* (amd64-only) */
 	{{NULL, NULL}, NULL, SHT_NOBITS,
 		SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
 		SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
 		(Sg_desc *)LD_DATA, 0, FALSE},
+
 	{{NULL, NULL}, NULL, NULL,
 		SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
 		SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
 		(Sg_desc *)LD_LDATA, 0, FALSE},
 #endif
+
 	{{NULL, NULL}, NULL, NULL,
 		SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE,
 		(Sg_desc *)LD_DATA, 0, FALSE},
+
 	{{NULL, NULL}, NULL, 0, 0, 0,
 		(Sg_desc *)LD_EXTRA, 0, FALSE}
 };
@@ -186,7 +222,7 @@
 {
 	Ent_desc	*enp;
 	Sg_desc		*sgp;
-	size_t		size;
+	size_t		idx;
 
 	/*
 	 * Initialize the elf library.
@@ -204,19 +240,12 @@
 	    SGSOFFSETOF(Sym_avlnode, sav_node));
 
 	/*
-	 * The data segment permissions can differ depending on whether
-	 * this object is built statically or dynamically.
-	 */
-	if (ofl->ofl_flags & FLG_OF_DYNAMIC) {
-		sg_desc[LD_DATA].sg_phdr.p_flags = M_DATASEG_PERM;
-		sg_desc[LD_SUNWBSS].sg_phdr.p_flags = M_DATASEG_PERM;
-	} else {
-		sg_desc[LD_DATA].sg_phdr.p_flags = M_DATASEG_PERM | PF_X;
-	}
-
-	/*
 	 * Allocate and initialize writable copies of both the entrance and
 	 * segment descriptors.
+	 *
+	 * Note that on non-amd64 targets, this allocates a few more
+	 * elements than are needed. For now, we are willing to overallocate
+	 * a small amount to simplify the code.
 	 */
 	if ((sgp = libld_malloc(sizeof (sg_desc))) == 0)
 		return (S_ERROR);
@@ -226,16 +255,45 @@
 	(void) memcpy(enp, ent_desc, sizeof (ent_desc));
 
 	/*
+	 * The data segment permissions can differ:
+	 *
+	 *	- Architecural/ABI per-platform differences
+	 *	- Whether the object is built statically or dynamically
+	 *
+	 * Those segments so affected have their program header flags
+	 * set here at runtime, rather than in the sg_desc templates above.
+	 */
+	sgp[LD_DATA].sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
+	sgp[LD_BSS].sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
+	sgp[LD_DYN].sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
+	sgp[LD_DTRACE].sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
+#if	defined(_ELF64)
+	sgp[LD_LDATA].sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
+	sgp[LD_DTRACE].sg_phdr.p_flags |= PF_X;
+#endif
+	if (ofl->ofl_flags & FLG_OF_DYNAMIC) {
+		sgp[LD_SUNWBSS].sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
+	} else {
+		sgp[LD_DATA].sg_phdr.p_flags |= PF_X;
+	}
+
+	/*
 	 * Traverse the new entrance descriptor list converting the segment
 	 * pointer entries to the absolute address within the new segment
 	 * descriptor list.  Add each entrance descriptor to the output file
 	 * list.
 	 */
-	for (size = 0; size < sizeof (ent_desc); size += sizeof (Ent_desc)) {
+	for (idx = 0; idx < (sizeof (ent_desc) / sizeof (ent_desc[0]));
+	    idx++, enp++) {
+#if	defined(_ELF64)
+		/* Don't use the amd64 entry conditions for non-amd64 targets */
+		if ((enp->ec_attrmask & SHF_AMD64_LARGE) &&
+		    (ld_targ.t_m.m_mach != EM_AMD64))
+			continue;
+#endif
 		enp->ec_segment = &sgp[(long)enp->ec_segment];
 		if ((list_appendc(&ofl->ofl_ents, enp)) == 0)
 			return (S_ERROR);
-		enp++;
 	}
 
 	/*
@@ -243,15 +301,25 @@
 	 * segment descriptor list.  For each loadable segment initialize
 	 * a default alignment (ld(1) and ld.so.1 initialize this differently).
 	 */
-	for (size = 0; size < sizeof (sg_desc); size += sizeof (Sg_desc)) {
+	for (idx = 0; idx < LD_NUM; idx++, sgp++) {
 		Phdr	*phdr = &(sgp->sg_phdr);
 
+#if	defined(_ELF64)
+		/* Ignore amd64 segment templates for non-amd64 targets */
+		switch (idx) {
+		case LD_LRODATA:
+		case LD_LDATA:
+		case LD_UNWIND:
+			if ((ld_targ.t_m.m_mach != EM_AMD64))
+				continue;
+		}
+#endif
+
 		if ((list_appendc(&ofl->ofl_segs, sgp)) == 0)
 			return (S_ERROR);
 		if (phdr->p_type == PT_LOAD)
 			phdr->p_align = segalign;
+	}
 
-		sgp++;
-	}
 	return (1);
 }
--- a/usr/src/cmd/sgs/libld/common/files.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/files.c	Tue Mar 18 09:17:00 2008 -0700
@@ -23,7 +23,7 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -31,6 +31,10 @@
 /*
  * Processing of relocatable objects and shared objects.
  */
+
+#define	ELF_TARGET_AMD64
+#define	ELF_TARGET_SPARC
+
 #include	<stdio.h>
 #include	<string.h>
 #include	<fcntl.h>
@@ -53,14 +57,14 @@
 	 * Check the validity of the elf header information for compatibility
 	 * with this machine and our own internal elf library.
 	 */
-	if ((ehdr->e_machine != M_MACH) &&
-	    ((ehdr->e_machine != M_MACHPLUS) &&
-	    ((ehdr->e_flags & M_FLAGSPLUS) == 0))) {
+	if ((ehdr->e_machine != ld_targ.t_m.m_mach) &&
+	    ((ehdr->e_machine != ld_targ.t_m.m_machplus) &&
+	    ((ehdr->e_flags & ld_targ.t_m.m_flagsplus) == 0))) {
 		rej->rej_type = SGS_REJ_MACH;
 		rej->rej_info = (uint_t)ehdr->e_machine;
 		return (0);
 	}
-	if (ehdr->e_ident[EI_DATA] != M_DATA) {
+	if (ehdr->e_ident[EI_DATA] != ld_targ.t_m.m_data) {
 		rej->rej_type = SGS_REJ_DATA;
 		rej->rej_info = (uint_t)ehdr->e_ident[EI_DATA];
 		return (0);
@@ -87,7 +91,8 @@
 
 	if (ifl_verify(ehdr, ofl, &_rej) == 0) {
 		_rej.rej_name = name;
-		DBG_CALL(Dbg_file_rejected(ofl->ofl_lml, &_rej));
+		DBG_CALL(Dbg_file_rejected(ofl->ofl_lml, &_rej,
+		    ld_targ.t_m.m_mach));
 		if (rej->rej_type == 0) {
 			*rej = _rej;
 			rej->rej_name = strdup(_rej.rej_name);
@@ -251,7 +256,7 @@
 	 */
 	if (ofl->ofl_flags1 & FLG_OF1_OVSFCAP) {
 		Dbg_cap_sec_entry(ofl->ofl_lml, DBG_CAP_IGNORE, CA_SUNW_SF_1,
-		    val, M_MACH);
+		    val, ld_targ.t_m.m_mach);
 		return;
 	}
 
@@ -278,9 +283,9 @@
 	}
 
 	Dbg_cap_sec_entry(ofl->ofl_lml, DBG_CAP_OLD, CA_SUNW_SF_1,
-	    ofl->ofl_sfcap_1, M_MACH);
+	    ofl->ofl_sfcap_1, ld_targ.t_m.m_mach);
 	Dbg_cap_sec_entry(ofl->ofl_lml, DBG_CAP_NEW, CA_SUNW_SF_1,
-	    val, M_MACH);
+	    val, ld_targ.t_m.m_mach);
 
 	/*
 	 * Determine the resolution of the present frame pointer and the
@@ -305,7 +310,7 @@
 	}
 
 	Dbg_cap_sec_entry(ofl->ofl_lml, DBG_CAP_RESOLVED, CA_SUNW_SF_1,
-	    ofl->ofl_sfcap_1, M_MACH);
+	    ofl->ofl_sfcap_1, ld_targ.t_m.m_mach);
 }
 
 /*
@@ -323,7 +328,7 @@
 	 */
 	if (ofl->ofl_flags1 & FLG_OF1_OVHWCAP) {
 		Dbg_cap_sec_entry(ofl->ofl_lml, DBG_CAP_IGNORE, CA_SUNW_HW_1,
-		    val, M_MACH);
+		    val, ld_targ.t_m.m_mach);
 		return;
 	}
 
@@ -335,13 +340,14 @@
 		return;
 
 	Dbg_cap_sec_entry(ofl->ofl_lml, DBG_CAP_OLD, CA_SUNW_HW_1,
-	    ofl->ofl_hwcap_1, M_MACH);
-	Dbg_cap_sec_entry(ofl->ofl_lml, DBG_CAP_NEW, CA_SUNW_HW_1, val, M_MACH);
+	    ofl->ofl_hwcap_1, ld_targ.t_m.m_mach);
+	Dbg_cap_sec_entry(ofl->ofl_lml, DBG_CAP_NEW, CA_SUNW_HW_1, val,
+	    ld_targ.t_m.m_mach);
 
 	ofl->ofl_hwcap_1 |= val;
 
 	Dbg_cap_sec_entry(ofl->ofl_lml, DBG_CAP_RESOLVED, CA_SUNW_HW_1,
-	    ofl->ofl_hwcap_1, M_MACH);
+	    ofl->ofl_hwcap_1, ld_targ.t_m.m_mach);
 }
 
 /*
@@ -395,7 +401,8 @@
 process_input(const char *name, Ifl_desc *ifl, Shdr *shdr, Elf_Scn *scn,
 	Word ndx, int ident, Ofl_desc *ofl)
 {
-	return (process_section(name, ifl, shdr, scn, ndx, M_ID_NULL, ofl));
+	return (process_section(name, ifl, shdr, scn, ndx,
+	    ld_targ.t_id.id_null, ofl));
 }
 
 /*
@@ -410,7 +417,7 @@
 	Word ndx, int ident, Ofl_desc *ofl)
 {
 	if (process_section(name, ifl,
-	    shdr, scn, ndx, M_ID_NULL, ofl) == S_ERROR)
+	    shdr, scn, ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
 		return (S_ERROR);
 
 	if (ifl->ifl_ehdr->e_type == ET_REL) {
@@ -453,9 +460,9 @@
 	 * be null.  Otherwise make sure we don't have a .strtab section as this
 	 * should not be added to the output section list either.
 	 */
-	if ((ident != M_ID_NULL) &&
+	if ((ident != ld_targ.t_id.id_null) &&
 	    (strcmp(name, MSG_ORIG(MSG_SCN_STRTAB)) == 0))
-		ident = M_ID_NULL;
+		ident = ld_targ.t_id.id_null;
 
 	error = process_section(name, ifl, shdr, scn, ndx, ident, ofl);
 	if ((error == 0) || (error == S_ERROR))
@@ -538,14 +545,14 @@
 	 */
 	if (ident) {
 		if (shdr->sh_flags & SHF_TLS)
-			ident = M_ID_TLS;
+			ident = ld_targ.t_id.id_tls;
 		else if ((shdr->sh_flags & ~ALL_SHF_IGNORE) ==
 		    (SHF_ALLOC | SHF_EXECINSTR))
-			ident = M_ID_TEXT;
+			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 = M_ID_NULL;
+				ident = ld_targ.t_id.id_null;
 			else if (stab_index) {
 				/*
 				 * This is a work-around for x86 compilers that
@@ -559,11 +566,11 @@
 				 * strip (ld -s) against a shared object whose
 				 * last section in the text segment is a .stab.
 				 */
-				ident = M_ID_INTERP;
+				ident = ld_targ.t_id.id_interp;
 			} else
-				ident = M_ID_DATA;
+				ident = ld_targ.t_id.id_data;
 		} else
-			ident = M_ID_NOTE;
+			ident = ld_targ.t_id.id_note;
 	}
 	return (process_section(name, ifl, shdr, scn, ndx, ident, ofl));
 }
@@ -593,13 +600,14 @@
 {
 	if (ident) {
 		if (shdr->sh_flags & SHF_TLS)
-			ident = M_ID_TLSBSS;
-#if	defined(__x86) && defined(_ELF64)
-		else if (shdr->sh_flags & SHF_AMD64_LARGE)
-			ident = M_ID_LBSS;
+			ident = ld_targ.t_id.id_tlsbss;
+#if	defined(_ELF64)
+		else if ((shdr->sh_flags & SHF_AMD64_LARGE) &&
+		    (ld_targ.t_m.m_mach == EM_AMD64))
+			ident = ld_targ.t_id.id_lbss;
 #endif
 		else
-			ident = M_ID_BSS;
+			ident = ld_targ.t_id.id_bss;
 	}
 	return (process_section(name, ifl, shdr, scn, ndx, ident, ofl));
 }
@@ -615,7 +623,7 @@
 	Is_desc	*isp;
 
 	if (ident)
-		ident = M_ID_ARRAY;
+		ident = ld_targ.t_id.id_array;
 
 	if (process_section(name, ifl, shdr, scn, ndx, ident, ofl) == S_ERROR)
 		return (S_ERROR);
@@ -1227,7 +1235,7 @@
 	/*
 	 * Make sure this is a valid relocation we can handle.
 	 */
-	if (shdr->sh_type != M_REL_SHT_TYPE) {
+	if (shdr->sh_type != ld_targ.t_m.m_rel_sht_type) {
 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_FIL_INVALSEC),
 		    ifl->ifl_name, isc->is_name,
 		    conv_sec_type(ifl->ifl_ehdr->e_machine,
@@ -1320,7 +1328,7 @@
 	return (process_section(name, ifl, shdr, scn, ndx, 0, ofl));
 }
 
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)
 
 static uintptr_t
 process_amd64_unwind(const char *name, Ifl_desc *ifl, Shdr *shdr,
@@ -1506,11 +1514,11 @@
 	if (ifl->ifl_ehdr->e_type == ET_DYN) {
 		column = 1;
 		ofl->ofl_soscnt++;
-		ident = M_ID_NULL;
+		ident = ld_targ.t_id.id_null;
 	} else {
 		column = 0;
 		ofl->ofl_objscnt++;
-		ident = M_ID_UNKNOWN;
+		ident = ld_targ.t_id.id_unknown;
 	}
 
 	DBG_CALL(Dbg_file_generic(ofl->ofl_lml, ifl));
@@ -1603,7 +1611,7 @@
 				break;
 			case SHT_SUNW_cap:
 				if (process_section(name, ifl, shdr, scn,
-				    ndx, M_ID_NULL, ofl) == S_ERROR)
+				    ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
 					return (S_ERROR);
 				capisp = ifl->ifl_isdesc[ndx];
 				break;
@@ -1615,12 +1623,12 @@
 				break;
 			case SHT_SUNW_move:
 				if (process_section(name, ifl, shdr, scn,
-				    ndx, M_ID_NULL, ofl) == S_ERROR)
+				    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, M_ID_NULL, ofl) == S_ERROR)
+				    ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
 					return (S_ERROR);
 				sifisp = ifl->ifl_isdesc[ndx];
 				break;
@@ -1632,45 +1640,67 @@
 				break;
 			case SHT_SUNW_verdef:
 				if (process_section(name, ifl, shdr, scn,
-				    ndx, M_ID_NULL, ofl) == S_ERROR)
+				    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, M_ID_NULL, ofl) == S_ERROR)
+				    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, M_ID_NULL, ofl) == S_ERROR)
+				    ndx, ld_targ.t_id.id_null, ofl) == S_ERROR)
 					return (S_ERROR);
 				vsyisp = ifl->ifl_isdesc[ndx];
 				break;
-#if	defined(__sparc)
 			case SHT_SPARC_GOTDATA:
+				/*
+				 * SHT_SPARC_GOTDATA (0x70000000) is in the
+				 * SHT_LOPROC - SHT_HIPROC range reserved
+				 * for processor-specific semantics. It is
+				 * only meaningful for sparc targets.
+				 */
+				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, M_ID_GOTDATA, ofl) == S_ERROR)
+				    ndx, ld_targ.t_id.id_gotdata, ofl) ==
+				    S_ERROR)
 					return (S_ERROR);
 				break;
-#endif
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)
 			case SHT_AMD64_UNWIND:
+				/*
+				 * SHT_AMD64_UNWIND (0x70000001) is in the
+				 * SHT_LOPROC - SHT_HIPROC range reserved
+				 * for processor-specific semantics. It is
+				 * only meaningful for amd64 targets.
+				 */
+				if (ld_targ.t_m.m_mach != EM_AMD64)
+					goto do_default;
+				/*
+				 * Target is x86, so this really is
+				 * SHT_AMD64_UNWIND
+				 */
 				if (column == 0) {
 					/*
 					 * column == ET_REL
 					 */
 					if (process_amd64_unwind(name, ifl,
-					    shdr, scn, ndx, M_ID_UNWIND,
-					    ofl) == S_ERROR)
+					    shdr, scn, ndx,
+					    ld_targ.t_id.id_unwind, ofl) ==
+					    S_ERROR)
 						return (S_ERROR);
 				}
 				break;
 #endif
 			default:
-				if (ident != M_ID_NULL)
-					ident = M_ID_USER;
+			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)
 					return (S_ERROR);
@@ -1717,7 +1747,7 @@
 			    ifl->ifl_shnum)) == (Os_desc *)S_ERROR)
 				return (S_ERROR);
 
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)
 			/*
 			 * If this section is 'ordered' then it was not
 			 * caught in the previous 'place_section' operation.
@@ -1727,7 +1757,9 @@
 			 */
 			if (osp &&
 			    (osp->os_shdr->sh_type == SHT_AMD64_UNWIND) &&
-			    (append_amd64_unwind(osp, ofl) == S_ERROR))
+			    (ld_targ.t_uw.uw_append_unwind != NULL) &&
+			    ((*ld_targ.t_uw.uw_append_unwind)(osp, ofl) ==
+			    S_ERROR))
 				return (S_ERROR);
 #endif
 		}
@@ -1936,7 +1968,7 @@
 			 * also occur, such as from a truncated or corrupt file.
 			 * Here we try and get the best error message possible.
 			 */
-			if (M_CLASS != _class) {
+			if (ld_targ.t_m.m_class != _class) {
 				_rej.rej_type = SGS_REJ_CLASS;
 				_rej.rej_info = (uint_t)_class;
 			} else {
@@ -1944,7 +1976,8 @@
 				_rej.rej_str = elf_errmsg(-1);
 			}
 			_rej.rej_name = name;
-			DBG_CALL(Dbg_file_rejected(ofl->ofl_lml, &_rej));
+			DBG_CALL(Dbg_file_rejected(ofl->ofl_lml, &_rej,
+			    ld_targ.t_m.m_mach));
 			if (rej->rej_type == 0) {
 				*rej = _rej;
 				rej->rej_name = strdup(_rej.rej_name);
@@ -2035,7 +2068,7 @@
 
 		switch (ehdr->e_type) {
 		case ET_REL:
-			ld_mach_eflags(ehdr, ofl);
+			(*ld_targ.t_mr.mr_mach_eflags)(ehdr, ofl);
 			error = process_elf(ifl, elf, ofl);
 			break;
 		case ET_DYN:
@@ -2085,7 +2118,8 @@
 			(void) elf_errno();
 			_rej.rej_type = SGS_REJ_UNKFILE;
 			_rej.rej_name = name;
-			DBG_CALL(Dbg_file_rejected(ofl->ofl_lml, &_rej));
+			DBG_CALL(Dbg_file_rejected(ofl->ofl_lml, &_rej,
+			    ld_targ.t_m.m_mach));
 			if (rej->rej_type == 0) {
 				*rej = _rej;
 				rej->rej_name = strdup(_rej.rej_name);
@@ -2097,7 +2131,8 @@
 		(void) elf_errno();
 		_rej.rej_type = SGS_REJ_UNKFILE;
 		_rej.rej_name = name;
-		DBG_CALL(Dbg_file_rejected(ofl->ofl_lml, &_rej));
+		DBG_CALL(Dbg_file_rejected(ofl->ofl_lml, &_rej,
+		    ld_targ.t_m.m_mach));
 		if (rej->rej_type == 0) {
 			*rej = _rej;
 			rej->rej_name = strdup(_rej.rej_name);
@@ -2293,7 +2328,8 @@
 					    MSG_INTL(reject[_rej.rej_type]),
 					    _rej.rej_name ? rej.rej_name :
 					    MSG_INTL(MSG_STR_UNKNOWN),
-					    conv_reject_desc(&_rej, &rej_buf));
+					    conv_reject_desc(&_rej, &rej_buf,
+					    ld_targ.t_m.m_mach));
 				} else
 					sdf->sdf_file = ifl;
 			}
@@ -2404,7 +2440,8 @@
 			    MSG_INTL(reject[rej.rej_type]),
 			    rej.rej_name ? rej.rej_name :
 			    MSG_INTL(MSG_STR_UNKNOWN),
-			    conv_reject_desc(&rej, &rej_buf));
+			    conv_reject_desc(&rej, &rej_buf,
+			    ld_targ.t_m.m_mach));
 		} else {
 			eprintf(ofl->ofl_lml, ERR_WARNING,
 			    MSG_INTL(MSG_FIL_NOTFOUND), file, sdf->sdf_rfile);
--- a/usr/src/cmd/sgs/libld/common/ldlibs.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/ldlibs.c	Tue Mar 18 09:17:00 2008 -0700
@@ -23,7 +23,7 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -313,7 +313,7 @@
 
 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(reject[rej.rej_type]),
 		    rej.rej_name ? rej.rej_name : MSG_INTL(MSG_STR_UNKNOWN),
-		    conv_reject_desc(&rej, &rej_buf));
+		    conv_reject_desc(&rej, &rej_buf, ld_targ.t_m.m_mach));
 	} else {
 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_LIB_NOTFOUND),
 		    name);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/libld/common/ldmachdep.c	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * Most of the source files in libld.so are not allowed to
+ * include the machdep.h header, because it supplies machine
+ * values that are specific to the platform running the linker,
+ * instead of the target machine. This module is used to provide
+ * information about the currently running host to the rest
+ * of the linker code.
+ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	<_libld.h>
+#include	<machdep.h>
+
+/*
+ * Return an ELF machine code that reflects the currently executing
+ * linker. This information can be used in cross link situations to
+ * know which platform the linker was running on, and whether the linker
+ * itself was a 32 or 64-bit program.
+ */
+Half
+ld_sunw_ldmach(void)
+{
+#ifdef _LP64
+	return (M_MACH_64);
+#else
+	return (M_MACH_32);
+#endif
+}
--- a/usr/src/cmd/sgs/libld/common/ldmain.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/ldmain.c	Tue Mar 18 09:17:00 2008 -0700
@@ -23,12 +23,16 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 /*
+ * Processing of relocatable objects and shared objects.
+ */
+
+/*
  * ld -- link/editor main program
  */
 #include	<sys/types.h>
@@ -42,6 +46,14 @@
 #include	"_libld.h"
 
 /*
+ * All target specific code is referenced via this global variable, which
+ * is initialized in ld_main(). This allows the linker to function as
+ * a cross linker, by vectoring to the target-specific code for the
+ * current target machine.
+ */
+Target		ld_targ;
+
+/*
  * A default library search path is used if one was not supplied on the command
  * line.  Note: these strings can not use MSG_ORIG() since they are modified as
  * part of the path processing.
@@ -56,13 +68,47 @@
  * A default elf header provides for simplifying diagnostic processing.
  */
 static Ehdr	def_ehdr = { { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
-			    M_CLASS, M_DATA }, 0, M_MACH, EV_CURRENT };
+			    ELFCLASSNONE, ELFDATANONE }, 0, EM_NONE,
+			    EV_CURRENT };
+
+/*
+ * Establish the global state necessary to link the desired machine
+ * target, as reflected by the ld_targ global variable.
+ */
+int
+ld_init_target(Lm_list *lml, Half mach)
+{
+	switch (mach) {
+	case EM_386:
+	case EM_AMD64:
+		ld_targ = *ld_targ_init_x86();
+		break;
+
+	case EM_SPARC:
+	case EM_SPARC32PLUS:
+	case EM_SPARCV9:
+		ld_targ = *ld_targ_init_sparc();
+		break;
+
+	default:
+		{
+			Conv_inv_buf_t	inv_buf;
+
+			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TARG_UNSUPPORTED),
+			    conv_ehdr_mach(mach, 0, &inv_buf));
+			return (1);
+		}
+	}
+
+	return (0);
+}
+
 
 /*
  * The main program
  */
 int
-ld_main(int argc, char **argv)
+ld_main(int argc, char **argv, Half mach)
 {
 	char		*sgs_support;	/* SGS_SUPPORT environment string */
 	Half		etype;
@@ -76,7 +122,18 @@
 	if ((ofl = libld_calloc(1, sizeof (Ofl_desc))) == 0)
 		return (1);
 
+	/* Initilize target state */
+	if (ld_init_target(NULL, mach) != 0)
+		return (1);
+
+	/*
+	 * Set up the output ELF header, and initialize the machine
+	 * and class details.
+	 */
 	ofl->ofl_dehdr = &def_ehdr;
+	def_ehdr.e_ident[EI_CLASS] = ld_targ.t_m.m_class;
+	def_ehdr.e_ident[EI_DATA] = ld_targ.t_m.m_data;
+	def_ehdr.e_machine = ld_targ.t_m.m_mach;
 
 	ld_init(ofl);
 
@@ -199,7 +256,7 @@
 			ofl->ofl_rpath = rpath;
 	}
 	if (ofl->ofl_flags & FLG_OF_EXEC)
-		ofl->ofl_segorigin = M_SEGM_ORIGIN;
+		ofl->ofl_segorigin = ld_targ.t_m.m_segm_origin;
 
 	/*
 	 * Argument pass two.  Input all libraries and objects.
@@ -309,13 +366,15 @@
 	if (ld_reloc_process(ofl) == S_ERROR)
 		return (ld_exit(ofl));
 
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)
 	/*
 	 * Fill in contents for Unwind Header
 	 */
-	if (populate_amd64_unwindhdr(ofl) == S_ERROR)
+	if ((ld_targ.t_uw.uw_populate_unwindhdr != NULL) &&
+	    ((*ld_targ.t_uw.uw_populate_unwindhdr)(ofl) == S_ERROR))
 		return (ld_exit(ofl));
 #endif
+
 	/*
 	 * Finally create the files elf checksum.
 	 */
@@ -323,6 +382,17 @@
 		*ofl->ofl_checksum = (Xword)elf_checksum(ofl->ofl_elf);
 
 	/*
+	 * If this is a cross link to a target with a different byte
+	 * order than the linker, swap the data to the target byte order.
+	 */
+	if (((ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0) &&
+	    (_elf_swap_wrimage(ofl->ofl_elf) != 0)) {
+		eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_SWAP_WRIMAGE),
+		    ofl->ofl_name);
+		return (ld_exit(ofl));
+	}
+
+	/*
 	 * We're done, so make sure the updates are flushed to the output file.
 	 */
 	if ((ofl->ofl_size = elf_update(ofl->ofl_welf, ELF_C_WRITE)) == 0) {
--- a/usr/src/cmd/sgs/libld/common/libld.chk.msg	Tue Mar 18 08:44:14 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-@ _START_
-
-# Messages to satisfy chkmsg target.  Numerous messages within common code
-# (reloc.h) aren't required for each target, but chkmsg has no way of dealing
-# with ifdefs, thus this file exists to satisfy common code messages.
-
-@ MSG_REL_UNIMPL	"relocation error: file %s:  symbol %s: \
-			 unimplemented relocation type: %d"
-@ MSG_REL_UNNOBITS	"relocation error: %s: file %s: symbol %s: \
-			 unsupported number of bits: %d"
-@ MSG_REL_LOSEBITS	"relocation error: %s: file %s: symbol %s: \
-			 value 0x%llx loses %d bits at offset 0x%llx"
-
-@ _END_
--- a/usr/src/cmd/sgs/libld/common/libld.intel.msg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/libld.intel.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# 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.
@@ -21,7 +20,7 @@
 #
 
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -31,8 +30,6 @@
 
 # Message file for cmd/sgs/libld - intel specific.
 
-@ MSG_REL_NOREG		"relocation error: REGISTER relocation not supported \
-			 on i386 architecture"
 @ MSG_REL_BADTLSINS	"relocation error: %s: file %s: symbol %s: section %s: \
 			 offset 0x%llx, relocation against unknown TLS \
 			 instruction sequence"
@@ -50,3 +47,5 @@
 @ MSG_SPECFIL_PLTENT    "<output_file>"
 
 @ MSG_SCN_UNWINDHDR	".eh_frame_hdr"
+
+@ MSG_PTH_RTLD_AMD64	"/usr/lib/amd64/ld.so.1"
--- a/usr/src/cmd/sgs/libld/common/libld.msg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/libld.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -197,6 +197,8 @@
 			 against COMDAT sections\n"
 @ MSG_ARG_DETAIL_ZRS	"\t[-z rescan]\trescan archive list until no further \
 			 member\n\t\t\textraction occurs\n"
+@ MSG_ARG_DETAIL_ZTARG	"\t[-z target=platform]\n\
+			 \t\t\ttarget machine for cross linking\n"
 @ MSG_ARG_DETAIL_ZT	"\t[-z text]\tdisallow output relocations against \
 			 text\n"
 @ MSG_ARG_DETAIL_ZTO	"\t[-z textoff]\tallow output relocations against \
@@ -225,8 +227,6 @@
 			 skipping null relocation record"
 @ MSG_REL_NOTSUP	"relocation error: %s: file %s: section %s: \
 			 relocation not currently supported"
-@ MSG_REL_NOSWAP	"relocation error: %s: file %s: symbol %s: \
-			 linker does not support byte swapping relocated data"
 @ MSG_REL_PICREDLOC	"relocation error: %s: file %s symbol %s: \
 			 -z redlocsym may not be used for pic code"
 @ MSG_REL_TLSLE		"relocation error: %s: file %s: symbol %s: \
@@ -296,6 +296,8 @@
 @ MSG_REL_SLOPCDATNAM	"relocation warning: %s: file %s: section %s: \
 			 symbol %s: relocation against discarded COMDAT \
 			 section %s redirected to file %s"
+@ MSG_REL_NOREG		"relocation error: REGISTER relocation not supported \
+			 on target architecture"
 
 #
 # TRANSLATION_NOTE
@@ -389,6 +391,11 @@
 @ MSG_SYS_MMAPANON	"file %s: mmap anon failed: %s"
 
 
+# Messages related to platform support
+@ MSG_TARG_UNSUPPORTED	"unsupported ELF machine type: %s"
+
+
+
 # ELF processing messages
 
 @ MSG_ELF_LIBELF	"libelf: version not supported: %d"
@@ -435,9 +442,9 @@
 @ MSG_SYM_TENTERR	"\ttentative symbol cannot override defined symbol \
 			 of smaller size"
 
-@ MSG_SYM_INVSHNDX	"symbol `%s' has invalid section index; \
+@ MSG_SYM_INVSHNDX	"symbol %s has invalid section index; \
 			 ignored:\n\t(file %s value=%s);"
-@ MSG_SYM_NONGLOB	"global symbol `%s' has non-global binding:\n\
+@ MSG_SYM_NONGLOB	"global symbol %s has non-global binding:\n\
 			 \t(file %s value=%s);"
 @ MSG_SYM_RESERVE	"reserved symbol `%s' already defined in file %s"
 @ MSG_SYM_NOTNULL	"undefined symbol `%s' with non-zero value encountered \
@@ -578,6 +585,7 @@
 @ MSG_ELF_NEWPHDR	"file %s: elf_newphdr"
 @ MSG_ELF_STRPTR	"file %s: elf_strptr"
 @ MSG_ELF_UPDATE	"file %s: elf_update"
+@ MSG_ELF_SWAP_WRIMAGE	"file %s: _elf_swap_wrimage"
 
 
 @ MSG_REJ_MACH		"file %s: wrong ELF machine type: %s"
@@ -612,10 +620,10 @@
 
 @ MSG_FMT_ARMEM		"%s(%s)"
 @ MSG_FMT_COLPATH	"%s:%s"
+@ MSG_FMT_SYMNAM	"`%s'"
+@ MSG_FMT_NULLSYMNAM	"%s[%d]"
 
 @ MSG_PTH_RTLD		"/usr/lib/ld.so.1"
-@ MSG_PTH_RTLD_SPARCV9	"/usr/lib/sparcv9/ld.so.1"
-@ MSG_PTH_RTLD_AMD64	"/usr/lib/amd64/ld.so.1"
 @ MSG_PTH_DEVZERO	"/dev/zero"
 
 @ MSG_SUNW_OST_SGS	"SUNW_OST_SGS"
@@ -1125,6 +1133,7 @@
 @ MSG_ARG_NOLDYNSYM	"noldynsym"
 @ MSG_ARG_RELAXRELOC	"relaxreloc"
 @ MSG_ARG_GLOBAUDIT	"globalaudit"
+@ MSG_ARG_TARGET	"target="
 
 @ MSG_ARG_HELP		"help"
 @ MSG_ARG_GROUP		"group"
--- a/usr/src/cmd/sgs/libld/common/libld.sparc.msg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/libld.sparc.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -78,3 +78,5 @@
 @ MSG_STO_REGISTERG5	"<SCRATCH REGISTER 5>"
 @ MSG_STO_REGISTERG6	"<SCRATCH REGISTER 6>"
 @ MSG_STO_REGISTERG7	"<SCRATCH REGISTER 7>"
+
+@ MSG_PTH_RTLD_SPARCV9	"/usr/lib/sparcv9/ld.so.1"
--- a/usr/src/cmd/sgs/libld/common/libs.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/libs.c	Tue Mar 18 09:17:00 2008 -0700
@@ -23,7 +23,7 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -626,7 +626,7 @@
 		eprintf(ofl->ofl_lml, ERR_WARNING,
 		    MSG_INTL(reject[rej.rej_type]),
 		    rej.rej_name ? rej.rej_name : MSG_INTL(MSG_STR_UNKNOWN),
-		    conv_reject_desc(&rej, &rej_buf));
+		    conv_reject_desc(&rej, &rej_buf, ld_targ.t_m.m_mach));
 	}
 
 	/*
--- a/usr/src/cmd/sgs/libld/common/llib-lld	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/llib-lld	Tue Mar 18 09:17:00 2008 -0700
@@ -22,7 +22,7 @@
 /* PROTOLIB1 */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -42,8 +42,8 @@
 uintptr_t	ld32_init_strings(Ofl_desc *);
 uintptr_t	ld64_init_strings(Ofl_desc *);
 
-int		ld32_main(int, char **);
-int		ld64_main(int, char **);
+int		ld32_main(int, char **, Elf32_Half);
+int		ld64_main(int, char **, Elf64_Half);
 uintptr_t	ld32_make_sections(Ofl_desc *);
 uintptr_t	ld64_make_sections(Ofl_desc *);
 
--- a/usr/src/cmd/sgs/libld/common/machrel.amd.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/machrel.amd.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,27 +20,38 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+/* Get the x86 version of the relocation engine */
+#define	DO_RELOC_LIBLD_X86
+
 #include	<string.h>
 #include	<stdio.h>
 #include	<strings.h>
 #include	<sys/elf_amd64.h>
 #include	<debug.h>
 #include	<reloc.h>
+#include	<i386/machdep_x86.h>
 #include	"msg.h"
 #include	"_libld.h"
+#include	"unwind.amd.h"
 
-Word
+
+/* Forward declarations */
+static Gotndx	*ld_find_gotndx(List *, Gotref, Ofl_desc *, Rel_desc *);
+static Xword	ld_calc_got_offset(Rel_desc *, Ofl_desc *);
+
+
+static Word
 ld_init_rel(Rel_desc *reld, void *reloc)
 {
 	Rela *	rel = (Rela *)reloc;
 
 	/* LINTED */
-	reld->rel_rtype = (Word)ELF_R_TYPE(rel->r_info);
+	reld->rel_rtype = (Word)ELF_R_TYPE(rel->r_info, M_MACH);
 	reld->rel_roffset = rel->r_offset;
 	reld->rel_raddend = rel->r_addend;
 	reld->rel_typedata = 0;
@@ -50,13 +61,13 @@
 	return ((Word)ELF_R_SYM(rel->r_info));
 }
 
-void
+static void
 ld_mach_eflags(Ehdr *ehdr, Ofl_desc *ofl)
 {
 	ofl->ofl_dehdr->e_flags |= ehdr->e_flags;
 }
 
-void
+static void
 ld_mach_make_dynamic(Ofl_desc *ofl, size_t *cnt)
 {
 	if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) {
@@ -68,7 +79,7 @@
 	}
 }
 
-void
+static void
 ld_mach_update_odynamic(Ofl_desc *ofl, Dyn **dyn)
 {
 	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && ofl->ofl_pltcnt) {
@@ -81,7 +92,7 @@
 	}
 }
 
-Xword
+static Xword
 ld_calc_plt_addr(Sym_desc *sdp, Ofl_desc *ofl)
 {
 	Xword	value;
@@ -111,7 +122,7 @@
 	Sword		plt_off;
 	Word		got_off;
 	Xword		val1;
-	int		bswap;
+	int		bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
 
 	got_off = sdp->sd_aux->sa_PLTGOTndx * M_GOT_ENTSIZE;
 	plt_off = M_PLT_RESERVSZ + ((sdp->sd_aux->sa_PLTndx - 1) *
@@ -127,6 +138,9 @@
 	/* LINTED */
 	*(Word *)gotent = ofl->ofl_osplt->os_shdr->sh_addr + plt_off +
 	    M_PLT_INSSIZE;
+	if (bswap)
+		/* LINTED */
+		*(Word *)gotent = ld_bswap_Word(*(Word *)gotent);
 
 	/*
 	 * If '-z noreloc' is specified - skip the do_reloc_ld
@@ -136,14 +150,6 @@
 		return (1);
 
 	/*
-	 * If the running linker has a different byte order than
-	 * the target host, tell do_reloc_ld() to swap bytes.
-	 *
-	 * We know the PLT is PROGBITS --- we don't have to check
-	 */
-	bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
-
-	/*
 	 * patchup:
 	 *	jmpq	*name1@gotpcrel(%rip)
 	 *
@@ -196,7 +202,7 @@
 	return (1);
 }
 
-uintptr_t
+static uintptr_t
 ld_perform_outreloc(Rel_desc * orsp, Ofl_desc * ofl)
 {
 	Os_desc *	relosp, * osp = 0;
@@ -593,7 +599,7 @@
 	return (FIX_RELOC);
 }
 
-uintptr_t
+static uintptr_t
 ld_do_activerelocs(Ofl_desc *ofl)
 {
 	Rel_desc	*arsp;
@@ -816,7 +822,7 @@
 				 */
 				if (ofl->ofl_flags1 & FLG_OF1_ENCDIFF)
 					*(Xword *)R2addr =
-					    ld_byteswap_Xword(value);
+					    ld_bswap_Xword(value);
 				else
 					*(Xword *)R2addr = value;
 				continue;
@@ -986,7 +992,7 @@
 	return (return_code);
 }
 
-uintptr_t
+static uintptr_t
 ld_add_outrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
 {
 	Rel_desc	*orsp;
@@ -1126,20 +1132,9 @@
 }
 
 /*
- * Stub routine since register symbols are not supported on amd64.
- */
-/* ARGSUSED */
-uintptr_t
-ld_reloc_register(Rel_desc * rsp, Is_desc * isp, Ofl_desc * ofl)
-{
-	eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_NOREG));
-	return (S_ERROR);
-}
-
-/*
  * process relocation for a LOCAL symbol
  */
-uintptr_t
+static uintptr_t
 ld_reloc_local(Rel_desc * rsp, Ofl_desc * ofl)
 {
 	Word		flags = ofl->ofl_flags;
@@ -1222,19 +1217,7 @@
 }
 
 
-uintptr_t
-/* ARGSUSED */
-ld_reloc_GOTOP(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
-{
-	/*
-	 * Stub routine for common code compatibility, we shouldn't
-	 * actually get here on amd64.
-	 */
-	assert(0);
-	return (S_ERROR);
-}
-
-uintptr_t
+static uintptr_t
 ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
 {
 	Word		rtype = rsp->rel_rtype;
@@ -1317,7 +1300,7 @@
 }
 
 /* ARGSUSED3 */
-Gotndx *
+static Gotndx *
 ld_find_gotndx(List * lst, Gotref gref, Ofl_desc * ofl, Rel_desc * rdesc)
 {
 	Listnode *	lnp;
@@ -1337,7 +1320,7 @@
 	return ((Gotndx *)0);
 }
 
-Xword
+static Xword
 ld_calc_got_offset(Rel_desc * rdesc, Ofl_desc * ofl)
 {
 	Os_desc		*osp = ofl->ofl_osgot;
@@ -1369,7 +1352,7 @@
 
 
 /* ARGSUSED5 */
-uintptr_t
+static uintptr_t
 ld_assign_got_ndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl,
     Rel_desc * rsp, Sym_desc * sdp)
 {
@@ -1433,7 +1416,7 @@
 	return (1);
 }
 
-void
+static void
 ld_assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl)
 {
 	sdp->sd_aux->sa_PLTndx = 1 + ofl->ofl_pltcnt++;
@@ -1453,9 +1436,11 @@
 /*
  * Initializes .got[0] with the _DYNAMIC symbol value.
  */
-uintptr_t
+static uintptr_t
 ld_fillin_gotplt(Ofl_desc *ofl)
 {
+	int	bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
+
 	if (ofl->ofl_osgot) {
 		Sym_desc	*sdp;
 
@@ -1467,6 +1452,11 @@
 			    (M_GOT_XDYNAMIC * M_GOT_ENTSIZE));
 			/* LINTED */
 			*(Xword *)genptr = sdp->sd_sym->st_value;
+			if (bswap)
+				/* LINTED */
+				*(Xword *)genptr =
+				    /* LINTED */
+				    ld_bswap_Xword(*(Xword *)genptr);
 		}
 	}
 
@@ -1483,7 +1473,6 @@
 	if ((ofl->ofl_flags & FLG_OF_DYNAMIC) && ofl->ofl_osplt) {
 		uchar_t	*pltent;
 		Xword	val1;
-		int	bswap;
 
 		pltent = (uchar_t *)ofl->ofl_osplt->os_outdata->d_buf;
 		bcopy(plt0_template, pltent, sizeof (plt0_template));
@@ -1496,15 +1485,6 @@
 			return (1);
 
 		/*
-		 * If the running linker has a different byte order than
-		 * the target host, tell do_reloc_ld() to swap bytes.
-		 *
-		 * We know the GOT is PROGBITS --- we don't have
-		 * to check.
-		 */
-		bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
-
-		/*
 		 * filin:
 		 *	PUSHQ GOT + 8(%rip)
 		 *
@@ -1543,3 +1523,142 @@
 
 	return (1);
 }
+
+
+
+/*
+ * Template for generating "void (*)(void)" function
+ */
+static const uchar_t nullfunc_tmpl[] = {	/* amd64 */
+/* 0x00 */	0x55,				/* pushq  %rbp */
+/* 0x01 */	0x48, 0x8b, 0xec,		/* movq   %rsp,%rbp */
+/* 0x04 */	0x48, 0x8b, 0xe5,		/* movq   %rbp,%rsp */
+/* 0x07 */	0x5d,				/* popq   %rbp */
+/* 0x08 */	0xc3				/* ret */
+};
+
+
+/*
+ * Return the ld_targ definition for this target.
+ */
+const Target *
+ld_targ_init_x86(void)
+{
+	static const Target _ld_targ = {
+		{			/* Target_mach */
+			M_MACH,			/* m_mach */
+			M_MACHPLUS,		/* m_machplus */
+			M_FLAGSPLUS,		/* m_flagsplus */
+			M_CLASS,		/* m_class */
+			M_DATA,			/* m_data */
+
+			M_SEGM_ALIGN,		/* m_segm_align */
+			M_SEGM_ORIGIN,		/* m_segm_origin */
+			M_DATASEG_PERM,		/* m_dataseg_perm */
+			M_WORD_ALIGN,		/* m_word_align */
+			MSG_ORIG(MSG_PTH_RTLD_AMD64), /* m_def_interp */
+
+			/* Relocation type codes */
+			M_R_ARRAYADDR,		/* m_r_arrayaddr */
+			M_R_COPY,		/* m_r_copy */
+			M_R_GLOB_DAT,		/* m_r_glob_dat */
+			M_R_JMP_SLOT,		/* m_r_jmp_slot */
+			M_R_NUM,		/* m_r_num */
+			M_R_NONE,		/* m_r_none */
+			M_R_RELATIVE,		/* m_r_relative */
+			M_R_REGISTER,		/* m_r_register */
+
+			/* Relocation related constants */
+			M_REL_DT_COUNT,		/* m_rel_dt_count */
+			M_REL_DT_ENT,		/* m_rel_dt_ent */
+			M_REL_DT_SIZE,		/* m_rel_dt_size */
+			M_REL_DT_TYPE,		/* m_rel_dt_type */
+			M_REL_SHT_TYPE,		/* m_rel_sht_type */
+
+			/* GOT related constants */
+			M_GOT_ENTSIZE,		/* m_got_entsize */
+			M_GOT_XNumber,		/* m_got_xnumber */
+
+			/* PLT related constants */
+			M_PLT_ALIGN,		/* m_plt_align */
+			M_PLT_ENTSIZE,		/* m_plt_entsize */
+			M_PLT_RESERVSZ,		/* m_plt_reservsz */
+			M_PLT_SHF_FLAGS,	/* m_plt_shf_flags */
+
+			M_DT_REGISTER,		/* m_dt_register */
+		},
+		{			/* Target_machid */
+			M_ID_ARRAY,		/* id_array */
+			M_ID_BSS,		/* id_bss */
+			M_ID_CAP,		/* id_cap */
+			M_ID_DATA,		/* id_data */
+			M_ID_DYNAMIC,		/* id_dynamic */
+			M_ID_DYNSORT,		/* id_dynsort */
+			M_ID_DYNSTR,		/* id_dynstr */
+			M_ID_DYNSYM,		/* id_dynsym */
+			M_ID_DYNSYM_NDX,	/* id_dynsym_ndx */
+			M_ID_GOT,		/* id_got */
+			M_ID_UNKNOWN,		/* id_gotdata (unused) */
+			M_ID_HASH,		/* id_hash */
+			M_ID_INTERP,		/* id_interp */
+			M_ID_LBSS,		/* id_lbss */
+			M_ID_LDYNSYM,		/* id_ldynsym */
+			M_ID_NOTE,		/* id_note */
+			M_ID_NULL,		/* id_null */
+			M_ID_PLT,		/* id_plt */
+			M_ID_REL,		/* id_rel */
+			M_ID_STRTAB,		/* id_strtab */
+			M_ID_SYMINFO,		/* id_syminfo */
+			M_ID_SYMTAB,		/* id_symtab */
+			M_ID_SYMTAB_NDX,	/* id_symtab_ndx */
+			M_ID_TEXT,		/* id_text */
+			M_ID_TLS,		/* id_tls */
+			M_ID_TLSBSS,		/* id_tlsbss */
+			M_ID_UNKNOWN,		/* id_unknown */
+			M_ID_UNWIND,		/* id_unwind */
+			M_ID_USER,		/* id_user */
+			M_ID_VERSION,		/* id_version */
+		},
+		{			/* Target_nullfunc */
+			nullfunc_tmpl,		/* nf_template */
+			sizeof (nullfunc_tmpl),	/* nf_size */
+		},
+		{			/* Target_machrel */
+			reloc_table,
+
+			ld_init_rel,		/* mr_init_rel */
+			ld_mach_eflags,		/* mr_mach_eflags */
+			ld_mach_make_dynamic,	/* mr_mach_make_dynamic */
+			ld_mach_update_odynamic, /* mr_mach_update_odynamic */
+			ld_calc_plt_addr,	/* mr_calc_plt_addr */
+			ld_perform_outreloc,	/* mr_perform_outreloc */
+			ld_do_activerelocs,	/* mr_do_activerelocs */
+			ld_add_outrel,		/* mr_add_outrel */
+			NULL,			/* mr_reloc_register */
+			ld_reloc_local,		/* mr_reloc_local */
+			NULL,			/* mr_reloc_GOTOP */
+			ld_reloc_TLS,		/* mr_reloc_TLS */
+			NULL,			/* mr_assign_got */
+			ld_find_gotndx,		/* mr_find_gotndx */
+			ld_calc_got_offset,	/* mr_calc_got_offset */
+			ld_assign_got_ndx,	/* mr_assign_got_ndx */
+			ld_assign_plt_ndx,	/* mr_assign_plt_ndx */
+			NULL,			/* mr_allocate_got */
+			ld_fillin_gotplt,	/* mr_fillin_gotplt */
+		},
+		{			/* Target_machsym */
+			NULL,			/* ms_reg_check */
+			NULL,			/* ms_mach_sym_typecheck */
+			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 */
+		}
+	};
+
+	return (&_ld_targ);
+}
--- a/usr/src/cmd/sgs/libld/common/machrel.intel.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/machrel.intel.c	Tue Mar 18 09:17:00 2008 -0700
@@ -29,21 +29,30 @@
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+/* Get the x86 version of the relocation engine */
+#define	DO_RELOC_LIBLD_X86
+
 #include	<string.h>
 #include	<stdio.h>
 #include	<sys/elf_386.h>
 #include	<debug.h>
 #include	<reloc.h>
+#include	<i386/machdep_x86.h>
 #include	"msg.h"
 #include	"_libld.h"
 
-Word
+/* Forward declarations */
+static Gotndx	*ld_find_gotndx(List *, Gotref, Ofl_desc *, Rel_desc *);
+static Xword	ld_calc_got_offset(Rel_desc *, Ofl_desc *);
+
+
+static Word
 ld_init_rel(Rel_desc *reld, void *reloc)
 {
 	Rel *	rel = (Rel *)reloc;
 
 	/* LINTED */
-	reld->rel_rtype = (Word)ELF_R_TYPE(rel->r_info);
+	reld->rel_rtype = (Word)ELF_R_TYPE(rel->r_info, M_MACH);
 	reld->rel_roffset = rel->r_offset;
 	reld->rel_raddend = 0;
 	reld->rel_typedata = 0;
@@ -51,13 +60,13 @@
 	return ((Word)ELF_R_SYM(rel->r_info));
 }
 
-void
+static void
 ld_mach_eflags(Ehdr *ehdr, Ofl_desc *ofl)
 {
 	ofl->ofl_dehdr->e_flags |= ehdr->e_flags;
 }
 
-void
+static void
 ld_mach_make_dynamic(Ofl_desc *ofl, size_t *cnt)
 {
 	if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) {
@@ -69,7 +78,7 @@
 	}
 }
 
-void
+static void
 ld_mach_update_odynamic(Ofl_desc *ofl, Dyn **dyn)
 {
 	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && ofl->ofl_pltcnt) {
@@ -82,7 +91,7 @@
 	}
 }
 
-Xword
+static Xword
 ld_calc_plt_addr(Sym_desc *sdp, Ofl_desc *ofl)
 {
 	Xword	value;
@@ -113,6 +122,7 @@
 	uchar_t		*pltent, *gotent;
 	Sword		plt_off;
 	Word		got_off;
+	int		bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
 
 	got_off = sdp->sd_aux->sa_PLTGOTndx * M_GOT_ENTSIZE;
 	plt_off = M_PLT_RESERVSZ + ((sdp->sd_aux->sa_PLTndx - 1) *
@@ -126,6 +136,9 @@
 	/* LINTED */
 	*(Word *)gotent = ofl->ofl_osplt->os_shdr->sh_addr + plt_off +
 	    M_PLT_INSSIZE;
+	if (bswap)
+		/* LINTED */
+		*(Word *)gotent = ld_bswap_Word(*(Word *)gotent);
 
 	if (!(ofl->ofl_flags & FLG_OF_SHAROBJ)) {
 		pltent[0] = M_SPECIAL_INST;
@@ -141,12 +154,18 @@
 		/* LINTED */
 		*(Word *)pltent = (Word)got_off;
 	}
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 	pltent += 4;
 
 	pltent[0] = M_INST_PUSHL;
 	pltent++;
 	/* LINTED */
 	*(Word *)pltent = (Word)rel_off;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 	pltent += 4;
 
 	plt_off = -(plt_off + 16);	/* JMP, PUSHL, JMP take 16 bytes */
@@ -154,9 +173,12 @@
 	pltent++;
 	/* LINTED */
 	*(Word *)pltent = (Word)plt_off;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 }
 
-uintptr_t
+static uintptr_t
 ld_perform_outreloc(Rel_desc * orsp, Ofl_desc * ofl)
 {
 	Os_desc *	relosp, * osp = 0;
@@ -657,7 +679,7 @@
 	return (FIX_RELOC);
 }
 
-uintptr_t
+static uintptr_t
 ld_do_activerelocs(Ofl_desc *ofl)
 {
 	Rel_desc	*arsp;
@@ -866,7 +888,7 @@
 				 */
 				if (ofl->ofl_flags1 & FLG_OF1_ENCDIFF)
 					*(Xword *)R2addr =
-					    ld_byteswap_Xword(value);
+					    ld_bswap_Xword(value);
 				else
 					*(Xword *)R2addr = value;
 				continue;
@@ -1035,7 +1057,7 @@
 /*
  * Add an output relocation record.
  */
-uintptr_t
+static uintptr_t
 ld_add_outrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
 {
 	Rel_desc	*orsp;
@@ -1175,20 +1197,9 @@
 }
 
 /*
- * Stub routine since register symbols are not supported on i386.
- */
-/* ARGSUSED */
-uintptr_t
-ld_reloc_register(Rel_desc * rsp, Is_desc * isp, Ofl_desc * ofl)
-{
-	eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_NOREG));
-	return (S_ERROR);
-}
-
-/*
  * process relocation for a LOCAL symbol
  */
-uintptr_t
+static uintptr_t
 ld_reloc_local(Rel_desc * rsp, Ofl_desc * ofl)
 {
 	Word		flags = ofl->ofl_flags;
@@ -1259,19 +1270,7 @@
 	return (ld_add_actrel(NULL, rsp, ofl));
 }
 
-uintptr_t
-/* ARGSUSED */
-ld_reloc_GOTOP(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
-{
-	/*
-	 * Stub routine for common code compatibility, we shouldn't
-	 * actually get here on x86.
-	 */
-	assert(0);
-	return (S_ERROR);
-}
-
-uintptr_t
+static uintptr_t
 ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
 {
 	Word		rtype = rsp->rel_rtype;
@@ -1393,7 +1392,7 @@
 }
 
 /* ARGSUSED3 */
-Gotndx *
+static Gotndx *
 ld_find_gotndx(List * lst, Gotref gref, Ofl_desc * ofl, Rel_desc * rdesc)
 {
 	Listnode *	lnp;
@@ -1409,7 +1408,7 @@
 	return ((Gotndx *)0);
 }
 
-Xword
+static Xword
 ld_calc_got_offset(Rel_desc * rdesc, Ofl_desc * ofl)
 {
 	Os_desc		*osp = ofl->ofl_osgot;
@@ -1441,7 +1440,7 @@
 
 
 /* ARGSUSED4 */
-uintptr_t
+static uintptr_t
 ld_assign_got_ndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl,
     Rel_desc * rsp, Sym_desc * sdp)
 {
@@ -1474,7 +1473,7 @@
 	return (1);
 }
 
-void
+static void
 ld_assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl)
 {
 	sdp->sd_aux->sa_PLTndx = 1 + ofl->ofl_pltcnt++;
@@ -1485,10 +1484,11 @@
 /*
  * Initializes .got[0] with the _DYNAMIC symbol value.
  */
-uintptr_t
+static uintptr_t
 ld_fillin_gotplt(Ofl_desc *ofl)
 {
 	Word	flags = ofl->ofl_flags;
+	int	bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
 
 	if (ofl->ofl_osgot) {
 		Sym_desc	*sdp;
@@ -1501,6 +1501,11 @@
 			    (M_GOT_XDYNAMIC * M_GOT_ENTSIZE));
 			/* LINTED */
 			*(Word *)genptr = (Word)sdp->sd_sym->st_value;
+			if (bswap)
+				/* LINTED */
+				*(Word *)genptr =
+				    /* LINTED */
+				    ld_bswap_Word(*(Word *)genptr);
 		}
 	}
 
@@ -1526,6 +1531,11 @@
 			/* LINTED */
 			*(Word *)pltent = (Word)(ofl->ofl_osgot->os_shdr->
 			    sh_addr + M_GOT_XLINKMAP * M_GOT_ENTSIZE);
+			if (bswap)
+				/* LINTED */
+				*(Word *)pltent =
+				    /* LINTED */
+				    ld_bswap_Word(*(Word *)pltent);
 			pltent += 4;
 			pltent[0] = M_SPECIAL_INST;
 			pltent[1] = M_JMP_DISP_IND;
@@ -1533,6 +1543,11 @@
 			/* LINTED */
 			*(Word *)pltent = (Word)(ofl->ofl_osgot->os_shdr->
 			    sh_addr + M_GOT_XRTLD * M_GOT_ENTSIZE);
+			if (bswap)
+				/* LINTED */
+				*(Word *)pltent =
+				    /* LINTED */
+				    ld_bswap_Word(*(Word *)pltent);
 		} else {
 			pltent[0] = M_SPECIAL_INST;
 			pltent[1] = M_PUSHL_REG_DISP;
@@ -1540,6 +1555,11 @@
 			/* LINTED */
 			*(Word *)pltent = (Word)(M_GOT_XLINKMAP *
 			    M_GOT_ENTSIZE);
+			if (bswap)
+				/* LINTED */
+				*(Word *)pltent =
+				    /* LINTED */
+				    ld_bswap_Word(*(Word *)pltent);
 			pltent += 4;
 			pltent[0] = M_SPECIAL_INST;
 			pltent[1] = M_JMP_REG_DISP_IND;
@@ -1547,7 +1567,148 @@
 			/* LINTED */
 			*(Word *)pltent = (Word)(M_GOT_XRTLD *
 			    M_GOT_ENTSIZE);
+			if (bswap)
+				/* LINTED */
+				*(Word *)pltent =
+				    /* LINTED */
+				    ld_bswap_Word(*(Word *)pltent);
 		}
 	}
 	return (1);
 }
+
+
+
+/*
+ * Template for generating "void (*)(void)" function
+ */
+static const uchar_t nullfunc_tmpl[] = {	/* IA32 */
+/* 0x00 */	0xc3				/* ret */
+};
+
+
+
+/*
+ * Return the ld_targ definition for this target.
+ */
+const Target *
+ld_targ_init_x86(void)
+{
+	static const Target _ld_targ = {
+		{			/* Target_mach */
+			M_MACH,			/* m_mach */
+			M_MACHPLUS,		/* m_machplus */
+			M_FLAGSPLUS,		/* m_flagsplus */
+			M_CLASS,		/* m_class */
+			M_DATA,			/* m_data */
+
+			M_SEGM_ALIGN,		/* m_segm_align */
+			M_SEGM_ORIGIN,		/* m_segm_origin */
+			M_DATASEG_PERM,		/* m_dataseg_perm */
+			M_WORD_ALIGN,		/* m_word_align */
+			MSG_ORIG(MSG_PTH_RTLD),	/* m_def_interp */
+
+			/* Relocation type codes */
+			M_R_ARRAYADDR,		/* m_r_arrayaddr */
+			M_R_COPY,		/* m_r_copy */
+			M_R_GLOB_DAT,		/* m_r_glob_dat */
+			M_R_JMP_SLOT,		/* m_r_jmp_slot */
+			M_R_NUM,		/* m_r_num */
+			M_R_NONE,		/* m_r_none */
+			M_R_RELATIVE,		/* m_r_relative */
+			M_R_REGISTER,		/* m_r_register */
+
+			/* Relocation related constants */
+			M_REL_DT_COUNT,		/* m_rel_dt_count */
+			M_REL_DT_ENT,		/* m_rel_dt_ent */
+			M_REL_DT_SIZE,		/* m_rel_dt_size */
+			M_REL_DT_TYPE,		/* m_rel_dt_type */
+			M_REL_SHT_TYPE,		/* m_rel_sht_type */
+
+			/* GOT related constants */
+			M_GOT_ENTSIZE,		/* m_got_entsize */
+			M_GOT_XNumber,		/* m_got_xnumber */
+
+			/* PLT related constants */
+			M_PLT_ALIGN,		/* m_plt_align */
+			M_PLT_ENTSIZE,		/* m_plt_entsize */
+			M_PLT_RESERVSZ,		/* m_plt_reservsz */
+			M_PLT_SHF_FLAGS,	/* m_plt_shf_flags */
+
+			M_DT_REGISTER,		/* m_dt_register */
+		},
+		{			/* Target_machid */
+			M_ID_ARRAY,		/* id_array */
+			M_ID_BSS,		/* id_bss */
+			M_ID_CAP,		/* id_cap */
+			M_ID_DATA,		/* id_data */
+			M_ID_DYNAMIC,		/* id_dynamic */
+			M_ID_DYNSORT,		/* id_dynsort */
+			M_ID_DYNSTR,		/* id_dynstr */
+			M_ID_DYNSYM,		/* id_dynsym */
+			M_ID_DYNSYM_NDX,	/* id_dynsym_ndx */
+			M_ID_GOT,		/* id_got */
+			M_ID_UNKNOWN,		/* id_gotdata (unused) */
+			M_ID_HASH,		/* id_hash */
+			M_ID_INTERP,		/* id_interp */
+			M_ID_LBSS,		/* id_lbss */
+			M_ID_LDYNSYM,		/* id_ldynsym */
+			M_ID_NOTE,		/* id_note */
+			M_ID_NULL,		/* id_null */
+			M_ID_PLT,		/* id_plt */
+			M_ID_REL,		/* id_rel */
+			M_ID_STRTAB,		/* id_strtab */
+			M_ID_SYMINFO,		/* id_syminfo */
+			M_ID_SYMTAB,		/* id_symtab */
+			M_ID_SYMTAB_NDX,	/* id_symtab_ndx */
+			M_ID_TEXT,		/* id_text */
+			M_ID_TLS,		/* id_tls */
+			M_ID_TLSBSS,		/* id_tlsbss */
+			M_ID_UNKNOWN,		/* id_unknown */
+			M_ID_UNWIND,		/* id_unwind */
+			M_ID_USER,		/* id_user */
+			M_ID_VERSION,		/* id_version */
+		},
+		{			/* Target_nullfunc */
+			nullfunc_tmpl,		/* nf_template */
+			sizeof (nullfunc_tmpl),	/* nf_size */
+		},
+		{			/* Target_machrel */
+			reloc_table,
+
+			ld_init_rel,		/* mr_init_rel */
+			ld_mach_eflags,		/* mr_mach_eflags */
+			ld_mach_make_dynamic,	/* mr_mach_make_dynamic */
+			ld_mach_update_odynamic, /* mr_mach_update_odynamic */
+			ld_calc_plt_addr,	/* mr_calc_plt_addr */
+			ld_perform_outreloc,	/* mr_perform_outreloc */
+			ld_do_activerelocs,	/* mr_do_activerelocs */
+			ld_add_outrel,		/* mr_add_outrel */
+			NULL,			/* mr_reloc_register */
+			ld_reloc_local,		/* mr_reloc_local */
+			NULL,			/* mr_reloc_GOTOP */
+			ld_reloc_TLS,		/* mr_reloc_TLS */
+			NULL,			/* mr_assign_got */
+			ld_find_gotndx,		/* mr_find_gotndx */
+			ld_calc_got_offset,	/* mr_calc_got_offset */
+			ld_assign_got_ndx,	/* mr_assign_got_ndx */
+			ld_assign_plt_ndx,	/* mr_assign_plt_ndx */
+			NULL,			/* mr_allocate_got */
+			ld_fillin_gotplt,	/* mr_fillin_gotplt */
+		},
+		{			/* Target_machsym */
+			NULL,			/* ms_reg_check */
+			NULL,			/* ms_mach_sym_typecheck */
+			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 */
+		}
+	};
+
+	return (&_ld_targ);
+}
--- a/usr/src/cmd/sgs/libld/common/machrel.sparc.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/machrel.sparc.c	Tue Mar 18 09:17:00 2008 -0700
@@ -23,18 +23,27 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+/* Get the sparc version of the relocation engine */
+#define	DO_RELOC_LIBLD_SPARC
+
 #include	<string.h>
 #include	<stdio.h>
 #include	<sys/elf_SPARC.h>
 #include	<debug.h>
 #include	<reloc.h>
+#include	<sparc/machdep_sparc.h>
 #include	"msg.h"
 #include	"_libld.h"
+#include	"machsym.sparc.h"
+
+/* Forward declarations */
+static Xword ld_calc_got_offset(Rel_desc *, Ofl_desc *);
+static Gotndx *ld_find_gotndx(List *, Gotref, Ofl_desc *, Rel_desc *);
 
 /*
  * Local Variable Definitions
@@ -43,13 +52,13 @@
 static Sword smlgotcnt = M_GOT_XNumber;	/* no. of small GOT symbols */
 static Sword mixgotcnt = 0;		/* # syms with both large/small GOT */
 
-Word
+static Word
 ld_init_rel(Rel_desc *reld, void *reloc)
 {
 	Rela *	rela = (Rela *)reloc;
 
 	/* LINTED */
-	reld->rel_rtype = (Word)ELF_R_TYPE(rela->r_info);
+	reld->rel_rtype = (Word)ELF_R_TYPE(rela->r_info, M_MACH);
 	reld->rel_roffset = rela->r_offset;
 	reld->rel_raddend = rela->r_addend;
 	reld->rel_typedata = (Word)ELF_R_TYPE_DATA(rela->r_info);
@@ -59,7 +68,7 @@
 	return ((Word)ELF_R_SYM(rela->r_info));
 }
 
-void
+static void
 ld_mach_eflags(Ehdr *ehdr, Ofl_desc *ofl)
 {
 	Word		eflags = ofl->ofl_dehdr->e_flags;
@@ -111,7 +120,7 @@
 	ofl->ofl_dehdr->e_flags = eflags;
 }
 
-void
+static void
 ld_mach_make_dynamic(Ofl_desc *ofl, size_t *cnt)
 {
 	if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) {
@@ -123,7 +132,7 @@
 	}
 }
 
-void
+static void
 ld_mach_update_odynamic(Ofl_desc *ofl, Dyn **dyn)
 {
 	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && ofl->ofl_pltcnt) {
@@ -138,7 +147,7 @@
 
 #if	defined(_ELF64)
 
-Xword
+static Xword
 ld_calc_plt_addr(Sym_desc *sdp, Ofl_desc *ofl)
 {
 	Xword	value, pltndx, farpltndx;
@@ -177,13 +186,13 @@
 /*
  * Instructions required for Far PLT's
  */
-static uint32_t farplt_instrs[6] = {
-	0x8a10000f,			/* mov   %o7, %g5	*/
-	0x40000002,			/* call  . + 0x8	*/
-	0x01000000,			/* nop			*/
-	0xc25be000,			/* ldx   [%o7 + 0], %g1	*/
-	0x83c3c001,			/* jmpl  %o7 + %g1, %g1	*/
-	0x9e100005			/* mov   %g5, %o7	*/
+static uchar_t farplt_instrs[24] = {
+	0x8a, 0x10, 0x00, 0x0f,		/* mov   %o7, %g5	*/
+	0x40, 0x00, 0x00, 0x02,		/* call  . + 0x8	*/
+	0x01, 0x00, 0x00, 0x00,		/* nop			*/
+	0xc2, 0x5b, 0xe0, 0x00,		/* ldx   [%o7 + 0], %g1	*/
+	0x83, 0xc3, 0xc0, 0x01,		/* jmpl  %o7 + %g1, %g1	*/
+	0x9e, 0x10, 0x00, 0x05		/* mov   %g5, %o7	*/
 };
 
 /*
@@ -217,7 +226,7 @@
  *		.xword .PLT0-(.PLT32927+4)
  *
  */
-void
+static void
 plt_far_entry(Ofl_desc *ofl, Xword pltndx, Xword *roffset, Sxword *raddend)
 {
 	uint_t		blockndx;	/* # of far PLT blocks */
@@ -336,8 +345,9 @@
 static void
 plt_entry(Ofl_desc *ofl, Xword pltndx, Xword *roffset, Sxword *raddend)
 {
-	uchar_t		*pltent;	/* PLT entry being created. */
-	Sxword		pltoff;		/* Offset of this entry from PLT top */
+	uchar_t	*pltent;	/* PLT entry being created. */
+	Sxword	pltoff;		/* Offset of this entry from PLT top */
+	int	bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
 
 	/*
 	 *  The second part of the V9 ABI (sec. 5.2.4)
@@ -360,6 +370,9 @@
 	 */
 	/* LINTED */
 	*(Word *)pltent = M_SETHIG1 | pltoff;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[1]: ba,a %xcc, .PLT1 (.PLT1 accessed as a
@@ -371,6 +384,9 @@
 	/* LINTED */
 	*(Word *)pltent = M_BA_A_XCC |
 	    (((pltoff + M_PLT_ENTSIZE) >> 2) & S_MASK(19));
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[2]: sethi 0, %g0 (NOP for delay slot of eventual CTI).
@@ -378,6 +394,9 @@
 	pltent += M_PLT_INSSIZE;
 	/* LINTED */
 	*(Word *)pltent = M_NOP;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[3]: sethi 0, %g0 (NOP for PLT padding).
@@ -385,6 +404,9 @@
 	pltent += M_PLT_INSSIZE;
 	/* LINTED */
 	*(Word *)pltent = M_NOP;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[4]: sethi 0, %g0 (NOP for PLT padding).
@@ -392,6 +414,9 @@
 	pltent += M_PLT_INSSIZE;
 	/* LINTED */
 	*(Word *)pltent = M_NOP;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[5]: sethi 0, %g0 (NOP for PLT padding).
@@ -399,6 +424,9 @@
 	pltent += M_PLT_INSSIZE;
 	/* LINTED */
 	*(Word *)pltent = M_NOP;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[6]: sethi 0, %g0 (NOP for PLT padding).
@@ -406,6 +434,9 @@
 	pltent += M_PLT_INSSIZE;
 	/* LINTED */
 	*(Word *)pltent = M_NOP;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[7]: sethi 0, %g0 (NOP for PLT padding).
@@ -413,12 +444,15 @@
 	pltent += M_PLT_INSSIZE;
 	/* LINTED */
 	*(Word *)pltent = M_NOP;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 }
 
 
 #else  /* Elf 32 */
 
-Xword
+static Xword
 ld_calc_plt_addr(Sym_desc *sdp, Ofl_desc *ofl)
 {
 	Xword	value, pltndx;
@@ -446,6 +480,7 @@
 {
 	Byte *	pltent;	/* PLT entry being created. */
 	Sxword	pltoff;	/* Offset of this entry from PLT top */
+	int	bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
 
 	pltoff = M_PLT_RESERVSZ + (pltndx - 1) * M_PLT_ENTSIZE;
 	pltent = (Byte *)ofl->ofl_osplt->os_outdata->d_buf + pltoff;
@@ -458,6 +493,9 @@
 	 */
 	/* LINTED */
 	*(Word *)pltent = M_SETHIG1 | pltoff;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[1]: ba,a .L0 (.L0 accessed as a PC-relative index of longwords)
@@ -467,6 +505,9 @@
 	pltoff = -pltoff;
 	/* LINTED */
 	*(Word *)pltent = M_BA_A | ((pltoff >> 2) & S_MASK(22));
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[2]: sethi 0, %g0 (NOP for delay slot of eventual CTI).
@@ -474,6 +515,9 @@
 	pltent += M_PLT_INSSIZE;
 	/* LINTED */
 	*(Word *)pltent = M_SETHIG0;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 
 	/*
 	 * PLT[3]: sethi 0, %g0 (NOP for PLT padding).
@@ -481,23 +525,26 @@
 	pltent += M_PLT_INSSIZE;
 	/* LINTED */
 	*(Word *)pltent = M_SETHIG0;
+	if (bswap)
+		/* LINTED */
+		*(Word *)pltent = ld_bswap_Word(*(Word *)pltent);
 }
 
 #endif /* _ELF64 */
 
-uintptr_t
+static uintptr_t
 ld_perform_outreloc(Rel_desc * orsp, Ofl_desc * ofl)
 {
-	Os_desc *		relosp, * osp = 0;
-	Xword			ndx, roffset, value;
-	Sxword			raddend;
-	const Rel_entry *	rep;
-	Rela			rea;
-	char			*relbits;
-	Sym_desc *		sdp, * psym = (Sym_desc *)0;
-	int			sectmoved = 0;
-	Word			dtflags1 = ofl->ofl_dtflags_1;
-	Word			flags = ofl->ofl_flags;
+	Os_desc *	relosp, * osp = 0;
+	Xword		ndx, roffset, value;
+	Sxword		raddend;
+	const Rel_entry	*rep;
+	Rela		rea;
+	char		*relbits;
+	Sym_desc *	sdp, * psym = (Sym_desc *)0;
+	int		sectmoved = 0;
+	Word		dtflags1 = ofl->ofl_dtflags_1;
+	Word		flags = ofl->ofl_flags;
 
 	raddend = orsp->rel_raddend;
 	sdp = orsp->rel_sym;
@@ -742,9 +789,11 @@
 {
 	Sym_desc	*sdp = arsp->rel_sym;
 	Word		rtype = arsp->rel_rtype;
-	uint_t		*offset;
+	Word		*offset, w;
+	int		bswap = OFL_SWAP_RELOC_DATA(ofl, arsp);
 
-	offset = (uint_t *)((uintptr_t)arsp->rel_roffset +
+
+	offset = (Word *)((uintptr_t)arsp->rel_roffset +
 	    (uintptr_t)_elf_getxoff(arsp->rel_isdesc->is_indata) +
 	    (uintptr_t)arsp->rel_osdesc->os_outdata->d_buf);
 
@@ -768,14 +817,18 @@
 		case R_SPARC_TLS_GD_ADD:
 			DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 			    R_SPARC_NONE, arsp));
-			*offset = (TLS_GD_IE_LD |
-			    (*offset & (FM3_REG_MSK_RS1 | FM3_REG_MSK_RS2)));
+			w = bswap ? ld_bswap_Word(*offset) : *offset;
+			w = (TLS_GD_IE_LD |
+			    (w & (FM3_REG_MSK_RS1 | FM3_REG_MSK_RS2)));
+			*offset = bswap ? ld_bswap_Word(w) : w;
 			return (FIX_DONE);
 
 		case R_SPARC_TLS_GD_CALL:
 			DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 			    R_SPARC_NONE, arsp));
 			*offset = TLS_GD_IE_ADD;
+			if (bswap)
+				*offset = ld_bswap_Word(*offset);
 			return (FIX_DONE);
 		}
 		return (FIX_RELOC);
@@ -815,8 +868,10 @@
 		 */
 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 		    R_SPARC_TLS_LE_LOX10, arsp));
-		*offset = TLS_GD_LE_XOR |
-		    (*offset & (FM3_REG_MSK_RS1 | FM3_REG_MSK_RD));
+		w = bswap ? ld_bswap_Word(*offset) : *offset;
+		w = TLS_GD_LE_XOR |
+		    (w & (FM3_REG_MSK_RS1 | FM3_REG_MSK_RD));
+		*offset = bswap ? ld_bswap_Word(w) : w;
 		arsp->rel_rtype = R_SPARC_TLS_LE_LOX10;
 		return (FIX_RELOC);
 
@@ -832,8 +887,9 @@
 		 */
 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 		    R_SPARC_NONE, arsp));
-		*offset = ((*offset) & (FM3_REG_MSK_RS2 | FM3_REG_MSK_RD)) |
-		    TLS_IE_LE_OR;
+		w = bswap ? ld_bswap_Word(*offset) : *offset;
+		w = (w & (FM3_REG_MSK_RS2 | FM3_REG_MSK_RD)) | TLS_IE_LE_OR;
+		*offset = bswap ? ld_bswap_Word(w) : w;
 		return (FIX_DONE);
 
 	case R_SPARC_TLS_LDO_ADD:
@@ -849,14 +905,18 @@
 		 */
 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 		    R_SPARC_NONE, arsp));
-		*offset = *offset & (~FM3_REG_MSK_RS1);
-		*offset = *offset | (REG_G7 << 14);
+		w = bswap ? ld_bswap_Word(*offset) : *offset;
+		w = w & (~FM3_REG_MSK_RS1);
+		w = w | (REG_G7 << 14);
+		*offset = bswap ? ld_bswap_Word(w) : w;
 		return (FIX_DONE);
 
 	case R_SPARC_TLS_LDM_CALL:
 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 		    R_SPARC_NONE, arsp));
 		*offset = TLS_LD_LE_CLRO0;
+		if (bswap)
+			*offset = ld_bswap_Word(*offset);
 		return (FIX_DONE);
 
 	case R_SPARC_TLS_LDM_HI22:
@@ -867,6 +927,8 @@
 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 		    R_SPARC_NONE, arsp));
 		*offset = M_NOP;
+		if (bswap)
+			*offset = ld_bswap_Word(*offset);
 		return (FIX_DONE);
 	}
 	return (FIX_RELOC);
@@ -878,9 +940,10 @@
 gotop_fixups(Ofl_desc *ofl, Rel_desc *arsp)
 {
 	Word		rtype = arsp->rel_rtype;
-	uint_t		*offset;
+	Word		*offset, w;
 	const char	*ifl_name;
 	Conv_inv_buf_t	inv_buf;
+	int		bswap;
 
 	switch (rtype) {
 	case R_SPARC_GOTDATA_OP_HIX22:
@@ -906,12 +969,14 @@
 		 */
 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 		    R_SPARC_NONE, arsp));
-		offset = (uint_t *)(uintptr_t)(arsp->rel_roffset +
+		offset = (Word *)(uintptr_t)(arsp->rel_roffset +
 		    _elf_getxoff(arsp->rel_isdesc->is_indata) +
 		    (uintptr_t)arsp->rel_osdesc->os_outdata->d_buf);
-
-		*offset = ((*offset) & (FM3_REG_MSK_RS1 |
+		bswap = OFL_SWAP_RELOC_DATA(ofl, arsp);
+		w = bswap ? ld_bswap_Word(*offset) : *offset;
+		w = (w & (FM3_REG_MSK_RS1 |
 		    FM3_REG_MSK_RS2 | FM3_REG_MSK_RD)) | GOTOP_ADDINST;
+		*offset = bswap ? ld_bswap_Word(w) : w;
 		return (FIX_DONE);
 	}
 	/*
@@ -930,7 +995,7 @@
 	return (FIX_ERROR);
 }
 
-uintptr_t
+static uintptr_t
 ld_do_activerelocs(Ofl_desc *ofl)
 {
 	Rel_desc	*arsp;
@@ -1150,7 +1215,7 @@
 				 */
 				if (ofl->ofl_flags1 & FLG_OF1_ENCDIFF)
 					*(Xword *)R2addr =
-					    ld_byteswap_Xword(value);
+					    ld_bswap_Xword(value);
 				else
 					*(Xword *)R2addr = value;
 				continue;
@@ -1288,7 +1353,7 @@
 	return (return_code);
 }
 
-uintptr_t
+static uintptr_t
 ld_add_outrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
 {
 	Rel_desc	*orsp;
@@ -1493,7 +1558,7 @@
  * search the input files global symbols to determine if this relocation is
  * appropriate.
  */
-uintptr_t
+static uintptr_t
 ld_reloc_register(Rel_desc * rsp, Is_desc * isp, Ofl_desc * ofl)
 {
 	if (ofl->ofl_flags & FLG_OF_MULDEFS) {
@@ -1521,7 +1586,7 @@
 /*
  * process relocation for a LOCAL symbol
  */
-uintptr_t
+static uintptr_t
 ld_reloc_local(Rel_desc * rsp, Ofl_desc * ofl)
 {
 	Word		flags = ofl->ofl_flags;
@@ -1621,7 +1686,7 @@
  * value is passed to the final relocation engine, a verification ("V")
  * relocation should trigger a fatal error condition.
  */
-uintptr_t
+static uintptr_t
 ld_reloc_GOTOP(Boolean local, Rel_desc *rsp, Ofl_desc *ofl)
 {
 	Word	rtype = rsp->rel_rtype;
@@ -1646,7 +1711,7 @@
 	return (ld_add_actrel(FLG_REL_GOTFIX, rsp, ofl));
 }
 
-uintptr_t
+static uintptr_t
 ld_reloc_TLS(Boolean local, Rel_desc *rsp, Ofl_desc *ofl)
 {
 	Word		rtype = rsp->rel_rtype;
@@ -1795,7 +1860,7 @@
 static	Sword mixed_index;	/* starting index for mixed GOT entries */
 static	Sword large_index;	/* starting index for large GOT entries */
 
-uintptr_t
+static uintptr_t
 ld_assign_got(Ofl_desc *ofl, Sym_desc * sdp)
 {
 	Listnode *	lnp;
@@ -1838,7 +1903,7 @@
 /*
  * Search the GOT index list for a GOT entry with the proper addend.
  */
-Gotndx *
+static Gotndx *
 ld_find_gotndx(List * lst, Gotref gref, Ofl_desc * ofl, Rel_desc * rdesc)
 {
 	Listnode *	lnp;
@@ -1855,7 +1920,7 @@
 	return ((Gotndx *)0);
 }
 
-Xword
+static Xword
 ld_calc_got_offset(Rel_desc * rdesc, Ofl_desc * ofl)
 {
 	Os_desc		*osp = ofl->ofl_osgot;
@@ -1886,7 +1951,7 @@
 	    (-neggotoffset * M_GOT_ENTSIZE)));
 }
 
-uintptr_t
+static uintptr_t
 ld_assign_got_ndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl,
     Rel_desc * rsp, Sym_desc * sdp)
 {
@@ -1996,14 +2061,14 @@
 	return (1);
 }
 
-void
+static void
 ld_assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl)
 {
 	sdp->sd_aux->sa_PLTndx = 1 + ofl->ofl_pltcnt++;
 }
 
 
-uintptr_t
+static uintptr_t
 ld_allocate_got(Ofl_desc * ofl)
 {
 	const Sword	first_large_ndx = M_GOT_MAXSMALL / 2;
@@ -2077,7 +2142,7 @@
 /*
  * Initializes .got[0] with the _DYNAMIC symbol value.
  */
-uintptr_t
+static uintptr_t
 ld_fillin_gotplt(Ofl_desc *ofl)
 {
 	if (ofl->ofl_osgot) {
@@ -2092,7 +2157,154 @@
 			    (M_GOT_XDYNAMIC * M_GOT_ENTSIZE));
 			/* LINTED */
 			*((Xword *)genptr) = sdp->sd_sym->st_value;
+			if (ofl->ofl_flags1 & FLG_OF1_ENCDIFF)
+				/* LINTED */
+				*((Xword *)genptr) =
+				    /* LINTED */
+				    ld_bswap_Xword(*((Xword *)genptr));
 		}
 	}
 	return (1);
 }
+
+
+
+/*
+ * Template for generating "void (*)(void)" function
+ */
+static const uchar_t nullfunc_tmpl[] = {
+/* 0x00 */	0x81, 0xc3, 0xe0, 0x08,		/* retl */
+/* 0x04 */	0x01, 0x00, 0x00, 0x00		/* nop */
+};
+
+
+
+/*
+ * Return the ld_targ definition for this target.
+ */
+const Target *
+ld_targ_init_sparc(void)
+{
+	static const Target _ld_targ = {
+		{			/* Target_mach */
+			M_MACH,			/* m_mach */
+			M_MACHPLUS,		/* m_machplus */
+			M_FLAGSPLUS,		/* m_flagsplus */
+			M_CLASS,		/* m_class */
+			M_DATA,			/* m_data */
+
+			M_SEGM_ALIGN,		/* m_segm_align */
+			M_SEGM_ORIGIN,		/* m_segm_origin */
+			M_DATASEG_PERM,		/* m_dataseg_perm */
+			M_WORD_ALIGN,		/* m_word_align */
+						/* m_def_interp */
+#if	defined(_ELF64)
+			MSG_ORIG(MSG_PTH_RTLD_SPARCV9),
+#else
+			MSG_ORIG(MSG_PTH_RTLD),
+#endif
+
+			/* Relocation type codes */
+			M_R_ARRAYADDR,		/* m_r_arrayaddr */
+			M_R_COPY,		/* m_r_copy */
+			M_R_GLOB_DAT,		/* m_r_glob_dat */
+			M_R_JMP_SLOT,		/* m_r_jmp_slot */
+			M_R_NUM,		/* m_r_num */
+			M_R_NONE,		/* m_r_none */
+			M_R_RELATIVE,		/* m_r_relative */
+			M_R_REGISTER,		/* m_r_register */
+
+			/* Relocation related constants */
+			M_REL_DT_COUNT,		/* m_rel_dt_count */
+			M_REL_DT_ENT,		/* m_rel_dt_ent */
+			M_REL_DT_SIZE,		/* m_rel_dt_size */
+			M_REL_DT_TYPE,		/* m_rel_dt_type */
+			M_REL_SHT_TYPE,		/* m_rel_sht_type */
+
+			/* GOT related constants */
+			M_GOT_ENTSIZE,		/* m_got_entsize */
+			M_GOT_XNumber,		/* m_got_xnumber */
+
+			/* PLT related constants */
+			M_PLT_ALIGN,		/* m_plt_align */
+			M_PLT_ENTSIZE,		/* m_plt_entsize */
+			M_PLT_RESERVSZ,		/* m_plt_reservsz */
+			M_PLT_SHF_FLAGS,	/* m_plt_shf_flags */
+
+			M_DT_REGISTER,		/* m_dt_register */
+		},
+		{			/* Target_machid */
+			M_ID_ARRAY,		/* id_array */
+			M_ID_BSS,		/* id_bss */
+			M_ID_CAP,		/* id_cap */
+			M_ID_DATA,		/* id_data */
+			M_ID_DYNAMIC,		/* id_dynamic */
+			M_ID_DYNSORT,		/* id_dynsort */
+			M_ID_DYNSTR,		/* id_dynstr */
+			M_ID_DYNSYM,		/* id_dynsym */
+			M_ID_DYNSYM_NDX,	/* id_dynsym_ndx */
+			M_ID_GOT,		/* id_got */
+			M_ID_GOTDATA,		/* id_gotdata */
+			M_ID_HASH,		/* id_hash */
+			M_ID_INTERP,		/* id_interp */
+			M_ID_UNKNOWN,		/* id_lbss (unused) */
+			M_ID_LDYNSYM,		/* id_ldynsym */
+			M_ID_NOTE,		/* id_note */
+			M_ID_NULL,		/* id_null */
+			M_ID_PLT,		/* id_plt */
+			M_ID_REL,		/* id_rel */
+			M_ID_STRTAB,		/* id_strtab */
+			M_ID_SYMINFO,		/* id_syminfo */
+			M_ID_SYMTAB,		/* id_symtab */
+			M_ID_SYMTAB_NDX,	/* id_symtab_ndx */
+			M_ID_TEXT,		/* id_text */
+			M_ID_TLS,		/* id_tls */
+			M_ID_TLSBSS,		/* id_tlsbss */
+			M_ID_UNKNOWN,		/* id_unknown */
+			M_ID_UNKNOWN,		/* id_unwind (unused) */
+			M_ID_USER,		/* id_user */
+			M_ID_VERSION,		/* id_version */
+		},
+		{			/* Target_nullfunc */
+			nullfunc_tmpl,		/* nf_template */
+			sizeof (nullfunc_tmpl),	/* nf_size */
+		},
+		{			/* Target_machrel */
+			reloc_table,
+
+			ld_init_rel,		/* mr_init_rel */
+			ld_mach_eflags,		/* mr_mach_eflags */
+			ld_mach_make_dynamic,	/* mr_mach_make_dynamic */
+			ld_mach_update_odynamic, /* mr_mach_update_odynamic */
+			ld_calc_plt_addr,	/* mr_calc_plt_addr */
+			ld_perform_outreloc,	/* mr_perform_outreloc */
+			ld_do_activerelocs,	/* mr_do_activerelocs */
+			ld_add_outrel,		/* mr_add_outrel */
+			ld_reloc_register,	/* mr_reloc_register */
+			ld_reloc_local,		/* mr_reloc_local */
+			ld_reloc_GOTOP,		/* mr_reloc_GOTOP */
+			ld_reloc_TLS,		/* mr_reloc_TLS */
+			ld_assign_got,		/* mr_assign_got */
+			ld_find_gotndx,		/* mr_find_gotndx */
+			ld_calc_got_offset,	/* mr_calc_got_offset */
+			ld_assign_got_ndx,	/* mr_assign_got_ndx */
+			ld_assign_plt_ndx,	/* mr_assign_plt_ndx */
+			ld_allocate_got,	/* mr_allocate_got */
+			ld_fillin_gotplt,	/* mr_fillin_gotplt */
+		},
+		{			/* Target_machsym */
+			ld_reg_check_sparc,	/* ms_reg_check */
+			ld_mach_sym_typecheck_sparc, /* ms_mach_sym_typecheck */
+			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 */
+		}
+	};
+
+	return (&_ld_targ);
+}
--- a/usr/src/cmd/sgs/libld/common/machsym.intel.c	Tue Mar 18 08:44:14 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +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 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include	<stdio.h>
-#include	<debug.h>
-#include	"_libld.h"
-
-
-/*
- * This file contains stub routines since currently register symbols
- * are not relevant to the i386 architecture.  But - having these
- * stub routines avoids #ifdefs in common codes - and I hate that.
- */
-/* ARGSUSED */
-int
-ld_reg_check(Sym_desc *sdp, Sym *nsym, const char *nname, Ifl_desc *ifl,
-    Ofl_desc * ofl)
-{
-	return (1);
-}
-
-/* ARGSUSED */
-int
-ld_mach_sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl)
-{
-	return (0);
-}
-
-/* ARGSUSED */
-const char *
-ld_is_regsym(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs,
-    int symndx, Word shndx, const char *symsecname, Word * flags)
-{
-	return (0);
-}
-
-/* ARGSUSED */
-Sym_desc *
-ld_reg_find(Sym * sym, Ofl_desc * ofl)
-{
-	return (0);
-}
-
-/* ARGSUSED */
-int
-ld_reg_enter(Sym_desc * sdp, Ofl_desc * ofl)
-{
-	return (0);
-}
--- a/usr/src/cmd/sgs/libld/common/machsym.sparc.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/machsym.sparc.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,11 +20,13 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+#define	ELF_TARGET_SPARC
+
 #include	<stdio.h>
 #include	<string.h>
 #include	<alloca.h>
@@ -32,6 +34,7 @@
 #include	<debug.h>
 #include	"msg.h"
 #include	"_libld.h"
+#include	"machsym.sparc.h"
 
 /*
  * Matrix of legal combinations of usage of a given register:
@@ -55,7 +58,7 @@
  *
  */
 int
-ld_reg_check(Sym_desc *sdp, Sym *nsym, const char *nname, Ifl_desc *ifl,
+ld_reg_check_sparc(Sym_desc *sdp, Sym *nsym, const char *nname, Ifl_desc *ifl,
     Ofl_desc * ofl)
 {
 	Sym		*osym = sdp->sd_sym;
@@ -129,7 +132,8 @@
 }
 
 int
-ld_mach_sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl)
+ld_mach_sym_typecheck_sparc(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl,
+    Ofl_desc *ofl)
 {
 	Conv_inv_buf_t	inv_buf1, inv_buf2;
 	Sym		*osym = sdp->sd_sym;
@@ -152,7 +156,7 @@
 			return (1);
 		}
 	} else if (otype == STT_SPARC_REGISTER)
-		return (ld_reg_check(sdp, nsym, sdp->sd_name, ifl, ofl));
+		return (ld_reg_check_sparc(sdp, nsym, sdp->sd_name, ifl, ofl));
 
 	return (0);
 }
@@ -165,7 +169,7 @@
 };
 
 const char *
-ld_is_regsym(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs,
+ld_is_regsym_sparc(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs,
     int symndx, Word shndx, const char *symsecname, Word * flags)
 {
 	const char	*name;
@@ -229,7 +233,7 @@
 }
 
 Sym_desc *
-ld_reg_find(Sym * sym, Ofl_desc * ofl)
+ld_reg_find_sparc(Sym * sym, Ofl_desc * ofl)
 {
 	if (ofl->ofl_regsyms == 0)
 		return (0);
@@ -238,7 +242,7 @@
 }
 
 int
-ld_reg_enter(Sym_desc * sdp, Ofl_desc * ofl)
+ld_reg_enter_sparc(Sym_desc * sdp, Ofl_desc * ofl)
 {
 	if (ofl->ofl_regsyms == 0) {
 		ofl->ofl_regsymsno = STO_SPARC_REGISTER_G7 + 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/libld/common/machsym.sparc.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+/*
+ * Sparc register symbols
+ */
+
+#ifndef	_MACHSYM_DOT_SPARC_DOT_H
+#define	_MACHSYM_DOT_SPARC_DOT_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if	defined(_ELF64)
+
+#define	ld_is_regsym_sparc	ld64_is_regsym_sparc
+#define	ld_mach_sym_typecheck_sparc	ld64_mach_sym_typecheck_sparc
+#define	ld_reg_check_sparc	ld64_reg_check_sparc
+#define	ld_reg_enter_sparc	ld64_reg_enter_sparc
+#define	ld_reg_find_sparc	ld64_reg_find_sparc
+
+#else
+
+#define	ld_is_regsym_sparc	ld32_is_regsym_sparc
+#define	ld_mach_sym_typecheck_sparc	ld32_mach_sym_typecheck_sparc
+#define	ld_reg_check_sparc	ld32_reg_check_sparc
+#define	ld_reg_enter_sparc	ld32_reg_enter_sparc
+#define	ld_reg_find_sparc	ld32_reg_find_sparc
+
+#endif
+
+extern const char	*ld_is_regsym_sparc(Ofl_desc *, Ifl_desc *, Sym *,
+			    const char *, int, Word, const char *, Word *);
+extern int		ld_mach_sym_typecheck_sparc(Sym_desc *, Sym *,
+			    Ifl_desc *, Ofl_desc *);
+extern int		ld_reg_check_sparc(Sym_desc *, Sym *, const char *,
+			    Ifl_desc *, Ofl_desc *);
+extern int		ld_reg_enter_sparc(Sym_desc *, Ofl_desc *);
+extern Sym_desc *	ld_reg_find_sparc(Sym *, Ofl_desc *);
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _MACHSYM_DOT_SPARC_DOT_H */
--- a/usr/src/cmd/sgs/libld/common/map.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/map.c	Tue Mar 18 09:17:00 2008 -0700
@@ -234,14 +234,16 @@
 		 */
 		if (type == CA_SUNW_HW_1) {
 			if ((number = (Xword)elfcap_hw1_from_str(
-			    ELFCAP_STYLE_LC, Start_tok, M_MACH)) != 0) {
+			    ELFCAP_STYLE_LC, Start_tok,
+			    ld_targ.t_m.m_mach)) != 0) {
 				ofl->ofl_hwcap_1 |= number;
 				used++;
 				continue;
 			}
 		} else {
 			if ((number = (Xword)elfcap_sf1_from_str(
-			    ELFCAP_STYLE_LC, Start_tok, M_MACH)) != 0) {
+			    ELFCAP_STYLE_LC, Start_tok,
+			    ld_targ.t_m.m_mach)) != 0) {
 				ofl->ofl_sfcap_1 |= number;
 				used++;
 				continue;
@@ -807,7 +809,7 @@
 			else if ((strcmp(Start_tok,
 			    MSG_ORIG(MSG_STR_REL)) == 0) ||
 			    (strcmp(Start_tok, MSG_ORIG(MSG_STR_RELA)) == 0))
-				enp->ec_type = M_REL_SHT_TYPE;
+				enp->ec_type = ld_targ.t_m.m_rel_sht_type;
 			else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_HASH)) == 0)
 				enp->ec_type = SHT_HASH;
 			else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_LIB)) == 0)
@@ -2491,7 +2493,8 @@
 				    ofl) == S_ERROR)
 					return (S_ERROR);
 				DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
-				    CA_SUNW_HW_1, ofl->ofl_hwcap_1, M_MACH));
+				    CA_SUNW_HW_1, ofl->ofl_hwcap_1,
+				    ld_targ.t_m.m_mach));
 				continue;
 
 			} else if (strcmp(sgp1->sg_name,
@@ -2500,7 +2503,8 @@
 				    ofl) == S_ERROR)
 					return (S_ERROR);
 				DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
-				    CA_SUNW_SF_1, ofl->ofl_sfcap_1, M_MACH));
+				    CA_SUNW_SF_1, ofl->ofl_sfcap_1,
+				    ld_targ.t_m.m_mach));
 				continue;
 
 			} else {
@@ -2592,7 +2596,8 @@
 					/*
 					 * Default to segment alignment
 					 */
-					sgp1->sg_phdr.p_align = M_SEGM_ALIGN;
+					sgp1->sg_phdr.p_align =
+					    ld_targ.t_m.m_segm_align;
 					sgp1->sg_flags |= FLG_SG_ALIGN;
 				}
 			}
--- a/usr/src/cmd/sgs/libld/common/mapfile-vers	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/mapfile-vers	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -37,7 +37,7 @@
 # definitions see:
 #	Policy for Shared Library Version Names and Interface Definitions
 
-SUNWprivate_4.2 {
+SUNWprivate_4.3 {
 	global:
 		dbg_print  = NODIRECT;	# interposed - ld(1) and ld.so.1(1)
 
@@ -50,6 +50,8 @@
 		ld64_ent_setup;
 		ld32_init_strings;
 		ld64_init_strings;
+		ld32_init_target;
+		ld64_init_target;
 		ld32_make_sections;
 		ld64_make_sections;
 		ld32_ofl_cleanup;
--- a/usr/src/cmd/sgs/libld/common/outfile.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/outfile.c	Tue Mar 18 09:17:00 2008 -0700
@@ -453,8 +453,9 @@
 			} else if (ptype == PT_TLS) {
 				if (flags & FLG_OF_TLSPHDR)
 					nseg++;
-#if	defined(__x86) && defined(_ELF64)
-			} else if (ptype == PT_SUNW_UNWIND) {
+#if	defined(_ELF64)
+			} else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
+			    (ptype == PT_SUNW_UNWIND)) {
 				if (ofl->ofl_unwindhdr)
 					nseg++;
 #endif
--- a/usr/src/cmd/sgs/libld/common/place.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/place.c	Tue Mar 18 09:17:00 2008 -0700
@@ -412,7 +412,8 @@
 	for (APLIST_TRAVERSE(sgp->sg_osdescs, idx1, osp)) {
 		Shdr	*_shdr = osp->os_shdr;
 
-		if ((ident == osp->os_scnsymndx) && (ident != M_ID_REL) &&
+		if ((ident == osp->os_scnsymndx) &&
+		    (ident != ld_targ.t_id.id_rel) &&
 		    (isp->is_namehash == osp->os_namehash) &&
 		    (shdr->sh_type != SHT_GROUP) &&
 		    (shdr->sh_type != SHT_SUNW_dof) &&
--- a/usr/src/cmd/sgs/libld/common/relocate.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/relocate.c	Tue Mar 18 09:17:00 2008 -0700
@@ -31,15 +31,49 @@
 /*
  * set-up for relocations
  */
+
+#define	ELF_TARGET_AMD64
+#define	ELF_TARGET_SPARC
+
 #include	<string.h>
 #include	<stdio.h>
 #include	<alloca.h>
-#include	<reloc.h>
 #include	<debug.h>
 #include	"msg.h"
 #include	"_libld.h"
 
 /*
+ * Set up the relocation table flag test macros so that they use the
+ * relocation table for the current target machine.
+ */
+#define	IS_PLT(X)	RELTAB_IS_PLT(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_GOT_RELATIVE(X) \
+	RELTAB_IS_GOT_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_GOT_PC(X)	RELTAB_IS_GOT_PC(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_GOTPCREL(X)	RELTAB_IS_GOTPCREL(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_GOT_BASED(X)	RELTAB_IS_GOT_BASED(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_GOT_OPINS(X)	RELTAB_IS_GOT_OPINS(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_GOT_REQUIRED(X) \
+	RELTAB_IS_GOT_REQUIRED(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_PC_RELATIVE(X) RELTAB_IS_PC_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_ADD_RELATIVE(X) \
+	RELTAB_IS_ADD_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_REGISTER(X)	RELTAB_IS_REGISTER(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_NOTSUP(X)	RELTAB_IS_NOTSUP(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_SEG_RELATIVE(X) \
+	RELTAB_IS_SEG_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_EXTOFFSET(X)	RELTAB_IS_EXTOFFSET(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_SEC_RELATIVE(X) \
+	RELTAB_IS_SEC_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_TLS_INS(X)	RELTAB_IS_TLS_INS(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_TLS_GD(X)	RELTAB_IS_TLS_GD(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_TLS_LD(X)	RELTAB_IS_TLS_LD(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_TLS_IE(X)	RELTAB_IS_TLS_IE(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_TLS_LE(X)	RELTAB_IS_TLS_LE(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_LOCALBND(X)	RELTAB_IS_LOCALBND(X, ld_targ.t_mr.mr_reloc_table)
+#define	IS_SIZE(X)	RELTAB_IS_SIZE(X, ld_targ.t_mr.mr_reloc_table)
+
+/*
  * Structure to hold copy relocation items.
  */
 typedef struct copy_rel {
@@ -73,8 +107,9 @@
 	if ((ifl->ifl_flags & FLG_IF_DISPDONE) &&
 	    (ofl->ofl_flags & FLG_OF_VERBOSE))
 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_REL_DISPREL2),
-		    conv_reloc_type(ifl->ifl_ehdr->e_machine, M_R_COPY,
-		    0, &inv_buf), ifl->ifl_name, demangle(sdp->sd_name));
+		    conv_reloc_type(ifl->ifl_ehdr->e_machine,
+		    ld_targ.t_m.m_r_copy, 0, &inv_buf),
+		    ifl->ifl_name, demangle(sdp->sd_name));
 
 	if ((ifl->ifl_flags & FLG_IF_DISPPEND) == 0)
 		return;
@@ -112,7 +147,8 @@
 			const char	*str;
 			Word		rstndx;
 
-			if (IS_PC_RELATIVE(ELF_R_TYPE(reloc->r_info)) == 0)
+			if (IS_PC_RELATIVE(ELF_R_TYPE(reloc->r_info,
+			    ld_targ.t_m.m_mach)) == 0)
 				continue;
 
 			/*
@@ -131,7 +167,8 @@
 				eprintf(ofl->ofl_lml,
 				    ERR_WARNING, MSG_INTL(MSG_REL_DISPREL1),
 				    conv_reloc_type(ifl->ifl_ehdr->e_machine,
-				    (uint_t)ELF_R_TYPE(reloc->r_info),
+				    (uint_t)ELF_R_TYPE(reloc->r_info,
+				    ld_targ.t_m.m_mach),
 				    0, &inv_buf), ifl->ifl_name, str,
 				    MSG_INTL(MSG_STR_UNKNOWN),
 				    EC_XWORD(reloc->r_offset),
@@ -160,7 +197,8 @@
 			eprintf(ofl->ofl_lml, ERR_WARNING,
 			    MSG_INTL(MSG_REL_DISPREL1),
 			    conv_reloc_type(ifl->ifl_ehdr->e_machine,
-			    (uint_t)ELF_R_TYPE(reloc->r_info), 0, &inv_buf),
+			    (uint_t)ELF_R_TYPE(reloc->r_info,
+			    ld_targ.t_m.m_mach), 0, &inv_buf),
 			    ifl->ifl_name, demangle(rsdp->sd_name), str,
 			    EC_XWORD(reloc->r_offset), str);
 		}
@@ -503,32 +541,27 @@
 	}
 
 	DBG_CALL(Dbg_reloc_ars_entry(ofl->ofl_lml, ELF_DBG_LD,
-	    arsp->rel_isdesc->is_shdr->sh_type, M_MACH, arsp));
+	    arsp->rel_isdesc->is_shdr->sh_type, ld_targ.t_m.m_mach, arsp));
 	return (1);
 }
 
 /*
  * In the platform specific machrel.XXX.c files, we sometimes write
- * a value directly into the GOT. This function can be used when
+ * a value directly into the got/plt. These function can be used when
  * the running linker has the opposite byte order of the object being
  * produced.
  */
-Xword
-ld_byteswap_Xword(Xword v)
+Word
+ld_bswap_Word(Word v)
 {
-#ifdef _ELF64
-	return ((v << 56) |
-	    ((v & 0x0000ff00) << 40) |
-	    ((v & 0x00ff0000) << 24) |
-	    ((v & 0xff000000) << 8) |
-	    ((v >> 8)  & 0xff000000) |
-	    ((v >> 24) & 0x00ff0000) |
-	    ((v >> 40) & 0x0000ff00) |
-	    (v >> 56));		/* Xword is unsigned - 0 bits enter from left */
-#else
-	return (((v << 24) | ((v & 0xff00) << 8) |
-	    ((v >> 8) & 0xff00) | (v >> 24)));
-#endif
+	return (BSWAP_WORD(v));
+}
+
+
+Xword
+ld_bswap_Xword(Xword v)
+{
+	return (BSWAP_XWORD(v));
 }
 
 
@@ -546,12 +579,12 @@
 	 * relocation we need to assign it a GOT token.  Once we've got
 	 * all of the GOT's assigned we can assign the actual indexes.
 	 */
-	if ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_GENERIC,
-	    ofl, rsp)) == 0) {
+	if ((gnp = (*ld_targ.t_mr.mr_find_gotndx)(&(sdp->sd_GOTndxs),
+	    GOT_REF_GENERIC, ofl, rsp)) == 0) {
 		Word	rtype = rsp->rel_rtype;
 
-		if (ld_assign_got_ndx(&(sdp->sd_GOTndxs), 0, GOT_REF_GENERIC,
-		    ofl, rsp, sdp) == S_ERROR)
+		if ((*ld_targ.t_mr.mr_assign_got_ndx)(&(sdp->sd_GOTndxs), 0,
+		    GOT_REF_GENERIC, ofl, rsp, sdp) == S_ERROR)
 			return (S_ERROR);
 
 		/*
@@ -584,9 +617,10 @@
 				if ((((sdp->sd_flags & FLG_SY_SPECSEC) == 0) ||
 				    (sdp->sd_sym->st_shndx != SHN_ABS)) ||
 				    (sdp->sd_aux && sdp->sd_aux->sa_symspec)) {
-					rsp->rel_rtype = M_R_RELATIVE;
-					if (ld_add_outrel((FLG_REL_GOT |
-					    FLG_REL_ADVAL), rsp,
+					rsp->rel_rtype =
+					    ld_targ.t_m.m_r_relative;
+					if ((*ld_targ.t_mr.mr_add_outrel)
+					    ((FLG_REL_GOT | FLG_REL_ADVAL), rsp,
 					    ofl) == S_ERROR)
 						return (S_ERROR);
 					rsp->rel_rtype = rtype;
@@ -597,14 +631,15 @@
 					return (S_ERROR);
 			}
 		} else {
-			rsp->rel_rtype = M_R_GLOB_DAT;
-			if (ld_add_outrel(FLG_REL_GOT, rsp, ofl) == S_ERROR)
+			rsp->rel_rtype = ld_targ.t_m.m_r_glob_dat;
+			if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_GOT,
+			    rsp, ofl) == S_ERROR)
 				return (S_ERROR);
 			rsp->rel_rtype = rtype;
 		}
 	} else {
-		if (ld_assign_got_ndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_GENERIC,
-		    ofl, rsp, sdp) == S_ERROR)
+		if ((*ld_targ.t_mr.mr_assign_got_ndx)(&(sdp->sd_GOTndxs), gnp,
+		    GOT_REF_GENERIC, ofl, rsp, sdp) == S_ERROR)
 			return (S_ERROR);
 	}
 
@@ -623,27 +658,29 @@
 {
 	Sym_desc	*sdp = rsp->rel_sym;
 
-#if	defined(__x86)
-#if	defined(_ELF64)
-	/*
-	 * AMD64 TLS code sequences do not use a unique TLS relocation to
-	 * reference the __tls_get_addr() function call.
-	 */
-	if ((ofl->ofl_flags & FLG_OF_EXEC) &&
-	    (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_U)) == 0)) {
-		return (ld_add_actrel(FLG_REL_TLSFIX, rsp, ofl));
+	switch (ld_targ.t_m.m_mach) {
+	case EM_AMD64:
+		/*
+		 * AMD64 TLS code sequences do not use a unique TLS
+		 * relocation to reference the __tls_get_addr() function call.
+		 */
+		if ((ofl->ofl_flags & FLG_OF_EXEC) &&
+		    (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_U)) ==
+		    0))
+			return (ld_add_actrel(FLG_REL_TLSFIX, rsp, ofl));
+		break;
+
+	case EM_386:
+		/*
+		 * GNUC IA32 TLS code sequences do not use a unique TLS
+		 * relocation to reference the ___tls_get_addr() function call.
+		 */
+		if ((ofl->ofl_flags & FLG_OF_EXEC) &&
+		    (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_UU)) ==
+		    0))
+			return (ld_add_actrel(FLG_REL_TLSFIX, rsp, ofl));
+		break;
 	}
-#else
-	/*
-	 * GNUC IA32 TLS code sequences do not use a unique TLS relocation to
-	 * reference the ___tls_get_addr() function call.
-	 */
-	if ((ofl->ofl_flags & FLG_OF_EXEC) &&
-	    (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_UU)) == 0)) {
-		return (ld_add_actrel(FLG_REL_TLSFIX, rsp, ofl));
-	}
-#endif
-#endif	/* __x86 */
 
 	/*
 	 * if (not PLT yet assigned)
@@ -655,7 +692,7 @@
 	if (sdp->sd_aux->sa_PLTndx == 0) {
 		Word	ortype = rsp->rel_rtype;
 
-		ld_assign_plt_ndx(sdp, ofl);
+		(*ld_targ.t_mr.mr_assign_plt_ndx)(sdp, ofl);
 
 		/*
 		 * If this symbol is binding to a LAZYLOADED object then
@@ -667,8 +704,9 @@
 		    (sdp->sd_file->ifl_flags & FLG_IF_LAZYLD)))
 			sdp->sd_flags |= FLG_SY_LAZYLD;
 
-		rsp->rel_rtype = M_R_JMP_SLOT;
-		if (ld_add_outrel(FLG_REL_PLT, rsp, ofl) == S_ERROR)
+		rsp->rel_rtype = ld_targ.t_m.m_r_jmp_slot;
+		if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_PLT, rsp, ofl) ==
+		    S_ERROR)
 			return (S_ERROR);
 		rsp->rel_rtype = ortype;
 	}
@@ -680,8 +718,9 @@
 	    IS_ADD_RELATIVE(rsp->rel_rtype)) {
 		Word	ortype	= rsp->rel_rtype;
 
-		rsp->rel_rtype = M_R_RELATIVE;
-		if (ld_add_outrel(FLG_REL_ADVAL, rsp, ofl) == S_ERROR)
+		rsp->rel_rtype = ld_targ.t_m.m_r_relative;
+		if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_ADVAL, rsp, ofl) ==
+		    S_ERROR)
 			return (S_ERROR);
 		rsp->rel_rtype = ortype;
 		return (1);
@@ -711,7 +750,7 @@
 	 */
 	if ((sdp->sd_flags & FLG_SY_SPECSEC) && (sym->st_shndx == SHN_ABS)) {
 		if ((ofl->ofl_flags1 & FLG_OF1_ABSEXEC) == 0)
-			return (ld_add_outrel(NULL, rsp, ofl));
+			return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl));
 
 		/*
 		 * If -zabsexec is set then promote the ABSOLUTE symbol to
@@ -734,7 +773,7 @@
 		if (sdp->sd_flags & FLG_SY_MVTOCOMM)
 			return (ld_add_actrel(NULL, rsp, ofl));
 		else
-			return (ld_add_outrel(NULL, rsp, ofl));
+			return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl));
 	}
 
 	/*
@@ -751,7 +790,7 @@
 		    ELF_ST_TYPE(sym->st_info), 0, &inv_buf),
 		    rsp->rel_isdesc->is_file->ifl_name,
 		    demangle(rsp->rel_sname), sdp->sd_file->ifl_name);
-		return (ld_add_outrel(NULL, rsp, ofl));
+		return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl));
 	}
 
 	/*
@@ -864,8 +903,8 @@
 		_sdp->sd_shndx = _sdp->sd_sym->st_shndx = SHN_COMMON;
 		_sdp->sd_flags |= FLG_SY_SPECSEC;
 		_sdp->sd_sym->st_value =
-		    (_sdp->sd_sym->st_size < (M_WORD_ALIGN * 2)) ?
-		    M_WORD_ALIGN : M_WORD_ALIGN * 2;
+		    (_sdp->sd_sym->st_size < (ld_targ.t_m.m_word_align * 2)) ?
+		    ld_targ.t_m.m_word_align : ld_targ.t_m.m_word_align * 2;
 
 		/*
 		 * Whether or not the symbol references initialized
@@ -893,8 +932,9 @@
 		if (list_appendc(&ofl->ofl_copyrels, cpy_rel) == 0)
 			return (S_ERROR);
 
-		rsp->rel_rtype = M_R_COPY;
-		if (ld_add_outrel(FLG_REL_BSS, rsp, ofl) == S_ERROR)
+		rsp->rel_rtype = ld_targ.t_m.m_r_copy;
+		if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_BSS, rsp, ofl) ==
+		    S_ERROR)
 			return (S_ERROR);
 		rsp->rel_rtype = rtype;
 
@@ -907,8 +947,8 @@
 			eprintf(ofl->ofl_lml, ERR_WARNING,
 			    MSG_INTL(MSG_REL_COPY),
 			    conv_reloc_type(_sdp->sd_file->ifl_ehdr->e_machine,
-			    M_R_COPY, 0, &inv_buf), _sdp->sd_file->ifl_name,
-			    _sdp->sd_name);
+			    ld_targ.t_m.m_r_copy, 0, &inv_buf),
+			    _sdp->sd_file->ifl_name, _sdp->sd_name);
 		}
 		DBG_CALL(Dbg_syms_reloc(ofl, sdp));
 	}
@@ -935,7 +975,7 @@
 	 * until runtime.
 	 */
 	if (ofl->ofl_flags & FLG_OF_SHAROBJ)
-		return (ld_add_outrel(NULL, rsp, ofl));
+		return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl));
 
 	/*
 	 * Otherwise process relocation now.
@@ -963,8 +1003,9 @@
 	 *	the relocation is pc-relative, and
 	 *	the relocation is against a symbol in same section
 	 */
-	if (local && !IS_GOT_RELATIVE(rtype) && !IS_GOT_BASED(rtype) &&
-	    !IS_GOT_PC(rtype) && IS_PC_RELATIVE(rtype) &&
+	if (local && !IS_GOT_RELATIVE(rtype) &&
+	    !IS_GOT_BASED(rtype) && !IS_GOT_PC(rtype) &&
+	    IS_PC_RELATIVE(rtype) &&
 	    ((sdp->sd_isc) && (sdp->sd_isc->is_osdesc == isp->is_osdesc)))
 		return (ld_add_actrel(NULL, rsp, ofl));
 
@@ -994,31 +1035,31 @@
 
 		/*
 		 * Indicate that this relocation should be processed the same
-		 * as a section symbol.  For SPARC and AMD64 (Rela), indicate
-		 * that the addend also needs to be applied to this relocation.
+		 * as a section symbol.  For RELA, indicate that the addend
+		 * also needs to be applied to this relocation.
 		 */
-#if	(defined(__i386) || defined(__amd64)) && !defined(_ELF64)
-		oflags = FLG_REL_SCNNDX;
-#else
-		oflags = FLG_REL_SCNNDX | FLG_REL_ADVAL;
-#endif
+		if ((rsp->rel_flags & FLG_REL_RELA) == FLG_REL_RELA)
+			oflags = FLG_REL_SCNNDX | FLG_REL_ADVAL;
+		else
+			oflags = FLG_REL_SCNNDX;
 	}
 
-#if	(defined(__i386) || defined(__amd64)) && !defined(_ELF64)
-	/*
-	 * Intel (Rel) relocations do not contain an addend.  Any addend is
-	 * contained within the file at the location identified by the
-	 * relocation offset.  Therefore, if we're processing a section symbol,
-	 * or a -zredlocsym relocation (that basically transforms a local symbol
-	 * reference into a section reference), perform an active relocation to
-	 * propagate any addend.
-	 */
-	if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) ||
-	    (oflags == FLG_REL_SCNNDX))
-		if (ld_add_actrel(NULL, rsp, ofl) == S_ERROR)
-			return (S_ERROR);
-#endif
-	return (ld_add_outrel(oflags, rsp, ofl));
+	if ((rsp->rel_flags & FLG_REL_RELA) == 0) {
+		/*
+		 * Intel (Rel) relocations do not contain an addend.  Any
+		 * addend is contained within the file at the location
+		 * identified by the relocation offset.  Therefore, if we're
+		 * processing a section symbol, or a -zredlocsym relocation
+		 * (that basically transforms a local symbol reference into
+		 * a section reference), perform an active relocation to
+		 * propagate any addend.
+		 */
+		if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) ||
+		    (oflags == FLG_REL_SCNNDX))
+			if (ld_add_actrel(NULL, rsp, ofl) == S_ERROR)
+				return (S_ERROR);
+	}
+	return ((*ld_targ.t_mr.mr_add_outrel)(oflags, rsp, ofl));
 }
 
 /*
@@ -1093,7 +1134,8 @@
 			    ifl->ifl_name, demangle(rsp->rel_sname));
 			return (S_ERROR);
 
-		} else if ((IS_TLS_IE(rtype)) && (flags & FLG_OF_VERBOSE)) {
+		} else if ((IS_TLS_IE(rtype)) &&
+		    (flags & FLG_OF_VERBOSE)) {
 			eprintf(ofl->ofl_lml, ERR_WARNING,
 			    MSG_INTL(MSG_REL_TLSIE),
 			    conv_reloc_type(mach, rtype, 0, &inv_buf1),
@@ -1101,7 +1143,7 @@
 		}
 	}
 
-	return (ld_reloc_TLS(local, rsp, ofl));
+	return ((*ld_targ.t_mr.mr_reloc_TLS)(local, rsp, ofl));
 }
 
 uintptr_t
@@ -1115,8 +1157,9 @@
 	Boolean		local;
 	Conv_inv_buf_t	inv_buf;
 
-	DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, M_MACH, M_REL_SHT_TYPE,
-	    (void *)reloc, isname, reld->rel_sname));
+	DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, ld_targ.t_m.m_mach,
+	    ld_targ.t_m.m_rel_sht_type, (void *)reloc, isname,
+	    reld->rel_sname));
 
 	/*
 	 * Indicate this symbol is being used for relocation and therefore must
@@ -1192,7 +1235,8 @@
 		    reld->rel_isdesc->is_shdr->sh_type == SHT_SUNW_dof) {
 			local = TRUE;
 		} else if (!(flags & FLG_OF_RELOBJ) &&
-		    (IS_LOCALBND(rtype) || IS_SEG_RELATIVE(rtype))) {
+		    (IS_LOCALBND(rtype) ||
+		    IS_SEG_RELATIVE(rtype))) {
 			local = TRUE;
 		} else if (sdp->sd_ref == REF_REL_NEED) {
 			/*
@@ -1220,8 +1264,10 @@
 	 * relocated symbol (PSARC 1999/636, bugid 4187211).  Scan the input
 	 * files symbol table to cross reference this relocation offset.
 	 */
-	if ((ofl->ofl_flags & FLG_OF_SHAROBJ) && IS_PC_RELATIVE(rtype) &&
-	    (IS_GOT_PC(rtype) == 0) && (IS_PLT(rtype) == 0)) {
+	if ((ofl->ofl_flags & FLG_OF_SHAROBJ) &&
+	    IS_PC_RELATIVE(rtype) &&
+	    (IS_GOT_PC(rtype) == 0) &&
+	    (IS_PLT(rtype) == 0)) {
 		if (disp_inspect(ofl, reld, local) == S_ERROR)
 			return (S_ERROR);
 	}
@@ -1231,7 +1277,8 @@
 	 * they are relevant to the current GOT.  If not building a relocatable
 	 * object - give a appropriate error message.
 	 */
-	if (!local && !(flags & FLG_OF_RELOBJ) && IS_GOT_BASED(rtype)) {
+	if (!local && !(flags & FLG_OF_RELOBJ) &&
+	    IS_GOT_BASED(rtype)) {
 		Ifl_desc	*ifl = reld->rel_isdesc->is_file;
 
 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_BADGOTBASED),
@@ -1264,8 +1311,14 @@
 	/*
 	 * Select the relocation to perform.
 	 */
-	if (IS_REGISTER(rtype))
-		return (ld_reloc_register(reld, isp, ofl));
+	if (IS_REGISTER(rtype)) {
+		if (ld_targ.t_mr.mr_reloc_register == NULL) {
+			eprintf(ofl->ofl_lml, ERR_FATAL,
+			    MSG_INTL(MSG_REL_NOREG));
+			return (S_ERROR);
+		}
+		return ((*ld_targ.t_mr.mr_reloc_register)(reld, isp, ofl));
+	}
 
 	if (flags & FLG_OF_RELOBJ)
 		return (reloc_relobj(local, reld, ofl));
@@ -1273,14 +1326,19 @@
 	if (IS_TLS_INS(rtype))
 		return (reloc_TLS(local, reld, ofl));
 
-	if (IS_GOT_OPINS(rtype))
-		return (ld_reloc_GOTOP(local, reld, ofl));
+	if (IS_GOT_OPINS(rtype)) {
+		if (ld_targ.t_mr.mr_reloc_GOTOP == NULL) {
+			assert(0);
+			return (S_ERROR);
+		}
+		return ((*ld_targ.t_mr.mr_reloc_GOTOP)(local, reld, ofl));
+	}
 
 	if (IS_GOT_RELATIVE(rtype))
 		return (ld_reloc_GOT_relative(local, reld, ofl));
 
 	if (local)
-		return (ld_reloc_local(reld, ofl));
+		return ((*ld_targ.t_mr.mr_reloc_local)(reld, ofl));
 
 	if ((IS_PLT(rtype)) && ((flags & FLG_OF_BFLAG) == 0))
 		return (ld_reloc_plt(reld, ofl));
@@ -1288,7 +1346,7 @@
 	if ((sdp->sd_ref == REF_REL_NEED) ||
 	    (flags & FLG_OF_BFLAG) || (flags & FLG_OF_SHAROBJ) ||
 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_NOTYPE))
-		return (ld_add_outrel(NULL, reld, ofl));
+		return ((*ld_targ.t_mr.mr_add_outrel)(NULL, reld, ofl));
 
 	if (sdp->sd_ref == REF_DYN_NEED)
 		return (reloc_exec(reld, ofl));
@@ -1553,7 +1611,7 @@
 	/*
 	 * Make sure the relocation is in the valid range.
 	 */
-	if (rtype >= M_R_NUM) {
+	if (rtype >= ld_targ.t_m.m_r_num) {
 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_INVALRELT),
 		    ifl->ifl_name, isp->is_name, rtype);
 		return (S_ERROR);
@@ -1570,10 +1628,15 @@
 		reld->rel_sym = 0;
 		reld->rel_sname = MSG_ORIG(MSG_STR_EMPTY);
 
-		DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, M_MACH,
-		    isp->is_shdr->sh_type, (void *)reloc, isp->is_name,
-		    reld->rel_sname));
-		return (ld_reloc_register(reld, isp, ofl));
+		DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD,
+		    ld_targ.t_m.m_mach, isp->is_shdr->sh_type,
+		    (void *)reloc, isp->is_name, reld->rel_sname));
+		if (ld_targ.t_mr.mr_reloc_register == NULL) {
+			eprintf(ofl->ofl_lml, ERR_FATAL,
+			    MSG_INTL(MSG_REL_NOREG));
+			return (S_ERROR);
+		}
+		return ((*ld_targ.t_mr.mr_reloc_register)(reld, isp, ofl));
 	}
 
 	/*
@@ -1607,16 +1670,17 @@
 	 * warning and continue (the compiler folks can get into this
 	 * state some time).  Normal users should never see this error.
 	 */
-	if (rtype == M_R_NONE) {
-		DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, M_MACH,
-		    M_REL_SHT_TYPE, (void *)reloc, isp->is_name,
-		    reld->rel_sname));
+	if (rtype == ld_targ.t_m.m_r_none) {
+		DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD,
+		    ld_targ.t_m.m_mach, ld_targ.t_m.m_rel_sht_type,
+		    (void *)reloc, isp->is_name, reld->rel_sname));
 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_REL_NULL),
 		    ifl->ifl_name, isp->is_name);
 		return (1);
 	}
 
-	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && IS_NOTSUP(rtype)) {
+	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) &&
+	    IS_NOTSUP(rtype)) {
 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_NOTSUP),
 		    conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype,
 		    0, &inv_buf), ifl->ifl_name, isp->is_name);
@@ -1783,7 +1847,7 @@
 		 * relocation records processing.
 		 */
 		reld.rel_flags = flags;
-		rsndx = ld_init_rel(&reld, (void *)reloc);
+		rsndx = (*ld_targ.t_mr.mr_init_rel)(&reld, (void *)reloc);
 
 		if (process_reld(ofl, rsect, &reld, rsndx, reloc) == S_ERROR)
 			ret = S_ERROR;
@@ -1926,7 +1990,7 @@
 		 * Initialize the relocation record information.
 		 */
 		reld.rel_flags = FLG_REL_LOAD;
-		rsndx = ld_init_rel(&reld, (void *)reloc);
+		rsndx = (*ld_targ.t_mr.mr_init_rel)(&reld, (void *)reloc);
 
 		if (((mp = get_move_entry(rsect, reloc->r_offset)) == 0) ||
 		    ((reld.rel_move = libld_malloc(sizeof (Mv_desc))) == 0))
@@ -2018,7 +2082,7 @@
 	if (ld_sym_spec(ofl) == S_ERROR)
 		return (S_ERROR);
 
-	ofl->ofl_gotcnt = M_GOT_XNumber;
+	ofl->ofl_gotcnt = ld_targ.t_m.m_got_xnumber;
 
 	/*
 	 * First process all of the relocations against NON-writable
@@ -2086,14 +2150,10 @@
 		if (ld_make_got(ofl) == S_ERROR)
 			return (S_ERROR);
 
-#if	defined(__sparc)
-		if (ld_allocate_got(ofl) == S_ERROR)
+		/* Allocate the GOT if required by target */
+		if ((ld_targ.t_mr.mr_allocate_got != NULL) &&
+		    ((*ld_targ.t_mr.mr_allocate_got)(ofl) == S_ERROR))
 			return (S_ERROR);
-#elif	defined(__x86)
-/* nothing to do */
-#else
-#error Unknown architecture!
-#endif
 	}
 
 	return (1);
@@ -2181,7 +2241,7 @@
 		    orsp < rcp->rc_free; orsp++) {
 			if (debug == 0) {
 				DBG_CALL(Dbg_reloc_dooutrel(ofl->ofl_lml,
-				    M_REL_SHT_TYPE));
+				    ld_targ.t_m.m_rel_sht_type));
 				debug = 1;
 			}
 
@@ -2190,13 +2250,14 @@
 			 * order that it was originally processed.
 			 */
 			if (orsp->rel_flags & FLG_REL_PLT) {
-				if (ld_perform_outreloc(orsp, ofl) == S_ERROR)
+				if ((*ld_targ.t_mr.mr_perform_outreloc)(orsp,
+				    ofl) == S_ERROR)
 					error = S_ERROR;
 				continue;
 			}
 
-			if ((orsp->rel_rtype == M_R_RELATIVE) ||
-			    (orsp->rel_rtype == M_R_REGISTER)) {
+			if ((orsp->rel_rtype == ld_targ.t_m.m_r_relative) ||
+			    (orsp->rel_rtype == ld_targ.t_m.m_r_register)) {
 				sorted_list[index].rl_key1 = 0;
 				sorted_list[index].rl_key2 =
 				    /* LINTED */
@@ -2210,9 +2271,10 @@
 
 			if (orsp->rel_flags & FLG_REL_GOT)
 				sorted_list[index].rl_key3 =
-				    ld_calc_got_offset(orsp, ofl);
+				    (*ld_targ.t_mr.mr_calc_got_offset)(orsp,
+				    ofl);
 			else {
-				if (orsp->rel_rtype == M_R_REGISTER)
+				if (orsp->rel_rtype == ld_targ.t_m.m_r_register)
 					sorted_list[index].rl_key3 = 0;
 				else {
 					sorted_list[index].rl_key3 =
@@ -2236,8 +2298,8 @@
 	 * and process each relocation.
 	 */
 	for (index = 0; index < ofl->ofl_reloccnt; index++) {
-		if (ld_perform_outreloc(sorted_list[index].rl_rsp, ofl) ==
-		    S_ERROR)
+		if ((*ld_targ.t_mr.mr_perform_outreloc)
+		    (sorted_list[index].rl_rsp, ofl) == S_ERROR)
 			error = S_ERROR;
 	}
 
@@ -2283,7 +2345,7 @@
 	if (do_sorted_outrelocs(ofl) == S_ERROR)
 		return (S_ERROR);
 
-	if (ld_do_activerelocs(ofl) == S_ERROR)
+	if ((*ld_targ.t_mr.mr_do_activerelocs)(ofl) == S_ERROR)
 		return (S_ERROR);
 
 	if ((ofl->ofl_flags & FLG_OF_COMREL) == 0) {
@@ -2355,7 +2417,7 @@
 	 * .dynamic section (_DYNAMIC).
 	 */
 	if (flags & FLG_OF_DYNAMIC) {
-		if (ld_fillin_gotplt(ofl) == S_ERROR)
+		if ((*ld_targ.t_mr.mr_fillin_gotplt)(ofl) == S_ERROR)
 			return (S_ERROR);
 	}
 
@@ -2364,7 +2426,8 @@
 	 * information if required.
 	 */
 	if ((osp = ofl->ofl_osgot) != NULL)
-		DBG_CALL(Dbg_got_display(ofl, osp->os_shdr->sh_addr, 1));
+		DBG_CALL(Dbg_got_display(ofl, osp->os_shdr->sh_addr, 1,
+		    ld_targ.t_m.m_got_xnumber, ld_targ.t_m.m_got_entsize));
 
 	return (1);
 }
@@ -2416,7 +2479,7 @@
 	/*
 	 * Only give relocation errors against loadable read-only segments.
 	 */
-	if ((orsp->rel_rtype == M_R_REGISTER) || (!osp) ||
+	if ((orsp->rel_rtype == ld_targ.t_m.m_r_register) || (!osp) ||
 	    (osp->os_sgdesc->sg_phdr.p_type != PT_LOAD) ||
 	    (osp->os_sgdesc->sg_phdr.p_flags & PF_W))
 		return;
@@ -2457,8 +2520,8 @@
 {
 	Word	rflags;
 
-	if (ld_assign_got_ndx(&(sdp->sd_GOTndxs), gnp, gref, ofl,
-	    rsp, sdp) == S_ERROR)
+	if ((*ld_targ.t_mr.mr_assign_got_ndx)(&(sdp->sd_GOTndxs), gnp,
+	    gref, ofl, rsp, sdp) == S_ERROR)
 		return (S_ERROR);
 
 	rflags = FLG_REL_GOT | rflag;
@@ -2466,7 +2529,7 @@
 		rflags |= FLG_REL_SCNNDX;
 	rsp->rel_rtype = rtype1;
 
-	if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR)
+	if ((*ld_targ.t_mr.mr_add_outrel)(rflags, rsp, ofl) == S_ERROR)
 		return (S_ERROR);
 
 	if (local && (gref == GOT_REF_TLSIE)) {
@@ -2488,7 +2551,8 @@
 			if (ld_add_actrel(rflags, rsp, ofl) == S_ERROR)
 				return (S_ERROR);
 		} else {
-			if (ld_add_outrel(rflags, rsp, ofl) == S_ERROR)
+			if ((*ld_targ.t_mr.mr_add_outrel)(rflags, rsp, ofl) ==
+			    S_ERROR)
 				return (S_ERROR);
 		}
 	}
@@ -2591,6 +2655,49 @@
 }
 
 
+
+/*
+ * Return True (1) if the code processing the given relocation
+ * needs to perform byte swapping when accessing the section data.
+ */
+int
+ld_swap_reloc_data(Ofl_desc *ofl, Rel_desc *rsp)
+{
+	/*
+	 * In a cross-link situation where the linker host and target
+	 * have opposite byte orders, it can be necessary to swap bytes
+	 * when doing relocation processing. This is indicated by the
+	 * presence of the FLG_OF1_ENCDIFF flag bit. However, swapping
+	 * is only needed for the section types that libelf doesn't
+	 * automatically xlate.
+	 */
+	if ((ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0) {
+		switch (rsp->rel_osdesc->os_shdr->sh_type) {
+		case SHT_PROGBITS:
+			return (1);
+
+		case SHT_SPARC_GOTDATA:
+			if (ld_targ.t_m.m_mach ==
+			    LD_TARG_BYCLASS(EM_SPARC, EM_SPARCV9))
+				return (1);
+			break;
+
+		case SHT_AMD64_UNWIND:
+			if (ld_targ.t_m.m_mach == EM_AMD64)
+				return (1);
+			break;
+		}
+	}
+
+	/*
+	 * If FLG_OF1_ENCDIFF isn't set, or the section isn't
+	 * progbits (or similar), then no swapping is needed.
+	 */
+	return (0);
+}
+
+
+
 /*
  * Obtain the current value at the given relocation target.
  *
@@ -2609,15 +2716,7 @@
 {
 	const Rel_entry	*rep;
 
-	/* We do not currently support running as a cross linker */
-	if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
-		REL_ERR_NOSWAP(ofl->ofl_lml,
-		    rsp->rel_isdesc->is_file->ifl_name, rsp->rel_sname,
-		    rsp->rel_rtype);
-		return (0);
-	}
-
-	rep = &reloc_table[rsp->rel_rtype];
+	rep = &ld_targ.t_mr.mr_reloc_table[rsp->rel_rtype];
 
 	switch (rep->re_fsize) {
 	case 1:
@@ -2625,20 +2724,41 @@
 		*value = (Xword) *((uchar_t *)data);
 		break;
 	case 2:
-		/* LINTED */
-		*value = (Xword) *((Half *)data);
+		{
+			Half	v;
+			uchar_t	*v_bytes = (uchar_t *)&v;
+
+			if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
+				UL_ASSIGN_BSWAP_HALF(v_bytes, data);
+			} else {
+				UL_ASSIGN_HALF(v_bytes, data);
+			}
+			*value = (Xword) v;
+		}
 		break;
 	case 4:
-		/* LINTED */
-		*value = *((Xword *)data);
+		{
+			Word	v;
+			uchar_t	*v_bytes = (uchar_t *)&v;
+
+			if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
+				UL_ASSIGN_BSWAP_WORD(v_bytes, data);
+			} else {
+				UL_ASSIGN_WORD(v_bytes, data);
+			}
+			*value = (Xword) v;
+		}
 		break;
 	default:
-		/*
-		 * To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ)
-		 */
-		REL_ERR_UNSUPSZ(ofl->ofl_lml,
-		    rsp->rel_isdesc->is_file->ifl_name, rsp->rel_sname,
-		    rsp->rel_rtype, rep->re_fsize);
+		{
+			Conv_inv_buf_t inv_buf;
+			eprintf(ofl->ofl_lml, ERR_FATAL,
+			    MSG_INTL(MSG_REL_UNSUPSZ),
+			    conv_reloc_type(ld_targ.t_m.m_mach, rsp->rel_rtype,
+			    0, &inv_buf), rsp->rel_isdesc->is_file->ifl_name,
+			    (rsp->rel_sname ? demangle(rsp->rel_sname) :
+			    MSG_INTL(MSG_STR_UNKNOWN)), (int)rep->re_fsize);
+		}
 		return (0);
 	}
 	return (1);
@@ -2663,15 +2783,7 @@
 {
 	const Rel_entry	*rep;
 
-	/* We do not currently support running as a cross linker */
-	if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
-		REL_ERR_NOSWAP(ofl->ofl_lml,
-		    rsp->rel_isdesc->is_file->ifl_name, rsp->rel_sname,
-		    rsp->rel_rtype);
-		return (0);
-	}
-
-	rep = &reloc_table[rsp->rel_rtype];
+	rep = &ld_targ.t_mr.mr_reloc_table[rsp->rel_rtype];
 
 	switch (rep->re_fsize) {
 	case 1:
@@ -2679,20 +2791,39 @@
 		*((uchar_t *)data) = (uchar_t)value;
 		break;
 	case 2:
-		/* LINTED */
-		*((Half *)data) = (Half)value;
+		{
+			Half	v = (Half)value;
+			uchar_t	*v_bytes = (uchar_t *)&v;
+
+			if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
+				UL_ASSIGN_BSWAP_HALF(data, v_bytes);
+			} else {
+				UL_ASSIGN_HALF(data, v_bytes);
+			}
+		}
 		break;
 	case 4:
-		/* LINTED */
-		*((Xword *)data) = value;
+		{
+			Word	v = (Word)value;
+			uchar_t	*v_bytes = (uchar_t *)&v;
+
+			if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
+				UL_ASSIGN_BSWAP_WORD(data, v_bytes);
+			} else {
+				UL_ASSIGN_WORD(data, v_bytes);
+			}
+		}
 		break;
 	default:
-		/*
-		 * To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ)
-		 */
-		REL_ERR_UNSUPSZ(ofl->ofl_lml,
-		    rsp->rel_isdesc->is_file->ifl_name, rsp->rel_sname,
-		    rsp->rel_rtype, rep->re_fsize);
+		{
+			Conv_inv_buf_t inv_buf;
+			eprintf(ofl->ofl_lml, ERR_FATAL,
+			    MSG_INTL(MSG_REL_UNSUPSZ),
+			    conv_reloc_type(ld_targ.t_m.m_mach, rsp->rel_rtype,
+			    0, &inv_buf), rsp->rel_isdesc->is_file->ifl_name,
+			    (rsp->rel_sname ? demangle(rsp->rel_sname) :
+			    MSG_INTL(MSG_STR_UNKNOWN)), (int)rep->re_fsize);
+		}
 		return (0);
 	}
 	return (1);
--- a/usr/src/cmd/sgs/libld/common/resolve.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/resolve.c	Tue Mar 18 09:17:00 2008 -0700
@@ -23,7 +23,7 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVR4 6.2/18.2 */
@@ -31,6 +31,8 @@
 /*
  * Symbol table resolution
  */
+#define	ELF_TARGET_AMD64
+
 #include	<stdio.h>
 #include	<debug.h>
 #include	"msg.h"
@@ -274,7 +276,8 @@
 	/*
 	 * Perform any machine specific type checking.
 	 */
-	if (ld_mach_sym_typecheck(sdp, nsym, ifl, ofl))
+	if ((ld_targ.t_ms.ms_mach_sym_typecheck != NULL) &&
+	    (*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym, ifl, ofl))
 		return;
 
 	/*
@@ -301,7 +304,9 @@
 	/*
 	 * Perform any machine specific type checking.
 	 */
-	(void) ld_mach_sym_typecheck(sdp, nsym, ifl, ofl);
+	if (ld_targ.t_ms.ms_mach_sym_typecheck != NULL)
+		(void) (*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym,
+		    ifl, ofl);
 }
 
 /*
@@ -574,7 +579,8 @@
 	/*
 	 * Perform any machine specific type checking.
 	 */
-	if (ld_mach_sym_typecheck(sdp, nsym, ifl, ofl))
+	if ((ld_targ.t_ms.ms_mach_sym_typecheck != NULL) &&
+	    (*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym, ifl, ofl))
 		return;
 
 	/*
@@ -835,25 +841,28 @@
 	size_t	size = 0;
 	Xword	value = 0;
 
-#if	defined(__x86) && defined(_ELF64)
-	/*
-	 * If the original and new symbols are both COMMON, but of a different
-	 * size model, take the small one.
-	 */
-	if ((sdp->sd_sym->st_shndx == SHN_COMMON) &&
-	    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
+#if	defined(_ELF64)
+	if (ld_targ.t_m.m_mach == EM_AMD64) {
 		/*
-		 * Take the original symbol.
+		 * If the original and new symbols are both COMMON, but of
+		 * a different size model, take the small one.
 		 */
-		return;
+		if ((sdp->sd_sym->st_shndx == SHN_COMMON) &&
+		    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
+			/*
+			 * Take the original symbol.
+			 */
+			return;
 
-	} else if ((sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
-	    (nsym->st_shndx == SHN_COMMON)) {
-		/*
-		 * Take the new symbol.
-		 */
-		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
-		return;
+		} else if ((sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
+		    (nsym->st_shndx == SHN_COMMON)) {
+			/*
+			 * Take the new symbol.
+			 */
+			sym_override(sdp, nsym, ifl, ofl, ndx, nshndx,
+			    nsymflags);
+			return;
+		}
 	}
 #endif
 
@@ -869,9 +878,10 @@
 	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
 	    (sdp->sd_sym->st_shndx == SHN_COMMON) &&
 	    (nsymflags & FLG_SY_SPECSEC) &&
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)
 	    (nsym->st_shndx == SHN_COMMON)) ||
-	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
+	    ((ld_targ.t_m.m_mach == EM_AMD64) &&
+	    (sdp->sd_flags & FLG_SY_SPECSEC) &&
 	    (sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
 	    (nsymflags & FLG_SY_SPECSEC) &&
 	    (nsym->st_shndx == SHN_X86_64_LCOMMON))) {
@@ -1126,8 +1136,9 @@
 	    (nsym->st_shndx == SHN_COMMON)) {
 		column = SYM_TENTATIVE;
 		nsymflags |= FLG_SY_TENTSYM;
-#if	defined(__x86) && defined(_ELF64)
-	} else if ((nsymflags & FLG_SY_SPECSEC) &&
+#if	defined(_ELF64)
+	} else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
+	    (nsymflags & FLG_SY_SPECSEC) &&
 	    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
 		column = SYM_TENTATIVE;
 		nsymflags |= FLG_SY_TENTSYM;
--- a/usr/src/cmd/sgs/libld/common/sections.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/sections.c	Tue Mar 18 09:17:00 2008 -0700
@@ -31,6 +31,9 @@
 /*
  * Module sections. Initialize special sections
  */
+
+#define	ELF_TARGET_AMD64
+
 #include	<string.h>
 #include	<strings.h>
 #include	<stdio.h>
@@ -302,7 +305,7 @@
 			if (!(flags & FLG_REL_PLT))
 				ofl->ofl_reloccntsub++;
 
-			if (rsp->rel_rtype == M_R_RELATIVE)
+			if (rsp->rel_rtype == ld_targ.t_m.m_r_relative)
 				ofl->ofl_relocrelcnt--;
 		}
 	}
@@ -358,6 +361,9 @@
 	 * containing those values and generates code to set the sec_info
 	 * pointer to refer to it. The pointer in sec_info remains valid
 	 * outside of the declaration scope because the info_s struct is static.
+	 *
+	 * We can't determine the value of M_WORD_ALIGN at compile time, so
+	 * a different variant is used for those cases.
 	 */
 #define	SET_SEC_INFO(d_type, d_align, sh_flags, sh_entsize) \
 	{ \
@@ -365,6 +371,13 @@
 		    sh_entsize}; \
 		sec_info = &info_s; \
 	}
+#define	SET_SEC_INFO_WORD_ALIGN(d_type, sh_flags, sh_entsize) \
+	{ \
+		static SEC_INFO_T info_s = { d_type, 0, sh_flags, \
+		    sh_entsize}; \
+		info_s.align = ld_targ.t_m.m_word_align; \
+		sec_info = &info_s; \
+	}
 
 	switch (shtype) {
 	case SHT_PROGBITS:
@@ -376,16 +389,16 @@
 		 * that they are correct or complete for any specific
 		 * purpose. The caller must provide the correct values.
 		 */
-		SET_SEC_INFO(ELF_T_BYTE, M_WORD_ALIGN, SHF_ALLOC, 0)
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC, 0)
 		break;
 
 	case SHT_SYMTAB:
-		SET_SEC_INFO(ELF_T_SYM, M_WORD_ALIGN, 0, sizeof (Sym))
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, 0, sizeof (Sym))
 		break;
 
 	case SHT_DYNSYM:
 	case SHT_SUNW_LDYNSYM:
-		SET_SEC_INFO(ELF_T_SYM, M_WORD_ALIGN, SHF_ALLOC, sizeof (Sym))
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, SHF_ALLOC, sizeof (Sym))
 		break;
 
 	case SHT_STRTAB:
@@ -405,7 +418,7 @@
 		 * Relocations with an addend (Everything except 32-bit X86).
 		 * The caller is expected to set all section header flags.
 		 */
-		SET_SEC_INFO(ELF_T_RELA, M_WORD_ALIGN, 0, sizeof (Rela))
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_RELA, 0, sizeof (Rela))
 		break;
 
 	case SHT_REL:
@@ -413,13 +426,13 @@
 		 * Relocations without an addend (32-bit X86 only).
 		 * The caller is expected to set all section header flags.
 		 */
-		SET_SEC_INFO(ELF_T_REL, M_WORD_ALIGN, 0, sizeof (Rel))
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_REL, 0, sizeof (Rel))
 		break;
 
 	case SHT_HASH:
 	case SHT_SUNW_symsort:
 	case SHT_SUNW_tlssort:
-		SET_SEC_INFO(ELF_T_WORD, M_WORD_ALIGN, SHF_ALLOC, sizeof (Word))
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC, sizeof (Word))
 		break;
 
 	case SHT_DYNAMIC:
@@ -428,7 +441,7 @@
 		 * on context, so we leave that flag unset and leave it to
 		 * the caller to add it if necessary.
 		 */
-		SET_SEC_INFO(ELF_T_DYN, M_WORD_ALIGN, SHF_WRITE, sizeof (Dyn))
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_DYN, SHF_WRITE, sizeof (Dyn))
 		break;
 
 	case SHT_NOBITS:
@@ -455,11 +468,11 @@
 		 * linker has no need for this information. It is purely
 		 * informational, used by elfdump(1), debuggers, etc.
 		 */
-		SET_SEC_INFO(ELF_T_WORD, M_WORD_ALIGN, 0, sizeof (Word));
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, 0, sizeof (Word));
 		break;
 
 	case SHT_SUNW_cap:
-		SET_SEC_INFO(ELF_T_CAP, M_WORD_ALIGN, SHF_ALLOC, sizeof (Cap));
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_CAP, SHF_ALLOC, sizeof (Cap));
 		break;
 
 	case SHT_SUNW_move:
@@ -478,7 +491,7 @@
 		 * to the header index of the associated .dynamic section,
 		 * so we also set SHF_INFO_LINK.
 		 */
-		SET_SEC_INFO(ELF_T_BYTE, M_WORD_ALIGN,
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE,
 		    SHF_ALLOC | SHF_INFO_LINK, sizeof (Syminfo));
 		break;
 
@@ -489,11 +502,11 @@
 		 * The entries in these sections are not of uniform size,
 		 * so we set the entsize to 0.
 		 */
-		SET_SEC_INFO(ELF_T_BYTE, M_WORD_ALIGN, SHF_ALLOC, 0);
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC, 0);
 		break;
 
 	case SHT_SUNW_versym:
-		SET_SEC_INFO(ELF_T_BYTE, M_WORD_ALIGN, SHF_ALLOC,
+		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC,
 		    sizeof (Versym));
 		break;
 
@@ -503,6 +516,7 @@
 		return (S_ERROR);
 	}
 #undef	SET_SEC_INFO
+#undef	SET_SEC_INFO_WORD_ALIGN
 
 	size = entcnt * sec_info->sh_entsize;
 
@@ -641,20 +655,20 @@
 
 	if (which == MAKE_TLS) {
 		isec->is_name = MSG_ORIG(MSG_SCN_TBSS);
-		ident = M_ID_TLSBSS;
+		ident = ld_targ.t_id.id_tlsbss;
 		ofl->ofl_istlsbss = isec;
 		shdr->sh_flags |= SHF_TLS;
 
 	} else if (which == MAKE_BSS) {
 		isec->is_name = MSG_ORIG(MSG_SCN_BSS);
 		ofl->ofl_isbss = isec;
-		ident = M_ID_BSS;
-
-#if	defined(__x86) && defined(_ELF64)
-	} else if (which == MAKE_LBSS) {
+		ident = ld_targ.t_id.id_bss;
+
+#if	defined(_ELF64)
+	} else if ((ld_targ.t_m.m_mach == EM_AMD64) && (which == MAKE_LBSS)) {
 		isec->is_name = MSG_ORIG(MSG_SCN_LBSS);
 		ofl->ofl_islbss = isec;
-		ident = M_ID_LBSS;
+		ident = ld_targ.t_id.id_lbss;
 		shdr->sh_flags |= SHF_AMD64_LARGE;
 #endif
 	}
@@ -722,7 +736,8 @@
 	if ((data->d_buf = libld_calloc(sizeof (Addr), entcount)) == 0)
 		return (S_ERROR);
 
-	if (ld_place_section(ofl, isec, M_ID_ARRAY, 0) == (Os_desc *)S_ERROR)
+	if (ld_place_section(ofl, isec, ld_targ.t_id.id_array, 0) ==
+	    (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	osp = isec->is_osdesc;
@@ -747,7 +762,7 @@
 	 * Fabricate the relocation information (as if a relocation record had
 	 * been input - see init_rel()).
 	 */
-	reld.rel_rtype = M_R_ARRAYADDR;
+	reld.rel_rtype = ld_targ.t_m.m_r_arrayaddr;
 	reld.rel_roffset = 0;
 	reld.rel_raddend = 0;
 	reld.rel_typedata = 0;
@@ -757,10 +772,11 @@
 	 * debugging requirements.
 	 */
 	reloc.r_offset = 0;
-	reloc.r_info = ELF_R_INFO(0, M_R_ARRAYADDR);
+	reloc.r_info = ELF_R_INFO(0, ld_targ.t_m.m_r_arrayaddr);
 	reloc.r_addend = 0;
 
-	DBG_CALL(Dbg_reloc_generate(ofl->ofl_lml, osp, M_REL_SHT_TYPE));
+	DBG_CALL(Dbg_reloc_generate(ofl->ofl_lml, osp,
+	    ld_targ.t_m.m_rel_sht_type));
 	for (LIST_TRAVERSE(list, lnp, sdp)) {
 		reld.rel_sname = sdp->sd_name;
 		reld.rel_sym = sdp;
@@ -800,7 +816,8 @@
 	shdr->sh_flags = 0;
 	shdr->sh_addralign = 1;
 
-	return ((uintptr_t)ld_place_section(ofl, isec, M_ID_NOTE, 0));
+	return ((uintptr_t)ld_place_section(ofl, isec,
+	    ld_targ.t_id.id_note, 0));
 }
 
 /*
@@ -831,7 +848,8 @@
 	if (!(flags & FLG_OF_RELOBJ))
 		shdr->sh_flags |= SHF_ALLOC;
 
-	osp = ofl->ofl_osdynamic = ld_place_section(ofl, isec, M_ID_DYNAMIC, 0);
+	osp = ofl->ofl_osdynamic =
+	    ld_place_section(ofl, isec, ld_targ.t_id.id_dynamic, 0);
 
 	/*
 	 * Reserve entries for any needed dependencies.
@@ -1103,7 +1121,7 @@
 	/*
 	 * Account for Architecture dependent .dynamic entries, and defaults.
 	 */
-	ld_mach_make_dynamic(ofl, &cnt);
+	(*ld_targ.t_mr.mr_mach_make_dynamic)(ofl, &cnt);
 
 	/*
 	 * DT_FLAGS, DT_FLAGS_1, DT_SUNW_STRPAD, and DT_NULL. Also,
@@ -1113,6 +1131,16 @@
 	cnt += 4 + DYNAMIC_EXTRA_ELTS;
 
 	/*
+	 * DT_SUNW_LDMACH. Used to hold the ELF machine code of the
+	 * linker that produced the output object. This information
+	 * allows us to determine whether a given object was linked
+	 * natively, or by a linker running on a different type of
+	 * system. This information can be valuable if one suspects
+	 * that a problem might be due to alignment or byte order issues.
+	 */
+	cnt++;
+
+	/*
 	 * Determine the size of the section from the number of entries.
 	 */
 	size = cnt * (size_t)shdr->sh_entsize;
@@ -1129,11 +1157,11 @@
 uintptr_t
 ld_make_got(Ofl_desc *ofl)
 {
-	Shdr		*shdr;
 	Elf_Data	*data;
-	Is_desc		*isec;
-	size_t		size = (size_t)ofl->ofl_gotcnt * M_GOT_ENTSIZE;
-	size_t		rsize = (size_t)ofl->ofl_relocgotsz;
+	Shdr	*shdr;
+	Is_desc	*isec;
+	size_t	size = (size_t)ofl->ofl_gotcnt * ld_targ.t_m.m_got_entsize;
+	size_t	rsize = (size_t)ofl->ofl_relocgotsz;
 
 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_GOT), 0,
 	    &isec, &shdr, &data) == S_ERROR)
@@ -1143,10 +1171,10 @@
 
 	shdr->sh_flags |= SHF_WRITE;
 	shdr->sh_size = (Xword)size;
-	shdr->sh_entsize = M_GOT_ENTSIZE;
-
-	if ((ofl->ofl_osgot = ld_place_section(ofl, isec, M_ID_GOT, 0)) ==
-	    (Os_desc *)S_ERROR)
+	shdr->sh_entsize = ld_targ.t_m.m_got_entsize;
+
+	ofl->ofl_osgot = ld_place_section(ofl, isec, ld_targ.t_id.id_got, 0);
+	if (ofl->ofl_osgot == (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	ofl->ofl_osgot->os_szoutrels = (Xword)rsize;
@@ -1186,16 +1214,8 @@
 	 * In the case of a dynamic executable supply a default interpreter
 	 * if a specific interpreter has not been specified.
 	 */
-	if (iname == 0) {
-		if (ofl->ofl_dehdr->e_machine == EM_SPARCV9)
-			iname = ofl->ofl_interp =
-			    MSG_ORIG(MSG_PTH_RTLD_SPARCV9);
-		else if (ofl->ofl_dehdr->e_machine == EM_AMD64)
-			iname = ofl->ofl_interp =
-			    MSG_ORIG(MSG_PTH_RTLD_AMD64);
-		else
-			iname = ofl->ofl_interp = MSG_ORIG(MSG_PTH_RTLD);
-	}
+	if (iname == NULL)
+		iname = ofl->ofl_interp = ld_targ.t_m.m_def_interp;
 
 	size = strlen(iname) + 1;
 
@@ -1207,7 +1227,8 @@
 	shdr->sh_size = (Xword)size;
 	data->d_align = shdr->sh_addralign = 1;
 
-	ofl->ofl_osinterp = ld_place_section(ofl, isec, M_ID_INTERP, 0);
+	ofl->ofl_osinterp =
+	    ld_place_section(ofl, isec, ld_targ.t_id.id_interp, 0);
 	return ((uintptr_t)ofl->ofl_osinterp);
 }
 
@@ -1260,7 +1281,7 @@
 	 * If we're not creating a relocatable object, save the output section
 	 * to trigger the creation of an associated program header.
 	 */
-	osec = ld_place_section(ofl, isec, M_ID_CAP, 0);
+	osec = ld_place_section(ofl, isec, ld_targ.t_id.id_cap, 0);
 	if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)
 		ofl->ofl_oscap = osec;
 
@@ -1276,32 +1297,31 @@
 	Shdr		*shdr;
 	Elf_Data	*data;
 	Is_desc		*isec;
-	size_t		size = (size_t)M_PLT_RESERVSZ +
+	size_t		size = ld_targ.t_m.m_plt_reservsz +
 	    (((size_t)ofl->ofl_pltcnt + (size_t)ofl->ofl_pltpad) *
-	    M_PLT_ENTSIZE);
+	    ld_targ.t_m.m_plt_entsize);
 	size_t		rsize = (size_t)ofl->ofl_relocpltsz;
 
-#if	defined(__sparc)
 	/*
-	 * Account for the NOP at the end of the plt.
+	 * On sparc, account for the NOP at the end of the plt.
 	 */
-	size += sizeof (Word);
-#endif
+	if (ld_targ.t_m.m_mach == LD_TARG_BYCLASS(EM_SPARC, EM_SPARCV9))
+		size += sizeof (Word);
 
 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_PLT), 0,
 	    &isec, &shdr, &data) == S_ERROR)
 		return (S_ERROR);
 
 	data->d_size = size;
-	data->d_align = M_PLT_ALIGN;
-
-	shdr->sh_flags = M_PLT_SHF_FLAGS;
+	data->d_align = ld_targ.t_m.m_plt_align;
+
+	shdr->sh_flags = ld_targ.t_m.m_plt_shf_flags;
 	shdr->sh_size = (Xword)size;
-	shdr->sh_addralign = M_PLT_ALIGN;
-	shdr->sh_entsize = M_PLT_ENTSIZE;
-
-	if ((ofl->ofl_osplt = ld_place_section(ofl, isec, M_ID_PLT, 0)) ==
-	    (Os_desc *)S_ERROR)
+	shdr->sh_addralign = ld_targ.t_m.m_plt_align;
+	shdr->sh_entsize = ld_targ.t_m.m_plt_entsize;
+
+	ofl->ofl_osplt = ld_place_section(ofl, isec, ld_targ.t_id.id_plt, 0);
+	if (ofl->ofl_osplt == (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	ofl->ofl_osplt->os_szoutrels = (Xword)rsize;
@@ -1336,8 +1356,8 @@
 	 * Place the section first since it will affect the local symbol
 	 * count.
 	 */
-	if ((ofl->ofl_oshash = ld_place_section(ofl, isec, M_ID_HASH, 0)) ==
-	    (Os_desc *)S_ERROR)
+	ofl->ofl_oshash = ld_place_section(ofl, isec, ld_targ.t_id.id_hash, 0);
+	if (ofl->ofl_oshash == (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	/*
@@ -1394,8 +1414,9 @@
 	 * Place the section first since it will affect the local symbol
 	 * count.
 	 */
-	if ((ofl->ofl_ossymtab = ld_place_section(ofl, isec, M_ID_SYMTAB, 0)) ==
-	    (Os_desc *)S_ERROR)
+	ofl->ofl_ossymtab =
+	    ld_place_section(ofl, isec, ld_targ.t_id.id_symtab, 0);
+	if (ofl->ofl_ossymtab == (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	/*
@@ -1413,7 +1434,7 @@
 			return (S_ERROR);
 
 		if ((ofl->ofl_ossymshndx = ld_place_section(ofl, xisec,
-		    M_ID_SYMTAB_NDX, 0)) == (Os_desc *)S_ERROR)
+		    ld_targ.t_id.id_symtab_ndx, 0)) == (Os_desc *)S_ERROR)
 			return (S_ERROR);
 	}
 	/*
@@ -1498,10 +1519,11 @@
 	 */
 	if (allow_ldynsym &&
 	    ((ofl->ofl_osldynsym = ld_place_section(ofl, lisec,
-	    M_ID_LDYNSYM, 0)) == (Os_desc *)S_ERROR))
+	    ld_targ.t_id.id_ldynsym, 0)) == (Os_desc *)S_ERROR))
 		return (S_ERROR);
-	if ((ofl->ofl_osdynsym = ld_place_section(ofl, isec, M_ID_DYNSYM, 0))
-	    == (Os_desc *)S_ERROR)
+	ofl->ofl_osdynsym =
+	    ld_place_section(ofl, isec, ld_targ.t_id.id_dynsym, 0);
+	if (ofl->ofl_osdynsym == (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	/*
@@ -1558,7 +1580,7 @@
 		return (S_ERROR);
 
 		if ((ofl->ofl_osdynsymsort = ld_place_section(ofl, isec,
-		    M_ID_DYNSORT, 0)) == (Os_desc *)S_ERROR)
+		    ld_targ.t_id.id_dynsort, 0)) == (Os_desc *)S_ERROR)
 			return (S_ERROR);
 	}
 
@@ -1570,7 +1592,7 @@
 		return (S_ERROR);
 
 		if ((ofl->ofl_osdyntlssort = ld_place_section(ofl, isec,
-		    M_ID_DYNSORT, 0)) == (Os_desc *)S_ERROR)
+		    ld_targ.t_id.id_dynsort, 0)) == (Os_desc *)S_ERROR)
 			return (S_ERROR);
 	}
 
@@ -1600,7 +1622,7 @@
 		return (S_ERROR);
 
 	if ((*ret_os = ld_place_section(ofl, isec,
-	    M_ID_DYNSYM_NDX, 0)) == (Os_desc *)S_ERROR)
+	    ld_targ.t_id.id_dynsym_ndx, 0)) == (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	assert(*ret_os);
@@ -1652,8 +1674,9 @@
 	 * Place the section first, as it may effect the number of section
 	 * headers to account for.
 	 */
-	if ((ofl->ofl_osshstrtab = ld_place_section(ofl, isec, M_ID_NOTE, 0)) ==
-	    (Os_desc *)S_ERROR)
+	ofl->ofl_osshstrtab =
+	    ld_place_section(ofl, isec, ld_targ.t_id.id_note, 0);
+	if (ofl->ofl_osshstrtab == (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	size = st_getstrtab_sz(ofl->ofl_shdrsttab);
@@ -1695,7 +1718,8 @@
 	data->d_size = size;
 	shdr->sh_size = (Xword)size;
 
-	ofl->ofl_osstrtab = ld_place_section(ofl, isec, M_ID_STRTAB, 0);
+	ofl->ofl_osstrtab =
+	    ld_place_section(ofl, isec, ld_targ.t_id.id_strtab, 0);
 	return ((uintptr_t)ofl->ofl_osstrtab);
 }
 
@@ -1774,7 +1798,8 @@
 
 	shdr->sh_size = (Xword)size;
 
-	ofl->ofl_osdynstr = ld_place_section(ofl, isec, M_ID_DYNSTR, 0);
+	ofl->ofl_osdynstr =
+	    ld_place_section(ofl, isec, ld_targ.t_id.id_dynstr, 0);
 	return ((uintptr_t)ofl->ofl_osdynstr);
 }
 
@@ -1799,7 +1824,7 @@
 	const char	*rel_prefix;
 
 	/* LINTED */
-	if (M_REL_SHT_TYPE == SHT_REL) {
+	if (ld_targ.t_m.m_rel_sht_type == SHT_REL) {
 		/* REL */
 		relsize = sizeof (Rel);
 		rel_prefix = MSG_ORIG(MSG_SCN_REL);
@@ -1834,8 +1859,8 @@
 	/* LINTED */
 	ofl->ofl_relocsz += (Xword)size;
 
-	if (new_section(ofl, M_REL_SHT_TYPE, sectname, 0, &isec, &shdr, &data)
-	    == S_ERROR)
+	if (new_section(ofl, ld_targ.t_m.m_rel_sht_type, sectname, 0, &isec,
+	    &shdr, &data) == S_ERROR)
 		return (S_ERROR);
 
 	data->d_size = size;
@@ -1856,8 +1881,8 @@
 	 * Associate this relocation section to the section its going to
 	 * relocate.
 	 */
-	if ((rosp = ld_place_section(ofl, isec, M_ID_REL, 0)) ==
-	    (Os_desc *)S_ERROR)
+	rosp = ld_place_section(ofl, isec, ld_targ.t_id.id_rel, 0);
+	if (rosp == (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	if (osp) {
@@ -1921,7 +1946,8 @@
 	data->d_size = ofl->ofl_verneedsz;
 	shdr->sh_size = (Xword)ofl->ofl_verneedsz;
 
-	ofl->ofl_osverneed = ld_place_section(ofl, isec, M_ID_VERSION, 0);
+	ofl->ofl_osverneed =
+	    ld_place_section(ofl, isec, ld_targ.t_id.id_version, 0);
 	return ((uintptr_t)ofl->ofl_osverneed);
 }
 
@@ -1966,7 +1992,8 @@
 	data->d_size = ofl->ofl_verdefsz;
 	shdr->sh_size = (Xword)ofl->ofl_verdefsz;
 
-	ofl->ofl_osverdef = ld_place_section(ofl, isec, M_ID_VERSION, 0);
+	ofl->ofl_osverdef =
+	    ld_place_section(ofl, isec, ld_targ.t_id.id_version, 0);
 	return ((uintptr_t)ofl->ofl_osverdef);
 }
 
@@ -2061,8 +2088,8 @@
 	 * symbol references are added.
 	 */
 	ofl->ofl_issunwdata1 = isec;
-	if ((osp = ld_place_section(ofl, isec, M_ID_DATA, 0)) ==
-	    (Os_desc *)S_ERROR)
+	osp = ld_place_section(ofl, isec, ld_targ.t_id.id_data, 0);
+	if (osp == (Os_desc *)S_ERROR)
 		return (S_ERROR);
 
 	if (!(osp->os_flags & FLG_OS_OUTREL)) {
@@ -2625,7 +2652,7 @@
 			return (S_ERROR);
 		if ((ofl->ofl_osversym = make_sym_sec(ofl,
 		    MSG_ORIG(MSG_SCN_SUNWVERSYM), SHT_SUNW_versym,
-		    M_ID_VERSION)) == (Os_desc*)S_ERROR)
+		    ld_targ.t_id.id_version)) == (Os_desc*)S_ERROR)
 			return (S_ERROR);
 	}
 
@@ -2635,7 +2662,7 @@
 	if (ofl->ofl_flags & FLG_OF_SYMINFO) {
 		if ((ofl->ofl_ossyminfo = make_sym_sec(ofl,
 		    MSG_ORIG(MSG_SCN_SUNWSYMINFO), SHT_SUNW_syminfo,
-		    M_ID_SYMINFO)) == (Os_desc *)S_ERROR)
+		    ld_targ.t_id.id_syminfo)) == (Os_desc *)S_ERROR)
 			return (S_ERROR);
 	}
 
@@ -2708,8 +2735,9 @@
 				return (S_ERROR);
 			if (make_dynsym(ofl) == S_ERROR)
 				return (S_ERROR);
-#if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
-			if (make_amd64_unwindhdr(ofl) == S_ERROR)
+#if	defined(_ELF64)
+			if ((ld_targ.t_uw.uw_make_unwindhdr != NULL) &&
+			    ((*ld_targ.t_uw.uw_make_unwindhdr)(ofl) == S_ERROR))
 				return (S_ERROR);
 #endif
 			if (make_dynsort(ofl) == S_ERROR)
@@ -2811,47 +2839,13 @@
 	shdr->sh_size = (Xword)size;
 	shdr->sh_flags |= SHF_WRITE;
 
-	if (ld_place_section(ofl, isec, M_ID_DATA, 0) == (Os_desc *)S_ERROR)
+	if (ld_place_section(ofl, isec, ld_targ.t_id.id_data, 0) ==
+	    (Os_desc *)S_ERROR)
 		return ((Is_desc *)S_ERROR);
 
 	return (isec);
 }
 
-/*
- * Define a set of templates for generating "void (*)(void)" function
- * definitions.
- */
-#if	defined(__i386) || defined(__amd64)
-#if	defined(__lint)
-static const uchar_t ret_template[] = { 0 };
-#else	/* __lint */
-#if	defined(_ELF64)
-#define	ret_template	ret64_template
-#else
-#define	ret_template	ret32_template
-#endif
-
-static const uchar_t ret32_template[] = {
-/* 0x00 */	0xc3				/* ret */
-};
-
-static const uchar_t ret64_template[] = {
-/* 0x00 */	0x55,				/* pushq  %rbp */
-/* 0x01 */	0x48, 0x8b, 0xec,		/* movq   %rsp,%rbp */
-/* 0x04 */	0x48, 0x8b, 0xe5,		/* movq   %rbp,%rsp */
-/* 0x07 */	0x5d,				/* popq   %rbp */
-/* 0x08 */	0xc3				/* ret */
-};
-#endif	/* __lint */
-
-#elif	defined(__sparc)
-static const uchar_t ret_template[] = {
-/* 0x00 */	0x81, 0xc3, 0xe0, 0x08,		/* retl */
-/* 0x04 */	0x01, 0x00, 0x00, 0x00		/* nop */
-};
-#else
-#error	unsupported architecture!
-#endif
 
 /*
  * Build an additional text section - used to back FUNC symbol definitions
@@ -2868,8 +2862,8 @@
 	 * Insure the size is sufficient to contain the minimum return
 	 * instruction.
 	 */
-	if (size < sizeof (ret_template))
-		size = sizeof (ret_template);
+	if (size < ld_targ.t_nf.nf_size)
+		size = ld_targ.t_nf.nf_size;
 
 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_TEXT), 0,
 	    &isec, &shdr, &data) == S_ERROR)
@@ -2879,12 +2873,18 @@
 	shdr->sh_size = (Xword)size;
 	shdr->sh_flags |= SHF_EXECINSTR;
 
-	/* Fill the buffer with the appropriate return instruction. */
+	/*
+	 * Fill the buffer with the appropriate return instruction.
+	 * Note that there is no need to swap bytes on a non-native,
+	 * link, as the data being copied is given in bytes.
+	 */
 	if ((data->d_buf = libld_calloc(size, 1)) == 0)
 		return ((Is_desc *)S_ERROR);
-	(void) memcpy(data->d_buf, ret_template, sizeof (ret_template));
-
-	if (ld_place_section(ofl, isec, M_ID_TEXT, 0) == (Os_desc *)S_ERROR)
+	(void) memcpy(data->d_buf, ld_targ.t_nf.nf_template,
+	    ld_targ.t_nf.nf_size);
+
+	if (ld_place_section(ofl, isec, ld_targ.t_id.id_text, 0) ==
+	    (Os_desc *)S_ERROR)
 		return ((Is_desc *)S_ERROR);
 
 	return (isec);
--- a/usr/src/cmd/sgs/libld/common/syms.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/syms.c	Tue Mar 18 09:17:00 2008 -0700
@@ -32,6 +32,9 @@
 /*
  * Symbol table management routines
  */
+
+#define	ELF_TARGET_AMD64
+
 #include	<stdio.h>
 #include	<string.h>
 #include	<debug.h>
@@ -78,7 +81,6 @@
     int symndx, Word shndx, const char *symsecname, const char *strsecname,
     Word *flags)
 {
-	const char	*regname;
 	Word		name = sym->st_name;
 
 	if (name) {
@@ -101,12 +103,16 @@
 	 * Determine if we're dealing with a register and if so validate it.
 	 * If it's a scratch register, a fabricated name will be returned.
 	 */
-	if ((regname = ld_is_regsym(ofl, ifl, sym, strs, symndx, shndx,
-	    symsecname, flags)) == (const char *)S_ERROR) {
-		return (0);
+	if (ld_targ.t_ms.ms_is_regsym != NULL) {
+		const char *regname = (*ld_targ.t_ms.ms_is_regsym)(ofl, ifl,
+		    sym, strs, symndx, shndx, symsecname, flags);
+
+		if (regname == (const char *)S_ERROR) {
+			return (0);
+		}
+		if (regname)
+			return (regname);
 	}
-	if (regname)
-		return (regname);
 
 	/*
 	 * If this isn't a register, but we have a global symbol with a null
@@ -123,6 +129,69 @@
 	return (strs + name);
 }
 
+
+/*
+ * For producing symbol names strings to use in error messages.
+ * If the symbol has a non-null name, then the string returned by
+ * this function is the output from demangle(), surrounded by
+ * single quotes. For null names, a descriptive string giving
+ * the symbol section and index is generated.
+ *
+ * This function uses an internal static buffer to hold the resulting
+ * string. The value returned is usable by the caller until the next
+ * call, at which point it is overwritten.
+ */
+static const char *
+demangle_symname(const char *name, const char *symtab_name, Word symndx)
+{
+#define	INIT_BUFSIZE 256
+
+	static char *buf;
+	static size_t bufsize = 0;
+
+	size_t		len;
+	int		use_name;
+
+
+	use_name = (name != NULL) && (*name != '\0');
+
+	if (use_name) {
+		name = demangle(name);
+		len = strlen(name) + 2;   /* Include room for quotes */
+	} else {
+		name = MSG_ORIG(MSG_STR_EMPTY);
+		len = strlen(symtab_name) + 2 + CONV32_INV_BUFSIZE;
+	}
+	len++;			/* Null termination */
+
+	/* If our buffer is too small, double it until it is big enough */
+	if (len > bufsize) {
+		size_t	new_bufsize = bufsize;
+		char	*new_buf;
+
+		if (new_bufsize == 0)
+			new_bufsize = INIT_BUFSIZE;
+		while (len > new_bufsize)
+			new_bufsize *= 2;
+		new_buf = libld_malloc(new_bufsize);
+		if (new_buf == NULL)
+			return (name);
+		buf = new_buf;
+		bufsize = new_bufsize;
+	}
+
+	if (use_name) {
+		(void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_SYMNAM), name);
+	} else {
+		(void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_NULLSYMNAM),
+		    symtab_name, EC_WORD(symndx));
+	}
+
+	return (buf);
+
+#undef INIT_BUFSIZE
+}
+
 /*
  * Shared objects can be built that define specific symbols that can not be
  * directly bound to.  These objects have a syminfo section (and an associated
@@ -356,8 +425,9 @@
 	if (sdflags & FLG_SY_SPECSEC) {
 		if (nsym->st_shndx == SHN_COMMON)
 			sdp->sd_flags |= FLG_SY_TENTSYM;
-#if	defined(__x86) && defined(_ELF64)
-		else if (nsym->st_shndx == SHN_X86_64_LCOMMON)
+#if	defined(_ELF64)
+		else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
+		    (nsym->st_shndx == SHN_X86_64_LCOMMON))
 			sdp->sd_flags |= FLG_SY_TENTSYM;
 #endif
 	}
@@ -464,9 +534,10 @@
 	if ((etype == ET_REL) &&
 	    (ELF_ST_BIND(nsym->st_info) == STB_GLOBAL) &&
 	    ((nsym->st_shndx == SHN_UNDEF) || ((sdflags & FLG_SY_SPECSEC) &&
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)
 	    ((nsym->st_shndx == SHN_COMMON) ||
-	    (nsym->st_shndx == SHN_X86_64_LCOMMON)))))
+	    ((ld_targ.t_m.m_mach == EM_AMD64) &&
+	    (nsym->st_shndx == SHN_X86_64_LCOMMON))))))
 #else
 	/* BEGIN CSTYLED */
 	    (nsym->st_shndx == SHN_COMMON))))
@@ -1022,7 +1093,7 @@
 	Word		undef = 0, needed = 0, verdesc = 0;
 	Xword		bssalign = 0, tlsalign = 0;
 	Xword		bsssize = 0, tlssize = 0;
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)
 	Xword		lbssalign = 0, lbsssize = 0;
 #endif
 	int		ret;
@@ -1381,13 +1452,14 @@
 			}
 		}
 
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)
 		/*
 		 * Calculate the size and alignment requirement for the global
 		 * .lbss. TLS or partially initialized symbols do not need to be
 		 * considered yet.
 		 */
-		if (sym->st_shndx == SHN_X86_64_LCOMMON) {
+		if ((ld_targ.t_m.m_mach == EM_AMD64) &&
+		    (sym->st_shndx == SHN_X86_64_LCOMMON)) {
 			lbsssize = (Xword)S_ROUND(lbsssize, sym->st_value) +
 			    sym->st_size;
 			if (sym->st_value > lbssalign)
@@ -1529,8 +1601,9 @@
 		if (ld_make_bss(ofl, tlssize, tlsalign, MAKE_TLS) == S_ERROR)
 			return (S_ERROR);
 	}
-#if	defined(__x86) && defined(_ELF64)
-	if (lbsssize && !(oflags & FLG_OF_RELOBJ)) {
+#if	defined(_ELF64)
+	if ((ld_targ.t_m.m_mach == EM_AMD64) &&
+	    lbsssize && !(oflags & FLG_OF_RELOBJ)) {
 		if (ld_make_bss(ofl, lbsssize, lbssalign, MAKE_LBSS) == S_ERROR)
 			return (S_ERROR);
 	}
@@ -1844,14 +1917,19 @@
 			Word		shndx, sdflags = FLG_SY_CLEAN;
 			const char	*name;
 			Sym_desc	*rsdp;
+			int		shndx_bad = 0;
 
 			/*
-			 * Determine the associated section index.
+			 * Determine and validate the associated section index.
 			 */
-			if (symshndx && (sym->st_shndx == SHN_XINDEX))
+			if (symshndx && (sym->st_shndx == SHN_XINDEX)) {
 				shndx = symshndx[ndx];
-			else if ((shndx = sym->st_shndx) >= SHN_LORESERVE)
+			} else if ((shndx = sym->st_shndx) >= SHN_LORESERVE) {
 				sdflags |= FLG_SY_SPECSEC;
+			} else if (shndx > ifl->ifl_ehdr->e_shnum) {
+				/* We need the name before we can issue error */
+				shndx_bad = 1;
+			}
 
 			/*
 			 * Check if st_name has a valid value or not.
@@ -1863,6 +1941,19 @@
 			}
 
 			/*
+			 * Now that we have the name, if the section index
+			 * was bad, report it.
+			 */
+			if (shndx_bad) {
+				eprintf(ofl->ofl_lml, ERR_WARNING,
+				    MSG_INTL(MSG_SYM_INVSHNDX),
+				    demangle_symname(name, isc->is_name, ndx),
+				    ifl->ifl_name,
+				    conv_sym_shndx(sym->st_shndx, &inv_buf));
+				continue;
+			}
+
+			/*
 			 * If this local symbol table originates from a shared
 			 * object, then we're only interested in recording
 			 * register symbols.  As local symbol descriptors aren't
@@ -1873,15 +1964,20 @@
 			 */
 			rsdp = sdp = 0;
 			if (sdflags & FLG_SY_REGSYM) {
-				if ((rsdp = ld_reg_find(sym, ofl)) != 0) {
+				/*
+				 * The presence of FLG_SY_REGSYM means that
+				 * the pointers in ld_targ.t_ms are non-NULL.
+				 */
+				rsdp = (*ld_targ.t_ms.ms_reg_find)(sym, ofl);
+				if (rsdp != 0) {
 					/*
 					 * The fact that another register def-
 					 * inition has been found is fatal.
 					 * Call the verification routine to get
 					 * the error message and move on.
 					 */
-					(void) ld_reg_check(rsdp, sym, name,
-					    ifl, ofl);
+					(void) (*ld_targ.t_ms.ms_reg_check)
+					    (rsdp, sym, name, ifl, ofl);
 					continue;
 				}
 
@@ -1936,9 +2032,13 @@
 				/*
 				 * If this register symbol hasn't already been
 				 * recorded, enter it now.
+				 *
+				 * The presence of FLG_SY_REGSYM means that
+				 * the pointers in ld_targ.t_ms are non-NULL.
 				 */
 				if ((rsdp == 0) &&
-				    (ld_reg_enter(sdp, ofl) == 0))
+				    ((*ld_targ.t_ms.ms_reg_enter)(sdp, ofl) ==
+				    0))
 					return (S_ERROR);
 			}
 
@@ -1969,8 +2069,8 @@
 				if (sym->st_shndx == SHN_UNDEF) {
 					eprintf(ofl->ofl_lml, ERR_WARNING,
 					    MSG_INTL(MSG_SYM_INVSHNDX),
-					    demangle(sdp->sd_name),
-					    ifl->ifl_name,
+					    demangle_symname(name, isc->is_name,
+					    ndx), ifl->ifl_name,
 					    conv_sym_shndx(sym->st_shndx,
 					    &inv_buf));
 				}
@@ -2022,7 +2122,8 @@
 			    (sdp->sd_isc && (sdp->sd_isc->is_osdesc == 0))) {
 				eprintf(ofl->ofl_lml, ERR_WARNING,
 				    MSG_INTL(MSG_SYM_INVSHNDX),
-				    demangle(sdp->sd_name), ifl->ifl_name,
+				    demangle_symname(name, isc->is_name, ndx),
+				    ifl->ifl_name,
 				    conv_sym_shndx(sym->st_shndx, &inv_buf));
 				sdp->sd_isc = NULL;
 				sdp->sd_flags |= FLG_SY_INVALID;
@@ -2080,16 +2181,18 @@
 	for (ndx = (int)local; ndx < total; sym++, ndx++) {
 		const char	*name;
 		Word		shndx, sdflags = 0;
+		int		shndx_bad = 0;
 
 		/*
-		 * Determine the associated section index.
+		 * Determine and validate the associated section index.
 		 */
 		if (symshndx && (sym->st_shndx == SHN_XINDEX)) {
 			shndx = symshndx[ndx];
-		} else {
-			shndx = sym->st_shndx;
-			if (sym->st_shndx >= SHN_LORESERVE)
-				sdflags |= FLG_SY_SPECSEC;
+		} else if ((shndx = sym->st_shndx) >= SHN_LORESERVE) {
+			sdflags |= FLG_SY_SPECSEC;
+		} else if (shndx > ifl->ifl_ehdr->e_shnum) {
+			/* We need the name before we can issue error */
+			shndx_bad = 1;
 		}
 
 		/*
@@ -2102,6 +2205,20 @@
 		}
 
 		/*
+		 * Now that we have the name, if the section index
+		 * was bad, report it.
+		 */
+		if (shndx_bad) {
+			eprintf(ofl->ofl_lml, ERR_WARNING,
+			    MSG_INTL(MSG_SYM_INVSHNDX),
+			    demangle_symname(name, isc->is_name, ndx),
+			    ifl->ifl_name,
+			    conv_sym_shndx(sym->st_shndx, &inv_buf));
+			continue;
+		}
+
+
+		/*
 		 * Test for the GNU hidden bit, and ignore symbols that
 		 * have it set.
 		 */
@@ -2136,7 +2253,8 @@
 		bind = ELF_ST_BIND(sym->st_info);
 		if ((bind != STB_GLOBAL) && (bind != STB_WEAK)) {
 			eprintf(ofl->ofl_lml, ERR_WARNING,
-			    MSG_INTL(MSG_SYM_NONGLOB), demangle(name),
+			    MSG_INTL(MSG_SYM_NONGLOB),
+			    demangle_symname(name, isc->is_name, ndx),
 			    ifl->ifl_name,
 			    conv_sym_info_bind(bind, 0, &inv_buf));
 			continue;
@@ -2158,7 +2276,8 @@
 				 * unless a relocation is required against it.
 				 */
 				eprintf(ofl->ofl_lml, ERR_WARNING,
-				    MSG_INTL(MSG_SYM_INVSHNDX), demangle(name),
+				    MSG_INTL(MSG_SYM_INVSHNDX),
+				    demangle_symname(name, isc->is_name, ndx),
 				    ifl->ifl_name,
 				    conv_sym_shndx(sym->st_shndx, &inv_buf));
 				continue;
@@ -2229,12 +2348,17 @@
 		if (sdp->sd_flags & FLG_SY_REGSYM) {
 			Sym_desc	*rsdp;
 
-			if ((rsdp = ld_reg_find(sdp->sd_sym, ofl)) == 0) {
-				if (ld_reg_enter(sdp, ofl) == 0)
+			/*
+			 * The presence of FLG_SY_REGSYM means that
+			 * the pointers in ld_targ.t_ms are non-NULL.
+			 */
+			rsdp = (*ld_targ.t_ms.ms_reg_find)(sdp->sd_sym, ofl);
+			if (rsdp == 0) {
+				if ((*ld_targ.t_ms.ms_reg_enter)(sdp, ofl) == 0)
 					return (S_ERROR);
 			} else if (rsdp != sdp) {
-				(void) ld_reg_check(rsdp, sdp->sd_sym,
-				    sdp->sd_name, ifl, ofl);
+				(void) (*ld_targ.t_ms.ms_reg_check)(rsdp,
+				    sdp->sd_sym, sdp->sd_name, ifl, ofl);
 			}
 		}
 
--- a/usr/src/cmd/sgs/libld/common/unwind.amd.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/unwind.amd.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,20 +20,23 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+#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	<sys/elf_amd64.h>
 #include	<dwarf.h>
 #include	<stdlib.h>
+#include	"unwind.amd.h"
 
 /*
  * A EH_FRAME_HDR consists of the following:
@@ -170,7 +173,7 @@
  *  6. Data Align Factor      sleb128    To be multiplied with all offset
  *                                       in the Call Frame Instructions
  *
- *  7. Ret Address Reg          1        A "virtual' register representation
+ *  7. Ret Address Reg          1        A "virtual" register representation
  *                                       of the return address. In Dwarf V2,
  *                                       this is a byte, otherwise it is
  *                                       uleb128. It is a byte in gcc 3.3.x
@@ -392,6 +395,7 @@
 					 */
 					cieversion = data[off + ndx];
 					ndx += 1;
+					/* BEGIN CSTYLED */
 					if (cieversion != 1) {
 					    eprintf(ofl->ofl_lml, ERR_FATAL,
 						MSG_INTL(MSG_UNW_BADCIEVERS),
@@ -399,8 +403,10 @@
 						isp->is_name, off);
 					    return (S_ERROR);
 					}
-				} else
+					/* END CSTYLED */
+				} else {
 					fde_cnt++;
+				}
 				off += length + 4;
 			}
 		}
@@ -461,16 +467,17 @@
 uintptr_t
 populate_amd64_unwindhdr(Ofl_desc *ofl)
 {
-	unsigned char	    *hdrdata;
-	uint_t		    *binarytable;
-	uint_t		    hdroff;
-	Listnode	    *lnp;
-	Addr		    hdraddr;
-	Os_desc		    *hdrosp;
-	Os_desc		    *osp;
-	Os_desc		    *first_unwind;
-	uint_t		    fde_count;
-	uint_t		    *uint_ptr;
+	unsigned char	*hdrdata;
+	uint_t		*binarytable;
+	uint_t		hdroff;
+	Listnode	*lnp;
+	Addr		hdraddr;
+	Os_desc		*hdrosp;
+	Os_desc		*osp;
+	Os_desc		*first_unwind;
+	uint_t		fde_count;
+	uint_t		*uint_ptr;
+	int		bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
 
 	/*
 	 * Are we building the unwind hdr?
@@ -595,6 +602,7 @@
 				 */
 				for (cieaugndx = 0; cieaugstr[cieaugndx];
 				    cieaugndx++) {
+					/* BEGIN CSTYLED */
 					switch (cieaugstr[cieaugndx]) {
 					case 'z':
 					    /* size */
@@ -626,6 +634,7 @@
 					    fndx++;
 					    break;
 					}
+					/* END CSTYLED */
 				}
 			} else {
 				uint_t	    bintabndx;
@@ -645,10 +654,10 @@
 				initloc = dwarf_ehe_extract(&fdata[foff],
 				    &fndx, cieRflag, ofl->ofl_dehdr->e_ident,
 				    shdr->sh_addr + foff + fndx);
-				binarytable[bintabndx] = (uint_t)(initloc -
-					hdraddr);
-				binarytable[bintabndx + 1] = (uint_t)(fdeaddr -
-					hdraddr);
+				binarytable[bintabndx] =
+				    (uint_t)(initloc - hdraddr);
+				binarytable[bintabndx + 1] =
+				    (uint_t)(fdeaddr - hdraddr);
 			}
 
 			/*
@@ -660,11 +669,21 @@
 	}
 
 	/*
-	 * Do a quick sort on the binary table
+	 * Do a quick sort 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.
 	 */
 	framehdr_addr = hdraddr;
 	qsort((void *)binarytable, (size_t)fde_count,
-		(size_t)(sizeof (uint_t) * 2), bintabcompare);
+	    (size_t)(sizeof (uint_t) * 2), bintabcompare);
+	if (bswap) {
+		uint_t	*btable = binarytable;
+		uint_t	cnt;
+
+		for (cnt = fde_count * 2; cnt-- > 0; btable++)
+			*btable = ld_bswap_Word(*btable);
+	}
+
 	/*
 	 * Fill in:
 	 *	first_frame_ptr
@@ -674,12 +693,16 @@
 	/* 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);
 
 	hdroff += 4;
 	/* LINTED */
 	uint_ptr = (uint_t *)&hdrdata[hdroff];
 	*uint_ptr = fde_count;
+	if (bswap)
+		*uint_ptr = ld_bswap_Word(*uint_ptr);
 
 	return (1);
 }
@@ -695,12 +718,12 @@
 	 */
 	for (LIST_TRAVERSE(&ofl->ofl_unwind, lnp, _osp))
 		if (osp == _osp)
-		    return (1);
+			return (1);
 
 	/*
 	 * Append output section to unwind list
 	 */
 	if (list_appendc(&ofl->ofl_unwind, osp) == 0)
-	    return (S_ERROR);
+		return (S_ERROR);
 	return (1);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/libld/common/unwind.amd.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,49 @@
+/*
+ * 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 */
--- a/usr/src/cmd/sgs/libld/common/update.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/common/update.c	Tue Mar 18 09:17:00 2008 -0700
@@ -33,6 +33,9 @@
  * displacement calculations on the program headers and sections headers,
  * and generate any new output section information.
  */
+
+#define	ELF_TARGET_AMD64
+
 #include	<stdio.h>
 #include	<string.h>
 #include	<unistd.h>
@@ -180,7 +183,7 @@
 	Word		bssndx, etext_ndx, edata_ndx = 0, end_ndx, start_ndx;
 	Word		end_abs = 0, etext_abs = 0, edata_abs;
 	Word		tlsbssndx = 0, sunwbssndx = 0, sunwdata1ndx;
-#if	defined(__x86) && defined(_ELF64)
+#if	defined(_ELF64)
 	Word		lbssndx = 0;
 	Addr		lbssaddr = 0;
 #endif
@@ -643,17 +646,13 @@
 			sdp = ifl->ifl_oldndx[lndx];
 			sym = sdp->sd_sym;
 
-#if	defined(__sparc)
 			/*
 			 * Assign a got offset if necessary.
 			 */
-			if (ld_assign_got(ofl, sdp) == S_ERROR)
+			if ((ld_targ.t_mr.mr_assign_got != NULL) &&
+			    (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR)
 				return ((Addr)S_ERROR);
-#elif	defined(__x86)
-/* nothing to do */
-#else
-#error Unknown architecture!
-#endif
+
 			if (DBG_ENABLED) {
 				for (LIST_TRAVERSE(&sdp->sd_GOTndxs,
 				    lnp2, gnp)) {
@@ -897,11 +896,12 @@
 		bssndx = elf_ndxscn(osp->os_scn);
 	}
 
-#if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
+#if	defined(_ELF64)
 	/*
-	 * Assign .lbss information for use with updating LCOMMON symbols.
+	 * For amd64 target, assign .lbss information for use
+	 * with updating LCOMMON symbols.
 	 */
-	if (ofl->ofl_islbss) {
+	if ((ld_targ.t_m.m_mach == EM_AMD64) && ofl->ofl_islbss) {
 		osp = ofl->ofl_islbss->is_osdesc;
 
 		lbssaddr = osp->os_shdr->sh_addr +
@@ -1063,8 +1063,9 @@
 				 */
 				symptr->st_value -= ofl->ofl_tlsphdr->p_vaddr;
 			}
-#if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
-		} else if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
+#if	defined(_ELF64)
+		} else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
+		    (sdp->sd_flags & FLG_SY_SPECSEC) &&
 		    ((sdp->sd_shndx = symptr->st_shndx) ==
 		    SHN_X86_64_LCOMMON) &&
 		    ((local || !(flags & FLG_OF_RELOBJ)))) {
@@ -1125,14 +1126,9 @@
 		/*
 		 * Assign a got offset if necessary.
 		 */
-#if	defined(__sparc)
-		if (ld_assign_got(ofl, sdp) == S_ERROR)
+		if ((ld_targ.t_mr.mr_assign_got != NULL) &&
+		    (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR)
 			return ((Addr)S_ERROR);
-#elif	defined(__x86)
-/* nothing to do */
-#else
-#error Unknown architecture!
-#endif
 
 		if (DBG_ENABLED) {
 			for (LIST_TRAVERSE(&sdp->sd_GOTndxs, lnp2, gnp)) {
@@ -1691,7 +1687,8 @@
 		    (ELF_ST_TYPE(sym->st_info) == STT_FUNC) &&
 		    !(flags & FLG_OF_BFLAG)) {
 			if (sap->sa_PLTndx)
-				sym->st_value = ld_calc_plt_addr(sdp, ofl);
+				sym->st_value =
+				    (*ld_targ.t_mr.mr_calc_plt_addr)(sdp, ofl);
 		}
 
 		/*
@@ -1833,7 +1830,8 @@
 	/*
 	 * Now display GOT debugging information if required.
 	 */
-	DBG_CALL(Dbg_got_display(ofl, 0, 0));
+	DBG_CALL(Dbg_got_display(ofl, 0, 0,
+	    ld_targ.t_m.m_got_xnumber, ld_targ.t_m.m_got_entsize));
 
 	/*
 	 * Update the section headers information. sh_info is
@@ -2223,7 +2221,7 @@
 		}
 
 		if ((ofl->ofl_flags & FLG_OF_COMREL) && ofl->ofl_relocrelcnt) {
-			dyn->d_tag = M_REL_DT_COUNT;
+			dyn->d_tag = ld_targ.t_m.m_rel_dt_count;
 			dyn->d_un.d_val = ofl->ofl_relocrelcnt;
 			dyn++;
 		}
@@ -2280,7 +2278,7 @@
 			dyn->d_un.d_ptr = shdr->sh_size;
 			dyn++;
 			dyn->d_tag = DT_PLTREL;
-			dyn->d_un.d_ptr = M_REL_DT_TYPE;
+			dyn->d_un.d_ptr = ld_targ.t_m.m_rel_dt_type;
 			dyn++;
 			dyn->d_tag = DT_JMPREL;
 			dyn->d_un.d_ptr = shdr->sh_addr;
@@ -2292,23 +2290,24 @@
 			dyn->d_tag = DT_PLTPAD;
 			if (ofl->ofl_pltcnt) {
 				dyn->d_un.d_ptr = shdr->sh_addr +
-				    M_PLT_RESERVSZ +
-				    ofl->ofl_pltcnt * M_PLT_ENTSIZE;
+				    ld_targ.t_m.m_plt_reservsz +
+				    ofl->ofl_pltcnt * ld_targ.t_m.m_plt_entsize;
 			} else
 				dyn->d_un.d_ptr = shdr->sh_addr;
 			dyn++;
 			dyn->d_tag = DT_PLTPADSZ;
-			dyn->d_un.d_val = ofl->ofl_pltpad * M_PLT_ENTSIZE;
+			dyn->d_un.d_val = ofl->ofl_pltpad *
+			    ld_targ.t_m.m_plt_entsize;
 			dyn++;
 		}
 		if (ofl->ofl_relocsz) {
-			dyn->d_tag = M_REL_DT_TYPE;
+			dyn->d_tag = ld_targ.t_m.m_rel_dt_type;
 			dyn->d_un.d_ptr = ofl->ofl_osrelhead->os_shdr->sh_addr;
 			dyn++;
-			dyn->d_tag = M_REL_DT_SIZE;
+			dyn->d_tag = ld_targ.t_m.m_rel_dt_size;
 			dyn->d_un.d_ptr = ofl->ofl_relocsz;
 			dyn++;
-			dyn->d_tag = M_REL_DT_ENT;
+			dyn->d_tag = ld_targ.t_m.m_rel_dt_ent;
 			if (ofl->ofl_osrelhead->os_shdr->sh_type == SHT_REL)
 				dyn->d_un.d_ptr = sizeof (Rel);
 			else
@@ -2348,7 +2347,7 @@
 				if ((sdp = ofl->ofl_regsyms[ndx]) == 0)
 					continue;
 
-				dyn->d_tag = M_DT_REGISTER;
+				dyn->d_tag = ld_targ.t_m.m_dt_register;
 				dyn->d_un.d_val = sdp->sd_symndx;
 				dyn++;
 			}
@@ -2411,7 +2410,11 @@
 	dyn->d_un.d_val = DYNSTR_EXTRA_PAD;
 	dyn++;
 
-	ld_mach_update_odynamic(ofl, &dyn);
+	dyn->d_tag = DT_SUNW_LDMACH;
+	dyn->d_un.d_val = ld_sunw_ldmach();
+	dyn++;
+
+	(*ld_targ.t_mr.mr_mach_update_odynamic)(ofl, &dyn);
 
 	for (cnt = 1 + DYNAMIC_EXTRA_ELTS; cnt--; dyn++) {
 		dyn->d_tag = DT_NULL;
@@ -2794,15 +2797,15 @@
 	 * Note. it may be necessary to update the `e_flags' field in the
 	 * machine dependent section.
 	 */
-	ehdr->e_ident[EI_DATA] = M_DATA;
+	ehdr->e_ident[EI_DATA] = ld_targ.t_m.m_data;
 	ehdr->e_machine = ofl->ofl_dehdr->e_machine;
 	ehdr->e_flags = ofl->ofl_dehdr->e_flags;
 	ehdr->e_version = ofl->ofl_dehdr->e_version;
 
-	if (ehdr->e_machine != M_MACH) {
-		if (ehdr->e_machine != M_MACHPLUS)
+	if (ehdr->e_machine != ld_targ.t_m.m_mach) {
+		if (ehdr->e_machine != ld_targ.t_m.m_machplus)
 			return (S_ERROR);
-		if ((ehdr->e_flags & M_FLAGSPLUS) == 0)
+		if ((ehdr->e_flags & ld_targ.t_m.m_flagsplus) == 0)
 			return (S_ERROR);
 	}
 
@@ -3284,7 +3287,7 @@
 				phdr->p_vaddr = shdr->sh_addr;
 				phdr->p_offset = shdr->sh_offset;
 				phdr->p_filesz = shdr->sh_size;
-				phdr->p_flags = M_DATASEG_PERM;
+				phdr->p_flags = ld_targ.t_m.m_dataseg_perm;
 
 				DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
 				ofl->ofl_phdr[phdrndx++] = *phdr;
@@ -3298,8 +3301,9 @@
 		 * information for the .eh_frame output section will have been
 		 * figured out by now.
 		 */
-#if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
-		if (phdr->p_type == PT_SUNW_UNWIND) {
+#if	defined(_ELF64)
+		if ((ld_targ.t_m.m_mach == EM_AMD64) &&
+		    (phdr->p_type == PT_SUNW_UNWIND)) {
 			Shdr	    *shdr;
 
 			if (ofl->ofl_unwindhdr == 0)
--- a/usr/src/cmd/sgs/libld/i386/Makefile	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/i386/Makefile	Tue Mar 18 09:17:00 2008 -0700
@@ -20,67 +20,19 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
 
-E_TOOLOBJS =	leb128.o
-L_MACHOBJS32 =	machrel.intel32.o	machsym.intel32.o
-L_MACHOBJS64 =	machrel.amd64.o		machsym.intel64.o	unwind.amd64.o
-
 include		../Makefile.com
 
 .KEEP_STATE:
 
-SGSMSGCHK =	../common/libld.chk.msg
-SGSMSGTARG +=	$(SGSMSGINTEL)
-
-#
-# For cross-compilation, it is necessary to trigger the correct include files
-# (see sys/elf.h).
-#
-ELFTARGET64 =	-DELF_TARGET_AMD64
-ELFTARGET32 =	-DELF_TARGET_386
-
 all:		$(DYNLIB) $(LIBLINKS)
 
 install \
 package:	all $(ROOTFS_DYNLIB)
 
 include		../Makefile.targ
-
-# Associate ELF32 and ELF64 objects to the appropriate headers.
-
-pics/%32.o :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld
-pics/%64.o :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld
-
-# Associate the various lint targets with the appropriate headers/files.
-
-$(LINTOUT32) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld \
-		    $(ELFTARGET32)
-$(LINTOUT64) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld \
-		    $(ELFTARGET64) -D_ELF64
-$(LINTLIB32) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld \
-		    $(ELFTARGET32)
-$(LINTLIB64) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld \
-		    $(ELFTARGET64) -D_ELF64
-
-LINTSRCS32 +=	$(G_MACHOBJS32:%32.o=$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld/%.c)
-LINTSRCS64 +=	$(G_MACHOBJS64:%64.o=$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld/%.c)
-
-# Compensate chkmsg with the doreloc family.
-
-CHKSRCS +=	$(G_MACHOBJS32:%32.o=$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld/%.c)
-CHKSRCS +=	$(G_MACHOBJS64:%64.o=$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld/%.c)
-
-pics/%32.o: \
-		$(SRCBASE)/uts/$(VAR_PLAT_i386)/krtld/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET32) $<
-		$(POST_PROCESS_O)
-
-pics/%64.o: \
-		$(SRCBASE)/uts/$(VAR_PLAT_amd64)/krtld/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET64) -D_ELF64 $<
-		$(POST_PROCESS_O)
--- a/usr/src/cmd/sgs/libld/sparc/Makefile	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/sparc/Makefile	Tue Mar 18 09:17:00 2008 -0700
@@ -20,58 +20,19 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
 
-L_MACHOBJS32 =	machrel.sparc32.o	machsym.sparc32.o
-L_MACHOBJS64 =	machrel.sparc64.o	machsym.sparc64.o
-
 include		../Makefile.com
 
 .KEEP_STATE:
 
-SGSMSGTARG +=	$(SGSMSGSPARC)
-
 all:		$(DYNLIB) $(LIBLINKS)
 
 install \
 package:	all $(ROOTFS_DYNLIB)
 
 include		../Makefile.targ
-
-# Associate ELF32 and ELF64 objects to the appropriate headers.
-
-pics/%32.o :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld
-pics/%64.o :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld
-
-# Associate the various lint targets with the appropriate headers/files.
-
-$(LINTOUT32) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld \
-		    $(ELFTARGET32)
-$(LINTOUT64) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld \
-		    $(ELFTARGET64) -D_ELF64
-$(LINTLIB32) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld \
-		    $(ELFTARGET32)
-$(LINTLIB64) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld \
-		    $(ELFTARGET64) -D_ELF64
-
-LINTSRCS32 +=	$(G_MACHOBJS32:%32.o=$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c)
-LINTSRCS64 +=	$(G_MACHOBJS64:%64.o=$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c)
-
-# Compensate chkmsg with the doreloc family.
-
-CHKSRCS +=	$(G_MACHOBJS32:%32.o=$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c)
-CHKSRCS +=	$(G_MACHOBJS64:%64.o=$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c)
-
-pics/%32.o: \
-		$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET32) $<
-		$(POST_PROCESS_O)
-
-pics/%64.o: \
-		$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET64) -D_ELF64 $<
-		$(POST_PROCESS_O)
--- a/usr/src/cmd/sgs/libld/sparcv9/Makefile	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/libld/sparcv9/Makefile	Tue Mar 18 09:17:00 2008 -0700
@@ -20,15 +20,12 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
 
-L_MACHOBJS32 =	machrel.sparc32.o	machsym.sparc32.o
-L_MACHOBJS64 =	machrel.sparc64.o	machsym.sparc64.o
-
 include		../Makefile.com
 
 .KEEP_STATE:
@@ -38,8 +35,6 @@
 ROOTFS_DYNLIB64 = \
 		$(DYNLIB:%=$(ROOTFS_LIBDIR64)/%)
 
-SGSMSGTARG +=	$(SGSMSGSPARC)
-
 ELFLIBDIR =	$(ELFLIBDIR64)
 LDDBGLIBDIR =	$(LDDBGLIBDIR64)
 CONVLIBDIR =	$(CONVLIBDIR64)
@@ -53,37 +48,3 @@
 
 include		../Makefile.targ
 include		../../Makefile.sub.64
-
-# Associate ELF32 and ELF64 objects to the appropriate headers.
-
-pics/%32.o :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld
-pics/%64.o :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld
-
-# Associate the various lint targets with the appropriate headers/files.
-
-$(LINTOUT32) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld \
-		    $(ELFTARGET32)
-$(LINTOUT64) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld \
-		    $(ELFTARGET64) -D_ELF64
-$(LINTLIB32) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld \
-		    $(ELFTARGET32)
-$(LINTLIB64) :=	CPPFLAGS += -I$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld \
-		    $(ELFTARGET64) -D_ELF64
-
-LINTSRCS32 +=	$(G_MACHOBJS32:%32.o=$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c)
-LINTSRCS64 +=	$(G_MACHOBJS64:%64.o=$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c)
-
-# Compensate chkmsg with the doreloc family.
-
-CHKSRCS +=	$(G_MACHOBJS32:%32.o=$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c)
-CHKSRCS +=	$(G_MACHOBJS64:%64.o=$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c)
-
-pics/%32.o: \
-		$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET32) $<
-		$(POST_PROCESS_O)
-
-pics/%64.o: \
-		$(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld/%.c
-		$(COMPILE.c) -o $@ $(ELFTARGET64) -D_ELF64 $<
-		$(POST_PROCESS_O)
--- a/usr/src/cmd/sgs/liblddbg/common/files.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/files.c	Tue Mar 18 09:17:00 2008 -0700
@@ -672,7 +672,7 @@
 };
 
 void
-Dbg_file_rejected(Lm_list *lml, Rej_desc *rej)
+Dbg_file_rejected(Lm_list *lml, Rej_desc *rej, Half mach)
 {
 	Conv_reject_desc_buf_t rej_buf;
 
@@ -682,7 +682,7 @@
 	Dbg_util_nl(lml, DBG_NL_STD);
 	dbg_print(lml, MSG_INTL(reject[rej->rej_type]), rej->rej_name ?
 	    rej->rej_name : MSG_INTL(MSG_STR_UNKNOWN),
-	    conv_reject_desc(rej, &rej_buf));
+	    conv_reject_desc(rej, &rej_buf, mach));
 	Dbg_util_nl(lml, DBG_NL_STD);
 }
 
--- a/usr/src/cmd/sgs/liblddbg/common/got.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/got.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -46,7 +46,8 @@
 }
 
 void
-Dbg_got_display(Ofl_desc *ofl, Off goff, int stage)
+Dbg_got_display(Ofl_desc *ofl, Off goff, int stage,
+    Word m_got_xnumber, size_t m_got_entsize)
 {
 	Lm_list		*lml = ofl->ofl_lml;
 	Gottable	*gtp = ofl->ofl_gottable;
@@ -56,7 +57,7 @@
 	if (DBG_NOTCLASS(DBG_C_GOT))
 		return;
 
-	if (ofl->ofl_gotcnt == M_GOT_XNumber)
+	if (ofl->ofl_gotcnt == m_got_xnumber)
 		return;
 
 	Dbg_util_nl(lml, DBG_NL_STD);
@@ -80,7 +81,7 @@
 		const char	*refstr, *name;
 		Gotndx		*gnp = &gtp->gt_gndx;
 		Lword		gotaddval;
-		Off		off = goff + (gotndx * M_GOT_ENTSIZE);
+		Off		off = goff + (gotndx * m_got_entsize);
 		char		index[INDEX_STR_SIZE];
 
 		(void) snprintf(index, INDEX_STR_SIZE, MSG_ORIG(MSG_GOT_INDEX),
@@ -125,7 +126,8 @@
 
 void
 Elf_got_entry(Lm_list *lml, Sword ndx, Addr addr, Xword value, Half mach,
-    Word type, void *reloc, const char *name)
+    uchar_t ei_target_data, uchar_t ei_host_data, Word type, void *reloc,
+    const char *name)
 {
 	Rela		*rela;
 	Rel		*rel;
@@ -136,15 +138,24 @@
 	(void) snprintf(index, INDEX_STR_SIZE, MSG_ORIG(MSG_GOT_INDEX),
 	    EC_SWORD(ndx));
 
+	/*
+	 * Got sections are SHT_PROGBITS, and are therefore not xlated by
+	 * libelf. If the target system has a different byte order than
+	 * the system displaying the data, swap the bytes so they are
+	 * presented properly.
+	 */
+	if (ei_target_data != ei_host_data)
+		value = BSWAP_XWORD(value);
+
 	if (reloc) {
 		if (type == SHT_RELA) {
 			rela = (Rela *)reloc;
-			str = conv_reloc_type(mach, ELF_R_TYPE(rela->r_info),
-			    0, &inv_buf);
+			str = conv_reloc_type(mach,
+			    ELF_R_TYPE(rela->r_info, mach), 0, &inv_buf);
 		} else {
 			rel = (Rel *)reloc;
-			str = conv_reloc_type(mach, ELF_R_TYPE(rel->r_info),
-			    0, &inv_buf);
+			str = conv_reloc_type(mach,
+			    ELF_R_TYPE(rel->r_info, mach), 0, &inv_buf);
 		}
 
 		if (name)
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg	Tue Mar 18 09:17:00 2008 -0700
@@ -22,7 +22,7 @@
 /* PROTOLIB1 */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -148,15 +148,17 @@
 void	Dbg64_file_preload(Lm_list *, const char *);
 void	Dbg32_file_prot(Rt_map *, int);
 void	Dbg64_file_prot(Rt_map *, int);
-void	Dbg32_file_rejected(Lm_list *, Rej_desc *);
-void	Dbg64_file_rejected(Lm_list *, Rej_desc *);
+void	Dbg32_file_rejected(Lm_list *, Rej_desc *, Elf32_Half);
+void	Dbg64_file_rejected(Lm_list *, Rej_desc *, Elf32_Half);
 void	Dbg32_file_reuse(Lm_list *, const char *, const char *);
 void	Dbg64_file_reuse(Lm_list *, const char *, const char *);
 void	Dbg32_file_skip(Lm_list *, const char *, const char *);
 void	Dbg64_file_skip(Lm_list *, const char *, const char *);
 
-void	Dbg32_got_display(Ofl_desc *, Elf32_Off, int);
-void	Dbg64_got_display(Ofl_desc *, Elf64_Off, int);
+void	Dbg32_got_display(Ofl_desc *, Elf32_Off, int,
+	    Elf32_Word, size_t m_got_entsize);
+void	Dbg64_got_display(Ofl_desc *, Elf64_Off, int,
+	    Elf64_Word, size_t m_got_entsize);
 
 void	Dbg32_libs_audit(Lm_list *, const char *, const char *);
 void	Dbg64_libs_audit(Lm_list *, const char *, const char *);
@@ -464,9 +466,9 @@
 void Elf32_ehdr(Lm_list *, Elf32_Ehdr *, Elf32_Shdr *);
 
 void Elf64_got_entry(Lm_list *, Elf64_Sword, Elf64_Addr, Elf64_Xword,
-    Elf64_Half, Elf64_Word, void *, const char *);
+    Elf64_Half, uchar_t, uchar_t, Elf64_Word, void *, const char *);
 void Elf32_got_entry(Lm_list *, Elf32_Sword, Elf32_Addr, Elf32_Word,
-    Elf32_Half, Elf32_Word, void *, const char *);
+    Elf32_Half, uchar_t, uchar_t, Elf32_Word, void *, const char *);
 void Elf64_got_title(Lm_list *);
 void Elf32_got_title(Lm_list *);
 
--- a/usr/src/cmd/sgs/liblddbg/common/relocate.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/relocate.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -594,14 +594,14 @@
 	if (type == SHT_RELA) {
 		Rela	*rela = (Rela *)reloc;
 
-		str = conv_reloc_type(mach, ELF_R_TYPE(rela->r_info),
+		str = conv_reloc_type(mach, ELF_R_TYPE(rela->r_info, mach),
 		    0, &inv_buf);
 		off = rela->r_offset;
 		add = rela->r_addend;
 	} else {
 		Rel	*rel = (Rel *)reloc;
 
-		str = conv_reloc_type(mach, ELF_R_TYPE(rel->r_info),
+		str = conv_reloc_type(mach, ELF_R_TYPE(rel->r_info, mach),
 		    0, &inv_buf);
 		off = rel->r_offset;
 		add = 0;
--- a/usr/src/cmd/sgs/librtld/amd64/_relocate.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/librtld/amd64/_relocate.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -43,7 +43,7 @@
 {
 	Rela		*rel = vrel;
 	const Rel_entry	*rep;
-	Xword		rtype = ELF_R_TYPE(rel->r_info);
+	Xword		rtype = ELF_R_TYPE(rel->r_info, M_MACH);
 	ulong_t		*_oaddr;
 	ulong_t		*_iaddr;
 
@@ -117,7 +117,7 @@
     Rt_map *lmp)
 {
 	Rela	*rel = vrel;
-	Xword	type = ELF_R_TYPE(rel->r_info);
+	Xword	type = ELF_R_TYPE(rel->r_info, M_MACH);
 	Xword	value = reloc->r_value + rel->r_addend;
 
 	if (type == R_AMD64_JUMP_SLOT) {
--- a/usr/src/cmd/sgs/librtld/common/relocate.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/librtld/common/relocate.c	Tue Mar 18 09:17:00 2008 -0700
@@ -94,7 +94,7 @@
 	    rel = (Rel *)((uintptr_t)rel + ent)) {
 		const char	*name;
 		/* LINTED */
-		uchar_t		type = (uchar_t)ELF_R_TYPE(rel->r_info);
+		uchar_t		type = (uchar_t)ELF_R_TYPE(rel->r_info, M_MACH);
 		uchar_t		bind;
 		ulong_t		offset = rel->r_offset + addr;
 		Rt_map		*_lmp;
@@ -441,7 +441,7 @@
 	    rel = (Rel *)((uintptr_t)rel + ent)) {
 		uchar_t		*iaddr, *oaddr;
 		/* LINTED */
-		uchar_t		type = (uchar_t)ELF_R_TYPE(rel->r_info);
+		uchar_t		type = (uchar_t)ELF_R_TYPE(rel->r_info, M_MACH);
 		Addr		off, bgn, end;
 
 		/*
--- a/usr/src/cmd/sgs/librtld/i386/_relocate.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/librtld/i386/_relocate.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -45,7 +45,7 @@
 	/* LINTED */
 	ulong_t	*_iaddr = (ulong_t *)iaddr;
 
-	switch (ELF_R_TYPE(rel->r_info)) {
+	switch (ELF_R_TYPE(rel->r_info, M_MACH)) {
 	case R_386_NONE:
 		break;
 
@@ -85,7 +85,7 @@
 	/* LINTED */
 	ulong_t	*_iaddr = (ulong_t *)iaddr;
 
-	if (ELF_R_TYPE(nrel->r_info) == R_386_JMP_SLOT) {
+	if (ELF_R_TYPE(nrel->r_info, M_MACH) == R_386_JMP_SLOT) {
 		if (_iaddr)
 			*_oaddr = *_iaddr + reloc->r_value;
 		else
@@ -118,7 +118,7 @@
     Rt_map *lmp)
 {
 	Rel	*rel = vrel;
-	Xword	type = ELF_R_TYPE(rel->r_info);
+	Xword	type = ELF_R_TYPE(rel->r_info, M_MACH);
 	Word	value = reloc->r_value;
 
 	if (type == R_386_JMP_SLOT) {
--- a/usr/src/cmd/sgs/librtld/sparc/_relocate.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/librtld/sparc/_relocate.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -42,7 +42,7 @@
 {
 	Rela		*rel = vrel;
 	const Rel_entry	*rep;
-	Xword		rtype = ELF_R_TYPE(rel->r_info);
+	Xword		rtype = ELF_R_TYPE(rel->r_info, M_MACH);
 	ulong_t		*_oaddr;
 	ulong_t		*_iaddr;
 
@@ -116,7 +116,7 @@
     Rt_map *lmp)
 {
 	Rela	*rel = vrel;
-	Xword	type = ELF_R_TYPE(rel->r_info);
+	Xword	type = ELF_R_TYPE(rel->r_info, M_MACH);
 	Xword	value = reloc->r_value + rel->r_addend;
 
 	if (type == R_SPARC_JMP_SLOT) {
--- a/usr/src/cmd/sgs/librtld/sparcv9/_relocate.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/librtld/sparcv9/_relocate.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -42,7 +42,7 @@
 {
 	Rela		*rel = vrel;
 	const Rel_entry	*rep;
-	Xword		rtype = ELF_R_TYPE(rel->r_info);
+	Xword		rtype = ELF_R_TYPE(rel->r_info, M_MACH);
 	ulong_t		*_oaddr;
 	ulong_t		*_iaddr;
 
@@ -116,7 +116,7 @@
     Rt_map *lmp)
 {
 	Rela	*rel = vrel;
-	Xword	type = ELF_R_TYPE(rel->r_info);
+	Xword	type = ELF_R_TYPE(rel->r_info, M_MACH);
 	Xword	value = reloc->r_value + rel->r_addend;
 
 	if (type == R_SPARC_JMP_SLOT) {
--- a/usr/src/cmd/sgs/packages/Makefile	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/packages/Makefile	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -151,10 +151,9 @@
 			$(ROOT)/usr/include/sys/auxv_SPARC.h \
 			$(ROOT)/usr/include/sys/auxv_386.h \
 			$(ROOT)/usr/include/sys/link.h \
+			$(ROOT)/usr/include/sys/machelf.h \
 			$(ROOT)/usr/include/sys/note.h \
 			$(ROOT)/usr/include/sys/systeminfo.h
-		@ cd $(SRC)/uts/$(M32)/sys; pwd; $(MAKE) \
-			$(ROOT)/usr/include/sys/machelf.h
 		@ cd ../tools/$(MACH); pwd; $(MAKE) sgsmsg piglatin
 		@ cd ..; pwd; $(MAKE) _msg_sgsmsg
 		@ cd ..; pwd; $(MAKE) native-add
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README	Tue Mar 18 09:17:00 2008 -0700
@@ -1321,3 +1321,5 @@
 6668050 First trip through PLT does not preserve args in xmm registers
 6672394 ldd(1) unused dependency processing is tricked by relocations errors
 6672544 elf_rtbndr must support non-ABI aligned stacks on amd64
+6671255 link-editor should support cross linking
+	PSARC 2008/179 cross link-editor
--- a/usr/src/cmd/sgs/packages/inc.flg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/packages/inc.flg	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI" 
@@ -79,6 +79,7 @@
 echo_file usr/src/uts/common/sys/Makefile
 echo_file usr/src/uts/Makefile.uts
 echo_file usr/src/uts/common/krtld/reloc.h
+echo_file usr/src/uts/common/krtld/reloc_defs.h
 echo_file usr/src/uts/common/sys/Makefile.syshdrs
 echo_file usr/src/uts/common/sys/auxv.h
 echo_file usr/src/uts/common/sys/auxv_386.h
@@ -90,18 +91,14 @@
 echo_file usr/src/uts/common/sys/elf_notes.h
 echo_file usr/src/uts/common/sys/elftypes.h
 echo_file usr/src/uts/common/sys/link.h
+echo_file usr/src/uts/common/sys/machelf.h
 echo_file usr/src/uts/common/sys/note.h
 echo_file usr/src/uts/common/sys/systeminfo.h
-echo_file usr/src/uts/sparc/sys/machelf.h
 echo_file usr/src/uts/sparc/sys/Makefile
 echo_file usr/src/uts/sparc/krtld/doreloc.c
-echo_file usr/src/uts/sparc/krtld/relmach.h
-echo_file usr/src/uts/intel/sys/machelf.h
 echo_file usr/src/uts/intel/sys/Makefile
 echo_file usr/src/uts/intel/ia32/krtld/doreloc.c
-echo_file usr/src/uts/intel/ia32/krtld/relmach.h
 echo_file usr/src/uts/intel/amd64/krtld/doreloc.c
-echo_file usr/src/uts/intel/amd64/krtld/relmach.h
 echo_file usr/src/cmd/sgs/Makefile
 echo_file usr/src/cmd/sgs/Makefile.com
 echo_file usr/src/cmd/sgs/Makefile.sub
--- a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c	Tue Mar 18 09:17:00 2008 -0700
@@ -408,7 +408,7 @@
 		if (relbgn >= relend)
 			break;
 
-		rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info);
+		rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 		roffset = ((Rela *)relbgn)->r_offset;
 
 	} while (rtype == R_AMD64_RELATIVE);
@@ -579,7 +579,7 @@
 	while (relbgn < relend) {
 		uint_t	sb_flags = 0;
 
-		rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info);
+		rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 
 		/*
 		 * If this is a RELATIVE relocation in a shared object (the
@@ -615,7 +615,7 @@
 
 			if (relbgn >= relend)
 				break;
-			rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info);
+			rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 		}
 
 		roffset = ((Rela *)relbgn)->r_offset;
--- a/usr/src/cmd/sgs/rtld/common/analyze.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/common/analyze.c	Tue Mar 18 09:17:00 2008 -0700
@@ -897,7 +897,7 @@
 		/* LINTED */
 		(void) snprintf(_reject, PATH_MAX,
 		    MSG_INTL(ldd_reject[rej->rej_type]),
-		    conv_reject_desc(rej, &rej_buf));
+		    conv_reject_desc(rej, &rej_buf, M_MACH));
 		if (rej->rej_name)
 			path = rej->rej_name;
 		reject = (char *)_reject;
@@ -1162,7 +1162,7 @@
 
 		eprintf(lml, ERR_FATAL, MSG_INTL(err_reject[rej->rej_type]),
 		    rej->rej_name ? rej->rej_name : MSG_INTL(MSG_STR_UNKNOWN),
-		    conv_reject_desc(rej, &rej_buf));
+		    conv_reject_desc(rej, &rej_buf, M_MACH));
 		return;
 	}
 
@@ -1364,7 +1364,7 @@
 		}
 		rej->rej_name = nname;
 		rej->rej_flag = (fdesc->fd_flags & FLG_FD_ALTER);
-		DBG_CALL(Dbg_file_rejected(lml, rej));
+		DBG_CALL(Dbg_file_rejected(lml, rej, M_MACH));
 	}
 	return (0);
 }
@@ -2232,7 +2232,7 @@
 			_rej.rej_name = name;
 			_rej.rej_type = SGS_REJ_STR;
 			_rej.rej_str = MSG_INTL(MSG_GEN_NOOPEN);
-			DBG_CALL(Dbg_file_rejected(lml, &_rej));
+			DBG_CALL(Dbg_file_rejected(lml, &_rej, M_MACH));
 			rejection_inherit(rej, &_rej);
 			remove_so(lml, nlmp);
 			return (0);
@@ -2266,7 +2266,7 @@
 			_rej.rej_name = name;
 			_rej.rej_type = SGS_REJ_STR;
 			_rej.rej_str = strerror(ENOENT);
-			DBG_CALL(Dbg_file_rejected(lml, &_rej));
+			DBG_CALL(Dbg_file_rejected(lml, &_rej, M_MACH));
 			rejection_inherit(rej, &_rej);
 			return (0);
 		}
--- a/usr/src/cmd/sgs/rtld/common/cap.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/common/cap.c	Tue Mar 18 09:17:00 2008 -0700
@@ -166,7 +166,7 @@
 		_rej.rej_type = SGS_REJ_STR;
 		_rej.rej_name = name;
 		_rej.rej_str = strerror(errno);
-		DBG_CALL(Dbg_file_rejected(lml, &_rej));
+		DBG_CALL(Dbg_file_rejected(lml, &_rej, M_MACH));
 		rejection_inherit(rej, &_rej);
 		return (0);
 	}
--- a/usr/src/cmd/sgs/rtld/common/object.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/common/object.c	Tue Mar 18 09:17:00 2008 -0700
@@ -79,8 +79,15 @@
 		return (0);
 
 	/*
-	 * Obtain a generic set of entrance criteria (this is the first call to
-	 * libld.so, which will effectively lazyload it).
+	 * Configure libld.so to process objects of the desired target
+	 * type (this is the first call to libld.so, which will effectively
+	 * lazyload it).
+	 */
+	if (ld_init_target(lml, M_MACH) != 0)
+		return (0);
+
+	/*
+	 * Obtain a generic set of entrance criteria
 	 */
 	if (ld_ent_setup(ofl, syspagsz) == S_ERROR)
 		return (0);
--- a/usr/src/cmd/sgs/rtld/common/rtld.sparc.msg	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/common/rtld.sparc.msg	Tue Mar 18 09:17:00 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # CDDL HEADER START
@@ -37,8 +37,6 @@
 			 value 0x%llx loses %d bits at offset 0x%llx"
 @ MSG_REL_NOFIT		"relocation error: %s: file %s: symbol %s: \
 			 value 0x%llx does not fit"
-@ MSG_REL_NOSWAP	"relocation error: %s: file %s: symbol %s: \
-			 linker does not support byte swapping relocated data"
 @ MSG_REL_BADREG	"relocation error: file %s: REGISTER relocation \
 			 against bad register offset: 0x%llx"
 
--- a/usr/src/cmd/sgs/rtld/common/setup.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/common/setup.c	Tue Mar 18 09:17:00 2008 -0700
@@ -418,7 +418,7 @@
 
 			eprintf(&lml_main, ERR_FATAL,
 			    MSG_INTL(err_reject[rej.rej_type]), argvname,
-			    conv_reject_desc(&rej, &rej_buf));
+			    conv_reject_desc(&rej, &rej_buf, M_MACH));
 			return (0);
 		}
 
--- a/usr/src/cmd/sgs/rtld/i386/i386_elf.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/i386/i386_elf.c	Tue Mar 18 09:17:00 2008 -0700
@@ -385,7 +385,7 @@
 		if (relbgn >= relend)
 			break;
 
-		rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info);
+		rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info, M_MACH);
 		roffset = ((Rel *)relbgn)->r_offset;
 
 	} while (rtype == R_386_RELATIVE);
@@ -555,7 +555,7 @@
 	while (relbgn < relend) {
 		uint_t	sb_flags = 0;
 
-		rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info);
+		rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info, M_MACH);
 
 		/*
 		 * If this is a RELATIVE relocation in a shared object (the
@@ -591,7 +591,7 @@
 			}
 			if (relbgn >= relend)
 				break;
-			rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info);
+			rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info, M_MACH);
 		}
 
 		roffset = ((Rel *)relbgn)->r_offset;
--- a/usr/src/cmd/sgs/rtld/sparc/common_sparc.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/sparc/common_sparc.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -201,7 +201,7 @@
 		if (relbgn >= relend)
 			break;
 
-		rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info);
+		rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 		roffset = ((Rela *)relbgn)->r_offset;
 
 	} while (rtype == R_SPARC_RELATIVE);
--- a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c	Tue Mar 18 09:17:00 2008 -0700
@@ -642,7 +642,7 @@
 		Addr		vaddr;
 		uint_t		sb_flags = 0;
 
-		rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info);
+		rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 
 		/*
 		 * If this is a RELATIVE relocation in a shared object (the
@@ -677,7 +677,7 @@
 			}
 			if (relbgn >= relend)
 				break;
-			rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info);
+			rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 		}
 
 		roffset = ((Rela *)relbgn)->r_offset;
--- a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c	Tue Mar 18 09:17:00 2008 -0700
@@ -885,7 +885,7 @@
 		Addr		vaddr;
 		uint_t		sb_flags = 0;
 
-		rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info);
+		rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 
 		/*
 		 * If this is a RELATIVE relocation in a shared object
@@ -921,7 +921,8 @@
 			}
 			if (relbgn >= relend)
 				break;
-			rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info);
+			rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info,
+			    M_MACH);
 		}
 
 		roffset = ((Rela *)relbgn)->r_offset;
--- a/usr/src/uts/common/krtld/kobj.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/uts/common/krtld/kobj.c	Tue Mar 18 09:17:00 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -2261,7 +2261,7 @@
 	Shdr *shp;
 	reloc_dest_t dest = NULL;
 	uintptr_t bits_ptr;
-	uintptr_t text = 0, data, sdata = 0, textptr;
+	uintptr_t text = 0, data, textptr;
 	uint_t shn;
 	int err = -1;
 
@@ -2380,8 +2380,6 @@
 
 		if ((shp->sh_flags & SHF_WRITE) == 0)
 			bits_ptr = text;
-		else if (shp->sh_flags & SHF_NEUT_SHORT)
-			bits_ptr = sdata;
 		else
 			bits_ptr = data;
 
@@ -2410,8 +2408,6 @@
 		bits_ptr += shp->sh_size;
 		if ((shp->sh_flags & SHF_WRITE) == 0)
 			text = bits_ptr;
-		else if (shp->sh_flags & SHF_NEUT_SHORT)
-			sdata = bits_ptr;
 		else
 			data = bits_ptr;
 	}
--- a/usr/src/uts/common/krtld/reloc.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/uts/common/krtld/reloc.h	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -30,17 +30,15 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #if defined(_KERNEL)
-#include <sys/machelf.h>
 #include <sys/bootconf.h>
 #include <sys/kobj.h>
 #include <sys/kobj_impl.h>
 #else
-#include <machdep.h>
 #include <rtld.h>
 #include <conv.h>
 #endif /* _KERNEL */
 
-#include <relmach.h>
+#include "reloc_defs.h"
 
 #ifdef	__cplusplus
 extern "C" {
@@ -48,107 +46,81 @@
 
 /*
  * Global include file for relocation common code.
- *
- * Flags for reloc_entry->re_flags
  */
-#define	FLG_RE_NOTREL		0x00000000
-#define	FLG_RE_GOTADD		0x00000001	/* create a GOT entry */
-#define	FLG_RE_GOTREL		0x00000002	/* GOT based */
-#define	FLG_RE_GOTPC		0x00000004	/* GOT - P */
-#define	FLG_RE_GOTOPINS		0x00000008	/* GOTOP instruction */
-#define	FLG_RE_PCREL		0x00000010
-#define	FLG_RE_PLTREL		0x00000020
-#define	FLG_RE_VERIFY		0x00000040	/* verify value fits */
-#define	FLG_RE_UNALIGN		0x00000080	/* offset is not aligned */
-#define	FLG_RE_WDISP16		0x00000100	/* funky sparc DISP16 rel */
-#define	FLG_RE_SIGN		0x00000200	/* value is signed */
-#define	FLG_RE_ADDRELATIVE	0x00000400	/* RELATIVE relocation */
-						/*	required for non- */
-						/*	fixed objects */
-#define	FLG_RE_EXTOFFSET	0x00000800	/* extra offset required */
-#define	FLG_RE_REGISTER		0x00001000	/* relocation initializes */
-						/*    a REGISTER by OLO10 */
-#define	FLG_RE_SIZE		0x00002000	/* symbol size required */
-
-#define	FLG_RE_NOTSUP		0x00010000	/* relocation not supported */
-
-#define	FLG_RE_SEGREL		0x00040000	/* segment relative */
-#define	FLG_RE_SECREL		0x00080000	/* section relative */
-
-#define	FLG_RE_TLSGD		0x00200000	/* TLS GD relocation */
-#define	FLG_RE_TLSLD		0x00400000	/* TLS LD relocation */
-#define	FLG_RE_TLSIE		0x00800000	/* TLS IE relocation */
-#define	FLG_RE_TLSLE		0x01000000	/* TLS LE relocation */
-#define	FLG_RE_LOCLBND		0x02000000	/* relocation must bind */
-						/*    locally */
 
 /*
  * In user land, redefine the relocation table and relocation engine to be
- * class specific if necessary.  This allows both engines to reside in the
- * intel/amd version of libld.
+ * class/machine specific if necessary.  This allows multiple engines to
+ * reside within a single instance of libld.
  */
 #if	!defined(_KERNEL)
+
+#if defined(DO_RELOC_LIBLD)
+#undef DO_RELOC_LIBLD
+#endif
+
+#if	defined(DO_RELOC_LIBLD_X86)
+
+#define	DO_RELOC_LIBLD
 #if	defined(_ELF64)
-#define	do_reloc_ld		do64_reloc_ld
+#define	do_reloc_ld		do64_reloc_ld_x86
+#define	reloc_table		reloc64_table_x86
+#else
+#define	do_reloc_ld		do32_reloc_ld_x86
+#define	reloc_table		reloc32_table_x86
+#endif
+
+#elif	defined(DO_RELOC_LIBLD_SPARC)
+
+#define	DO_RELOC_LIBLD
+#if	defined(_ELF64)
+#define	do_reloc_ld		do64_reloc_ld_sparc
+#define	reloc_table		reloc64_table_sparc
+#else
+#define	do_reloc_ld		do32_reloc_ld_sparc
+#define	reloc_table		reloc32_table_sparc
+#endif
+
+#else				/* rtld */
+
+#if	defined(_ELF64)
 #define	do_reloc_rtld		do64_reloc_rtld
 #define	reloc_table		reloc64_table
 #else
-#define	do_reloc_ld		do32_reloc_ld
 #define	do_reloc_rtld		do32_reloc_rtld
 #define	reloc_table		reloc32_table
 #endif
+
 #endif
 
+#endif	/* !_KERNEL */
+
 /*
  * Relocation table and macros for testing relocation table flags.
  */
-extern	const Rel_entry		reloc_table[];
+extern	const Rel_entry	reloc_table[];
 
-#define	IS_PLT(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_PLTREL) != 0)
-#define	IS_GOT_RELATIVE(X)	((reloc_table[(X)].re_flags & \
-					FLG_RE_GOTADD) != 0)
-#define	IS_GOT_PC(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_GOTPC) != 0)
-#define	IS_GOTPCREL(X)		((reloc_table[(X)].re_flags & \
-					(FLG_RE_GOTPC | FLG_RE_GOTADD)) == \
-					(FLG_RE_GOTPC | FLG_RE_GOTADD))
-#define	IS_GOT_BASED(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_GOTREL) != 0)
-#define	IS_GOT_OPINS(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_GOTOPINS) != 0)
-#define	IS_GOT_REQUIRED(X)	((reloc_table[(X)].re_flags & \
-					(FLG_RE_GOTADD | FLG_RE_GOTREL | \
-					FLG_RE_GOTPC | FLG_RE_GOTOPINS)) != 0)
-#define	IS_PC_RELATIVE(X)	((reloc_table[(X)].re_flags & \
-					FLG_RE_PCREL) != 0)
-#define	IS_ADD_RELATIVE(X)	((reloc_table[(X)].re_flags & \
-					FLG_RE_ADDRELATIVE) != 0)
-#define	IS_REGISTER(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_REGISTER) != 0)
-#define	IS_NOTSUP(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_NOTSUP) != 0)
-#define	IS_SEG_RELATIVE(X)	((reloc_table[(X)].re_flags & \
-					FLG_RE_SEGREL) != 0)
-#define	IS_EXTOFFSET(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_EXTOFFSET) != 0)
-#define	IS_SEC_RELATIVE(X)	((reloc_table[(X)].re_flags & \
-					FLG_RE_SECREL) != 0)
-#define	IS_TLS_INS(X)		((reloc_table[(X)].re_flags & \
-					(FLG_RE_TLSGD | FLG_RE_TLSLD | \
-					FLG_RE_TLSIE | FLG_RE_TLSLE)) != 0)
-#define	IS_TLS_GD(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_TLSGD) != 0)
-#define	IS_TLS_LD(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_TLSLD) != 0)
-#define	IS_TLS_IE(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_TLSIE) != 0)
-#define	IS_TLS_LE(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_TLSLE) != 0)
-#define	IS_LOCALBND(X)		((reloc_table[(X)].re_flags & \
-					FLG_RE_LOCLBND) != 0)
-#define	IS_SIZE(X)		((reloc_table[(X)].re_flags &\
-					FLG_RE_SIZE) != 0)
+#define	IS_PLT(X)		RELTAB_IS_PLT(X, reloc_table)
+#define	IS_GOT_RELATIVE(X)	RELTAB_IS_GOT_RELATIVE(X, reloc_table)
+#define	IS_GOT_PC(X)		RELTAB_IS_GOT_PC(X, reloc_table)
+#define	IS_GOTPCREL(X)		RELTAB_IS_GOTPCREL(X, reloc_table)
+#define	IS_GOT_BASED(X)		RELTAB_IS_GOT_BASED(X, reloc_table)
+#define	IS_GOT_OPINS(X)		RELTAB_IS_GOT_OPINS(X, reloc_table)
+#define	IS_GOT_REQUIRED(X)	RELTAB_IS_GOT_REQUIRED(X, reloc_table)
+#define	IS_PC_RELATIVE(X)	RELTAB_IS_PC_RELATIVE(X, reloc_table)
+#define	IS_ADD_RELATIVE(X)	RELTAB_IS_ADD_RELATIVE(X, reloc_table)
+#define	IS_REGISTER(X)		RELTAB_IS_REGISTER(X, reloc_table)
+#define	IS_NOTSUP(X)		RELTAB_IS_NOTSUP(X, reloc_table)
+#define	IS_SEG_RELATIVE(X)	RELTAB_IS_SEG_RELATIVE(X, reloc_table)
+#define	IS_EXTOFFSET(X)		RELTAB_IS_EXTOFFSET(X, reloc_table)
+#define	IS_SEC_RELATIVE(X)	RELTAB_IS_SEC_RELATIVE(X, reloc_table)
+#define	IS_TLS_INS(X)		RELTAB_IS_TLS_INS(X, reloc_table)
+#define	IS_TLS_GD(X)		RELTAB_IS_TLS_GD(X, reloc_table)
+#define	IS_TLS_LD(X)		RELTAB_IS_TLS_LD(X, reloc_table)
+#define	IS_TLS_IE(X)		RELTAB_IS_TLS_IE(X, reloc_table)
+#define	IS_TLS_LE(X)		RELTAB_IS_TLS_LE(X, reloc_table)
+#define	IS_LOCALBND(X)		RELTAB_IS_LOCALBND(X, reloc_table)
+#define	IS_SIZE(X)		RELTAB_IS_SIZE(X, reloc_table)
 
 /*
  * Relocation engine.
@@ -161,6 +133,11 @@
  *		the relocation engine that the data it is relocating
  *		has the opposite byte order of the system running the
  *		linker.
+ *	- The linker is a cross-linker, meaning that it can examine
+ *		relocation records for target hosts other than that of
+ *		the currently running system. This means that multiple
+ *		versions of the relocation code must be able to reside
+ *		in a single program, without namespace clashes.
  *
  * To ensure that there is never any confusion about which version is
  * being linked to, we give each variant a different name, even though
@@ -170,7 +147,7 @@
  *	The kernel version is provided if the _KERNEL macro is defined.
  *
  *	do_reloc_ld()
- *	The ld version is provided if the DO_RELOC_LIBLD macro is defined.
+ *	The ld version is provided if the DO_RELOC_LIBLD_ macro is defined.
  *
  *	do_reloc_rtld()
  *	The rtld version is provided if neither _KERNEL or DO_RELOC_LIBLD
@@ -240,6 +217,7 @@
 #error platform not defined!
 #endif
 
+
 /*
  * Note:  dlerror() only keeps track of a single error string, and therefore
  * must have errors reported through a single eprintf() call.  The kernel's
@@ -320,11 +298,6 @@
 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
 	    EC_XWORD((uvalue))))
 
-#define	REL_ERR_NOSWAP(lml, file, sym, rtype) \
-	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSWAP), \
-	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
-	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN))))
-
 #endif	/* _KERNEL */
 
 #ifdef	__cplusplus
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/krtld/reloc_defs.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+#ifndef	_RELOC_DEFS_DOT_H
+#define	_RELOC_DEFS_DOT_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/machelf.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Definitions used by the relocation common code.
+ */
+
+
+/*
+ * Structure used to build the reloc_table[]
+ */
+typedef struct {
+	Xword	re_mask;	/* mask to apply to reloc (sparc only) */
+	Word	re_flags;	/* relocation attributes */
+	uchar_t	re_fsize;	/* field size (in bytes) */
+	uchar_t	re_bshift;	/* number of bits to shift (sparc only) */
+	uchar_t	re_sigbits;	/* number of significant bits */
+} Rel_entry;
+
+/*
+ * Flags for reloc_entry->re_flags
+ */
+#define	FLG_RE_NOTREL		0x00000000
+#define	FLG_RE_GOTADD		0x00000001	/* create a GOT entry */
+#define	FLG_RE_GOTREL		0x00000002	/* GOT based */
+#define	FLG_RE_GOTPC		0x00000004	/* GOT - P */
+#define	FLG_RE_GOTOPINS		0x00000008	/* GOTOP instruction */
+#define	FLG_RE_PCREL		0x00000010
+#define	FLG_RE_PLTREL		0x00000020
+#define	FLG_RE_VERIFY		0x00000040	/* verify value fits */
+#define	FLG_RE_UNALIGN		0x00000080	/* offset is not aligned */
+#define	FLG_RE_WDISP16		0x00000100	/* funky sparc DISP16 rel */
+#define	FLG_RE_SIGN		0x00000200	/* value is signed */
+#define	FLG_RE_ADDRELATIVE	0x00000400	/* RELATIVE relocation */
+						/*	required for non- */
+						/*	fixed objects */
+#define	FLG_RE_EXTOFFSET	0x00000800	/* extra offset required */
+#define	FLG_RE_REGISTER		0x00001000	/* relocation initializes */
+						/*    a REGISTER by OLO10 */
+#define	FLG_RE_SIZE		0x00002000	/* symbol size required */
+
+#define	FLG_RE_NOTSUP		0x00010000	/* relocation not supported */
+
+#define	FLG_RE_SEGREL		0x00040000	/* segment relative */
+#define	FLG_RE_SECREL		0x00080000	/* section relative */
+
+#define	FLG_RE_TLSGD		0x00200000	/* TLS GD relocation */
+#define	FLG_RE_TLSLD		0x00400000	/* TLS LD relocation */
+#define	FLG_RE_TLSIE		0x00800000	/* TLS IE relocation */
+#define	FLG_RE_TLSLE		0x01000000	/* TLS LE relocation */
+#define	FLG_RE_LOCLBND		0x02000000	/* relocation must bind */
+						/*    locally */
+
+/*
+ * Relocation table and macros for testing relocation table flags.
+ */
+
+#define	RELTAB_IS_PLT(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_PLTREL) != 0)
+
+#define	RELTAB_IS_GOT_RELATIVE(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_GOTADD) != 0)
+
+#define	RELTAB_IS_GOT_PC(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_GOTPC) != 0)
+
+#define	RELTAB_IS_GOTPCREL(X, _reltab) \
+	((_reltab[(X)].re_flags & (FLG_RE_GOTPC | FLG_RE_GOTADD)) == \
+	(FLG_RE_GOTPC | FLG_RE_GOTADD))
+
+#define	RELTAB_IS_GOT_BASED(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_GOTREL) != 0)
+
+#define	RELTAB_IS_GOT_OPINS(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_GOTOPINS) != 0)
+
+#define	RELTAB_IS_GOT_REQUIRED(X, _reltab) \
+	((_reltab[(X)].re_flags & (FLG_RE_GOTADD | FLG_RE_GOTREL | \
+	FLG_RE_GOTPC | FLG_RE_GOTOPINS)) != 0)
+
+#define	RELTAB_IS_PC_RELATIVE(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_PCREL) != 0)
+
+#define	RELTAB_IS_ADD_RELATIVE(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_ADDRELATIVE) != 0)
+
+#define	RELTAB_IS_REGISTER(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_REGISTER) != 0)
+
+#define	RELTAB_IS_NOTSUP(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_NOTSUP) != 0)
+
+#define	RELTAB_IS_SEG_RELATIVE(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_SEGREL) != 0)
+
+#define	RELTAB_IS_EXTOFFSET(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_EXTOFFSET) != 0)
+
+#define	RELTAB_IS_SEC_RELATIVE(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_SECREL) != 0)
+
+#define	RELTAB_IS_TLS_INS(X, _reltab) \
+	((_reltab[(X)].re_flags & \
+	(FLG_RE_TLSGD | FLG_RE_TLSLD | FLG_RE_TLSIE | FLG_RE_TLSLE)) != 0)
+
+#define	RELTAB_IS_TLS_GD(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_TLSGD) != 0)
+
+#define	RELTAB_IS_TLS_LD(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_TLSLD) != 0)
+
+#define	RELTAB_IS_TLS_IE(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_TLSIE) != 0)
+
+#define	RELTAB_IS_TLS_LE(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_TLSLE) != 0)
+
+#define	RELTAB_IS_LOCALBND(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_LOCLBND) != 0)
+
+#define	RELTAB_IS_SIZE(X, _reltab) \
+	((_reltab[(X)].re_flags & FLG_RE_SIZE) != 0)
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _RELOC_DEFS_DOT_H */
--- a/usr/src/uts/common/sys/Makefile	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/uts/common/sys/Makefile	Tue Mar 18 09:17:00 2008 -0700
@@ -347,6 +347,7 @@
 	lwp_upimutex_impl.h	\
 	mac.h			\
 	mac_impl.h		\
+	machelf.h		\
 	map.h			\
 	md4.h			\
 	md5.h			\
--- a/usr/src/uts/common/sys/link.h	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/uts/common/sys/link.h	Tue Mar 18 09:17:00 2008 -0700
@@ -23,7 +23,7 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -155,6 +155,8 @@
 
 #define	DT_SUNW_STRPAD		0x60000019	/* # of unused bytes at the */
 						/*	end of dynstr */
+#define	DT_SUNW_LDMACH		0x6000001b	/* EM_ machine code of linker */
+						/*	that produced object */
 
 /*
  * DT_* encoding rules do not apply between DT_HIOS and DT_LOPROC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/machelf.h	Tue Mar 18 09:17:00 2008 -0700
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+#ifndef	_SYS_MACHELF_H
+#define	_SYS_MACHELF_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if defined(__amd64)
+#include <sys/elf_amd64.h>
+#elif defined(__i386)
+#include <sys/elf_386.h>
+#elif defined(__sparc)
+#include <sys/elf_SPARC.h>
+#endif
+#ifndef	_ASM
+#include <sys/types.h>
+#include <sys/elf.h>
+#include <sys/link.h>	/* for Elf*_Dyn */
+#endif	/* _ASM */
+
+/*
+ * Make machine class dependent data types transparent to the common code
+ */
+#if defined(_ELF64) && !defined(_ELF32_COMPAT)
+
+#ifndef	_ASM
+typedef	Elf64_Xword	Xword;
+typedef	Elf64_Lword	Lword;
+typedef	Elf64_Sxword	Sxword;
+typedef	Elf64_Word	Word;
+typedef	Elf64_Sword	Sword;
+typedef	Elf64_Half	Half;
+typedef	Elf64_Addr	Addr;
+typedef	Elf64_Off	Off;
+typedef	uchar_t		Byte;
+#endif	/* _ASM */
+
+#if defined(_KERNEL)
+#define	ELF_R_TYPE	ELF64_R_TYPE
+#define	ELF_R_SYM	ELF64_R_SYM
+#define	ELF_R_TYPE_DATA ELF64_R_TYPE_DATA
+#define	ELF_R_INFO	ELF64_R_INFO
+#define	ELF_ST_BIND	ELF64_ST_BIND
+#define	ELF_ST_TYPE	ELF64_ST_TYPE
+#define	ELF_M_SYM	ELF64_M_SYM
+#define	ELF_M_SIZE	ELF64_M_SIZE
+#endif
+
+#ifndef	_ASM
+typedef	Elf64_Ehdr	Ehdr;
+typedef	Elf64_Shdr	Shdr;
+typedef	Elf64_Sym	Sym;
+typedef	Elf64_Syminfo	Syminfo;
+typedef	Elf64_Rela	Rela;
+typedef	Elf64_Rel	Rel;
+typedef	Elf64_Nhdr	Nhdr;
+typedef	Elf64_Phdr	Phdr;
+typedef	Elf64_Dyn	Dyn;
+typedef	Elf64_Boot	Boot;
+typedef	Elf64_Verdef	Verdef;
+typedef	Elf64_Verdaux	Verdaux;
+typedef	Elf64_Verneed	Verneed;
+typedef	Elf64_Vernaux	Vernaux;
+typedef	Elf64_Versym	Versym;
+typedef	Elf64_Move	Move;
+typedef	Elf64_Cap	Cap;
+#endif	/* _ASM */
+
+#else	/* _ILP32 */
+
+#ifndef	_ASM
+typedef	Elf32_Word	Xword;	/* Xword/Sxword are 32-bits in Elf32 */
+typedef	Elf32_Lword	Lword;
+typedef	Elf32_Sword	Sxword;
+typedef	Elf32_Word	Word;
+typedef	Elf32_Sword	Sword;
+typedef	Elf32_Half	Half;
+typedef	Elf32_Addr	Addr;
+typedef	Elf32_Off	Off;
+typedef	uchar_t		Byte;
+#endif	/* _ASM */
+
+#if defined(_KERNEL)
+#define	ELF_R_TYPE	ELF32_R_TYPE
+#define	ELF_R_SYM	ELF32_R_SYM
+#define	ELF_R_TYPE_DATA(x)	(0)
+#define	ELF_R_INFO	ELF32_R_INFO
+#define	ELF_ST_BIND	ELF32_ST_BIND
+#define	ELF_ST_TYPE	ELF32_ST_TYPE
+#define	ELF_M_SYM	ELF32_M_SYM
+#define	ELF_M_SIZE	ELF32_M_SIZE
+#endif
+
+#ifndef	_ASM
+typedef	Elf32_Ehdr	Ehdr;
+typedef	Elf32_Shdr	Shdr;
+typedef	Elf32_Sym	Sym;
+typedef	Elf32_Syminfo	Syminfo;
+typedef	Elf32_Rela	Rela;
+typedef	Elf32_Rel	Rel;
+typedef	Elf32_Nhdr	Nhdr;
+typedef	Elf32_Phdr	Phdr;
+typedef	Elf32_Dyn	Dyn;
+typedef	Elf32_Boot	Boot;
+typedef	Elf32_Verdef	Verdef;
+typedef	Elf32_Verdaux	Verdaux;
+typedef	Elf32_Verneed	Verneed;
+typedef	Elf32_Vernaux	Vernaux;
+typedef	Elf32_Versym	Versym;
+typedef	Elf32_Move	Move;
+typedef	Elf32_Cap	Cap;
+#endif	/* _ASM */
+
+#endif	/* _ILP32 */
+
+/*
+ * Elf `printf' type-cast macros.  These force arguments to be a fixed size
+ * so that Elf32 and Elf64 can share common format strings.
+ */
+#ifndef	__lint
+#define	EC_ADDR(a)	((Elf64_Addr)(a))		/* "ull" */
+#define	EC_OFF(a)	((Elf64_Off)(a))		/* "ull"  */
+#define	EC_HALF(a)	((Elf64_Half)(a))		/* "d"   */
+#define	EC_WORD(a)	((Elf64_Word)(a))		/* "u"   */
+#define	EC_SWORD(a)	((Elf64_Sword)(a))		/* "d"   */
+#define	EC_XWORD(a)	((Elf64_Xword)(a))		/* "ull" */
+#define	EC_SXWORD(a)	((Elf64_Sxword)(a))		/* "ll"  */
+#define	EC_LWORD(a)	((Elf64_Lword)(a))		/* "ull" */
+
+/*
+ * A native pointer is special.  Although it can be convenient to display
+ * these from a common format (ull), compilers may flag the cast of a pointer
+ * to an integer as illegal.  Casting these pointers to the native pointer
+ * size, suppresses any compiler errors.
+ */
+#define	EC_NATPTR(a)	((Elf64_Xword)(uintptr_t)(a))	/* "ull" */
+#else
+#define	EC_ADDR(a)	((u_longlong_t)(a))
+#define	EC_OFF(a)	((u_longlong_t)(a))
+#define	EC_HALF(a)	((ushort_t)(a))
+#define	EC_WORD(a)	((uint_t)(a))
+#define	EC_SWORD(a)	((int)(a))
+#define	EC_XWORD(a)	((u_longlong_t)(a))
+#define	EC_SXWORD(a)	((longlong_t)(a))
+#define	EC_LWORD(a)	((u_longlong_t)(a))
+
+#define	EC_NATPTR(a)	((u_longlong_t)(a))
+#endif
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_MACHELF_H */
--- a/usr/src/uts/intel/amd64/krtld/doreloc.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/uts/intel/amd64/krtld/doreloc.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -30,6 +30,11 @@
 #include	<sys/types.h>
 #include	"reloc.h"
 #else
+#define	ELF_TARGET_AMD64
+#if defined(DO_RELOC_LIBLD)
+#undef DO_RELOC_LIBLD
+#define	DO_RELOC_LIBLD_X86
+#endif
 #include	<stdio.h>
 #include	"sgs.h"
 #include	"machdep.h"
@@ -40,46 +45,64 @@
 #endif
 
 /*
+ * We need to build this code differently when it is used for
+ * cross linking:
+ *	- Data alignment requirements can differ from those
+ *		of the running system, so we can't access data
+ *		in units larger than a byte
+ *	- We have to include code to do byte swapping when the
+ *		target and linker host use different byte ordering,
+ *		but such code is a waste when running natively.
+ */
+#if !defined(DO_RELOC_LIBLD) || defined(__i386) || defined(__amd64)
+#define	DORELOC_NATIVE
+#endif
+
+/*
  * This table represents the current relocations that do_reloc() is able to
  * process.  The relocations below that are marked SPECIAL are relocations that
  * take special processing and shouldn't actually ever be passed to do_reloc().
  */
 const Rel_entry	reloc_table[R_AMD64_NUM] = {
-/* R_AMD64_NONE */	{FLG_RE_NOTREL, 0},
-/* R_AMD64_64 */	{FLG_RE_NOTREL, 8},
-/* R_AMD64_PC32 */	{FLG_RE_PCREL, 4},
-/* R_AMD64_GOT32 */	{FLG_RE_NOTSUP, 0},
-/* R_AMD64_PLT32 */	{FLG_RE_PCREL | FLG_RE_PLTREL |
-			    FLG_RE_VERIFY | FLG_RE_SIGN, 4},
-/* R_AMD64_COPY */	{FLG_RE_NOTSUP, 0},		/* SPECIAL */
-/* R_AMD64_GLOB_DAT */	{FLG_RE_NOTREL, 8},
-/* R_AMD64_JUMP_SLOT */	{FLG_RE_NOTSUP, 0},		/* SPECIAL */
-/* R_AMD64_RELATIVE */	{FLG_RE_NOTREL, 8},
-/* R_AMD64_GOTPCREL */	{FLG_RE_GOTPC | FLG_RE_GOTADD, 4},
-/* R_AMD64_32 */	{FLG_RE_NOTREL, 4},
-/* R_AMD64_32S */	{FLG_RE_NOTREL, 4},
-/* R_AMD64_16 */	{FLG_RE_NOTREL, 2},
-/* R_AMD64_PC16 */	{FLG_RE_PCREL, 2},
-/* R_AMD64_8 */		{FLG_RE_NOTREL, 1},
-/* R_AMD64_PC8 */	{FLG_RE_PCREL, 1},
-/* R_AMD64_DTPMOD64 */	{FLG_RE_NOTREL, 8},
-/* R_AMD64_DTPOFF64 */	{FLG_RE_NOTREL, 8},
-/* R_AMD64_TPOFF64 */	{FLG_RE_NOTREL, 8},
-/* R_AMD64_TLSGD */	{FLG_RE_GOTPC | FLG_RE_GOTADD | FLG_RE_TLSGD, 4},
-/* R_AMD64_TLSLD */	{FLG_RE_GOTPC | FLG_RE_GOTADD | FLG_RE_TLSLD, 4},
-/* R_AMD64_DTPOFF32 */	{FLG_RE_TLSLD, 4},
-/* R_AMD64_GOTTPOFF */	{FLG_RE_GOTPC | FLG_RE_GOTADD | FLG_RE_TLSIE, 4},
-/* R_AMD64_TPOFF32 */	{FLG_RE_TLSLE, 4},
-/* R_AMD64_PC64 */	{FLG_RE_PCREL, 8},
-/* R_AMD64_GOTOFF64 */	{FLG_RE_GOTREL, 8},
-/* R_AMD64_GOTPC32 */	{FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4},
-/* R_AMD64_GOT64 */	{FLG_RE_NOTSUP, 0},
-/* R_AMD64_GOTPCREL64 */	{FLG_RE_NOTSUP, 0},
-/* R_AMD64_GOTPC6 */	{FLG_RE_NOTSUP, 0},
-/* R_AMD64_GOTPLT64 */	{FLG_RE_NOTSUP, 0},
-/* R_AMD64_PLTOFF64 */	{FLG_RE_NOTSUP, 0},
-/* R_AMD64_SIZE32 */	{FLG_RE_SIZE, 4},
-/* R_AMD64_SIZE64 */	{FLG_RE_SIZE, 8}
+/* R_AMD64_NONE */	{0, FLG_RE_NOTREL, 0, 0, 0},
+/* R_AMD64_64 */	{0, FLG_RE_NOTREL, 8, 0, 0},
+/* R_AMD64_PC32 */	{0, FLG_RE_PCREL, 4, 0, 0},
+/* R_AMD64_GOT32 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_AMD64_PLT32 */	{0, FLG_RE_PCREL | FLG_RE_PLTREL |
+			    FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 0},
+/* R_AMD64_COPY */	{0, FLG_RE_NOTSUP, 0, 0, 0},	/* SPECIAL */
+/* R_AMD64_GLOB_DAT */	{0, FLG_RE_NOTREL, 8, 0, 0},
+/* R_AMD64_JUMP_SLOT */	{0, FLG_RE_NOTSUP, 0, 0, 0},	/* SPECIAL */
+/* R_AMD64_RELATIVE */	{0, FLG_RE_NOTREL, 8, 0, 0},
+/* R_AMD64_GOTPCREL */	{0, FLG_RE_GOTPC | FLG_RE_GOTADD, 4, 0, 0},
+/* R_AMD64_32 */	{0, FLG_RE_NOTREL, 4, 0, 0},
+/* R_AMD64_32S */	{0, FLG_RE_NOTREL, 4, 0, 0},
+/* R_AMD64_16 */	{0, FLG_RE_NOTREL, 2, 0, 0},
+/* R_AMD64_PC16 */	{0, FLG_RE_PCREL, 2, 0, 0},
+/* R_AMD64_8 */		{0, FLG_RE_NOTREL, 1, 0, 0},
+/* R_AMD64_PC8 */	{0, FLG_RE_PCREL, 1, 0, 0},
+/* R_AMD64_DTPMOD64 */	{0, FLG_RE_NOTREL, 8, 0, 0},
+/* R_AMD64_DTPOFF64 */	{0, FLG_RE_NOTREL, 8, 0, 0},
+/* R_AMD64_TPOFF64 */	{0, FLG_RE_NOTREL, 8, 0, 0},
+/* R_AMD64_TLSGD */	{0, FLG_RE_GOTPC | FLG_RE_GOTADD | FLG_RE_TLSGD,
+			    4, 0, 0},
+/* R_AMD64_TLSLD */	{0, FLG_RE_GOTPC | FLG_RE_GOTADD | FLG_RE_TLSLD,
+			    4, 0, 0},
+/* R_AMD64_DTPOFF32 */	{0, FLG_RE_TLSLD, 4},
+/* R_AMD64_GOTTPOFF */	{0, FLG_RE_GOTPC | FLG_RE_GOTADD | FLG_RE_TLSIE,
+			    4, 0, 0},
+/* R_AMD64_TPOFF32 */	{0, FLG_RE_TLSLE, 4, 0, 0},
+/* R_AMD64_PC64 */	{0, FLG_RE_PCREL, 8, 0, 0},
+/* R_AMD64_GOTOFF64 */	{0, FLG_RE_GOTREL, 8, 0, 0},
+/* R_AMD64_GOTPC32 */	{0, FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND,
+			    4, 0, 0},
+/* R_AMD64_GOT64 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_AMD64_GOTPCREL64 */	{FLG_RE_NOTSUP, 0, 0, 0},
+/* R_AMD64_GOTPC6 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_AMD64_GOTPLT64 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_AMD64_PLTOFF64 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_AMD64_SIZE32 */	{0, FLG_RE_SIZE, 4, 0, 0},
+/* R_AMD64_SIZE64 */	{0, FLG_RE_SIZE, 8, 0, 0}
 };
 #if	(R_AMD64_NUM != (R_AMD64_SIZE64 + 1))
 #error	"R_AMD64_NUM has grown"
@@ -163,6 +186,7 @@
 do_reloc_krtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
     const char *file)
 #elif defined(DO_RELOC_LIBLD)
+/*ARGSUSED5*/
 int
 do_reloc_ld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
     const char *file, int bswap, void *lml)
@@ -174,17 +198,6 @@
 {
 	const Rel_entry	*rep;
 
-#if defined(DO_RELOC_LIBLD)
-	/*
-	 * We do not support building the amd64 linker as a cross linker
-	 * at this time.
-	 */
-	if (bswap) {
-		REL_ERR_NOSWAP(lml, file, sym, rtype);
-		return (0);
-	}
-#endif
-
 	rep = &reloc_table[rtype];
 
 	switch (rep->re_fsize) {
@@ -192,10 +205,25 @@
 		/* LINTED */
 		*((uchar_t *)off) = (uchar_t)(*value);
 		break;
+
 	case 2:
+#if defined(DORELOC_NATIVE)
 		/* LINTED */
 		*((Half *)off) = (Half)(*value);
+#else
+		{
+			Half	v = (Half)(*value);
+			uchar_t	*v_bytes = (uchar_t *)&v;
+
+			if (bswap) {
+				UL_ASSIGN_BSWAP_HALF(off, v_bytes);
+			} else {
+				UL_ASSIGN_HALF(off, v_bytes);
+			}
+		}
+#endif
 		break;
+
 	case 4:
 		/*
 		 * The amd64 psABI requires that we perform the following
@@ -242,12 +270,48 @@
 				return (0);
 			}
 		}
+
+#if defined(DORELOC_NATIVE)
 		/* LINTED */
 		*((Word *)off) += *value;
+#else
+		{
+			Word	v;
+			uchar_t	*v_bytes = (uchar_t *)&v;
+
+			if (bswap) {
+				UL_ASSIGN_BSWAP_WORD(v_bytes, off);
+				v += *value;
+				UL_ASSIGN_BSWAP_WORD(off, v_bytes);
+			} else {
+				UL_ASSIGN_WORD(v_bytes, off);
+				v += *value;
+				UL_ASSIGN_WORD(off, v_bytes);
+			}
+		}
+#endif
 		break;
+
 	case 8:
+#if defined(DORELOC_NATIVE)
 		/* LINTED */
 		*((Xword *)off) += *value;
+#else
+		{
+			Xword	v;
+			uchar_t	*v_bytes = (uchar_t *)&v;
+
+			if (bswap) {
+				UL_ASSIGN_BSWAP_XWORD(v_bytes, off);
+				v += *value;
+				UL_ASSIGN_BSWAP_XWORD(off, v_bytes);
+			} else {
+				UL_ASSIGN_XWORD(v_bytes, off);
+				v += *value;
+				UL_ASSIGN_XWORD(off, v_bytes);
+			}
+		}
+#endif
 		break;
 	default:
 		/*
--- a/usr/src/uts/intel/amd64/krtld/relmach.h	Tue Mar 18 08:44:14 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (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 2004 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_RELMACH_H
-#define	_RELMACH_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Architecture specific flags presented in a architecture neutral format
- */
-#define	SHF_NEUT_SHORT	0
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _RELMACH_H */
--- a/usr/src/uts/intel/ia32/krtld/doreloc.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/uts/intel/ia32/krtld/doreloc.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -30,6 +30,11 @@
 #include	<sys/types.h>
 #include	"reloc.h"
 #else
+#define	ELF_TARGET_386
+#if defined(DO_RELOC_LIBLD)
+#undef DO_RELOC_LIBLD
+#define	DO_RELOC_LIBLD_X86
+#endif
 #include	<stdio.h>
 #include	"sgs.h"
 #include	"machdep.h"
@@ -40,50 +45,67 @@
 #endif
 
 /*
+ * We need to build this code differently when it is used for
+ * cross linking:
+ *	- Data alignment requirements can differ from those
+ *		of the running system, so we can't access data
+ *		in units larger than a byte
+ *	- We have to include code to do byte swapping when the
+ *		target and linker host use different byte ordering,
+ *		but such code is a waste when running natively.
+ */
+#if !defined(DO_RELOC_LIBLD) || defined(__i386) || defined(__amd64)
+#define	DORELOC_NATIVE
+#endif
+
+/*
  * This table represents the current relocations that do_reloc() is able to
  * process.  The relocations below that are marked SPECIAL are relocations that
  * take special processing and shouldn't actually ever be passed to do_reloc().
  */
 const Rel_entry	reloc_table[R_386_NUM] = {
-/* R_386_NONE */	{FLG_RE_NOTREL, 0},
-/* R_386_32 */		{FLG_RE_NOTREL, 4},
-/* R_386_PC32 */	{FLG_RE_PCREL, 4},
-/* R_386_GOT32 */	{FLG_RE_GOTADD, 4},
-/* R_386_PLT32 */	{FLG_RE_PLTREL | FLG_RE_PCREL, 4},
-/* R_386_COPY */	{FLG_RE_NOTREL, 0},			/* SPECIAL */
-/* R_386_GLOB_DAT */	{FLG_RE_NOTREL, 4},
-/* R_386_JMP_SLOT */	{FLG_RE_NOTREL, 4},			/* SPECIAL */
-/* R_386_RELATIVE */	{FLG_RE_NOTREL, 4},
-/* R_386_GOTOFF */	{FLG_RE_GOTREL, 4},
-/* R_386_GOTPC */	{FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4},
-/* R_386_32PLT */	{FLG_RE_PLTREL, 4},
-/* R_386_TLS_GD_PLT */	{FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSGD, 4},
-/* R_386_TLS_LDM_PLT */	{FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSLD, 4},
-/* R_386_TLS_TPOFF */	{FLG_RE_NOTREL, 4},
-/* R_386_TLS_IE */	{FLG_RE_GOTADD | FLG_RE_TLSIE, 4},
-/* R_386_TLS_GOTIE */	{FLG_RE_GOTADD | FLG_RE_TLSIE, 4},
-/* R_386_TLS_LE */	{FLG_RE_TLSLE, 4},
-/* R_386_TLS_GD */	{FLG_RE_GOTADD | FLG_RE_TLSGD, 4},
-/* R_386_TLS_LDM */	{FLG_RE_GOTADD | FLG_RE_TLSLD, 4},
-/* R_386_16 */		{FLG_RE_NOTREL, 2},
-/* R_386_PC16 */	{FLG_RE_PCREL, 2},
-/* R_386_8 */		{FLG_RE_NOTREL, 1},
-/* R_386_PC8 */		{FLG_RE_PCREL, 1},
-/* R_386_UNKNOWN24 */	{FLG_RE_NOTSUP, 0},
-/* R_386_UNKNOWN25 */	{FLG_RE_NOTSUP, 0},
-/* R_386_UNKNOWN26 */	{FLG_RE_NOTSUP, 0},
-/* R_386_UNKNOWN27 */	{FLG_RE_NOTSUP, 0},
-/* R_386_UNKNOWN28 */	{FLG_RE_NOTSUP, 0},
-/* R_386_UNKNOWN29 */	{FLG_RE_NOTSUP, 0},
-/* R_386_UNKNOWN30 */	{FLG_RE_NOTSUP, 0},
-/* R_386_UNKNOWN31 */	{FLG_RE_NOTSUP, 0},
-/* R_386_TLS_LDO_32 */	{FLG_RE_TLSLD, 4},
-/* R_386_UNKNOWN33 */	{FLG_RE_NOTSUP, 0},
-/* R_386_UNKNOWN34 */	{FLG_RE_NOTSUP, 0},
-/* R_386_TLS_DTPMOD32 */ {FLG_RE_NOTREL, 4},
-/* R_386_TLS_DTPOFF32 */ {FLG_RE_NOTREL, 4},
-/* R_386_UNKONWN37 */	{FLG_RE_NOTSUP, 0},
-/* R_386_SIZE32 */	{FLG_RE_SIZE | FLG_RE_VERIFY, 4}
+/* R_386_NONE */	{0, FLG_RE_NOTREL, 0, 0, 0},
+/* R_386_32 */		{0, FLG_RE_NOTREL, 4, 0, 0},
+/* R_386_PC32 */	{0, FLG_RE_PCREL, 4, 0, 0},
+/* R_386_GOT32 */	{0, FLG_RE_GOTADD, 4, 0, 0},
+/* R_386_PLT32 */	{0, FLG_RE_PLTREL | FLG_RE_PCREL, 4, 0, 0},
+/* R_386_COPY */	{0, FLG_RE_NOTREL, 0, 0, 0},		/* SPECIAL */
+/* R_386_GLOB_DAT */	{0, FLG_RE_NOTREL, 4, 0, 0},
+/* R_386_JMP_SLOT */	{0, FLG_RE_NOTREL, 4, 0, 0},		/* SPECIAL */
+/* R_386_RELATIVE */	{0, FLG_RE_NOTREL, 4, 0, 0},
+/* R_386_GOTOFF */	{0, FLG_RE_GOTREL, 4, 0, 0},
+/* R_386_GOTPC */	{0, FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4,
+			    0, 0},
+/* R_386_32PLT */	{0, FLG_RE_PLTREL, 4, 0, 0},
+/* R_386_TLS_GD_PLT */	{0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSGD, 4,
+			    0, 0},
+/* R_386_TLS_LDM_PLT */	{0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSLD, 4,
+			    0, 0},
+/* R_386_TLS_TPOFF */	{0, FLG_RE_NOTREL, 4, 0, 0},
+/* R_386_TLS_IE */	{0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 0, 0},
+/* R_386_TLS_GOTIE */	{0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 0, 0},
+/* R_386_TLS_LE */	{0, FLG_RE_TLSLE, 4, 0, 0},
+/* R_386_TLS_GD */	{0, FLG_RE_GOTADD | FLG_RE_TLSGD, 4, 0, 0},
+/* R_386_TLS_LDM */	{0, FLG_RE_GOTADD | FLG_RE_TLSLD, 4, 0, 0},
+/* R_386_16 */		{0, FLG_RE_NOTREL, 2, 0, 0},
+/* R_386_PC16 */	{0, FLG_RE_PCREL, 2, 0, 0},
+/* R_386_8 */		{0, FLG_RE_NOTREL, 1, 0, 0},
+/* R_386_PC8 */		{0, FLG_RE_PCREL, 1, 0, 0},
+/* R_386_UNKNOWN24 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_UNKNOWN25 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_UNKNOWN26 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_UNKNOWN27 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_UNKNOWN28 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_UNKNOWN29 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_UNKNOWN30 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_UNKNOWN31 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_TLS_LDO_32 */	{0, FLG_RE_TLSLD, 4, 0, 0},
+/* R_386_UNKNOWN33 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_UNKNOWN34 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_TLS_DTPMOD32 */ {0, FLG_RE_NOTREL, 4, 0, 0},
+/* R_386_TLS_DTPOFF32 */ {0, FLG_RE_NOTREL, 4, 0, 0},
+/* R_386_UNKONWN37 */	{0, FLG_RE_NOTSUP, 0, 0, 0},
+/* R_386_SIZE32 */	{0, FLG_RE_SIZE | FLG_RE_VERIFY, 4, 0, 0}
 };
 
 /*
@@ -168,6 +190,7 @@
 do_reloc_krtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
     const char *file)
 #elif defined(DO_RELOC_LIBLD)
+/*ARGSUSED5*/
 int
 do_reloc_ld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
     const char *file, int bswap, void *lml)
@@ -179,17 +202,6 @@
 {
 	const Rel_entry	*rep;
 
-#if defined(DO_RELOC_LIBLD)
-	/*
-	 * We do not support building the X86 linker as a cross linker
-	 * at this time.
-	 */
-	if (bswap) {
-		REL_ERR_NOSWAP(lml, file, sym, rtype);
-		return (0);
-	}
-#endif
-
 	rep = &reloc_table[rtype];
 
 	switch (rep->re_fsize) {
@@ -197,13 +209,49 @@
 		/* LINTED */
 		*((uchar_t *)off) += (uchar_t)(*value);
 		break;
+
 	case 2:
+#if defined(DORELOC_NATIVE)
 		/* LINTED */
 		*((Half *)off) += (Half)(*value);
+#else
+		{
+			Half	v;
+			uchar_t	*v_bytes = (uchar_t *)&v;
+
+			if (bswap) {
+				UL_ASSIGN_BSWAP_HALF(v_bytes, off);
+				v += *value;
+				UL_ASSIGN_BSWAP_HALF(off, v_bytes);
+			} else {
+				UL_ASSIGN_HALF(v_bytes, off);
+				v += *value;
+				UL_ASSIGN_HALF(off, v_bytes);
+			}
+		}
+#endif
 		break;
+
 	case 4:
+#if defined(DORELOC_NATIVE)
 		/* LINTED */
 		*((Xword *)off) += *value;
+#else
+		{
+			Word	v;
+			uchar_t	*v_bytes = (uchar_t *)&v;
+
+			if (bswap) {
+				UL_ASSIGN_BSWAP_WORD(v_bytes, off);
+				v += *value;
+				UL_ASSIGN_BSWAP_WORD(off, v_bytes);
+			} else {
+				UL_ASSIGN_WORD(v_bytes, off);
+				v += *value;
+				UL_ASSIGN_WORD(off, v_bytes);
+			}
+		}
+#endif
 		break;
 	default:
 		/*
--- a/usr/src/uts/intel/ia32/krtld/relmach.h	Tue Mar 18 08:44:14 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (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 (c) 1998-1999 by Sun Microsystems, Inc.
- * All rights reserved.
- */
-
-#ifndef	_RELMACH_H
-#define	_RELMACH_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Architecture specific flags presented in a architecture neutral format
- */
-#define	SHF_NEUT_SHORT	0
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _RELMACH_H */
--- a/usr/src/uts/intel/sys/Makefile	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/uts/intel/sys/Makefile	Tue Mar 18 09:17:00 2008 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -51,7 +51,6 @@
 	kd.h			\
 	kdi_machimpl.h		\
 	kdi_regs.h		\
-	machelf.h		\
 	machlock.h		\
 	machsig.h		\
 	machtypes.h		\
--- a/usr/src/uts/intel/sys/machelf.h	Tue Mar 18 08:44:14 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +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 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SYS_MACHELF_H
-#define	_SYS_MACHELF_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#if defined(__amd64)
-#include <sys/elf_amd64.h>
-#elif defined(__i386)
-#include <sys/elf_386.h>
-#endif
-#ifndef	_ASM
-#include <sys/types.h>
-#include <sys/elf.h>
-#include <sys/link.h>	/* for Elf*_Dyn */
-#endif	/* _ASM */
-
-/*
- * Make machine class dependent data types transparent to the common code
- */
-#if defined(_ELF64) && !defined(_ELF32_COMPAT)
-
-#ifndef	_ASM
-typedef	Elf64_Xword	Xword;
-typedef	Elf64_Lword	Lword;
-typedef	Elf64_Sxword	Sxword;
-typedef	Elf64_Word	Word;
-typedef	Elf64_Sword	Sword;
-typedef	Elf64_Half	Half;
-typedef	Elf64_Addr	Addr;
-typedef	Elf64_Off	Off;
-typedef	uchar_t		Byte;
-#endif	/* _ASM */
-
-#if defined(_KERNEL)
-#define	ELF_R_TYPE	ELF64_R_TYPE
-#define	ELF_R_SYM	ELF64_R_SYM
-#define	ELF_R_INFO	ELF64_R_INFO
-#define	ELF_ST_BIND	ELF64_ST_BIND
-#define	ELF_ST_TYPE	ELF64_ST_TYPE
-#define	ELF_M_SYM	ELF64_M_SYM
-#define	ELF_M_SIZE	ELF64_M_SIZE
-#endif
-
-#ifndef	_ASM
-typedef	Elf64_Ehdr	Ehdr;
-typedef	Elf64_Shdr	Shdr;
-typedef	Elf64_Sym	Sym;
-typedef	Elf64_Syminfo	Syminfo;
-typedef	Elf64_Rela	Rela;
-typedef	Elf64_Rel	Rel;
-typedef	Elf64_Nhdr	Nhdr;
-typedef	Elf64_Phdr	Phdr;
-typedef	Elf64_Dyn	Dyn;
-typedef	Elf64_Boot	Boot;
-typedef	Elf64_Verdef	Verdef;
-typedef	Elf64_Verdaux	Verdaux;
-typedef	Elf64_Verneed	Verneed;
-typedef	Elf64_Vernaux	Vernaux;
-typedef	Elf64_Versym	Versym;
-typedef	Elf64_Move	Move;
-typedef	Elf64_Cap	Cap;
-
-/*
- * Structure used to build the reloc_table[]
- */
-typedef struct {
-	Word		re_flags;	/* relocation attributes */
-	uchar_t		re_fsize;	/* field size (in bytes) */
-	uchar_t		re_sigbits;	/* number of significant bits */
-} Rel_entry;
-
-#endif	/* _ASM */
-
-#else	/* _ILP32 */
-
-#ifndef	_ASM
-typedef	Elf32_Word	Xword;	/* Xword/Sxword are 32-bits in Elf32 */
-typedef	Elf32_Lword	Lword;
-typedef	Elf32_Sword	Sxword;
-typedef	Elf32_Word	Word;
-typedef	Elf32_Sword	Sword;
-typedef	Elf32_Half	Half;
-typedef	Elf32_Addr	Addr;
-typedef	Elf32_Off	Off;
-typedef	uchar_t		Byte;
-#endif	/* _ASM */
-
-#if defined(_KERNEL)
-#define	ELF_R_TYPE	ELF32_R_TYPE
-#define	ELF_R_SYM	ELF32_R_SYM
-#define	ELF_R_INFO	ELF32_R_INFO
-#define	ELF_ST_BIND	ELF32_ST_BIND
-#define	ELF_ST_TYPE	ELF32_ST_TYPE
-#define	ELF_M_SYM	ELF32_M_SYM
-#define	ELF_M_SIZE	ELF32_M_SIZE
-#endif
-
-#ifndef	_ASM
-typedef	Elf32_Ehdr	Ehdr;
-typedef	Elf32_Shdr	Shdr;
-typedef	Elf32_Sym	Sym;
-typedef	Elf32_Syminfo	Syminfo;
-typedef	Elf32_Rela	Rela;
-typedef	Elf32_Rel	Rel;
-typedef	Elf32_Nhdr	Nhdr;
-typedef	Elf32_Phdr	Phdr;
-typedef	Elf32_Dyn	Dyn;
-typedef	Elf32_Boot	Boot;
-typedef	Elf32_Verdef	Verdef;
-typedef	Elf32_Verdaux	Verdaux;
-typedef	Elf32_Verneed	Verneed;
-typedef	Elf32_Vernaux	Vernaux;
-typedef	Elf32_Versym	Versym;
-typedef	Elf32_Move	Move;
-typedef	Elf32_Cap	Cap;
-
-/*
- * Structure used to build the reloc_table[]
- */
-typedef struct {
-	uint_t		re_flags;	/* relocation attributes */
-	uchar_t		re_fsize;	/* field size (in bytes) */
-} Rel_entry;
-
-#endif	/* _ASM */
-
-#endif	/* _ILP32 */
-
-/*
- * Elf `printf' type-cast macros.  These force arguments to be a fixed size
- * so that Elf32 and Elf64 can share common format strings.
- */
-#ifndef	__lint
-#define	EC_ADDR(a)	((Elf64_Addr)(a))		/* "ull" */
-#define	EC_OFF(a)	((Elf64_Off)(a))		/* "ull"  */
-#define	EC_HALF(a)	((Elf64_Half)(a))		/* "d"   */
-#define	EC_WORD(a)	((Elf64_Word)(a))		/* "u"   */
-#define	EC_SWORD(a)	((Elf64_Sword)(a))		/* "d"   */
-#define	EC_XWORD(a)	((Elf64_Xword)(a))		/* "ull" */
-#define	EC_SXWORD(a)	((Elf64_Sxword)(a))		/* "ll"  */
-#define	EC_LWORD(a)	((Elf64_Lword)(a))		/* "ull" */
-
-/*
- * A native pointer is special.  Although it can be convenient to display
- * these from a common format (ull), compilers may flag the cast of a pointer
- * to an integer as illegal.  Casting these pointers to the native pointer
- * size, suppresses any compiler errors.
- */
-#define	EC_NATPTR(a)	((Elf64_Xword)(uintptr_t)(a))	/* "ull" */
-#else
-#define	EC_ADDR(a)	((u_longlong_t)(a))
-#define	EC_OFF(a)	((u_longlong_t)(a))
-#define	EC_HALF(a)	((ushort_t)(a))
-#define	EC_WORD(a)	((uint_t)(a))
-#define	EC_SWORD(a)	((int)(a))
-#define	EC_XWORD(a)	((u_longlong_t)(a))
-#define	EC_SXWORD(a)	((longlong_t)(a))
-#define	EC_LWORD(a)	((u_longlong_t)(a))
-
-#define	EC_NATPTR(a)	((u_longlong_t)(a))
-#endif
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_MACHELF_H */
--- a/usr/src/uts/sparc/krtld/doreloc.c	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/uts/sparc/krtld/doreloc.c	Tue Mar 18 09:17:00 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -30,6 +30,11 @@
 #include	<sys/types.h>
 #include	"krtld/reloc.h"
 #else
+#define	ELF_TARGET_SPARC
+#if defined(DO_RELOC_LIBLD)
+#undef DO_RELOC_LIBLD
+#define	DO_RELOC_LIBLD_SPARC
+#endif
 #include	<stdio.h>
 #include	"sgs.h"
 #include	"machdep.h"
@@ -40,11 +45,25 @@
 #endif
 
 /*
+ * We need to build this code differently when it is used for
+ * cross linking:
+ *	- Data alignment requirements can differ from those
+ *		of the running system, so we can't access data
+ *		in units larger than a byte
+ *	- We have to include code to do byte swapping when the
+ *		target and linker host use different byte ordering,
+ *		but such code is a waste when running natively.
+ */
+#if !defined(DO_RELOC_LIBLD) || defined(__sparc)
+#define	DORELOC_NATIVE
+#endif
+
+/*
  * This table represents the current relocations that do_reloc() is able to
  * process.  The relocations below that are marked SPECIAL are relocations that
  * take special processing and shouldn't actually ever be passed to do_reloc().
  */
-const Rel_entry	reloc_table[R_SPARC_NUM] = {
+const Rel_entry reloc_table[R_SPARC_NUM] = {
 /* R_SPARC_NONE */	{0x0, FLG_RE_NOTREL, 0, 0, 0},
 /* R_SPARC_8 */		{0x0, FLG_RE_VERIFY, 1, 0, 0},
 /* R_SPARC_16 */	{0x0, FLG_RE_VERIFY, 2, 0, 0},
@@ -350,6 +369,7 @@
 do_reloc_krtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
     const char *file)
 #elif defined(DO_RELOC_LIBLD)
+/*ARGSUSED5*/
 int
 do_reloc_ld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
     const char *file, int bswap, void *lml)
@@ -359,23 +379,12 @@
     const char *file, void *lml)
 #endif
 {
-	Xword			uvalue = 0;
-	Xword			basevalue, sigbit_mask, sigfit_mask;
-	Xword			corevalue = *value;
-	uchar_t			bshift;
-	int			field_size, re_flags;
-	const Rel_entry *	rep;
-
-#if defined(DO_RELOC_LIBLD)
-	/*
-	 * We do not support building the sparc linker as a cross linker
-	 * at this time.
-	 */
-	if (bswap) {
-		REL_ERR_NOSWAP(lml, file, sym, rtype);
-		return (0);
-	}
-#endif
+	Xword	uvalue = 0;
+	Xword	basevalue, sigbit_mask, sigfit_mask;
+	Xword	corevalue = *value;
+	uchar_t	bshift;
+	int	field_size, re_flags;
+	const	Rel_entry	*rep;
 
 	rep = &reloc_table[rtype];
 	bshift = rep->re_bshift;
@@ -398,22 +407,62 @@
 		return (0);
 	}
 
-	if (re_flags & FLG_RE_UNALIGN) {
+	/*
+	 * We have two ways to retrieve the base value, a general one
+	 * that will work with data of any alignment, and another that is
+	 * fast, but which requires the data to be aligned according to
+	 * sparc alignment rules.
+	 *
+	 * For non-native linking, we always use the general path. For
+	 * native linking, the FLG_RE_UNALIGN determines it.
+	 */
+#if defined(DORELOC_NATIVE)
+	if (re_flags & FLG_RE_UNALIGN)
+#endif
+	{
 		int	i;
 		uchar_t	*dest = (uchar_t *)&basevalue;
 
-		/*
-		 * Adjust the offset.
-		 */
-		/* LINTED */
-		i = (int)(sizeof (Xword) - field_size);
-		if (i > 0)
-			dest += i;
+		basevalue = 0;
+#if !defined(DORELOC_NATIVE)
+		if (bswap) {
+			int j = field_size - 1;
+
+			for (i = 0; i < field_size; i++, j--)
+				dest[i] = off[j];
 
-		basevalue = 0;
-		for (i = field_size - 1; i >= 0; i--)
-			dest[i] = off[i];
-	} else {
+		} else
+#endif
+		{
+			/*
+			 * Adjust the offset
+			 */
+			/* LINTED */
+			i = (int)(sizeof (Xword) - field_size);
+			if (i > 0)
+				dest += i;
+			for (i = field_size - 1; i >= 0; i--)
+				dest[i] = off[i];
+		}
+	}
+
+	/*
+	 * Non-native linker: We have already fetched the value above,
+	 *	but if the relocation does not have the FLG_RE_UNALIGN
+	 *	flag set, we still need to do the same error checking we
+	 *	would do on a native linker.
+	 * Native-linker: If this is an aligned relocation, we need to
+	 *	fetch the value and also do the error checking.
+	 *
+	 * The FETCH macro is used to conditionalize the fetching so that
+	 * it only happens in the native case.
+	 */
+#if defined(DORELOC_NATIVE)
+#define	FETCH(_type) basevalue = (Xword)*((_type *)off);
+#else
+#define	FETCH(_type)
+#endif
+	if ((re_flags & FLG_RE_UNALIGN) == 0) {
 		if (((field_size == 2) && ((uintptr_t)off & 0x1)) ||
 		    ((field_size == 4) && ((uintptr_t)off & 0x3)) ||
 		    ((field_size == 8) && ((uintptr_t)off & 0x7))) {
@@ -422,19 +471,20 @@
 		}
 		switch (field_size) {
 		case 1:
-			basevalue = (Xword)*((uchar_t *)off);
+			/* LINTED */
+			FETCH(uchar_t);
 			break;
 		case 2:
 			/* LINTED */
-			basevalue = (Xword)*((Half *)off);
+			FETCH(Half);
 			break;
 		case 4:
 			/* LINTED */
-			basevalue = (Xword)*((Word *)off);
+			FETCH(Word);
 			break;
 		case 8:
 			/* LINTED */
-			basevalue = (Xword)*((Xword *)off);
+			FETCH(Xword);
 			break;
 		default:
 			REL_ERR_UNNOBITS(lml, file, sym, rtype,
@@ -442,6 +492,7 @@
 			return (0);
 		}
 	}
+#undef FETCH
 
 	if (sigbit_mask) {
 		/*
@@ -543,37 +594,68 @@
 	}
 	*value = corevalue;
 
-	if (re_flags & FLG_RE_UNALIGN) {
+	/*
+	 * Now, we store uvalue back at the location given by off.
+	 * This is similar to the fetch case above:
+	 *	- We have general (unaligned) and fast (aligned) cases
+	 *	- Cross linkers need to use the unaligned case even
+	 *		when the relocation does not specify FLG_RE_UNALIGN.
+	 *	- A cross linker that processes a relocation that does not
+	 *		have FLG_RE_UNALIGN set has to do the same error
+	 *		checking that a native linker would do, while avoiding
+	 *		the aligned store (accomplished with the STORE macro).
+	 */
+#if defined(DORELOC_NATIVE)
+	if (re_flags & FLG_RE_UNALIGN)
+#endif
+	{
 		int	i;
 		uchar_t	*src = (uchar_t *)&uvalue;
 
-		/*
-		 * Adjust the offset.
-		 */
-		/* LINTED */
-		i = (int)(sizeof (Xword) - field_size);
-		if (i > 0)
-			src += i;
+#if !defined(DORELOC_NATIVE)
+		if (bswap) {
+			int j = field_size - 1;
+
+			for (i = 0; i < field_size; i++, j--)
+				off[i] = src[j];
 
-		for (i = field_size - 1; i >= 0; i--)
-			off[i] = src[i];
-	} else {
+		} else
+#endif
+		{
+			/*
+			 * Adjust the offset.
+			 */
+			/* LINTED */
+			i = (int)(sizeof (Xword) - field_size);
+			if (i > 0)
+				src += i;
+			for (i = field_size - 1; i >= 0; i--)
+				off[i] = src[i];
+		}
+	}
+
+#if defined(DORELOC_NATIVE)
+#define	STORE(_type) *((_type *)off) = (_type)uvalue
+#else
+#define	STORE(_type)
+#endif
+	if ((re_flags & FLG_RE_UNALIGN) == 0) {
 		switch (rep->re_fsize) {
 		case 1:
 			/* LINTED */
-			*((uchar_t *)off) = (uchar_t)uvalue;
+			STORE(uchar_t);
 			break;
 		case 2:
 			/* LINTED */
-			*((Half *)off) = (Half)uvalue;
+			STORE(Half);
 			break;
 		case 4:
 			/* LINTED */
-			*((Word *)off) = uvalue;
+			STORE(Word);
 			break;
 		case 8:
 			/* LINTED */
-			*((Xword *)off) = uvalue;
+			STORE(Xword);
 			break;
 		default:
 			/*
@@ -583,5 +665,7 @@
 			return (0);
 		}
 	}
+#undef STORE
+
 	return (1);
 }
--- a/usr/src/uts/sparc/krtld/relmach.h	Tue Mar 18 08:44:14 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (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 (c) 1998-1999 by Sun Microsystems, Inc.
- * All rights reserved.
- */
-
-#ifndef	_RELMACH_H
-#define	_RELMACH_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Architecture specific flags presented in a architecture nutral format
- */
-#define	SHF_NEUT_SHORT	0
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _RELMACH_H */
--- a/usr/src/uts/sparc/sys/Makefile	Tue Mar 18 08:44:14 2008 -0700
+++ b/usr/src/uts/sparc/sys/Makefile	Tue Mar 18 09:17:00 2008 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -38,7 +38,6 @@
 	fsr.h		\
 	inline.h	\
 	kdi_machimpl.h	\
-	machelf.h	\
 	machlock.h	\
 	machsig.h	\
 	machtypes.h	\
--- a/usr/src/uts/sparc/sys/machelf.h	Tue Mar 18 08:44:14 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +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 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SYS_MACHELF_H
-#define	_SYS_MACHELF_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#include <sys/elf_SPARC.h>
-#ifndef	_ASM
-#include <sys/types.h>
-#include <sys/elf.h>
-#include <sys/link.h>	/* for Elf*_Dyn */
-#endif	/* _ASM */
-
-/*
- * Make machine class dependent data types transparent to the common code
- */
-#if defined(_ELF64) && !defined(_ELF32_COMPAT)
-
-#ifndef	_ASM
-typedef	Elf64_Xword	Xword;
-typedef	Elf64_Lword	Lword;
-typedef	Elf64_Sxword	Sxword;
-typedef	Elf64_Word	Word;
-typedef	Elf64_Sword	Sword;
-typedef	Elf64_Half	Half;
-typedef	Elf64_Addr	Addr;
-typedef	Elf64_Off	Off;
-typedef	uchar_t		Byte;
-#endif	/* _ASM */
-
-#if defined(_KERNEL)
-#define	ELF_R_TYPE	ELF64_R_TYPE
-#define	ELF_R_SYM	ELF64_R_SYM
-#define	ELF_R_TYPE_DATA ELF64_R_TYPE_DATA
-#define	ELF_R_INFO	ELF64_R_INFO
-#define	ELF_ST_BIND	ELF64_ST_BIND
-#define	ELF_ST_TYPE	ELF64_ST_TYPE
-#define	ELF_M_SYM	ELF64_M_SYM
-#define	ELF_M_SIZE	ELF64_M_SIZE
-#endif
-
-#ifndef	_ASM
-typedef	Elf64_Ehdr	Ehdr;
-typedef	Elf64_Shdr	Shdr;
-typedef	Elf64_Sym	Sym;
-typedef	Elf64_Syminfo	Syminfo;
-typedef	Elf64_Rela	Rela;
-typedef	Elf64_Rel	Rel;
-typedef	Elf64_Nhdr	Nhdr;
-typedef	Elf64_Phdr	Phdr;
-typedef	Elf64_Dyn	Dyn;
-typedef	Elf64_Boot	Boot;
-typedef	Elf64_Verdef	Verdef;
-typedef	Elf64_Verdaux	Verdaux;
-typedef	Elf64_Verneed	Verneed;
-typedef	Elf64_Vernaux	Vernaux;
-typedef	Elf64_Versym	Versym;
-typedef	Elf64_Move	Move;
-typedef	Elf64_Cap	Cap;
-#endif	/* _ASM */
-
-#else	/* _ILP32 */
-
-#ifndef	_ASM
-typedef	Elf32_Word	Xword;	/* Xword/Sxword are 32-bits in Elf32 */
-typedef	Elf32_Lword	Lword;
-typedef	Elf32_Sword	Sxword;
-typedef	Elf32_Word	Word;
-typedef	Elf32_Sword	Sword;
-typedef	Elf32_Half	Half;
-typedef	Elf32_Addr	Addr;
-typedef	Elf32_Off	Off;
-typedef	uchar_t		Byte;
-#endif	/* _ASM */
-
-#if defined(_KERNEL)
-#define	ELF_R_TYPE	ELF32_R_TYPE
-#define	ELF_R_SYM	ELF32_R_SYM
-#define	ELF_R_INFO	ELF32_R_INFO
-#define	ELF_R_TYPE_DATA(x)	(0)
-#define	ELF_ST_BIND	ELF32_ST_BIND
-#define	ELF_ST_TYPE	ELF32_ST_TYPE
-#define	ELF_M_SYM	ELF32_M_SYM
-#define	ELF_M_SIZE	ELF32_M_SIZE
-#endif
-
-#ifndef	_ASM
-typedef	Elf32_Ehdr	Ehdr;
-typedef	Elf32_Shdr	Shdr;
-typedef	Elf32_Sym	Sym;
-typedef	Elf32_Syminfo	Syminfo;
-typedef	Elf32_Rela	Rela;
-typedef	Elf32_Rel	Rel;
-typedef	Elf32_Nhdr	Nhdr;
-typedef	Elf32_Phdr	Phdr;
-typedef	Elf32_Dyn	Dyn;
-typedef	Elf32_Boot	Boot;
-typedef	Elf32_Verdef	Verdef;
-typedef	Elf32_Verdaux	Verdaux;
-typedef	Elf32_Verneed	Verneed;
-typedef	Elf32_Vernaux	Vernaux;
-typedef	Elf32_Versym	Versym;
-typedef	Elf32_Move	Move;
-typedef	Elf32_Cap	Cap;
-#endif	/* _ASM */
-
-#endif	/* _ILP32 */
-
-/*
- * Elf `printf' type-cast macros.  These force arguments to be a fixed size
- * so that Elf32 and Elf64 can share common format strings.
- */
-#ifndef	__lint
-#define	EC_ADDR(a)	((Elf64_Addr)(a))		/* "ull" */
-#define	EC_OFF(a)	((Elf64_Off)(a))		/* "ull"  */
-#define	EC_HALF(a)	((Elf64_Half)(a))		/* "d"   */
-#define	EC_WORD(a)	((Elf64_Word)(a))		/* "u"   */
-#define	EC_SWORD(a)	((Elf64_Sword)(a))		/* "d"   */
-#define	EC_XWORD(a)	((Elf64_Xword)(a))		/* "ull" */
-#define	EC_SXWORD(a)	((Elf64_Sxword)(a))		/* "ll"  */
-#define	EC_LWORD(a)	((Elf64_Lword)(a))		/* "ull" */
-
-/*
- * A native pointer is special.  Although it can be convenient to display
- * these from a common format (ull), compilers may flag the cast of a pointer
- * to an integer as illegal.  Casting these pointers to the native pointer
- * size, suppresses any compiler errors.
- */
-#define	EC_NATPTR(a)	((Elf64_Xword)(uintptr_t)(a))	/* "ull" */
-#else
-#define	EC_ADDR(a)	((u_longlong_t)(a))
-#define	EC_OFF(a)	((u_longlong_t)(a))
-#define	EC_HALF(a)	((ushort_t)(a))
-#define	EC_WORD(a)	((uint_t)(a))
-#define	EC_SWORD(a)	((int)(a))
-#define	EC_XWORD(a)	((u_longlong_t)(a))
-#define	EC_SXWORD(a)	((longlong_t)(a))
-#define	EC_LWORD(a)	((u_longlong_t)(a))
-
-#define	EC_NATPTR(a)	((u_longlong_t)(a))
-#endif
-
-#ifndef	_ASM
-/*
- * Structure used to build the reloc_table[]
- */
-typedef struct {
-	Xword		re_mask;	/* mask to apply to reloc */
-	Word		re_flags;	/* relocation attributes */
-	uchar_t		re_fsize;	/* field size (in bytes) */
-	uchar_t		re_bshift;	/* number of bits to shift */
-	uchar_t		re_sigbits;	/* number of significant bits */
-} Rel_entry;
-
-#endif	/* _ASM */
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_MACHELF_H */