]> Zhao Yanbai Git Server - minix.git/commitdiff
switch to netbsd csu
authorBen Gras <ben@minix3.org>
Fri, 30 Mar 2012 22:35:32 +0000 (00:35 +0200)
committerBen Gras <ben@minix3.org>
Thu, 12 Apr 2012 11:26:24 +0000 (13:26 +0200)
        . file- and functionality-compatible with previous situation
          (FreeBSD csu) (with a crt1.o -> crt0.o symlink in /usr/lib)
        . harmonizes source with netbsd
        . harmonizes linker invocation (e.g. clang) with netbsd
        . helpful to get some arm code in there for the arm port project

146 files changed:
common/include/sys/exec_elf.h
include/sys/Makefile
include/sys/cdefs_elf.h
include/sys/exec.h [new file with mode: 0644]
lib/csu/Makefile
lib/csu/README [new file with mode: 0644]
lib/csu/alpha/Makefile [new file with mode: 0644]
lib/csu/alpha/crt0.c [new file with mode: 0644]
lib/csu/alpha/crtfm.c [new file with mode: 0644]
lib/csu/alpha/dot_init.h [new file with mode: 0644]
lib/csu/arch/arm/Makefile.inc [new file with mode: 0644]
lib/csu/arch/arm/crt0.S [new file with mode: 0644]
lib/csu/arch/arm/crti.S [new file with mode: 0644]
lib/csu/arch/arm/crtn.S [new file with mode: 0644]
lib/csu/arch/i386/Makefile.inc [new file with mode: 0644]
lib/csu/arch/i386/crt0.S [new file with mode: 0644]
lib/csu/arch/i386/crtbegin.S [moved from lib/csu/i386-elf/crtbegin.S with 100% similarity]
lib/csu/arch/i386/crtend.S [moved from lib/csu/i386-elf/crtend.S with 100% similarity]
lib/csu/arch/i386/crti.S [new file with mode: 0644]
lib/csu/arch/i386/crtn.S [new file with mode: 0644]
lib/csu/arch/m68k/Makefile.inc [new file with mode: 0644]
lib/csu/arch/m68k/crt0.S [new file with mode: 0644]
lib/csu/arch/m68k/crti.S [new file with mode: 0644]
lib/csu/arch/m68k/crtn.S [new file with mode: 0644]
lib/csu/arch/sh3/Makefile.inc [new file with mode: 0644]
lib/csu/arch/sh3/crt0.S [moved from lib/csu/i386-elf/crtn.S with 60% similarity]
lib/csu/arch/sh3/crti.S [new file with mode: 0644]
lib/csu/arch/sh3/crtn.S [new file with mode: 0644]
lib/csu/arch/sparc/Makefile.inc [new file with mode: 0644]
lib/csu/arch/sparc/crt0.S [new file with mode: 0644]
lib/csu/arch/sparc/crti.S [new file with mode: 0644]
lib/csu/arch/sparc/crtn.S [new file with mode: 0644]
lib/csu/arch/vax/Makefile.inc [new file with mode: 0644]
lib/csu/arch/vax/crt0.S [new file with mode: 0644]
lib/csu/arch/vax/crti.S [new file with mode: 0644]
lib/csu/arch/vax/crtn.S [new file with mode: 0644]
lib/csu/arch/x86_64/Makefile.inc [new file with mode: 0644]
lib/csu/arch/x86_64/crt0.S [moved from lib/csu/i386-elf/crti.S with 58% similarity]
lib/csu/arch/x86_64/crtbegin.S [new file with mode: 0644]
lib/csu/arch/x86_64/crtend.S [new file with mode: 0644]
lib/csu/arch/x86_64/crti.S [new file with mode: 0644]
lib/csu/arch/x86_64/crtn.S [new file with mode: 0644]
lib/csu/arm_elf/Makefile [new file with mode: 0644]
lib/csu/arm_elf/crt0.c [new file with mode: 0644]
lib/csu/arm_elf/dot_init.h [new file with mode: 0644]
lib/csu/common/Makefile.inc [new file with mode: 0644]
lib/csu/common/crt0-common.c [new file with mode: 0644]
lib/csu/common/sysident.S [new file with mode: 0644]
lib/csu/common/sysident_assym.cf [new file with mode: 0644]
lib/csu/common_elf/Makefile.inc [new file with mode: 0644]
lib/csu/common_elf/common.c [new file with mode: 0644]
lib/csu/common_elf/common.h [new file with mode: 0644]
lib/csu/common_elf/crti.c [new file with mode: 0644]
lib/csu/common_elf/crtn.c [new file with mode: 0644]
lib/csu/common_elf/dot_init.h [new file with mode: 0644]
lib/csu/common_elf/dwarf2_eh.h [new file with mode: 0644]
lib/csu/hppa/Makefile [new file with mode: 0644]
lib/csu/hppa/crt0.c [new file with mode: 0644]
lib/csu/hppa/dot_init.h [new file with mode: 0644]
lib/csu/i386-elf/Makefile [deleted file]
lib/csu/ia64/Makefile [new file with mode: 0644]
lib/csu/ia64/crt0.c [new file with mode: 0644]
lib/csu/ia64/dot_init.h [new file with mode: 0644]
lib/csu/m68k_elf/Makefile [new file with mode: 0644]
lib/csu/m68k_elf/crt0.c [new file with mode: 0644]
lib/csu/m68k_elf/dot_init.h [new file with mode: 0644]
lib/csu/mips/Makefile [new file with mode: 0644]
lib/csu/mips/crt0.c [new file with mode: 0644]
lib/csu/mips/dot_init.h [new file with mode: 0644]
lib/csu/powerpc/Makefile [new file with mode: 0644]
lib/csu/powerpc/crt0.c [new file with mode: 0644]
lib/csu/powerpc/dot_init.h [new file with mode: 0644]
lib/csu/powerpc64/Makefile [new file with mode: 0644]
lib/csu/powerpc64/crt0.c [new file with mode: 0644]
lib/csu/powerpc64/dot_init.h [new file with mode: 0644]
lib/csu/sh3_elf/Makefile [new file with mode: 0644]
lib/csu/sh3_elf/crt0.c [new file with mode: 0644]
lib/csu/sh3_elf/dot_init.h [new file with mode: 0644]
lib/csu/sparc64/Makefile [new file with mode: 0644]
lib/csu/sparc64/crt0.c [new file with mode: 0644]
lib/csu/sparc_elf/Makefile [new file with mode: 0644]
lib/csu/sparc_elf/crt0.c [new file with mode: 0644]
lib/csu/sparc_elf/dot_init.h [new file with mode: 0644]
lib/csu/vax_elf/Makefile [new file with mode: 0644]
lib/csu/vax_elf/crt0.c [new file with mode: 0644]
lib/csu/vax_elf/dot_init.h [new file with mode: 0644]
lib/libc/net/nsdispatch.c
libexec/ld.elf_so/Makefile [new file with mode: 0644]
libexec/ld.elf_so/README [new file with mode: 0644]
libexec/ld.elf_so/TODO [new file with mode: 0644]
libexec/ld.elf_so/arch/alpha/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/alpha/alpha_reloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/alpha/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/arm/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/arm/mdreloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/arm/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/hppa/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/hppa/hppa_reloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/hppa/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/i386/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/i386/mdreloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/i386/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/m68k/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/m68k/mdreloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/m68k/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/mips/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/mips/mips_reloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/mips/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/powerpc/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/powerpc/ld.so.script [new file with mode: 0644]
libexec/ld.elf_so/arch/powerpc/ppc_reloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/powerpc/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/sh3/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/sh3/mdreloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/sh3/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/sparc/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/sparc/mdreloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/sparc/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/sparc64/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/sparc64/mdreloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/sparc64/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/vax/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/vax/mdreloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/vax/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/arch/x86_64/Makefile.inc [new file with mode: 0644]
libexec/ld.elf_so/arch/x86_64/mdreloc.c [new file with mode: 0644]
libexec/ld.elf_so/arch/x86_64/rtld_start.S [new file with mode: 0644]
libexec/ld.elf_so/debug.c [moved from lib/csu/i386-elf/crt1_c.c with 52% similarity]
libexec/ld.elf_so/debug.h [moved from lib/csu/i386-elf/crt1_s.S with 58% similarity]
libexec/ld.elf_so/expand.c [new file with mode: 0644]
libexec/ld.elf_so/headers.c [new file with mode: 0644]
libexec/ld.elf_so/ld.elf_so.1 [new file with mode: 0644]
libexec/ld.elf_so/load.c [new file with mode: 0644]
libexec/ld.elf_so/map_object.c [new file with mode: 0644]
libexec/ld.elf_so/paths.c [new file with mode: 0644]
libexec/ld.elf_so/reloc.c [new file with mode: 0644]
libexec/ld.elf_so/rtld.c [new file with mode: 0644]
libexec/ld.elf_so/rtld.h [new file with mode: 0644]
libexec/ld.elf_so/rtldenv.h [new file with mode: 0644]
libexec/ld.elf_so/search.c [new file with mode: 0644]
libexec/ld.elf_so/symbol.c [new file with mode: 0644]
libexec/ld.elf_so/sysident.h [new file with mode: 0644]
libexec/ld.elf_so/xmalloc.c [new file with mode: 0644]
libexec/ld.elf_so/xprintf.c [new file with mode: 0644]
share/mk/bsd.own.mk
tools/nbsd_ports

index e7815a74d16ec5218bb0577a639668362eeb8df2..0b86122374c2861fe654df3d3ec4d448666d5012 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: exec_elf.h,v 1.108 2010/12/24 12:41:43 skrll Exp $     */
+/*     $NetBSD: exec_elf.h,v 1.117 2011/08/03 00:22:05 enami Exp $     */
 
 /*-
  * Copyright (c) 1994 The NetBSD Foundation, Inc.
@@ -169,22 +169,22 @@ typedef struct {
 /* e_ident[EI_OSABI] */
 #define        ELFOSABI_SYSV           0       /* UNIX System V ABI */
 #define        ELFOSABI_HPUX           1       /* HP-UX operating system */
-#define ELFOSABI_NETBSD                2       /* NetBSD */
-#define ELFOSABI_LINUX         3       /* GNU/Linux */
-#define ELFOSABI_HURD          4       /* GNU/Hurd */
-#define ELFOSABI_86OPEN                5       /* 86Open */
-#define ELFOSABI_SOLARIS       6       /* Solaris */
-#define ELFOSABI_MONTEREY      7       /* Monterey */
-#define ELFOSABI_IRIX          8       /* IRIX */
-#define ELFOSABI_FREEBSD       9       /* FreeBSD */
-#define ELFOSABI_TRU64         10      /* TRU64 UNIX */
-#define ELFOSABI_MODESTO       11      /* Novell Modesto */
-#define ELFOSABI_OPENBSD       12      /* OpenBSD */
+#define        ELFOSABI_NETBSD         2       /* NetBSD */
+#define        ELFOSABI_LINUX          3       /* GNU/Linux */
+#define        ELFOSABI_HURD           4       /* GNU/Hurd */
+#define        ELFOSABI_86OPEN         5       /* 86Open */
+#define        ELFOSABI_SOLARIS        6       /* Solaris */
+#define        ELFOSABI_MONTEREY       7       /* Monterey */
+#define        ELFOSABI_IRIX           8       /* IRIX */
+#define        ELFOSABI_FREEBSD        9       /* FreeBSD */
+#define        ELFOSABI_TRU64          10      /* TRU64 UNIX */
+#define        ELFOSABI_MODESTO        11      /* Novell Modesto */
+#define        ELFOSABI_OPENBSD        12      /* OpenBSD */
 #define        ELFOSABI_OPENVMS        13      /* OpenVMS */
 #define        ELFOSABI_NSK            14      /* HP Non-Stop Kernel */
 #define        ELFOSABI_AROS           15      /* Amiga Research OS */
 /* Unofficial OSABIs follow */
-#define ELFOSABI_ARM           97      /* ARM */
+#define        ELFOSABI_ARM            97      /* ARM */
 #define        ELFOSABI_STANDALONE     255     /* Standalone (embedded) application */
 
 #define        ELFOSABI_NONE           ELFOSABI_SYSV
@@ -344,7 +344,12 @@ typedef struct {
 #define        PT_NUM          8
 
 #define        PT_LOOS         0x60000000      /* OS-specific range */
-#define        PT_GNU_EH_FRAME 0x6474e550      /* GNU-specific EH frame segment */
+
+/* GNU-specific */
+#define        PT_GNU_EH_FRAME 0x6474e550      /* EH frame segment */
+#define        PT_GNU_STACK    0x6474e551      /* Indicate executable stack */
+#define        PT_GNU_RELRO    0x6474e552      /* Make read-only after relocation */
+
 #define        PT_HIOS         0x6fffffff
 #define        PT_LOPROC       0x70000000      /* Processor-specific range */
 #define        PT_HIPROC       0x7fffffff
@@ -414,11 +419,11 @@ typedef struct {
 #define        SHT_LOOS        0x60000000      /* Operating system specific range */
 #define        SHT_SUNW_move   0x6ffffffa
 #define        SHT_SUNW_syminfo 0x6ffffffc
-#define SHT_SUNW_verdef        0x6ffffffd      /* Versions defined by file */
+#define        SHT_SUNW_verdef 0x6ffffffd      /* Versions defined by file */
 #define        SHT_GNU_verdef  SHT_SUNW_verdef
-#define SHT_SUNW_verneed 0x6ffffffe    /* Versions needed by file */
+#define        SHT_SUNW_verneed 0x6ffffffe     /* Versions needed by file */
 #define        SHT_GNU_verneed SHT_SUNW_verneed
-#define SHT_SUNW_versym        0x6fffffff      /* Symbol versions */
+#define        SHT_SUNW_versym 0x6fffffff      /* Symbol versions */
 #define        SHT_GNU_versym  SHT_SUNW_versym
 #define        SHT_HIOS        0x6fffffff
 #define        SHT_LOPROC      0x70000000      /* Processor-specific range */
@@ -459,7 +464,7 @@ typedef struct {
 /* Symbol Table index of the undefined symbol */
 #define        ELF_SYM_UNDEFINED       0
 
-#define STN_UNDEF              0       /* undefined index */
+#define        STN_UNDEF               0       /* undefined index */
 
 /* st_info: Symbol Bindings */
 #define        STB_LOCAL               0       /* local symbol */
@@ -571,7 +576,7 @@ typedef struct {
 } Elf32_Move;
 
 #define        ELF32_M_SYM(info)       ((info) >> 8)
-#define        ELF32_M_SIZE(info)      (info) & 0xff)
+#define        ELF32_M_SIZE(info)      ((info) & 0xff)
 #define        ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size))
 
 typedef struct {
@@ -583,7 +588,7 @@ typedef struct {
 } Elf64_Move;
 
 #define        ELF64_M_SYM(info)       ((info) >> 8)
-#define        ELF64_M_SIZE(info)      (info) & 0xff)
+#define        ELF64_M_SIZE(info)      ((info) & 0xff)
 #define        ELF64_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size))
 
 /*
@@ -657,12 +662,12 @@ typedef struct {
 #define        DT_NUM          29
 
 #define        DT_LOOS         0x60000000      /* Operating system specific range */
-#define DT_VERSYM      0x6ffffff0      /* Symbol versions */
+#define        DT_VERSYM       0x6ffffff0      /* Symbol versions */
 #define        DT_FLAGS_1      0x6ffffffb      /* ELF dynamic flags */
-#define DT_VERDEF      0x6ffffffc      /* Versions defined by file */
-#define DT_VERDEFNUM   0x6ffffffd      /* Number of versions defined by file */
-#define DT_VERNEED     0x6ffffffe      /* Versions needed by file */
-#define DT_VERNEEDNUM  0x6fffffff      /* Number of versions needed by file */
+#define        DT_VERDEF       0x6ffffffc      /* Versions defined by file */
+#define        DT_VERDEFNUM    0x6ffffffd      /* Number of versions defined by file */
+#define        DT_VERNEED      0x6ffffffe      /* Versions needed by file */
+#define        DT_VERNEEDNUM   0x6fffffff      /* Number of versions needed by file */
 #define        DT_HIOS         0x6fffffff
 #define        DT_LOPROC       0x70000000      /* Processor-specific range */
 #define        DT_HIPROC       0x7fffffff
@@ -741,20 +746,86 @@ typedef struct {
        Elf64_Word n_type;
 } Elf64_Nhdr;
 
-#define        ELF_NOTE_TYPE_ABI_TAG           1
+#define        ELF_NOTE_GNU_NAMESZ             4
+#define        ELF_NOTE_GNU_NAME               "GNU\0"
 
+/*
+ * GNU-specific note type: ABI tag
+ * name: GNU\0
+ * namesz: 4
+ * desc:
+ *     word[0]: OS tag
+ *     word[1]: major version
+ *     word[2]: minor version
+ *     word[3]: teeny version
+ * descsz: 16
+ */
 /* GNU-specific note name and description sizes */
-#define        ELF_NOTE_ABI_NAMESZ             4
+#define        ELF_NOTE_TYPE_ABI_TAG           1
+#define        ELF_NOTE_ABI_NAME               ELF_NOTE_GNU_NAME
+#define        ELF_NOTE_ABI_NAMESZ             ELF_NOTE_GNU_NAMESZ
 #define        ELF_NOTE_ABI_DESCSZ             16
-/* GNU-specific note name */
-#define        ELF_NOTE_ABI_NAME               "GNU\0"
-
 /* GNU-specific OS/version value stuff */
 #define        ELF_NOTE_ABI_OS_LINUX           0
 #define        ELF_NOTE_ABI_OS_HURD            1
 #define        ELF_NOTE_ABI_OS_SOLARIS         2
+#define        ELF_NOTE_ABI_OS_KFREEBSD        3
+#define        ELF_NOTE_ABI_OS_KNETBSD         4
 
-/* NetBSD-specific note type: Emulation name.  desc is emul name string. */
+/*
+ * GNU-specific note type: Hardware capabilities
+ * name: GNU\0
+ * namesz: 4
+ * desc:
+ *     word[0]: Number of entries
+ *     word[1]: Bitmask of enabled entries
+ *     Followed by a byte id, and a NUL terminated string per entry
+ * descsz: variable
+ */
+#define        ELF_NOTE_TYPE_GNU_HWCAP         2
+
+/*
+ * GNU-specific note type: Build ID generated by ld
+ * name: GNU\0
+ * desc:
+ *     word[0..4] SHA1 [default] 
+ * or
+ *     word[0..3] md5 or uuid
+ * descsz: 16 or 20
+ */
+#define        ELF_NOTE_TYPE_GNU_BUILD_ID      3
+
+/* SuSE-specific note type: version
+ * name: SuSE\0\0\0\0
+ * namesz: 8
+ * desc: 
+ *      word[0] = VVTTMMmm
+ *
+ *     V = version of following data
+ *     T = product type: [box, sles, nld, whatever]
+ *     M = product major version
+ *     m = product minor version
+ * descsz: 8
+ */
+#define        ELF_NOTE_TYPE_SUSE_TAG          0x45537553      /* SuSE in LE */
+/* SuSE-specific note name and description sizes */
+#define        ELF_NOTE_SUSE_NAMESZ            8
+#define        ELF_NOTE_SUSE_DESCSZ            8
+/* SuSE-specific note name */
+#define        ELF_NOTE_SUSE_NAME              "SuSE\0\0\0\0"
+
+/* NetBSD-specific note type: Emulation name.
+ * name: NetBSD\0\0
+ * namesz: 8
+ * desc: 
+ *      word[0]: MMmmrrpp00
+ *
+ *     M = major version
+ *     m = minor version
+ *     r = release ["",A-Z,Z[A-Z] but numeric]
+ *     p = patchlevel
+ * descsz: 4
+ */
 #define        ELF_NOTE_TYPE_NETBSD_TAG        1
 /* NetBSD-specific note name and description sizes */
 #define        ELF_NOTE_NETBSD_NAMESZ          7
@@ -762,26 +833,39 @@ typedef struct {
 /* NetBSD-specific note name */
 #define        ELF_NOTE_NETBSD_NAME            "NetBSD\0\0"
 
-/* NetBSD-specific note type: Checksum.  There should be 1 NOTE per PT_LOAD
-   section.  desc is a tuple of <phnum>(16),<chk-type>(16),<chk-value>. */
+/* NetBSD-specific note type: Checksum. 
+ * There should be 1 NOTE per PT_LOAD section.
+ * name: ???
+ * namesz: ???
+ * desc:
+ *     a tuple of <phnum>(16),<chk-type>(16),<chk-value>.
+ * descsz: ???
+ */
 #define        ELF_NOTE_TYPE_CHECKSUM_TAG      2
 #define        ELF_NOTE_CHECKSUM_CRC32         1
 #define        ELF_NOTE_CHECKSUM_MD5           2
 #define        ELF_NOTE_CHECKSUM_SHA1          3
 #define        ELF_NOTE_CHECKSUM_SHA256        4
 
-/* NetBSD-specific note type: PaX.  There should be 1 NOTE per executable.
-   section.  desc is a 32 bit bitmask */
-#define ELF_NOTE_TYPE_PAX_TAG          3
+/*
+ * NetBSD-specific note type: PaX.
+ * There should be 1 NOTE per executable.
+ * name: PaX\0
+ * namesz: 4
+ * desc:
+ *     word[0]: capability bitmask
+ * descsz: 4
+ */
+#define        ELF_NOTE_TYPE_PAX_TAG           3
 #define        ELF_NOTE_PAX_MPROTECT           0x01    /* Force enable Mprotect */
 #define        ELF_NOTE_PAX_NOMPROTECT         0x02    /* Force disable Mprotect */
 #define        ELF_NOTE_PAX_GUARD              0x04    /* Force enable Segvguard */
 #define        ELF_NOTE_PAX_NOGUARD            0x08    /* Force disable Servguard */
 #define        ELF_NOTE_PAX_ASLR               0x10    /* Force enable ASLR */
 #define        ELF_NOTE_PAX_NOASLR             0x20    /* Force disable ASLR */
-#define ELF_NOTE_PAX_NAMESZ            4
-#define ELF_NOTE_PAX_NAME              "PaX\0"
-#define ELF_NOTE_PAX_DESCSZ            4
+#define        ELF_NOTE_PAX_NAMESZ             4
+#define        ELF_NOTE_PAX_NAME               "PaX\0"
+#define        ELF_NOTE_PAX_DESCSZ             4
 
 /*
  * NetBSD-specific core file information.
@@ -865,6 +949,11 @@ struct netbsd_elfcore_procinfo {
 #define        Elf_Off         Elf32_Off
 #define        Elf_SOff        Elf32_SOff
 #define        Elf_Nhdr        Elf32_Nhdr
+#define        Elf_Verdef      Elf32_Verdef
+#define        Elf_Verdaux     Elf32_Verdaux
+#define        Elf_Verneed     Elf32_Verneed
+#define        Elf_Vernaux     Elf32_Vernaux
+#define        Elf_Versym      Elf32_Versym
 
 #define        ELF_R_SYM       ELF32_R_SYM
 #define        ELF_R_TYPE      ELF32_R_TYPE
@@ -886,6 +975,11 @@ struct netbsd_elfcore_procinfo {
 #define        Elf_Off         Elf64_Off
 #define        Elf_SOff        Elf64_SOff
 #define        Elf_Nhdr        Elf64_Nhdr
+#define        Elf_Verdef      Elf64_Verdef
+#define        Elf_Verdaux     Elf64_Verdaux
+#define        Elf_Verneed     Elf64_Verneed
+#define        Elf_Vernaux     Elf64_Vernaux
+#define        Elf_Versym      Elf64_Versym
 
 #define        ELF_R_SYM       ELF64_R_SYM
 #define        ELF_R_TYPE      ELF64_R_TYPE
@@ -944,13 +1038,18 @@ typedef struct {
 /*
  * These constants are used for Elf32_Verdef struct's version number.  
  */
-#define VER_DEF_NONE           0
+#define        VER_DEF_NONE            0
 #define        VER_DEF_CURRENT         1
 
+/*
+ * These constants are used for Elf32_Verdef struct's vd_ndx.
+ */
+#define        VER_DEF_IDX(x)          VER_NDX(x)
+
 /*
  * These constants are used for Elf32_Verdef struct's vd_flags.  
  */
-#define VER_FLG_BASE           0x1
+#define        VER_FLG_BASE            0x1
 #define        VER_FLG_WEAK            0x2
 
 /*
@@ -958,6 +1057,7 @@ typedef struct {
  */
 #define        VER_NDX_LOCAL           0
 #define        VER_NDX_GLOBAL          1
+#define        VER_NDX_GIVEN           2
 
 /*
  * These constants are used for Elf32_Verneed struct's version number.  
@@ -966,7 +1066,17 @@ typedef struct {
 #define        VER_NEED_CURRENT        1
 
 /*
- * GNU Extension hidding symb
+ * These constants are used for Elf32_Vernaux struct's vna_other.
+ */
+#define        VER_NEED_HIDDEN         VER_NDX_HIDDEN
+#define        VER_NEED_IDX(x)         VER_NDX(x)
+
+/* index */
+#define        VER_NDX_HIDDEN          0x8000
+#define        VER_NDX(x)              ((x) & ~VER_NDX_HIDDEN)
+
+/*
+ * GNU Extension hidding symbol
  */
 #define        VERSYM_HIDDEN           0x8000
 #define        VERSYM_VERSION          0x7fff
@@ -1019,18 +1129,18 @@ typedef Elf32_Versym    Elf64_Versym;
 
 #ifdef _KERNEL
 
-#define ELF_AUX_ENTRIES        14      /* Max size of aux array passed to loader */
-#define ELF32_NO_ADDR  (~(Elf32_Addr)0) /* Indicates addr. not yet filled in */
-#define ELF32_LINK_ADDR        ((Elf32_Addr)-2) /* advises to use link address */
-#define ELF64_NO_ADDR  (~(Elf64_Addr)0) /* Indicates addr. not yet filled in */
-#define ELF64_LINK_ADDR        ((Elf64_Addr)-2) /* advises to use link address */
+#define        ELF_AUX_ENTRIES 14      /* Max size of aux array passed to loader */
+#define        ELF32_NO_ADDR   (~(Elf32_Addr)0) /* Indicates addr. not yet filled in */
+#define        ELF32_LINK_ADDR ((Elf32_Addr)-2) /* advises to use link address */
+#define        ELF64_NO_ADDR   (~(Elf64_Addr)0) /* Indicates addr. not yet filled in */
+#define        ELF64_LINK_ADDR ((Elf64_Addr)-2) /* advises to use link address */
 
 #if defined(ELFSIZE) && (ELFSIZE == 64)
-#define ELF_NO_ADDR    ELF64_NO_ADDR
-#define ELF_LINK_ADDR  ELF64_LINK_ADDR
+#define        ELF_NO_ADDR     ELF64_NO_ADDR
+#define        ELF_LINK_ADDR   ELF64_LINK_ADDR
 #elif defined(ELFSIZE) && (ELFSIZE == 32)
-#define ELF_NO_ADDR    ELF32_NO_ADDR
-#define ELF_LINK_ADDR  ELF32_LINK_ADDR
+#define        ELF_NO_ADDR     ELF32_NO_ADDR
+#define        ELF_LINK_ADDR   ELF32_LINK_ADDR
 #endif
 
 #ifndef ELF32_EHDR_FLAGS_OK
@@ -1061,6 +1171,8 @@ struct elf_args {
 #include "opt_execfmt.h"
 #endif
 
+struct ps_strings;
+
 #ifdef EXEC_ELF32
 int    exec_elf32_makecmds(struct lwp *, struct exec_package *);
 int    elf32_copyargs(struct lwp *, struct exec_package *,
index 02af8846fcceec7127619554670a76b1ed6a6aa2..50c82258402335290322a971241c8d40ac646554 100644 (file)
@@ -35,7 +35,7 @@ INCS+=        ansi.h atomic.h \
        tree.h ttycom.h ttydefaults.h \
        types.h \
        ucontext.h ucred.h uio.h un.h unistd.h utsname.h uuid.h \
-       wait.h
+       wait.h exec.h
 
 INCSYMLINKS=\
        sys/fcntl.h ${NETBSDINCSDIR}/fcntl.h \
index e3e56a4368c53d8f34eafba9c98753caaf2753d7..4872136b65e9ffa1c43e7d3ab3d8e8245129a01f 100644 (file)
@@ -64,7 +64,7 @@
 #define        __weak_extern(sym)                                              \
     __asm(".weak " _C_LABEL_STRING(#sym));
 
-#if __GNUC_PREREQ__(4, 0) && !defined(__minix)
+#if __GNUC_PREREQ__(4, 0)
 #define        __weak_reference(sym)   __attribute__((__weakref__))
 #else
 #define        __weak_reference(sym)   ; __asm(".weak " _C_LABEL_STRING(#sym))
diff --git a/include/sys/exec.h b/include/sys/exec.h
new file mode 100644 (file)
index 0000000..9d2ce87
--- /dev/null
@@ -0,0 +1,298 @@
+/*     $NetBSD: exec.h,v 1.133 2011/03/04 22:25:32 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)exec.h      8.4 (Berkeley) 2/19/95
+ */
+
+/*-
+ * Copyright (c) 1993 Theo de Raadt.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1994 Christopher G. Demetriou
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)exec.h      8.4 (Berkeley) 2/19/95
+ */
+
+#ifndef _SYS_EXEC_H_
+#define _SYS_EXEC_H_
+
+struct pathbuf; /* from namei.h */
+
+
+/*
+ * The following structure is found at the top of the user stack of each
+ * user process. The ps program uses it to locate argv and environment
+ * strings. Programs that wish ps to display other information may modify
+ * it; normally ps_argvstr points to argv[0], and ps_nargvstr is the same
+ * as the program's argc. The fields ps_envstr and ps_nenvstr are the
+ * equivalent for the environment.
+ */
+struct ps_strings {
+       char    **ps_argvstr;   /* first of 0 or more argument strings */
+       int     ps_nargvstr;    /* the number of argument strings */
+       char    **ps_envstr;    /* first of 0 or more environment strings */
+       int     ps_nenvstr;     /* the number of environment strings */
+};
+
+#ifdef _KERNEL
+struct ps_strings32 {
+       uint32_t        ps_argvstr;     /* first of 0 or more argument strings */
+       int32_t         ps_nargvstr;    /* the number of argument strings */
+       uint32_t        ps_envstr;      /* first of 0 or more environment strings */
+       int32_t         ps_nenvstr;     /* the number of environment strings */
+};
+#endif
+
+/*
+ * the following structures allow execve() to put together processes
+ * in a more extensible and cleaner way.
+ *
+ * the exec_package struct defines an executable being execve()'d.
+ * it contains the header, the vmspace-building commands, the vnode
+ * information, and the arguments associated with the newly-execve'd
+ * process.
+ *
+ * the exec_vmcmd struct defines a command description to be used
+ * in creating the new process's vmspace.
+ */
+
+#include <sys/uio.h>
+
+struct lwp;
+struct proc;
+struct exec_package;
+struct vnode;
+
+typedef int (*exec_makecmds_fcn)(struct lwp *, struct exec_package *);
+
+struct execsw {
+       u_int   es_hdrsz;               /* size of header for this format */
+       exec_makecmds_fcn es_makecmds;  /* function to setup vmcmds */
+       union {                         /* probe function */
+               int (*elf_probe_func)(struct lwp *,
+                       struct exec_package *, void *, char *, vaddr_t *);
+               int (*ecoff_probe_func)(struct lwp *, struct exec_package *);
+               int (*mach_probe_func)(const char **);
+       } u;
+       struct  emul *es_emul;          /* os emulation */
+       int     es_prio;                /* entry priority */
+       int     es_arglen;              /* Extra argument size in words */
+                                       /* Copy arguments on the new stack */
+       int     (*es_copyargs)(struct lwp *, struct exec_package *,
+                       struct ps_strings *, char **, void *);
+                                       /* Set registers before execution */
+       void    (*es_setregs)(struct lwp *, struct exec_package *, vaddr_t);
+                                       /* Dump core */
+       int     (*es_coredump)(struct lwp *, void *);
+       int     (*es_setup_stack)(struct lwp *, struct exec_package *);
+};
+
+#define EXECSW_PRIO_ANY                0x000   /* default, no preference */
+#define EXECSW_PRIO_FIRST      0x001   /* this should be among first */
+#define EXECSW_PRIO_LAST       0x002   /* this should be among last */
+
+/* exec vmspace-creation command set; see below */
+struct exec_vmcmd_set {
+       u_int   evs_cnt;
+       u_int   evs_used;
+       struct  exec_vmcmd *evs_cmds;
+};
+
+#define        EXEC_DEFAULT_VMCMD_SETSIZE      9       /* # of cmds in set to start */
+
+struct exec_package {
+       const char *ep_name;            /* file's name */
+       const char *ep_kname;           /* kernel-side copy of file's name */
+       char *ep_resolvedname;          /* fully resolved path from namei */
+       void    *ep_hdr;                /* file's exec header */
+       u_int   ep_hdrlen;              /* length of ep_hdr */
+       u_int   ep_hdrvalid;            /* bytes of ep_hdr that are valid */
+       struct  exec_vmcmd_set ep_vmcmds;  /* vmcmds used to build vmspace */
+       struct  vnode *ep_vp;           /* executable's vnode */
+       struct  vattr *ep_vap;          /* executable's attributes */
+       vaddr_t ep_taddr;               /* process's text address */
+       vsize_t ep_tsize;               /* size of process's text */
+       vaddr_t ep_daddr;               /* process's data(+bss) address */
+       vsize_t ep_dsize;               /* size of process's data(+bss) */
+       vaddr_t ep_maxsaddr;            /* proc's max stack addr ("top") */
+       vaddr_t ep_minsaddr;            /* proc's min stack addr ("bottom") */
+       vsize_t ep_ssize;               /* size of process's stack */
+       vaddr_t ep_entry;               /* process's entry point */
+       vaddr_t ep_vm_minaddr;          /* bottom of process address space */
+       vaddr_t ep_vm_maxaddr;          /* top of process address space */
+       u_int   ep_flags;               /* flags; see below. */
+       size_t  ep_fa_len;              /* byte size of ep_fa */
+       struct exec_fakearg {
+               char *fa_arg;
+               size_t fa_len;
+       } *ep_fa;                       /* a fake args vector for scripts */
+       int     ep_fd;                  /* a file descriptor we're holding */
+       void    *ep_emul_arg;           /* emulation argument */
+       const struct    execsw *ep_esch;/* execsw entry */
+       struct vnode *ep_emul_root;     /* base of emulation filesystem */
+       struct vnode *ep_interp;        /* vnode of (elf) interpeter */
+       uint32_t ep_pax_flags;          /* pax flags */
+       char    *ep_path;               /* absolute path of executable */
+};
+#define        EXEC_INDIR      0x0001          /* script handling already done */
+#define        EXEC_HASFD      0x0002          /* holding a shell script */
+#define        EXEC_HASARGL    0x0004          /* has fake args vector */
+#define        EXEC_SKIPARG    0x0008          /* don't copy user-supplied argv[0] */
+#define        EXEC_DESTR      0x0010          /* destructive ops performed */
+#define        EXEC_32         0x0020          /* 32-bit binary emulation */
+#define        EXEC_FORCEAUX   0x0040          /* always use ELF AUX vector */
+
+struct exec_vmcmd {
+       int     (*ev_proc)(struct lwp *, struct exec_vmcmd *);
+                               /* procedure to run for region of vmspace */
+       vsize_t ev_len;         /* length of the segment to map */
+       vaddr_t ev_addr;        /* address in the vmspace to place it at */
+       struct  vnode *ev_vp;   /* vnode pointer for the file w/the data */
+       vsize_t ev_offset;      /* offset in the file for the data */
+       u_int   ev_prot;        /* protections for segment */
+       int     ev_flags;
+#define        VMCMD_RELATIVE  0x0001  /* ev_addr is relative to base entry */
+#define        VMCMD_BASE      0x0002  /* marks a base entry */
+#define        VMCMD_FIXED     0x0004  /* entry must be mapped at ev_addr */
+#define        VMCMD_STACK     0x0008  /* entry is for a stack */
+};
+
+#ifdef _KERNEL
+/*
+ * funtions used either by execve() or the various CPU-dependent execve()
+ * hooks.
+ */
+void   kill_vmcmd              (struct exec_vmcmd **);
+int    exec_makecmds           (struct lwp *, struct exec_package *);
+int    exec_runcmds            (struct lwp *, struct exec_package *);
+void   vmcmdset_extend         (struct exec_vmcmd_set *);
+void   kill_vmcmds             (struct exec_vmcmd_set *);
+int    vmcmd_map_pagedvn       (struct lwp *, struct exec_vmcmd *);
+int    vmcmd_map_readvn        (struct lwp *, struct exec_vmcmd *);
+int    vmcmd_readvn            (struct lwp *, struct exec_vmcmd *);
+int    vmcmd_map_zero          (struct lwp *, struct exec_vmcmd *);
+int    copyargs                (struct lwp *, struct exec_package *,
+                                   struct ps_strings *, char **, void *);
+int    copyin_psstrings        (struct proc *, struct ps_strings *);
+int    copy_procargs           (struct proc *, int, size_t *,
+    int (*)(void *, const void *, size_t, size_t), void *);
+void   setregs                 (struct lwp *, struct exec_package *, vaddr_t);
+int    check_veriexec          (struct lwp *, struct vnode *,
+                                    struct exec_package *, int);
+int    check_exec              (struct lwp *, struct exec_package *,
+                                    struct pathbuf *);
+int    exec_init               (int);
+int    exec_read_from          (struct lwp *, struct vnode *, u_long off,
+                                   void *, size_t);
+int    exec_setup_stack        (struct lwp *, struct exec_package *);
+
+int    coredump_write          (void *, enum uio_seg, const void *, size_t);
+/*
+ * Machine dependent functions
+ */
+struct core;
+struct core32;
+int    cpu_coredump(struct lwp *, void *, struct core *);
+int    cpu_coredump32(struct lwp *, void *, struct core32 *);
+
+int    exec_add(struct execsw *, int);
+int    exec_remove(struct execsw *, int);
+
+void   new_vmcmd(struct exec_vmcmd_set *,
+                   int (*)(struct lwp *, struct exec_vmcmd *),
+                   vsize_t, vaddr_t, struct vnode *, u_long, u_int, int);
+#define        NEW_VMCMD(evsp,lwp,len,addr,vp,offset,prot) \
+       new_vmcmd(evsp,lwp,len,addr,vp,offset,prot,0)
+#define        NEW_VMCMD2(evsp,lwp,len,addr,vp,offset,prot,flags) \
+       new_vmcmd(evsp,lwp,len,addr,vp,offset,prot,flags)
+
+typedef        int (*execve_fetch_element_t)(char * const *, size_t, char **);
+int    execve1(struct lwp *, const char *, char * const *, char * const *,
+    execve_fetch_element_t);
+
+extern int     maxexec;
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_EXEC_H_ */
index 7764c4b8129d3f6d01d07b282748561be2c5fc23..d212be07e26a4babd42531dc142dbdec23f778b0 100644 (file)
@@ -1,5 +1,33 @@
+#      $NetBSD: Makefile,v 1.28 2010/11/28 18:40:56 skrll Exp $
+
 .include <bsd.own.mk>
 
-SUBDIR=${ARCH}-elf
+CSU_MACHINE_ARCH?=     ${MACHINE_ARCH}
+
+.if ${USE_COMPILERCRTSTUFF} != "yes"
+
+ARCHDIR:=      ${.PARSEDIR}/arch/${CSU_MACHINE_ARCH}
+.PATH: ${ARCHDIR}
+.  include "${ARCHDIR}/Makefile.inc"
+
+.  include "${.PARSEDIR}/common/Makefile.inc"
+
+.else
+
+.  if exists(${CSU_MACHINE_ARCH}_elf/Makefile)
+SUBDIR=        ${CSU_MACHINE_ARCH}_elf
+.  elif exists(${CSU_MACHINE_ARCH}/Makefile)
+SUBDIR=        ${CSU_MACHINE_ARCH}
+.  elif exists(${MACHINE_CPU}_elf/Makefile)
+SUBDIR=        ${MACHINE_CPU}_elf
+.  elif exists(${MACHINE_CPU}/Makefile)
+SUBDIR=        ${MACHINE_CPU}
+.  else
+.BEGIN:
+       @echo no SUBDIR for ${MACHINE_ARCH}_elf, ${MACHINE_ARCH} nor \
+           ${MACHINE_CPU}
+       @false
+.  endif
 
-.include <bsd.subdir.mk>
+.  include <bsd.subdir.mk>
+.endif
diff --git a/lib/csu/README b/lib/csu/README
new file mode 100644 (file)
index 0000000..e552c52
--- /dev/null
@@ -0,0 +1,63 @@
+Overview of the common runtime support
+
+The common runtime support contains two modules, crtbegin and crtend.
+crtbegin is linked before all other object files of the program or
+dynamic library, crtend after all other object files.  They frame the
+lists of constructors, destructors, Java types and exception handling frames.
+
+If done correctly, crtend contains no code and is therefore position
+independent.  crtendS.o is therefore just a link to crtend.o.
+
+crtbegin should be position-independent code.  crtbeginT.o doesn't have
+to be PIC as it is statically linked.  The overhead is generally not
+worth the trouble though.
+
+
+Section types:
+.ctor: writeable
+.dtor: writeable
+.eh_frame: read-only if platform allows mixing read-only and read-write
+sections.  This is supported by GNU ld.
+.jcr: writeable
+.init: executable
+.fini: executable
+
+
+Non-local symbols:
+
+Weak references:
+- _Jv_RegisterClasses,
+- __cxa_finalize (crtbeginS.o)
+- __deregister_frame_info
+- __register_frame_info
+
+Hidden:
+- __dso_handle: pointer to self for crtbeginS.o, NULL otherwise.
+- __CTOR_LIST_END__
+
+
+Initialisation (called from .init):
+
+1.  Check that the init code hasn't started already, otherwise bail out.
+2.  If __register_frame_info is NULL, skip to 4
+3.  Call __register_frame_info with start of .eh_frame as first argument
+    and a data object of at least 8 pointers as second argument.
+4:  If _Jv_RegisterClasses is NULL, skip to 6
+5:  Call _Jv_RegisterClasses with the first pointer of the .jcr section
+    as argument.
+6:  Iterate from the end of the .ctor section to the start.  Skip the
+    terminating NULL and stop when reaching the starting (void *)-1 element.
+    Call the pointers as void (*)(void) functions.
+
+
+Deinitialisation (called from .fini):
+
+1.  Check if the init code has already started, otherwise bail out.
+2.  If this is not crtbeginS.o or __cxa_finalize is NULL, skip to 4.
+3.  Call __cxa_finalize with a pointer into this Dynamic Shared Object (DSO)
+    as first argument.
+4.  Iterate from the start of the .dtor section to the send.  Skip the
+    initial (void *)-1 and stop when reaching the terminating NULL element.
+    Call the pointers as void (*)(void) functions.
+5.  If __deregister_frame_info is NULL, return.
+6.  Call __deregister_frame_info with the start of .eh_frame as the argument.
diff --git a/lib/csu/alpha/Makefile b/lib/csu/alpha/Makefile
new file mode 100644 (file)
index 0000000..f619e3c
--- /dev/null
@@ -0,0 +1,18 @@
+#      $NetBSD: Makefile,v 1.24 2008/07/21 15:34:58 lukem Exp $
+
+.include <bsd.own.mk>
+
+ELFSIZE=       64
+
+#Uncomment the next line to enable the new .init fallthru
+CPPFLAGS+=     -I${.CURDIR}
+
+OBJS+= crtfm.o
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
+
+crtfm.o: crtfm.c
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.c} ${.ALLSRC} -o ${.TARGET}.o
+       ${LD} -x -r -o ${.TARGET} ${.TARGET}.o
+       rm -f ${.TARGET}.o
diff --git a/lib/csu/alpha/crt0.c b/lib/csu/alpha/crt0.c
new file mode 100644 (file)
index 0000000..58534d7
--- /dev/null
@@ -0,0 +1,90 @@
+/* $NetBSD: crt0.c,v 1.24 2003/07/26 19:24:25 salo Exp $ */
+
+/*
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+void __start __P((char **, void (*cleanup) __P((void)), const Obj_Entry *,
+               struct ps_strings *));
+
+void
+__start(sp, cleanup, obj, ps_strings)
+       char **sp;
+       void (*cleanup) __P((void));            /* from shared loader */
+       const Obj_Entry *obj;                   /* from shared loader */
+       struct ps_strings *ps_strings;
+{
+       long argc;
+       char **argv, *namep;
+
+       argc = *(long *)sp;
+       argv = sp + 1;
+       environ = sp + 2 + argc;                /* 2: argc + NULL ending argv */
+
+       if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(namep, '/')) == NULL)
+                       __progname = namep;
+               else
+                       __progname++;
+       }
+
+       if (ps_strings != (struct ps_strings *)0 &&
+           ps_strings != (struct ps_strings *)0xbabefacedeadbeef)
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       if (&_DYNAMIC != NULL)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.24 2003/07/26 19:24:25 salo Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/alpha/crtfm.c b/lib/csu/alpha/crtfm.c
new file mode 100644 (file)
index 0000000..cdfcfda
--- /dev/null
@@ -0,0 +1,68 @@
+/*     $NetBSD: crtfm.c,v 1.2 2002/01/14 01:31:00 thorpej Exp $        */
+
+/*
+ * Copyright (c) 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed for the NetBSD Project by
+ *     Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Support for the GCC "-ffast-math" option on the Alpha.
+ */
+
+#include <sys/types.h>
+
+#include <machine/fpu.h>
+#include <machine/sysarch.h>
+
+/*
+ * Must provide this wrapper around sysarch(2) so that statically-linked
+ * programs work properly.
+ */
+
+extern void __alpha_sysarch(int, void *);
+
+__asm(".ent __alpha_sysarch 0  ;\n"
+"__alpha_sysarch:              ;\n"
+"      ldiq    $0, 165         ;\n" /* v0 = SYS_sysarch */
+"      call_pal 0x0083         ;\n" /* PAL_OSF1_callsys */
+"      ret     $31,($26),1     ;\n"
+".end __alpha_sysarch");
+
+static void __attribute__((__constructor__))
+__alpha_set_fast_math(void)
+{
+       struct alpha_fp_c_args args;
+
+       args.fp_c = IEEE_MAP_DMZ|IEEE_MAP_UMZ;
+       __alpha_sysarch(ALPHA_SET_FP_C, &args);
+}
diff --git a/lib/csu/alpha/dot_init.h b/lib/csu/alpha/dot_init.h
new file mode 100644 (file)
index 0000000..1fd022a
--- /dev/null
@@ -0,0 +1,78 @@
+/* $NetBSD: dot_init.h,v 1.8 2008/05/10 15:31:03 martin Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+#include <machine/asm.h>
+
+#define        ASM_SETUP "sp = $30; gp = $29; pv = $27; ra = $26 \n"
+
+#define        MD_SECTION_PROLOGUE(sect, entry_pt)             \
+               __asm (                                 \
+               ASM_SETUP                               \
+               ".section "#sect",\"ax\",@progbits      \n"\
+               ".global "#entry_pt"                    \n"\
+               #entry_pt":                             \n"\
+               "       ldgp    gp, 0(pv)               \n"\
+               "       lda     sp, -32(sp)             \n"\
+               "       stq     ra, 0(sp)               \n"\
+               "       stq     gp, 8(sp)               \n"\
+               "       .align  5                       \n"\
+               "       /* fall thru */                 \n"\
+               ".previous")
+
+#define        MD_SECTION_EPILOGUE(sect)                       \
+               __asm (                                 \
+               ASM_SETUP                               \
+               ".section "#sect",\"ax\",@progbits      \n"\
+               "       ldq     gp, 8(sp)               \n"\
+               "       ldq     ra, 0(sp)               \n"\
+               "       lda     sp, 32(sp)              \n"\
+               "       RET                             \n"\
+               ".previous")
+
+#define        MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define        MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define        MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define        MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
+
+/* We assume we need to reload our GP. */
+#define MD_CALL_STATIC_FUNCTION(section, func) \
+__asm(".section " #section "\n"                \
+"    br $29, 1f                \n"             \
+"1:  ldgp $29, 0($29)  \n"             \
+"    unop              \n"             \
+"    jsr $26, " #func "\n"             \
+"    .align 3; .previous");
diff --git a/lib/csu/arch/arm/Makefile.inc b/lib/csu/arch/arm/Makefile.inc
new file mode 100644 (file)
index 0000000..7751943
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:33 joerg Exp $
+
+CPPFLAGS+=     -DELFSIZE=32
+
+
diff --git a/lib/csu/arch/arm/crt0.S b/lib/csu/arch/arm/crt0.S
new file mode 100644 (file)
index 0000000..4e71c18
--- /dev/null
@@ -0,0 +1,56 @@
+/*     $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:33 joerg Exp $   */
+
+/*
+ * Copyright (C) 1997 Mark Brinicombe
+ * Copyright (C) 1995 Wolfgang Solfrank.
+ * Copyright (C) 1995 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:33 joerg Exp $")
+
+STRONG_ALIAS(_start,__start)
+
+_ENTRY(__start)
+       mov     r5, r2          /* cleanup */
+       mov     r4, r1          /* obj_main */
+       mov     r3, r0          /* ps_strings */
+       /* Get argc, argv, and envp from stack */
+       ldr     r0, [sp, #0x0000]
+       add     r1, sp, #0x0004
+       add     r2, r1, r0, lsl #2
+       add     r2, r2, #0x0004
+
+       /* Ensure the stack is properly aligned before calling C code. */
+       bic     sp, sp, #7
+       sub     sp, sp, #8
+       str     r5, [sp, #4]
+       str     r4, [sp, #0]
+
+       b       ___start
diff --git a/lib/csu/arch/arm/crti.S b/lib/csu/arch/arm/crti.S
new file mode 100644 (file)
index 0000000..fe3ab87
--- /dev/null
@@ -0,0 +1,56 @@
+/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:33 joerg Exp $")
+
+#include "sysident.S"
+
+       .section ".init", "ax", @progbits
+       .align 0
+       .globl _init
+_init:
+       mov     ip, sp
+       stmfd   sp!, {fp, ip, lr, pc}
+       sub     fp, ip, #4
+
+       .section ".fini", "ax", @progbits
+       .align 0
+       .globl _fini
+_fini:
+       mov     ip, sp
+       stmfd   sp!, {fp, ip, lr, pc}
+       sub     fp, ip, #4
diff --git a/lib/csu/arch/arm/crtn.S b/lib/csu/arch/arm/crtn.S
new file mode 100644 (file)
index 0000000..8d85e09
--- /dev/null
@@ -0,0 +1,44 @@
+/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:33 joerg Exp $")
+
+       .section ".init", "ax", @progbits
+       ldmea   fp, {fp, sp, pc}
+
+       .section ".fini", "ax", @progbits
+       ldmea   fp, {fp, sp, pc}
diff --git a/lib/csu/arch/i386/Makefile.inc b/lib/csu/arch/i386/Makefile.inc
new file mode 100644 (file)
index 0000000..7751943
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:33 joerg Exp $
+
+CPPFLAGS+=     -DELFSIZE=32
+
+
diff --git a/lib/csu/arch/i386/crt0.S b/lib/csu/arch/i386/crt0.S
new file mode 100644 (file)
index 0000000..bc975d9
--- /dev/null
@@ -0,0 +1,53 @@
+/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */
+
+/*
+ * Copyright (c) 1998 Christos Zoulas
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:33 joerg Exp $")
+
+STRONG_ALIAS(_start,__start)
+_ENTRY(__start)
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       movl    12(%esp),%eax
+       leal    16(%esp),%edx
+       leal    20(%esp,%eax,4),%ecx
+       pushl   %ecx
+       pushl   %edx
+       pushl   %eax
+       call    ___start
diff --git a/lib/csu/arch/i386/crti.S b/lib/csu/arch/i386/crti.S
new file mode 100644 (file)
index 0000000..fbc5ddd
--- /dev/null
@@ -0,0 +1,54 @@
+/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:33 joerg Exp $")
+
+#include "sysident.S"
+
+       .section ".init", "ax", @progbits
+       .align 16
+       .globl _init
+_init:
+       pushl   %ebp
+       movl    %esp, %ebp
+
+       .section ".fini", "ax", @progbits
+       .align 16
+       .globl _fini
+_fini:
+       pushl   %ebp
+       movl    %esp, %ebp
diff --git a/lib/csu/arch/i386/crtn.S b/lib/csu/arch/i386/crtn.S
new file mode 100644 (file)
index 0000000..644d6a6
--- /dev/null
@@ -0,0 +1,46 @@
+/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+       .section ".init", "ax", @progbits
+       leave
+       ret
+
+       .section ".fini", "ax", @progbits
+       leave
+       ret
diff --git a/lib/csu/arch/m68k/Makefile.inc b/lib/csu/arch/m68k/Makefile.inc
new file mode 100644 (file)
index 0000000..ade4171
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+=     -DELFSIZE=32
+
+
diff --git a/lib/csu/arch/m68k/crt0.S b/lib/csu/arch/m68k/crt0.S
new file mode 100644 (file)
index 0000000..6d4d4e4
--- /dev/null
@@ -0,0 +1,52 @@
+#include <machine/asm.h>
+
+/*
+ * Copyright (c) 1999 Klaus Klein
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+STRONG_ALIAS(_start,__start)
+
+_ENTRY(__start)
+       movl    (%sp),%d0
+       movl    %a2,-(%sp)              | ps_strings
+       movl    %a0,-(%sp)              | obj
+       movl    %a1,-(%sp)              | cleanup
+       movl    %d0,%d1
+       lsll    #2,%d1
+       pea     (16+4)(%sp,%d1.l)       | envp = &argv[argc + 1]
+       pea     20(%sp)                 | argv
+       movl    %d0,-(%sp)              | argc
+       jsr     ___start
diff --git a/lib/csu/arch/m68k/crti.S b/lib/csu/arch/m68k/crti.S
new file mode 100644 (file)
index 0000000..df84a46
--- /dev/null
@@ -0,0 +1,50 @@
+/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+#include "sysident.S"
+
+       .section ".init", "ax", @progbits
+       .align 2
+       .globl _init
+_init:
+
+       .section ".fini", "ax", @progbits
+       .align 2
+       .globl _fini
+_fini:
diff --git a/lib/csu/arch/m68k/crtn.S b/lib/csu/arch/m68k/crtn.S
new file mode 100644 (file)
index 0000000..9614561
--- /dev/null
@@ -0,0 +1,44 @@
+/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+       .section ".init", "ax", @progbits
+       rts
+
+       .section ".fini", "ax", @progbits
+       rts
diff --git a/lib/csu/arch/sh3/Makefile.inc b/lib/csu/arch/sh3/Makefile.inc
new file mode 100644 (file)
index 0000000..ade4171
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+=     -DELFSIZE=32
+
+
similarity index 60%
rename from lib/csu/i386-elf/crtn.S
rename to lib/csu/arch/sh3/crt0.S
index ae0754726d6e83506f3ce6f3868d98e5bc7e7cfe..86ddcf52b2f0df0d1067e4290ae0fe2b61eb34ed 100644 (file)
@@ -1,7 +1,10 @@
-/*-
- * Copyright 1996, 1997, 1998, 2000 John D. Polstra.
+/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*
+ * Copyright (c) 1998 Christos Zoulas
+ * Copyright (c) 1995 Christopher G. Demetriou
  * All rights reserved.
- *
+ * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
  */
 
-       .section .init,"ax",@progbits
-       add     $12,%esp
-       ret
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
 
-       .section .fini,"ax",@progbits
-       add     $12,%esp
-       ret
+STRONG_ALIAS(_start,__start)
 
-       .section .rodata
-.ascii "$MINIX$\0"
+_ENTRY(__start)
+       mov.l   r9,@-r15
+       bra ___start
+       mov.l   r8,@-r15
diff --git a/lib/csu/arch/sh3/crti.S b/lib/csu/arch/sh3/crti.S
new file mode 100644 (file)
index 0000000..808c363
--- /dev/null
@@ -0,0 +1,56 @@
+/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+#include "sysident.S"
+
+       .section ".init", "ax", @progbits
+       .align 4
+       .globl _init
+_init:
+       mov.l   r14, @-sp
+       sts.l   pr, @-sp
+       mov     sp, r14
+
+       .section ".fini", "ax", @progbits
+       .align 4
+       .globl _fini
+_fini:
+       mov.l   r14, @-sp
+       sts.l   pr, @-sp
+       mov     sp, r14
diff --git a/lib/csu/arch/sh3/crtn.S b/lib/csu/arch/sh3/crtn.S
new file mode 100644 (file)
index 0000000..54edfb9
--- /dev/null
@@ -0,0 +1,50 @@
+/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+       .section ".init", "ax", @progbits
+       mov     r14, sp
+       lds.l   @sp+, pr
+       rts
+        mov.l  @sp+, r14
+
+       .section ".fini", "ax", @progbits
+       mov     r14, sp
+       lds.l   @sp+, pr
+       rts
+        mov.l  @sp+, r14
diff --git a/lib/csu/arch/sparc/Makefile.inc b/lib/csu/arch/sparc/Makefile.inc
new file mode 100644 (file)
index 0000000..ade4171
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+=     -DELFSIZE=32
+
+
diff --git a/lib/csu/arch/sparc/crt0.S b/lib/csu/arch/sparc/crt0.S
new file mode 100644 (file)
index 0000000..05b20c5
--- /dev/null
@@ -0,0 +1,56 @@
+/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*
+ * Copyright (c) 1998 Christos Zoulas
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+STRONG_ALIAS(_start,__start)
+
+_ENTRY(__start)
+       mov     0, %fp
+       ld      [%sp + 64], %o0         ! get argc
+       add     %sp, 68, %o1            ! get argv
+       sll     %o0, 2, %o2             !
+       add     %o2, 4, %o2             ! envp = argv + (argc << 2) + 4
+       add     %o1, %o2, %o2           !
+       andn    %sp, 7, %sp             ! align
+       sub     %sp, 24, %sp            ! expand to standard stack frame size
+       mov     %g3, %o3
+       mov     %g2, %o4
+       call    ___start
+        mov    %g1, %o5
diff --git a/lib/csu/arch/sparc/crti.S b/lib/csu/arch/sparc/crti.S
new file mode 100644 (file)
index 0000000..8f8128a
--- /dev/null
@@ -0,0 +1,78 @@
+/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*
+ * Copyright (c) 2001 Matthew R. Green
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+#include "sysident.S"
+
+       .section ".init", "ax", @progbits
+       .align 4
+       .globl _init
+_init:
+       save    %sp, -96, %sp
+
+       .section ".fini", "ax", @progbits
+       .align 4
+       .globl _fini
+_fini:
+       save    %sp, -96, %sp
diff --git a/lib/csu/arch/sparc/crtn.S b/lib/csu/arch/sparc/crtn.S
new file mode 100644 (file)
index 0000000..d86319a
--- /dev/null
@@ -0,0 +1,74 @@
+/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*
+ * Copyright (c) 2001 Matthew R. Green
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+       .section ".init", "ax", @progbits
+       .align 4
+       ret
+        restore
+
+       .section ".fini", "ax", @progbits
+       .align 4
+       ret
+        restore
diff --git a/lib/csu/arch/vax/Makefile.inc b/lib/csu/arch/vax/Makefile.inc
new file mode 100644 (file)
index 0000000..ade4171
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+=     -DELFSIZE=32
+
+
diff --git a/lib/csu/arch/vax/crt0.S b/lib/csu/arch/vax/crt0.S
new file mode 100644 (file)
index 0000000..2db43a5
--- /dev/null
@@ -0,0 +1,53 @@
+/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*
+ * Copyright (c) 1999 Matt Thomas
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+STRONG_ALIAS(_start,__start)
+
+_ENTRY(__start)
+       .word   0x0101
+       pushl   %r9             /* ps_strings */
+       pushl   %r8             /* obj */
+       pushl   %r7             /* cleanup */
+       movl    (%r6),%r0       /* argc */
+       pushal  8(%r6)[%r0]     /* envp = &argv[argc + 1] */
+       pushal  4(%r6)          /* argv */
+       pushl   %r0             /* argc */
+       calls   $6,___start
diff --git a/lib/csu/arch/vax/crti.S b/lib/csu/arch/vax/crti.S
new file mode 100644 (file)
index 0000000..6a55453
--- /dev/null
@@ -0,0 +1,52 @@
+/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+#include "sysident.S"
+
+       .section ".init", "ax", @progbits
+       .align 1
+       .globl _init
+_init:
+       .word 0
+
+       .section ".fini", "ax", @progbits
+       .align 1
+       .globl _fini
+_fini:
+       .word 0
diff --git a/lib/csu/arch/vax/crtn.S b/lib/csu/arch/vax/crtn.S
new file mode 100644 (file)
index 0000000..3cfb466
--- /dev/null
@@ -0,0 +1,44 @@
+/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+       .section ".init", "ax", @progbits
+       ret
+
+       .section ".fini", "ax", @progbits
+       ret
diff --git a/lib/csu/arch/x86_64/Makefile.inc b/lib/csu/arch/x86_64/Makefile.inc
new file mode 100644 (file)
index 0000000..2cb588f
--- /dev/null
@@ -0,0 +1,3 @@
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+=     -DELFSIZE=64
similarity index 58%
rename from lib/csu/i386-elf/crti.S
rename to lib/csu/arch/x86_64/crt0.S
index f06517c8812fad6a77dcfcf8114b3b5db9977adf..39bf6eec4d1906c3592f656d4b9da5d9bddb1b31 100644 (file)
@@ -1,7 +1,10 @@
-/*-
- * Copyright 1996, 1997, 1998, 2000 John D. Polstra.
+/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+
+/*
+ * Copyright (c) 1998 Christos Zoulas
+ * Copyright (c) 1995 Christopher G. Demetriou
  * All rights reserved.
- *
+ * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-       .section .init,"ax",@progbits
-       .align  4
-       .globl  _init
-       .type   _init,@function
-_init:
-       sub     $12,%esp        /* re-align stack pointer */
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
 
-       .section .fini,"ax",@progbits
-       .align  4
-       .globl  _fini
-       .type   _fini,@function
-_fini:
-       sub     $12,%esp        /* re-align stack pointer */
+STRONG_ALIAS(_start,__start)
 
-       .section .rodata
-.ascii "$MINIX$\0"
+_ENTRY(__start)
+       movq    %rbx,%r9
+       movq    %rcx,%r8
+       movq    %rdx,%rcx
+       movq    (%rsp),%rdi
+       leaq    16(%rsp,%rdi,8),%rdx
+       leaq    8(%rsp),%rsi
+       subq    $8,%rsp
+       andq    $~15,%rsp
+       addq    $8,%rsp
+       jmp     ___start
diff --git a/lib/csu/arch/x86_64/crtbegin.S b/lib/csu/arch/x86_64/crtbegin.S
new file mode 100644 (file)
index 0000000..7efba68
--- /dev/null
@@ -0,0 +1,156 @@
+/*     $NetBSD: crtbegin.S,v 1.2 2010/11/30 18:37:59 joerg Exp $       */
+/*-
+ * Copyright (c) 2010 Joerg Sonnenberger <joerg@NetBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crtbegin.S,v 1.2 2010/11/30 18:37:59 joerg Exp $")
+
+       .section        .ctors, "aw", @progbits
+       .align 8
+__CTOR_LIST__:
+       .quad -1
+
+       .section        .dtors, "aw", @progbits
+       .align 8
+__DTOR_LIST__:
+       .quad -1
+
+       .section        .eh_frame, "a", @progbits
+       .align 8
+__EH_FRAME_LIST__:
+
+       .section        .jcr, "aw", @progbits
+       .align 8
+__JCR_LIST__:
+
+       .section        .data.rel, "aw", @progbits
+       .align 8
+       .type   __dso_handle, @object
+       .size   __dso_handle, 8
+       .globl  __dso_handle
+       .hidden __dso_handle
+__dso_handle:
+#ifdef SHARED
+       .quad   __dso_handle
+#else
+       .quad   0
+#endif
+
+__dwarf_eh_object:
+       .zero   64
+
+__initialized:
+       .zero   1
+__finished:
+       .zero   1
+
+       .text
+       .weak   __cxa_finalize
+       .weak   __deregister_frame_info
+       .weak   __register_frame_info
+       .weak   _Jv_RegisterClasses
+
+__do_global_dtors_aux:
+       cmpb    $0, __finished(%rip)
+       je      1f
+       ret
+1:
+       pushq   %rbx
+       movb    $1, __finished(%rip)
+
+
+#ifdef SHARED
+       cmpq    $0, __cxa_finalize@GOTPCREL(%rip)
+       je      2f
+       movq    __dso_handle(%rip), %rdi
+       call    __cxa_finalize@PLT
+2:
+#endif
+
+       leaq    8+__DTOR_LIST__(%rip), %rbx
+3:
+       movq    (%rbx), %rax
+       testq   %rax, %rax
+       je      4f
+       call    *%rax
+       addq    $8, %rbx
+       jmp     3b      
+4:
+
+       cmpq    $0, __deregister_frame_info@GOTPCREL(%rip)
+       je      5f
+       leaq    __EH_FRAME_LIST__(%rip), %rdi
+       call    __deregister_frame_info@PLT
+5:
+       popq    %rbx
+       ret
+
+
+__do_global_ctors_aux:
+       cmpb    $0, __initialized(%rip)
+       je      1f
+       ret
+1:
+       pushq   %rbx
+       movb    $1, __initialized(%rip)
+
+       cmpq    $0, __register_frame_info@GOTPCREL(%rip)
+       je      2f
+       leaq    __dwarf_eh_object(%rip), %rsi
+       leaq    __EH_FRAME_LIST__(%rip), %rdi
+       call    __register_frame_info@PLT
+
+2:
+       cmpq    $0, _Jv_RegisterClasses@GOTPCREL(%rip)
+       je      3f
+       leaq    __JCR_LIST__(%rip), %rdi
+       cmpq    $0, (%rdi)
+       je      3f
+       call    _Jv_RegisterClasses@PLT
+3:
+
+       leaq    -8+__CTOR_LIST_END__(%rip), %rbx
+4:
+       movq    (%rbx), %rax
+       cmpq    $-1, %rax
+       je      5f
+       call    *%rax
+       subq    $8, %rbx
+       jmp     4b
+
+5:
+       popq    %rbx
+
+       ret
+
+       .section        .init, "ax", @progbits
+       call    __do_global_ctors_aux
+       .section        .fini, "ax", @progbits
+       call    __do_global_dtors_aux
diff --git a/lib/csu/arch/x86_64/crtend.S b/lib/csu/arch/x86_64/crtend.S
new file mode 100644 (file)
index 0000000..ae7f1e4
--- /dev/null
@@ -0,0 +1,52 @@
+/*     $NetBSD: crtend.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */
+/*-
+ * Copyright (c) 2010 Joerg Sonnenberger <joerg@NetBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crtend.S,v 1.1 2010/08/07 18:01:34 joerg Exp $")
+
+       .section        .ctors, "aw", @progbits
+       .align 8
+       .global         __CTOR_LIST_END__
+       .hidden         __CTOR_LIST_END__
+__CTOR_LIST_END__:
+       .quad 0
+
+       .section        .dtors, "aw", @progbits
+       .align 8
+       .quad 0
+
+       .section        .eh_frame, "a", @progbits
+       .align 8
+       .quad 0
+
+       .section        .jcr, "aw", @progbits
+       .align 8
+       .quad 0
diff --git a/lib/csu/arch/x86_64/crti.S b/lib/csu/arch/x86_64/crti.S
new file mode 100644 (file)
index 0000000..1b00f5a
--- /dev/null
@@ -0,0 +1,52 @@
+/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:35 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:35 joerg Exp $")
+
+#include "sysident.S"
+
+       .section ".init", "ax", @progbits
+       .align 16
+       .globl _init
+_init:
+       subq    $8, %rsp
+
+       .section ".fini", "ax", @progbits
+       .align 16
+       .globl _fini
+_fini:
+       subq    $8, %rsp
diff --git a/lib/csu/arch/x86_64/crtn.S b/lib/csu/arch/x86_64/crtn.S
new file mode 100644 (file)
index 0000000..3119cbd
--- /dev/null
@@ -0,0 +1,46 @@
+/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:35 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:35 joerg Exp $")
+
+       .section ".init", "ax", @progbits
+       addq    $8, %rsp
+       ret
+
+       .section ".fini", "ax", @progbits
+       addq    $8, %rsp
+       ret
diff --git a/lib/csu/arm_elf/Makefile b/lib/csu/arm_elf/Makefile
new file mode 100644 (file)
index 0000000..d357eee
--- /dev/null
@@ -0,0 +1,8 @@
+#      $NetBSD: Makefile,v 1.4 2006/05/19 19:11:12 christos Exp $
+CPPFLAGS+= -I${.CURDIR}
+
+# Temporary hack to work around ld problems when linking Thumb applications
+# where the linker does not correctly insert an interworking veneer.
+CFLAGS+=-mlong-calls
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/arm_elf/crt0.c b/lib/csu/arm_elf/crt0.c
new file mode 100644 (file)
index 0000000..fa2aa2b
--- /dev/null
@@ -0,0 +1,109 @@
+/*     $NetBSD: crt0.c,v 1.7 2008/06/21 00:52:52 gmcgarry Exp $        */
+
+/*
+ * Copyright (C) 1997 Mark Brinicombe
+ * Copyright (C) 1995 Wolfgang Solfrank.
+ * Copyright (C) 1995 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+
+#include <machine/asm.h>
+#include <stdlib.h>
+
+#include "common.h"
+
+extern void            _start(void);
+       void            ___start(int, char *[], char *[], struct ps_strings *,
+                               const Obj_Entry *, void (*)(void));
+
+__asm("        .text                   \n"
+"      .align  0               \n"
+"      .globl  _start          \n"
+"      .globl  __start         \n"
+"_start:                       \n"
+"__start:                      \n"
+"      mov     r5, r2          /* cleanup */           \n"
+"      mov     r4, r1          /* obj_main */          \n"
+"      mov     r3, r0          /* ps_strings */        \n"
+"      /* Get argc, argv, and envp from stack */       \n"
+"      ldr     r0, [sp, #0x0000]       \n"
+"      add     r1, sp, #0x0004         \n"
+"      add     r2, r1, r0, lsl #2      \n"
+"      add     r2, r2, #0x0004         \n"
+"\n"
+"      /* Ensure the stack is properly aligned before calling C code. */\n"
+"      bic     sp, sp, #" ___STRING(STACKALIGNBYTES) " \n"
+"      sub     sp, sp, #8      \n"
+"      str     r5, [sp, #4]    \n"
+"      str     r4, [sp, #0]    \n"
+"\n"
+"      b       " ___STRING(_C_LABEL(___start)) " ");
+
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.7 2008/06/21 00:52:52 gmcgarry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+void
+___start(int argc, char **argv, char **envp, struct ps_strings *ps_strings,
+       const Obj_Entry *obj, void (*cleanup)(void))
+{
+       char *ap;
+
+       environ = envp;
+       __ps_strings = ps_strings;
+
+       if ((ap = argv[0])) {
+               if ((__progname = _strrchr(ap, '/')) == NULL)
+                       __progname = ap;
+               else
+                       ++__progname;
+       }
+
+#ifdef DYNAMIC
+       /* ld(1) convention: if DYNAMIC = 0 then statically linked */
+       if (&_DYNAMIC)
+                _rtld_setup(cleanup, obj);
+#endif /* DYNAMIC */
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif /* MCRT0 */
+
+       atexit(_fini);
+       _init();
+
+__asm("__callmain:");          /* Defined for the benefit of debuggers */
+       exit(main(argc, argv, envp));
+}
+
+#include "common.c"
+
diff --git a/lib/csu/arm_elf/dot_init.h b/lib/csu/arm_elf/dot_init.h
new file mode 100644 (file)
index 0000000..275185a
--- /dev/null
@@ -0,0 +1,61 @@
+/* $NetBSD: dot_init.h,v 1.6 2008/05/10 15:31:03 martin Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+#include <machine/asm.h>
+
+#define        MD_SECTION_PROLOGUE(sect, entry_pt)             \
+               __asm (                                 \
+               ".section "#sect",\"ax\",%progbits      \n"\
+               ".global "#entry_pt"                    \n"\
+               "       .align  0                       \n"\
+               #entry_pt":                             \n"\
+               "mov    ip, sp                          \n"\
+               "stmfd  sp!, {fp, ip, lr, pc}           \n"\
+               "sub    fp, ip, #4                      \n"\
+               "       /* fall thru */                 \n"\
+               ".previous")
+
+#define        MD_SECTION_EPILOGUE(sect)                       \
+               __asm (                                 \
+               ".section "#sect",\"ax\",%progbits      \n"\
+               "ldmea  fp, {fp, sp, pc}                \n"\
+               ".previous")
+
+#define        MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define        MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define        MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define        MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
diff --git a/lib/csu/common/Makefile.inc b/lib/csu/common/Makefile.inc
new file mode 100644 (file)
index 0000000..b780992
--- /dev/null
@@ -0,0 +1,87 @@
+#      $NetBSD: Makefile.inc,v 1.2 2010/12/07 19:51:02 joerg Exp $
+
+.include <bsd.own.mk>
+
+COMMON_DIR:=   ${.PARSEDIR}
+.PATH:         ${COMMON_DIR}
+
+CPPFLAGS+=     -I${NETBSDSRCDIR}/libexec/ld.elf_so -I${COMMON_DIR} -I.
+
+OBJS+=         crt0.o gcrt0.o crti.o crtn.o
+OBJS+=         crtbegin.o crtbeginS.o crtend.o
+
+realall: ${OBJS}
+
+crtbegin.o: crtbegin.S
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.S} ${ARCHDIR}/crtbegin.S -o ${.TARGET}.o
+       ${LD} -x -r -o ${.TARGET} ${.TARGET}.o
+       rm -f ${.TARGET}.o
+.if ${MKSTRIPIDENT} != "no"
+       ${OBJCOPY} -R .ident ${.TARGET}
+.endif
+
+crtbeginS.o: crtbegin.S
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.S} -DSHARED ${ARCHDIR}/crtbegin.S -o ${.TARGET}.o
+       ${LD} -x -r -o ${.TARGET} ${.TARGET}.o
+       rm -f ${.TARGET}.o
+.if ${MKSTRIPIDENT} != "no"
+       ${OBJCOPY} -R .ident ${.TARGET}
+.endif
+
+crtend.o: crtend.S
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.S} ${ARCHDIR}/crtend.S -o ${.TARGET}.o
+       ${LD} -x -r -o ${.TARGET} ${.TARGET}.o
+       rm -f ${.TARGET}.o
+.if ${MKSTRIPIDENT} != "no"
+       ${OBJCOPY} -R .ident ${.TARGET}
+.endif
+
+.if ${MKPIC} != "no"
+PICFLAGS=      -fPIC
+.else
+PICFLAGS=
+.endif
+
+crt0.o: crt0-common.c crt0.S
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.c} ${PICFLAGS} ${COMMON_DIR}/crt0-common.c -o ${.TARGET}.c.o
+       ${COMPILE.S} ${ARCHDIR}/crt0.S -o ${.TARGET}.S.o
+       ${LD} -x -r -o ${.TARGET} ${.TARGET}.c.o ${.TARGET}.S.o
+       rm -f ${.TARGET}.c.o ${.TARGET}.S.o
+.if ${MKSTRIPIDENT} != "no"
+       ${OBJCOPY} -R .ident ${.TARGET}
+.endif
+
+gcrt0.o: crt0-common.c crt0.S
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.c} ${PICFLAGS} -DMCRT0 ${COMMON_DIR}/crt0-common.c -o ${.TARGET}.c.o
+       ${COMPILE.S} ${ARCHDIR}/crt0.S -o ${.TARGET}.S.o
+       ${LD} -x -r -o ${.TARGET} ${.TARGET}.c.o ${.TARGET}.S.o
+       rm -f ${.TARGET}.c.o ${.TARGET}.S.o
+.if ${MKSTRIPIDENT} != "no"
+       ${OBJCOPY} -R .ident ${.TARGET}
+.endif
+
+sysident_assym.h: ${GENASSYM_CONF} ${GENASSYM_EXTRAS}
+       ${_MKTARGET_CREATE}
+       cat ${COMMON_DIR}/sysident_assym.cf | \
+           ${TOOL_GENASSYM} -- ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} \
+           > sysident_assym.h.tmp && \
+       mv -f sysident_assym.h.tmp sysident_assym.h
+
+CLEANFILES+=   sysident_assym.h
+
+crti.o: crti.S sysident_assym.h
+crtn.o: crtn.S
+
+FILES=${OBJS}
+FILESDIR=${LIBDIR}
+CLEANFILES+=${OBJS}
+SYMLINKS+=     crtbegin.o ${LIBDIR}/crtbeginT.o
+SYMLINKS+=     crtend.o ${LIBDIR}/crtendS.o
+SYMLINKS+=     crt0.o ${LIBDIR}/crt1.o
+
+.include <bsd.prog.mk>
diff --git a/lib/csu/common/crt0-common.c b/lib/csu/common/crt0-common.c
new file mode 100644 (file)
index 0000000..77e1a09
--- /dev/null
@@ -0,0 +1,137 @@
+/* $NetBSD: crt0-common.c,v 1.1 2010/08/07 18:01:33 joerg Exp $ */
+
+/*
+ * Copyright (c) 1998 Christos Zoulas
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: crt0-common.c,v 1.1 2010/08/07 18:01:33 joerg Exp $");
+
+#include <sys/types.h>
+#ifndef __minix
+#include <sys/syscall.h>
+#endif
+#include <machine/profile.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "rtld.h"
+
+extern int main(int, char **, char **);
+
+extern void    _init(void);
+extern void    _fini(void);
+
+/*
+ * Arrange for _DYNAMIC to be weak and undefined (and therefore to show up
+ * as being at address zero, unless something else defines it).  That way,
+ * if we happen to be compiling without -static but with without any
+ * shared libs present, things will still work.
+ */
+
+#if __GNUC_PREREQ__(4,2)
+static int rtld_DYNAMIC __attribute__((__weakref__, __alias__("_DYNAMIC")));
+#define        DYNAMIC_SYM     rtld_DYNAMIC
+#else
+extern int _DYNAMIC __weak_reference(_DYNAMIC);
+#define        DYNAMIC_SYM     _DYNAMIC
+#endif
+
+#ifdef MCRT0
+extern void    monstartup(u_long, u_long);
+extern void    _mcleanup(void);
+extern unsigned char __etext, __eprol;
+#endif /* MCRT0 */
+
+char           **environ;
+struct ps_strings *__ps_strings = 0;
+
+static char     empty_string[] = "";
+char           *__progname = empty_string;
+
+void           ___start(int, char **, char **, void (*)(void),
+    const Obj_Entry *, struct ps_strings *);
+
+#ifndef __minix
+#define        write(fd, s, n) __syscall(SYS_write, (fd), (s), (n))
+#else
+#define        write(fd, s, n) /* NO write() from here on minix */
+#endif
+
+#define        _FATAL(str)                             \
+do {                                           \
+       write(2, str, sizeof(str)-1);           \
+       _exit(1);                               \
+} while (0)
+
+void
+___start(int argc, char **argv, char **envp,
+    void (*cleanup)(void),                     /* from shared loader */
+    const Obj_Entry *obj,                      /* from shared loader */
+    struct ps_strings *ps_strings)
+{
+       environ = envp;
+
+       if (argv[0] != NULL) {
+               char *c;
+               __progname = argv[0];
+               for (c = argv[0]; *c; ++c) {
+                       if (*c == '/')
+                               __progname = c + 1;
+               }
+       } else {
+               __progname = empty_string;
+       }
+
+       if (ps_strings != NULL)
+               __ps_strings = ps_strings;
+
+       if (&DYNAMIC_SYM != NULL) {
+               if ((obj == NULL) || (obj->magic != RTLD_MAGIC))
+                       _FATAL("Corrupt Obj_Entry pointer in GOT\n");
+               if (obj->version != RTLD_VERSION)
+                       _FATAL("Dynamic linker version mismatch\n");
+               atexit(cleanup);
+       }
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&__eprol, (u_long)&__etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
diff --git a/lib/csu/common/sysident.S b/lib/csu/common/sysident.S
new file mode 100644 (file)
index 0000000..bb83367
--- /dev/null
@@ -0,0 +1,82 @@
+/* $NetBSD: sysident.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */
+
+/*
+ * Copyright (c) 1997 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+/*
+ * Here we define the NetBSD OS Version in an ELF .note section, structured
+ * like:
+ *
+ * [NOTE HEADER]
+ *     long            name size
+ *     long            description size
+ *     long            note type
+ *
+ * [NOTE DATUM]
+ *     string          OS name
+ *
+ * OSVERSION notes also have:
+ *     long            OS version (__NetBSD_Version__ constant from param.h)
+ *
+ * The DATUM fields should be padded out such that their actual (not
+ * declared) sizes % 4 == 0.
+ *
+ * These are used by the kernel to determine if this binary is really a
+ * NetBSD binary, or some other OS's.
+ */
+
+#include "sysident_assym.h"
+
+#ifdef __minix
+        .section .rodata
+       .ascii "$MINIX$\0"
+#else
+       .section ".note.netbsd.ident", "a"
+       .align 4
+
+       .long   ELF_NOTE_NETBSD_NAMESZ
+       .long   ELF_NOTE_NETBSD_DESCSZ
+       .long   ELF_NOTE_TYPE_NETBSD_TAG
+       .ascii  "NetBSD\0\0"    /* ELF_NOTE_NETBSD_NAME */
+       .long   __NetBSD_Version__
+
+       .section ".note.netbsd.pax", "a"
+       .align 4
+
+       .long   ELF_NOTE_PAX_NAMESZ
+       .long   ELF_NOTE_PAX_DESCSZ
+       .long   ELF_NOTE_TYPE_PAX_TAG
+       .ascii  "PaX\0"         /* ELF_NOTE_PAX_NAME */
+       .long   0
+#endif
diff --git a/lib/csu/common/sysident_assym.cf b/lib/csu/common/sysident_assym.cf
new file mode 100644 (file)
index 0000000..6a8d83d
--- /dev/null
@@ -0,0 +1,12 @@
+include <sys/param.h>
+include <sys/exec_elf.h>
+
+define ELF_NOTE_NETBSD_NAMESZ          ELF_NOTE_NETBSD_NAMESZ
+define ELF_NOTE_NETBSD_DESCSZ          ELF_NOTE_NETBSD_DESCSZ
+define ELF_NOTE_TYPE_NETBSD_TAG        ELF_NOTE_TYPE_NETBSD_TAG
+#define        ELF_NOTE_NETBSD_NAME            ELF_NOTE_NETBSD_NAME
+define __NetBSD_Version__              __NetBSD_Version__
+define ELF_NOTE_PAX_NAMESZ             ELF_NOTE_PAX_NAMESZ
+define ELF_NOTE_PAX_DESCSZ             ELF_NOTE_PAX_DESCSZ
+define ELF_NOTE_TYPE_PAX_TAG           ELF_NOTE_TYPE_PAX_TAG
+#define        ELF_NOTE_PAX_NAME               ELF_NOTE_PAX_NAME
diff --git a/lib/csu/common_elf/Makefile.inc b/lib/csu/common_elf/Makefile.inc
new file mode 100644 (file)
index 0000000..6e41446
--- /dev/null
@@ -0,0 +1,74 @@
+#      $NetBSD: Makefile.inc,v 1.32 2009/12/13 08:52:38 mrg Exp $
+
+.if !defined(ELFSIZE)
+ELFSIZE=32
+.endif
+
+.include "../../Makefile.inc"
+
+CPPFLAGS+=     -DLIBC_SCCS -DPIC -DDYNAMIC -DELFSIZE=${ELFSIZE}
+CPPFLAGS+=     -I${NETBSDSRCDIR}/libexec/ld.elf_so
+CPPFLAGS+=     -I${.CURDIR}/../common_elf
+CPPFLAGS+=     -I${NETBSDSRCDIR}/lib/libc/dlfcn
+CPPFLAGS+=     -DDWARF2_EH
+CPPFLAGS+=     -DJCR
+CPPFLAGS+=     -DDSO_HANDLE
+
+.if defined(HAVE_GCC) && ${HAVE_GCC} > 3
+CFLAGS+=       -fno-unit-at-a-time
+.endif
+
+.include <bsd.own.mk>
+
+.PATH:         ${.CURDIR}/../common_elf
+
+SRCS+=         crt0.c crti.c crtn.c
+OBJS+=         crt0.o gcrt0.o crti.o crtn.o
+.if ${MKPIC} != "no"
+COPTS+=                -fPIC
+.endif
+
+realall: ${OBJS}
+
+crt0.o: crt0.c
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.c} -DCRT0 ${.IMPSRC} -o ${.TARGET}.o
+       ${LD} -x -r -o ${.TARGET} ${.TARGET}.o
+       rm -f ${.TARGET}.o
+.if ${MKSTRIPIDENT} != "no"
+       ${OBJCOPY} -R .ident ${.TARGET}
+.endif
+
+# dependant on crt0.o to pick up header dependencies
+gcrt0.o: ${.CURDIR}/crt0.c crt0.o
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.c} -DMCRT0 ${.CURDIR}/crt0.c -o ${.TARGET}.o
+       ${LD} -x -r -o ${.TARGET} ${.TARGET}.o
+       rm -f ${.TARGET}.o
+.if ${MKSTRIPIDENT} != "no"
+       ${OBJCOPY} -R .ident ${.TARGET}
+.endif
+
+crti.o: crti.c
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.c} ${.IMPSRC} -o ${.TARGET}.o
+       ${LD} -X -r -o ${.TARGET} ${.TARGET}.o
+       rm -f ${.TARGET}.o
+.if ${MKSTRIPIDENT} != "no"
+       ${OBJCOPY} -R .ident ${.TARGET}
+.endif
+
+crtn.o: crtn.c
+       ${_MKTARGET_COMPILE}
+       ${COMPILE.c} ${.IMPSRC} -o ${.TARGET}.o
+       ${LD} -X -r -o ${.TARGET} ${.TARGET}.o
+       rm -f ${.TARGET}.o
+.if ${MKSTRIPIDENT} != "no"
+       ${OBJCOPY} -R .ident ${.TARGET}
+.endif
+
+FILES=${OBJS}
+FILESDIR=${LIBDIR}
+CLEANFILES=${OBJS}
+
+.include <bsd.prog.mk>
diff --git a/lib/csu/common_elf/common.c b/lib/csu/common_elf/common.c
new file mode 100644 (file)
index 0000000..2eca5f2
--- /dev/null
@@ -0,0 +1,77 @@
+/* $NetBSD: common.c,v 1.17 2005/12/24 22:53:15 perry Exp $ */
+
+/*
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+/*
+ * NOT A STANDALONE FILE!
+ */
+
+static char *
+_strrchr(char *p, int ch)
+{
+       char *save;
+
+       for (save = NULL;; ++p) {
+               if (*p == ch)
+                       save = (char *)p;
+               if (!*p)
+                       return(save);
+       }
+       /* NOTREACHED */
+}
+
+#ifdef MCRT0
+__asm ("  .text");
+#ifdef EPROL_EXPORT
+EPROL_EXPORT;
+#endif
+__asm ("_eprol:");
+#endif
+
+#ifdef DYNAMIC
+
+void
+_rtld_setup(void (*cleanup)(void), const Obj_Entry *obj)
+{
+
+       if ((obj == NULL) || (obj->magic != RTLD_MAGIC))
+               _FATAL("Corrupt Obj_Entry pointer in GOT\n");
+       if (obj->version != RTLD_VERSION)
+               _FATAL("Dynamic linker version mismatch\n");
+
+       atexit(cleanup);
+}
+
+#endif /* DYNAMIC */
diff --git a/lib/csu/common_elf/common.h b/lib/csu/common_elf/common.h
new file mode 100644 (file)
index 0000000..f121aaf
--- /dev/null
@@ -0,0 +1,95 @@
+/* $NetBSD: common.h,v 1.13 2009/12/14 01:04:02 matt Exp $ */
+
+/*
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include <sys/types.h>
+#include <sys/exec.h>
+#ifndef __minix
+#include <sys/syscall.h>
+#endif
+
+#include <stdlib.h>
+#ifdef DYNAMIC
+#ifdef __weak_alias
+#define dlopen _dlopen
+#define dlclose        _dlclose
+#define dlsym  _dlsym
+#define dlerror        _dlerror
+#define dladdr _dladdr
+#endif
+#include <dlfcn.h>
+#include "rtld.h"
+#else
+typedef void Obj_Entry;
+#endif
+
+extern quad_t  __syscall(quad_t, ...);
+#define        _exit(v)        __syscall(SYS_exit, (v))
+#define        write(fd, s, n) __syscall(SYS_write, (fd), (s), (n))
+
+#define        _FATAL(str)                             \
+do {                                           \
+       write(2, str, sizeof(str)-1);           \
+       _exit(1);                               \
+} while (0)
+
+static char    *_strrchr(char *, int);
+
+char   **environ;
+char   *__progname = "";
+struct ps_strings *__ps_strings = 0;
+
+extern void    _init(void);
+extern void    _fini(void);
+
+#ifdef DYNAMIC
+void   _rtld_setup(void (*)(void), const Obj_Entry *obj);
+
+/*
+ * Arrange for _DYNAMIC to be weak and undefined (and therefore to show up
+ * as being at address zero, unless something else defines it).  That way,
+ * if we happen to be compiling without -static but with without any
+ * shared libs present, things will still work.
+ */
+extern int _DYNAMIC __weak_reference(_DYNAMIC);
+#endif /* DYNAMIC */
+
+#ifdef MCRT0
+extern void    monstartup(u_long, u_long);
+extern void    _mcleanup(void);
+extern unsigned char _etext, _eprol;
+#endif /* MCRT0 */
+
+int main(int, char **, char **);
diff --git a/lib/csu/common_elf/crti.c b/lib/csu/common_elf/crti.c
new file mode 100644 (file)
index 0000000..e277fd1
--- /dev/null
@@ -0,0 +1,40 @@
+/*     $NetBSD: crti.c,v 1.6 2008/04/28 20:22:54 martin Exp $  */
+
+/*- 
+ * Copyright (c) 1998, 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg, Ross Harvey, and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:     
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>         /* sysident.h requires `NetBSD' constant */
+#include <sys/exec.h> 
+#include <sys/exec_elf.h>
+
+#include "sysident.h"
+#include <dot_init.h>
+
+MD_INIT_SECTION_PROLOGUE;
+MD_FINI_SECTION_PROLOGUE;
diff --git a/lib/csu/common_elf/crtn.c b/lib/csu/common_elf/crtn.c
new file mode 100644 (file)
index 0000000..b37319f
--- /dev/null
@@ -0,0 +1,35 @@
+/*     $NetBSD: crtn.c,v 1.3 2008/04/28 20:22:54 martin Exp $  */
+
+/*- 
+ * Copyright (c) 1998, 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg, Ross Harvey, and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:     
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <dot_init.h>
+
+MD_INIT_SECTION_EPILOGUE;
+MD_FINI_SECTION_EPILOGUE;
diff --git a/lib/csu/common_elf/dot_init.h b/lib/csu/common_elf/dot_init.h
new file mode 100644 (file)
index 0000000..8cf25bf
--- /dev/null
@@ -0,0 +1,48 @@
+/* $NetBSD: dot_init.h,v 1.3 2008/05/10 15:31:03 martin Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+
+#define        INIT_FALLTHRU_DECL
+#define        FINI_FALLTHRU_DECL
+
+#define        INIT_FALLTHRU()
+#define        FINI_FALLTHRU()
+
+#define        MD_INIT_SECTION_PROLOGUE
+#define        MD_FINI_SECTION_PROLOGUE
+
+#define        MD_INIT_SECTION_EPILOGUE
+#define        MD_FINI_SECTION_EPILOGUE
diff --git a/lib/csu/common_elf/dwarf2_eh.h b/lib/csu/common_elf/dwarf2_eh.h
new file mode 100644 (file)
index 0000000..dfa60fd
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: dwarf2_eh.h,v 1.3 2008/04/28 20:22:54 martin Exp $     */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Definitions for DWARF2 stack frame unwinding/exception handling.
+ */
+
+#ifdef __GNUC__
+/*
+ * We must pass a DWARF2 unwind object to __register_frame_info().
+ * Since we don't reference any members of this object, but rather
+ * only provide storage for it, we just declare it in a simple,
+ * dumb way.  We need room for 6 pointers in GCC 2.95.3 and GCC 3.0,
+ * but declare it with a little slop at the end.
+ */
+struct dwarf2_eh_object {
+       void *space[8];
+};
+
+/*
+ * These routines are provided by libgcc to register/unregister
+ * frame info.  Note these prototypes must generate weak references
+ * (even though the routines in libgcc have strong definitions).
+ * This is so that we can link with a libgcc that doesn't have these
+ * routines (e.g. one that uses sjlj exceptions).
+ */
+
+/*
+ * A few platforms (x86_64, s390) have read-only .eh_frame by default,
+ * so they must have it declared 'const'. These platforms will override
+ * __EH_FRAME_CONST (which is empty by default) in their CPP flags.
+ */
+
+#ifndef __EH_FRAME_CONST
+#define __EH_FRAME_CONST
+#endif
+
+extern void __register_frame_info(__EH_FRAME_CONST void *,
+    struct dwarf2_eh_object *) __attribute__((weak));
+extern void __deregister_frame_info(__EH_FRAME_CONST void *)
+    __attribute__((weak));
+#endif /* __GNUC__ */
diff --git a/lib/csu/hppa/Makefile b/lib/csu/hppa/Makefile
new file mode 100644 (file)
index 0000000..533cca5
--- /dev/null
@@ -0,0 +1,4 @@
+#      $NetBSD: Makefile,v 1.3 2006/05/19 19:11:12 christos Exp $
+CPPFLAGS+=     -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/hppa/crt0.c b/lib/csu/hppa/crt0.c
new file mode 100644 (file)
index 0000000..f46b3f0
--- /dev/null
@@ -0,0 +1,158 @@
+/*     $NetBSD: crt0.c,v 1.7 2004/08/26 21:07:14 thorpej Exp $ */
+
+/*
+ * Copyright (c) 2002 Matt Fredette
+ * Copyright (c) 1999 Klaus Klein
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+static void ___start(struct ps_strings *,
+    void (*cleanup)(void), const Obj_Entry *, int)
+#ifdef __GNUC__
+    __attribute__((__used__))
+#endif
+    ;
+
+__asm("\n"
+"      .text                           \n"
+"      .align  4                       \n"
+"      .globl  _start                  \n"
+"      .globl  __start                 \n"
+"      .type   _start,@function        \n"
+"      .type   __start,@function       \n"
+"_start:                               \n"
+"__start:                              \n"
+"      .import _GLOBAL_OFFSET_TABLE_   \n"
+"\n"
+"      bl      L$lpc, %r27             \n"
+"      depi    0, 31, 2, %r27          \n"
+"L$lpc:        addil   L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 8), %r27      \n"
+"      ldo     R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 12)(%r1),%r27 \n"
+"      copy    %r27, %r19              \n"
+"      b       ___start                \n"
+"      copy    %r27, %arg3             \n");
+
+static void
+___start(struct ps_strings *ps_strings,
+    void (*cleanup)(void),                     /* from shared loader */
+    const Obj_Entry *obj,                      /* from shared loader */
+    int dp)
+{
+       int argc;
+       char **argv;
+       int fini_plabel[2];
+
+       argc = ps_strings->ps_nargvstr;
+       argv = ps_strings->ps_argvstr;
+       environ = ps_strings->ps_envstr;
+
+       if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(__progname, '/')) == NULL)
+                       __progname = argv[0];
+               else
+                       __progname++;
+       }
+
+       if (ps_strings != (struct ps_strings *)0)
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       /*
+        * XXX fredette - when not compiling PIC, you currently 
+        * can't detect an undefined weak symbol by seeing if 
+        * its address is NULL.  The compiler emits code to find 
+        * _DYNAMIC relative to %dp, the assembler notes the 
+        * needed relocations, but when the linker sees that the 
+        * (weak) symbol isn't defined it drops the ball - the 
+        * relocations are never filled, and the binary ends up 
+        * with code that sees an address of %dp plus zero, 
+        * which != NULL.
+        *
+        * Arguably the linker could/should distinguish between
+        * code that is after a weak undefined symbol's contents 
+        * from code that is after its address.  In the first case, 
+        * it would warn and/or bail.  In the second case, it 
+        * would fix up instructions to give a symbol address
+        * of NULL.
+        *
+        * For now, we take the easy way out and compare &_DYNAMIC 
+        * to %dp, as well as to NULL.
+        */
+       if (&_DYNAMIC != NULL && (int)&_DYNAMIC != dp)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       /*
+        * Since crt0.o, crtbegin.o, and crtend.o are always
+        * compiled PIC, they must have %r19 set correctly on
+        * entry to any function they contain.  However, when
+        * a program is linked statically, the linker does
+        * not fill a PLABEL relocation with a pointer to a 
+        * true PLABEL, it just fills it with the offset of the
+        * function.  This shows the linker's assumption that 
+        * when linking statically, *all* of the code has *not* 
+        * been compiled PIC.  I guess to assume otherwise
+        * would be a performance hit, as you would end up
+        * with unnecessary PLABELs for function pointers.
+        *
+        * But here, passing the address of the PIC _fini to
+        * atexit, we must make sure that we pass a PLABEL.
+        */
+       fini_plabel[0] = (int)_fini;
+       if (fini_plabel[0] & 2)
+               /* _fini is already a PLABEL. */
+               atexit(_fini);
+       else {
+               fini_plabel[1] = dp;
+               atexit((void (*)(void))(((int)fini_plabel) | 2));
+       }
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.7 2004/08/26 21:07:14 thorpej Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/hppa/dot_init.h b/lib/csu/hppa/dot_init.h
new file mode 100644 (file)
index 0000000..8010f77
--- /dev/null
@@ -0,0 +1,69 @@
+/* $NetBSD: dot_init.h,v 1.8 2008/05/10 15:31:04 martin Exp $ */
+
+/*-
+ * Copyright (c) 2004 Nick Hudson
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+
+#define        MD_SECTION_PROLOGUE(sect, entry_pt)             \
+               __asm (                                 \
+               ".section "#sect",\"ax\",@progbits      \n"\
+               ".global "#entry_pt"                    \n"\
+               ".proc                                  \n"\
+               ".callinfo frame=64, calls, save_rp, save_sp, entry_gr=3\n"\
+               ".entry                                 \n"\
+               #entry_pt":                             \n"\
+               "       stw     %rp, -20(%sp)           \n"\
+               "       copy    %r3, %r1                \n"\
+               "       copy    %sp, %r3                \n"\
+               "       stw,ma  %r1, 64(%sp)            \n"\
+               "       /* fall thru */                 \n"\
+               ".exit                                  \n"\
+               ".procend                               \n"\
+               ".previous")
+
+#define        MD_SECTION_EPILOGUE(sect)                       \
+               __asm (                                 \
+               ".section "#sect",\"ax\",@progbits      \n"\
+               "       ldw     -20(%r3) ,%rp           \n"\
+               "       ldo     64(%r3), %sp            \n"\
+               "       ldw,mb  -64(%sp), %r3           \n"\
+               "       bv,n    %r0(%rp)                \n"\
+               ".previous")
+
+#define        MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define        MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define        MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define        MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
diff --git a/lib/csu/i386-elf/Makefile b/lib/csu/i386-elf/Makefile
deleted file mode 100644 (file)
index 54abd00..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-.include <bsd.own.mk>
-
-SRCS=          crti.S crtn.S crtbegin.S crtend.S
-OBJS=          ${SRCS:N*.h:R:S/$/.o/g} gcrt1.o crt1.o Scrt1.o
-
-realall: ${OBJS}
-
-FILES=${OBJS}
-FILESDIR=${LIBDIR}
-CLEANFILES=${OBJS} crt1_c.o crt1_s.o gcrt1_c.o Scrt1_c.o
-
-gcrt1_c.o: crt1_c.c
-       ${CC} ${CFLAGS} -DGCRT -c -o gcrt1_c.o ${.CURDIR}/crt1_c.c
-
-gcrt1.o: gcrt1_c.o crt1_s.o
-       ${LD} ${LDFLAGS} -o gcrt1.o -r crt1_s.o gcrt1_c.o
-
-crt1.o:        crt1_c.o crt1_s.o
-       ${LD} ${LDFLAGS} -o crt1.o -r crt1_s.o crt1_c.o
-       ${OBJCOPY} --localize-symbol _start1 crt1.o
-
-Scrt1_c.o:     crt1_c.c
-       ${CC} ${CFLAGS} -fPIC -DPIC -c -o Scrt1_c.o ${.CURDIR}/crt1_c.c
-
-Scrt1.o: Scrt1_c.o crt1_s.o
-       ${LD} ${LDFLAGS} -o Scrt1.o -r crt1_s.o Scrt1_c.o
-       ${OBJCOPY} --localize-symbol _start1 Scrt1.o
-
-.include <bsd.prog.mk>
diff --git a/lib/csu/ia64/Makefile b/lib/csu/ia64/Makefile
new file mode 100644 (file)
index 0000000..322c9e2
--- /dev/null
@@ -0,0 +1,8 @@
+#      $NetBSD: Makefile,v 1.2 2006/09/14 23:55:54 cherry Exp $
+
+ELFSIZE=       64
+
+#Uncomment the next line to enable the new .init fallthru
+CPPFLAGS+=     -I- -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/ia64/crt0.c b/lib/csu/ia64/crt0.c
new file mode 100644 (file)
index 0000000..3983db9
--- /dev/null
@@ -0,0 +1,97 @@
+/* $NetBSD: crt0.c,v 1.2 2006/09/15 05:29:44 skrll Exp $ */
+
+/*
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+void   __start(char **, void (*cleanup)(void), const Obj_Entry *,
+    struct ps_strings *);
+
+void
+__start(char **sp,
+    void (*cleanup)(void),     /* from shared loader */
+    const Obj_Entry *obj,      /* from shared loader */
+    struct ps_strings *ps_strings)
+{
+       long argc;
+       char **argv, *namep;
+
+       __asm __volatile__ ("1:                                         \
+                               { .mii                                  \
+                                 mov           r15=@gprel(1b)  \n      \
+                                 mov           r16=ip  ;;      \n      \
+                                 sub           gp=r16,r15      \n      \
+                               ;;                                      \
+                               } ");
+
+       argc = *(long *)sp;
+       argv = sp + 1;
+       environ = sp + 2 + argc;                /* 2: argc + NULL ending argv */
+
+       if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(namep, '/')) == NULL)
+                       __progname = namep;
+               else
+                       __progname++;
+       }
+
+       if (ps_strings != (struct ps_strings *)0 &&
+           ps_strings != (struct ps_strings *)0xbabefacedeadbeef) /* XXX: Debug: see machdep.c:setregs() */
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       if (&_DYNAMIC != NULL)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));        /* XXX: ia64 ABI says 4 parameters. */
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.2 2006/09/15 05:29:44 skrll Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/ia64/dot_init.h b/lib/csu/ia64/dot_init.h
new file mode 100644 (file)
index 0000000..293b7da
--- /dev/null
@@ -0,0 +1,74 @@
+/* $NetBSD: dot_init.h,v 1.6 2009/11/09 14:34:42 skrll Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+#include <machine/asm.h>
+
+/*-
+ * $FreeBSD: src/lib/csu/ia64/crti.S,v 1.3 2001/11/03 06:31:27 peter Exp $
+ */
+
+#define        MD_SECTION_PROLOGUE(sect, entry_pt)                     \
+               __asm (                                         \
+               ".section "#sect",\"ax\",@progbits      \n"     \
+               ".proc "#entry_pt"                      \n"     \
+               ".global "#entry_pt"                    \n"     \
+               #entry_pt":                             \n"     \
+               ".regstk        0,2,0,0                 \n"     \
+               ".prologue 12,loc0                      \n"     \
+               ".save  ar.pfs,loc1                     \n"     \
+               "alloc  loc1=ar.pfs,0,2,0,0             \n"     \
+               "mov    loc0=b0 /* Save return addr */  \n"     \
+               ".endp "#entry_pt"                      \n"     \
+               ".previous")
+
+/*-
+ * $FreeBSD: src/lib/csu/ia64/crtn.S,v 1.2 2001/10/29 10:18:58 peter Exp $
+ */
+
+#define        MD_SECTION_EPILOGUE(sect)                               \
+               __asm (                                         \
+               ".section "#sect",\"ax\",@progbits      \n"     \
+               ".regstk 0,2,0,0                        \n"     \
+               "mov    b0=loc0 /*Recover return addr*/ \n"     \
+               "mov    ar.pfs=loc1                     \n"     \
+               "br.ret.sptk.many b0                    \n"     \
+               ".previous")
+
+#define        MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define        MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define        MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define        MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
diff --git a/lib/csu/m68k_elf/Makefile b/lib/csu/m68k_elf/Makefile
new file mode 100644 (file)
index 0000000..257ad99
--- /dev/null
@@ -0,0 +1,6 @@
+#      $NetBSD: Makefile,v 1.7 2006/05/19 19:11:12 christos Exp $
+
+#Uncomment the next line to enable the new .init fallthru
+CPPFLAGS+=     -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/m68k_elf/crt0.c b/lib/csu/m68k_elf/crt0.c
new file mode 100644 (file)
index 0000000..fcb5e75
--- /dev/null
@@ -0,0 +1,100 @@
+/* $NetBSD: crt0.c,v 1.11 2004/08/26 21:09:52 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 Klaus Klein
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+void __start(int, char **, char **, void (*cleanup)(void),
+    const Obj_Entry *, struct ps_strings *);
+
+__asm("\n"
+"      .text                           \n"
+"      .align  4                       \n"
+"      .globl  _start                  \n"
+"_start:                               \n"
+"      movl    (%sp),%d0               \n"
+"      movl    %a2,-(%sp)              | ps_strings    \n"
+"      movl    %a0,-(%sp)              | obj           \n"
+"      movl    %a1,-(%sp)              | cleanup       \n"
+"      movl    %d0,%d1                 \n"
+"      lsll    #2,%d1                  \n"
+"      pea     (16+4)(%sp,%d1.l)       | envp = &argv[argc + 1]        \n"
+"      pea     20(%sp)                 | argv          \n"
+"      movl    %d0,-(%sp)              | argc          \n"
+"      jsr     __start");
+
+void
+__start(int argc, char **argv, char **envp,
+    void (*cleanup)(void),                     /* from shared loader */
+    const Obj_Entry *obj,                      /* from shared loader */
+    struct ps_strings *ps_strings)
+{
+       environ = envp;
+
+       if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(__progname, '/')) == NULL)
+                       __progname = argv[0];
+               else
+                       __progname++;
+       }
+
+       if (ps_strings != (struct ps_strings *)0)
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       if (&_DYNAMIC != NULL)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.11 2004/08/26 21:09:52 thorpej Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/m68k_elf/dot_init.h b/lib/csu/m68k_elf/dot_init.h
new file mode 100644 (file)
index 0000000..db1faac
--- /dev/null
@@ -0,0 +1,60 @@
+/* $NetBSD: dot_init.h,v 1.6 2008/05/10 15:31:04 martin Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+#include <machine/asm.h>
+
+#define        MD_SECTION_PROLOGUE(sect, entry_pt)             \
+               __asm (                                 \
+               ".section "#sect",\"ax\",@progbits      \n"\
+               ".global "#entry_pt"                    \n"\
+               #entry_pt":                             \n"\
+               "       .align  2                       \n"\
+               "       /* fall thru */                 \n"\
+               ".previous")
+
+               /* placement of the .align _after_ the label is intentional */
+
+#define        MD_SECTION_EPILOGUE(sect)                       \
+               __asm (                                 \
+               ".section "#sect",\"ax\",@progbits      \n"\
+               "       rts                             \n"\
+               ".previous")
+
+#define        MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define        MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define        MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define        MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
diff --git a/lib/csu/mips/Makefile b/lib/csu/mips/Makefile
new file mode 100644 (file)
index 0000000..a584c0a
--- /dev/null
@@ -0,0 +1,6 @@
+#      $NetBSD: Makefile,v 1.24 2006/05/19 19:11:12 christos Exp $
+
+#Uncomment the next line to enable the new .init fallthru
+CPPFLAGS+=     -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/mips/crt0.c b/lib/csu/mips/crt0.c
new file mode 100644 (file)
index 0000000..3241838
--- /dev/null
@@ -0,0 +1,169 @@
+/* $NetBSD: crt0.c,v 1.20 2009/12/14 01:04:02 matt Exp $ */
+
+/*
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Modifications for NetBSD/mips:
+ *
+ *     Jonathan Stone
+ *     Jason R. Thorpe, Numerical Aerospace Simulation Facility,
+ *         NASA Ames Research Center
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Christopher G. Demetriou
+ *     for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common.h"
+
+/*
+ *     C start-up.  Assumes kernel (or ld.so) passes the
+ *     following parameters to user-space in registers:
+ *
+ *     a0      stack pointer (0 if setregs didn't fill this in)
+ *     a1      cleanup
+ *     a2      Obj_Entry
+ *     a3      ps_strings
+ *
+ *     XXX Does this violate the ABI?
+ *     as well as the usual registers (pc, sp, and t9 == pc for ABI).
+ */
+
+void __start(u_long, void (*)(void), const Obj_Entry *,
+               struct ps_strings *);
+
+__asm(".text; .align 4;  .globl _start; _start:");
+
+void
+__start(u_long sp,
+    void (*cleanup)(void),             /* from shared loader */
+    const Obj_Entry *obj,              /* from shared loader */
+    struct ps_strings *ps_strings)
+{
+       char **ksp;
+       char **argv, *namep;
+       int argc;
+
+       /*
+        * Grab the argc, argv, and envp set up by the kernel.
+        * Layout of stuff on the stack:
+        *
+        *      [ high ]
+        *      char    kenvstr[1];     // size varies
+        *      char    kargstr[1];     // size varies
+        *      char    *argv[1];       // varies on argc
+        *      int     argc;
+        *      [ low ]                 <--- kernel's SP points here
+        *      .
+        *      .
+        *      .
+        *      [ current stack pointer ]
+        *
+        * WARNING!  There is an implicit sizeof(int) == sizeof(char *) here!
+        */
+
+#ifndef DYNAMIC
+#ifdef _LP64
+       __asm volatile("dla $28,_gp");
+#else
+       __asm volatile("la $28,_gp");
+#endif
+#endif
+
+       ksp = (char**)sp;
+#if defined(__mips_n32) || defined(__mips_n64)
+       if (ksp == 0) {
+               /*
+                * Uh, oh. We're running on a old kernel that passed
+                * us zero in $a0-$a3.  Try adjusting the current
+                * $sp for our own stack-frame size and see  what
+                * we find.
+                * WARNING!  The constants 56 and 64 below were determined
+                * by examining GCC assembler output of __start to find the
+                * frame size.  If you change the code or compiler,
+                * you _will_ lose!
+                */
+
+#ifndef DYNAMIC
+               /* XXX 56 is compiler and stackframe dependent */
+               __asm volatile("        addiu   %0,$29,56" : "=r" (ksp));
+#else
+               /* XXX 64 is compiler and stackframe dependent */
+               __asm volatile("        addiu   %0,$29,64" : "=r" (ksp));
+#endif
+       }
+#endif
+
+
+       argc = *(int *)ksp;
+       argv = ksp + 1;
+       environ = ksp + 2 + argc;       /* 2: argc + NULL ending argv */
+
+       if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(namep, '/')) == NULL)
+                       __progname = namep;
+               else
+                       __progname++;
+       }
+
+       /*
+        * Deal with stuff that is only provided if setregs() did
+        * did the right thing.
+        */
+       if (sp != 0) {
+               if (ps_strings != (struct ps_strings *)0)
+                       __ps_strings = ps_strings;
+#ifdef DYNAMIC
+               /*
+                * XXX Old MIPS ld.so didn't do any of this at all.
+                * XXX If we were loaded by that loader, just abort
+                * XXX the rtld setup.
+                */
+               if (&_DYNAMIC != NULL && cleanup != NULL && obj != NULL)
+                       _rtld_setup(cleanup, obj);
+#endif
+       }
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * RCSid. Place after __start for programs that assume start of text
+ *  is the entrypoint. (Only needed for old toolchains).
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.20 2009/12/14 01:04:02 matt Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/mips/dot_init.h b/lib/csu/mips/dot_init.h
new file mode 100644 (file)
index 0000000..7a7a1cf
--- /dev/null
@@ -0,0 +1,137 @@
+/* $NetBSD: dot_init.h,v 1.10 2009/12/14 01:04:02 matt Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * Copyright (c) 2001 Simon Burge
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+
+#define        t9      "$25"
+
+/*
+ * For O32/O64, allocate 8 "slots" for the stack frame.  Store GP in the 4th
+ * (zero-based) slot (since this is where compiler generated code for fallthru
+ * processing expects it to be), and the RA in seventh (highest address).
+ *
+ * For N32/N64, allocate 4 8-byte "slots" for the stack frame.  Store GP in the
+ * 2nd (zero-based) slot (since ...) and the RA in third (highest address).
+ */
+
+#ifdef __mips_o32
+#define        sPTR_ADDU               "addu"
+#define        sREG_L                  "lw"
+#define        sREG_S                  "sw"
+#define sRAOFF                 "28"
+#define sFRAMESZ               "32"
+#define        MD_GPRESTORE            /* nothing */
+#else
+#define        sPTR_ADDU               "daddu"
+#define        sREG_L                  "ld"
+#define        sREG_S                  "sd"
+#if defined(__mips_n32) || defined(__mips_n64)
+#define        MD_GPRESTORE            "ld     $gp,8($sp)"             "\n\t"
+#define sRAOFF                 "24"
+#define sFRAMESZ               "32"
+#elif defined(__mips_o64)
+#define sRAOFF                 "56"
+#define sFRAMESZ               "64"
+#define        MD_GPRESTORE            /* nothing */
+#endif
+#endif
+
+#ifdef __ABICALLS__
+#if defined(__mips_o32) || defined(__mips_o64)
+#define        MD_FUNCTION_PROLOGUE(entry_pt)                                  \
+               ".set   noreorder"                              "\n\t"  \
+               ".cpload "t9                                    "\n\t"  \
+               ".set   reorder"                                "\n\t"  \
+               sPTR_ADDU"      $sp,$sp,-"sFRAMESZ              "\n\t"  \
+               ".cprestore 16"                                 "\n\t"  \
+               sREG_S" $ra,"sRAOFF"($sp)"                      "\n\t"
+
+#elif defined(__mips_n32) || defined(__mips_n64)
+#define        MD_FUNCTION_PROLOGUE(entry_pt)                                  \
+               ".set   noreorder"                              "\n\t"  \
+               "daddu  $sp,$sp,-32"                            "\n\t"  \
+               ".cpsetup "t9", 8, "#entry_pt                   "\n\t"  \
+               "sd     $ra,24($sp)"                            "\n\t"  \
+               ".set   reorder"                                "\n\t"
+#else
+#error ABI not supported (__ABICALLS)
+#endif
+#else
+#if defined(__mips_o32) || defined(__mips_o64)
+#define        MD_FUNCTION_PROLOGUE(entry_pt)                                  \
+               sPTR_ADDU"      $sp,$sp,-"sFRAMESZ              "\n\t"  \
+               sREG_S" $ra,"sRAOFF"($sp)"                      "\n\t"
+
+#elif defined(__mips_n32) || defined(__mips_n64)
+/*
+ * On N32/N64, GP is callee-saved.
+ */
+#define        MD_FUNCTION_PROLOGUE(entry_pt)                                  \
+               "daddu  $sp,$sp,-32"                            "\n\t"  \
+               "sd     $gp,8($sp)"                             "\n\t"  \
+               "sd     $ra,24($sp)"                            "\n\t"
+#else
+#error ABI not supported (!__ABICALLS)
+#endif
+#endif /* __ABICALLS */
+
+
+#define        MD_SECTION_PROLOGUE(sect, entry_pt)                             \
+               __asm (                                                 \
+               ".section "#sect",\"ax\",@progbits"             "\n\t"  \
+               ".align 2"                                      "\n\t"  \
+               ".globl "#entry_pt                              "\n\t"  \
+               #entry_pt":"                                    "\n\t"  \
+               MD_FUNCTION_PROLOGUE(entry_pt)                          \
+               "       /* fall thru */"                        "\n\t"  \
+               ".previous")
+
+#define        MD_SECTION_EPILOGUE(sect)                                       \
+               __asm (                                                 \
+               ".section "#sect",\"ax\",@progbits"             "\n\t"  \
+               sREG_L" $ra,"sRAOFF"($sp)"                      "\n\t"  \
+               MD_GPRESTORE                                            \
+               ".set   noreorder"                              "\n\t"  \
+               "j      $ra"                                    "\n\t"  \
+               sPTR_ADDU"      $sp,$sp,"sFRAMESZ               "\n\t"  \
+               ".set   reorder"                                "\n\t"  \
+               ".previous")
+
+#define        MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define        MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define        MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define        MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
diff --git a/lib/csu/powerpc/Makefile b/lib/csu/powerpc/Makefile
new file mode 100644 (file)
index 0000000..7db5654
--- /dev/null
@@ -0,0 +1,5 @@
+#      $NetBSD: Makefile,v 1.13 2006/05/19 19:11:12 christos Exp $
+
+CPPFLAGS+= -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/powerpc/crt0.c b/lib/csu/powerpc/crt0.c
new file mode 100644 (file)
index 0000000..4f0e777
--- /dev/null
@@ -0,0 +1,107 @@
+/* $NetBSD: crt0.c,v 1.26 2006/05/18 17:54:19 christos Exp $ */
+
+/*
+ * Copyright (c) 1997 Jason R. Thorpe.
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+/*
+ * Small Data Area designators.  If not defined, will show up as being
+ * at address zero.
+ */
+extern int _SDA_BASE_[] __weak_reference(_SDA_BASE_);
+extern int _SDA2_BASE_[] __weak_reference(_SDA2_BASE_);
+
+/*
+ * First 5 arguments are specified by the PowerPC SVR4 ABI.  The
+ * last argument, ps_strings, is a NetBSD extension.
+ */
+void _start(int, char **, char **, const Obj_Entry *,
+               void (*)(void), struct ps_strings *);
+
+void
+_start(int argc, char **argv, char **envp,
+    const Obj_Entry *obj,                      /* from shared loader */
+    void (*cleanup)(void),                     /* from shared loader */
+    struct ps_strings *ps_strings)             /* NetBSD extension */
+{
+       char *namep;
+
+       /*
+        * Initialize the Small Data Area registers.
+        * _SDA_BASE is defined in the SVR4 ABI for PPC.
+        * _SDA2_BASE is defined in the E[mbedded] ABI for PPC.
+        */
+       __asm(  "lis %r13,_SDA_BASE_@ha;"
+               "addi %r13,%r13,_SDA_BASE_@l;"
+               "lis %r2,_SDA2_BASE_@ha;"
+               "addi %r2,%r2,_SDA2_BASE_@l" );
+
+       if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(namep, '/')) == NULL)
+                       __progname = namep;
+               else
+                       __progname++;
+       }
+
+       environ = envp;
+
+       if (ps_strings != (struct ps_strings *)0)
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       if (&_DYNAMIC != NULL)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.26 2006/05/18 17:54:19 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/powerpc/dot_init.h b/lib/csu/powerpc/dot_init.h
new file mode 100644 (file)
index 0000000..6918dd7
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $NetBSD: dot_init.h,v 1.7 2008/05/10 15:31:04 martin Exp $      */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+
+#define MD_SECTION_PROLOGUE(sect, entry_pt)                \
+               __asm (                                     \
+               ".section "#sect",\"ax\",@progbits      \n" \
+               ".global "#entry_pt"                    \n" \
+               #entry_pt":                             \n" \
+               "       stwu    %r1,-16(%r1)            \n" \
+               "       mflr    %r0                     \n" \
+               "       stw     %r0,12(%r1)             \n" \
+               "       /* fall thru */                 \n" \
+               ".previous")
+
+#define MD_SECTION_EPILOGUE(sect)                          \
+               __asm (                                     \
+               ".section "#sect",\"ax\",@progbits      \n" \
+               "       lwz     %r0,12(%r1)             \n" \
+               "       mtlr    %r0                     \n" \
+               "       la      %r1,16(%r1)             \n" \
+               "       blr                             \n" \
+               ".previous")
+
+#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
diff --git a/lib/csu/powerpc64/Makefile b/lib/csu/powerpc64/Makefile
new file mode 100644 (file)
index 0000000..3231bfa
--- /dev/null
@@ -0,0 +1,5 @@
+#      $NetBSD: Makefile,v 1.1 2006/06/30 22:49:50 ross Exp $
+
+CPPFLAGS+= -I- -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/powerpc64/crt0.c b/lib/csu/powerpc64/crt0.c
new file mode 100644 (file)
index 0000000..8ee3660
--- /dev/null
@@ -0,0 +1,99 @@
+/* $NetBSD: crt0.c,v 1.2 2006/07/01 01:39:17 ross Exp $ */
+
+/*
+ * Copyright (c) 1997 Jason R. Thorpe.
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+/*
+ * Small Data Area designators.  If not defined, will show up as being
+ * at address zero.
+ */
+extern int _SDA_BASE_[];
+__weak_extern(_SDA_BASE_);
+extern int _SDA2_BASE_[];
+__weak_extern(_SDA2_BASE_);
+
+/*
+ * First 5 arguments are specified by the PowerPC SVR4 ABI.  The
+ * last argument, ps_strings, is a NetBSD extension.
+ */
+void _start(int, char **, char **, const Obj_Entry *,
+               void (*)(void), struct ps_strings *);
+
+void
+_start(int argc, char **argv, char **envp,
+    const Obj_Entry *obj,                      /* from shared loader */
+    void (*cleanup)(void),                     /* from shared loader */
+    struct ps_strings *ps_strings)             /* NetBSD extension */
+{
+       char *namep;
+
+       if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(namep, '/')) == NULL)
+                       __progname = namep;
+               else
+                       __progname++;
+       }
+
+       environ = envp;
+
+       if (ps_strings != (struct ps_strings *)0)
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       if (&_DYNAMIC != NULL)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.2 2006/07/01 01:39:17 ross Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/powerpc64/dot_init.h b/lib/csu/powerpc64/dot_init.h
new file mode 100644 (file)
index 0000000..c91f367
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: dot_init.h,v 1.7 2008/05/10 15:31:04 martin Exp $      */
+
+/*-
+ * Copyright (c) 2001, 2006 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+
+#define MD_SECTION_PROLOGUE(sect, entry_pt)                \
+               __asm (                                     \
+               ".globl  " #entry_pt "                  \n" \
+               ".globl ." #entry_pt "                  \n" \
+               ".pushsection \".opd\",\"aw\"           \n" \
+               ".align 3                               \n" \
+               #entry_pt": .quad ." #entry_pt ",.TOC.@tocbase,0\n"     \
+               ".size " #entry_pt ",24                 \n" \
+               ".type " #entry_pt ",@function          \n" \
+               ".pushsection "#sect",\"ax\",@progbits  \n" \
+               "." #entry_pt":                         \n" \
+               "       stdu    %r1,-48(%r1)            \n" \
+               "       mflr    %r0                     \n" \
+               "       std     %r0,16(%r1)             \n" \
+               "       /* fall thru */                 \n" \
+               ".popsection                            \n" \
+               ".popsection")
+
+#define MD_SECTION_EPILOGUE(sect)                          \
+               __asm (                                     \
+               ".pushsection "#sect",\"ax\",@progbits  \n" \
+               "       ld      %r0,16(%r1)             \n" \
+               "       mtlr    %r0                     \n" \
+               "       la      %r1,48(%r1)             \n" \
+               "       blr                             \n" \
+               ".popsection")
+
+#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
diff --git a/lib/csu/sh3_elf/Makefile b/lib/csu/sh3_elf/Makefile
new file mode 100644 (file)
index 0000000..b8ff0f8
--- /dev/null
@@ -0,0 +1,5 @@
+#      $NetBSD: Makefile,v 1.3 2006/05/19 19:11:12 christos Exp $
+
+CPPFLAGS+= -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/sh3_elf/crt0.c b/lib/csu/sh3_elf/crt0.c
new file mode 100644 (file)
index 0000000..f47cea2
--- /dev/null
@@ -0,0 +1,94 @@
+/* $NetBSD: crt0.c,v 1.10 2004/08/26 21:16:41 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1998 Christos Zoulas
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+void ___start(int, char **, char **, void (*cleanup)(void),
+                       const Obj_Entry *, struct ps_strings *);
+
+__asm( "       .text                   \n"
+       "       .align 2                \n"
+       "       .globl _start           \n"
+       "       .globl __start          \n"
+       "_start:                        \n"
+       "__start:                       \n"
+       "       mov.l   r9,@-r15        \n"
+       "       bra ___start            \n"
+       "       mov.l   r8,@-r15");
+
+void
+___start(int argc, char **argv, char **envp,
+    void (*cleanup)(void),                     /* from shared loader */
+    const Obj_Entry *obj,                      /* from shared loader */
+    struct ps_strings *ps_strings)
+{
+       environ = envp;
+
+       if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(__progname, '/')) == NULL)
+                       __progname = argv[0];
+               else
+                       __progname++;
+       }
+
+       if (ps_strings != (struct ps_strings *)0)
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       if (&_DYNAMIC != NULL)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.10 2004/08/26 21:16:41 thorpej Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/sh3_elf/dot_init.h b/lib/csu/sh3_elf/dot_init.h
new file mode 100644 (file)
index 0000000..529b6dc
--- /dev/null
@@ -0,0 +1,91 @@
+/*     $NetBSD: dot_init.h,v 1.7 2008/05/10 15:31:04 martin Exp $      */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+
+
+/*
+ * Don't use C versions of _init/_fini, they have become just a
+ * rudimentary indirection to the entry points we would supply with
+ * MD_SECTION_PROLOGUE.
+ */
+#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
+
+
+#define MD_ASM_IN_SECTION(section, content)                            \
+       __asm(                                                          \
+               ".section " #section ",\"ax\",@progbits\n"              \
+                       content "\n"                                    \
+               ".previous")
+
+/*
+ * Declare the entry point global.
+ */
+#define MD_SECTION_PROLOGUE(section, entry_pt)                         \
+       MD_ASM_IN_SECTION(section,                                      \
+               "       .global "_C_LABEL_STRING(#entry_pt)"    \n"     \
+               "       .type "_C_LABEL_STRING(#entry_pt)",@function\n" \
+               _C_LABEL_STRING(#entry_pt)":                    \n"     \
+               "       mov.l   r14, @-sp                       \n"     \
+               "       sts.l   pr, @-sp                        \n"     \
+               "       mov     sp, r14                         \n"     \
+               "       .p2align 2")
+
+/*
+ * NOTE 1: Supply the semicolon here because crtbegin.c doesn't.
+ * NOTE 2: We don't use our crtbegin.c for gcc3 and later,
+ *         we use gcc crtstuff.c via src/gnu/lib/crtstuff*
+ */
+#define MD_CALL_STATIC_FUNCTION(section, func)                         \
+       MD_ASM_IN_SECTION(section,                                      \
+               "       mov.l   1f, r1                          \n"     \
+               "       mova    2f, r0                          \n"     \
+               "0:     braf    r1                              \n"     \
+               "        lds    r0, pr                          \n"     \
+                                                                       \
+               "       .p2align 2                              \n"     \
+               "1:     .long "_C_LABEL_STRING(#func)" - (0b+4) \n"     \
+               "2:     ");
+
+#define MD_SECTION_EPILOGUE(section)                                   \
+       MD_ASM_IN_SECTION(section,                                      \
+               "       mov     r14, sp                         \n"     \
+               "       lds.l   @sp+, pr                        \n"     \
+               "       rts                                     \n"     \
+               "        mov.l  @sp+, r14")
diff --git a/lib/csu/sparc64/Makefile b/lib/csu/sparc64/Makefile
new file mode 100644 (file)
index 0000000..21a68d6
--- /dev/null
@@ -0,0 +1,8 @@
+#      $NetBSD: Makefile,v 1.6 2006/05/19 19:11:12 christos Exp $
+
+#Uncomment the next line to enable the new .init fallthru
+CPPFLAGS+=     -I${.CURDIR}/../sparc_elf
+
+ELFSIZE=64
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/sparc64/crt0.c b/lib/csu/sparc64/crt0.c
new file mode 100644 (file)
index 0000000..73ef61e
--- /dev/null
@@ -0,0 +1,119 @@
+/* $NetBSD: crt0.c,v 1.24 2005/12/24 21:38:40 perry Exp $ */
+
+/*
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+/*
+ * __start needs to gather up argc, argv, env_p, ps_strings, the termination
+ * routine passed in %g1 and call ___start to finish up the startup processing.
+ *
+ * NB: We are violating the ELF spec by passing a pointer to the ps strings in
+ *     %g1 instead of a termination routine.
+ */
+
+__asm("\n\
+       .data\n\
+__data_start:                                  ! Start of data section\n\
+       .text\n\
+       .align 4\n\
+       .global _start\n\
+       .global __start\n\
+       .register %g3,#scratch\n\
+       .register %g2,#scratch\n\
+_start:\n\
+__start:\n\
+       setx    __data_start, %o0, %g4          ! Point %g4 to start of data section\n\
+       clr     %g4                             ! egcs thinks this is zero. XXX\n\
+       clr     %fp\n\
+       add     %sp, 8*16 + 0x7ff, %o0          ! start of stack\n\
+       mov     %g1, %o1                        ! Cleanup routine\n\
+       mov     %g3, %o1                        ! XXXX our rtld uses %g3\n\
+       mov     %g2, %o2                        ! XXXX obj from rtld.\n\
+       ba,pt   %icc, ___start                  ! XXXX jump over the retl egcs 2.96 inserts\n\
+       mov     %g1, %o3                        ! ps_strings XXXX\n\
+");
+
+void ___start(char **, void (*cleanup)(void), const Obj_Entry *,
+               struct ps_strings *);
+
+void
+___start(char **sp,
+    void (*cleanup)(void),                     /* from shared loader */
+    const Obj_Entry *obj,                      /* from shared loader */
+    struct ps_strings *ps_strings)
+{
+       long argc;
+       char **argv, *namep;
+
+       argc = *(long *)sp;
+       argv = sp + 1;
+       environ = sp + 2 + argc;                /* 2: argc + NULL ending argv */
+
+       if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(namep, '/')) == NULL)
+                       __progname = namep;
+               else
+                       __progname++;
+       }
+
+       if (ps_strings != (struct ps_strings *)0 &&
+           ps_strings != (struct ps_strings *)0xbabefacedeadbeef)
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       if (&_DYNAMIC != NULL)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ _start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.24 2005/12/24 21:38:40 perry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/sparc_elf/Makefile b/lib/csu/sparc_elf/Makefile
new file mode 100644 (file)
index 0000000..68929c4
--- /dev/null
@@ -0,0 +1,6 @@
+#      $NetBSD: Makefile,v 1.6 2006/05/19 19:11:12 christos Exp $
+
+#Uncomment the next line to enable the new .init fallthru
+CPPFLAGS+=     -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/sparc_elf/crt0.c b/lib/csu/sparc_elf/crt0.c
new file mode 100644 (file)
index 0000000..cc27c9b
--- /dev/null
@@ -0,0 +1,104 @@
+/* $NetBSD: crt0.c,v 1.12 2004/08/26 21:18:36 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1998 Christos Zoulas
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+void ___start(int, char **, char **, void (*cleanup)(void),
+    const Obj_Entry *, struct ps_strings *);
+
+__asm("        .text\n\
+       .align  4\n\
+       .global __start\n\
+       .global _start\n\
+__start:\n\
+_start:\n\
+       mov     0, %fp\n\
+       ld      [%sp + 64], %o0         ! get argc\n\
+       add     %sp, 68, %o1            ! get argv\n\
+       sll     %o0, 2, %o2             !\n\
+       add     %o2, 4, %o2             ! envp = argv + (argc << 2) + 4\n\
+       add     %o1, %o2, %o2           !\n\
+       andn    %sp, 7, %sp             ! align\n\
+       sub     %sp, 24, %sp            ! expand to standard stack frame size\n\
+       mov     %g3, %o3\n\
+       mov     %g2, %o4\n\
+       call    ___start\n\
+        mov    %g1, %o5\n\
+");
+
+void
+___start(int argc, char **argv, char **envp,
+    void (*cleanup)(void),                     /* from shared loader */
+    const Obj_Entry *obj,                      /* from shared loader */
+    struct ps_strings *ps_strings)
+{
+       environ = envp;
+
+       if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(__progname, '/')) == NULL)
+                       __progname = argv[0];
+               else
+                       __progname++;
+       }
+
+       if (ps_strings != (struct ps_strings *)0)
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       if (&_DYNAMIC != NULL)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.12 2004/08/26 21:18:36 thorpej Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/sparc_elf/dot_init.h b/lib/csu/sparc_elf/dot_init.h
new file mode 100644 (file)
index 0000000..6af62bb
--- /dev/null
@@ -0,0 +1,92 @@
+/* $NetBSD: dot_init.h,v 1.9 2008/05/29 14:51:25 mrg Exp $ */
+
+/*
+ * Copyright (c) 2001 Matthew R. Green
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+
+#ifdef __sparc64__
+#define SAVE   "       save    %sp, -176, %sp          \n"
+#else
+#define SAVE   "       save    %sp, -96, %sp           \n"
+#endif
+
+#define        MD_SECTION_PROLOGUE(sect, entry_pt)             \
+               __asm (                                 \
+               ".section "#sect",\"ax\",@progbits      \n"\
+               "       .align 4                        \n"\
+               ".global "#entry_pt"                    \n"\
+               #entry_pt":                             \n"\
+               SAVE                                    \
+               "       /* fall thru */                 \n"\
+               ".previous")
+
+#define        MD_SECTION_EPILOGUE(sect)                       \
+               __asm (                                 \
+               ".section "#sect",\"ax\",@progbits      \n"\
+               "       .align 4                        \n"\
+               "       ret                             \n"\
+               "        restore                        \n"\
+               ".previous")
+
+#define        MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define        MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define        MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define        MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
diff --git a/lib/csu/vax_elf/Makefile b/lib/csu/vax_elf/Makefile
new file mode 100644 (file)
index 0000000..533cca5
--- /dev/null
@@ -0,0 +1,4 @@
+#      $NetBSD: Makefile,v 1.3 2006/05/19 19:11:12 christos Exp $
+CPPFLAGS+=     -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
diff --git a/lib/csu/vax_elf/crt0.c b/lib/csu/vax_elf/crt0.c
new file mode 100644 (file)
index 0000000..1ee9963
--- /dev/null
@@ -0,0 +1,101 @@
+/* $NetBSD: crt0.c,v 1.10 2004/08/26 21:24:09 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 Matt Thomas
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+#include "common.h"
+
+void ___start(int, char **, char **, void (*cleanup)(void),
+    const Obj_Entry *, struct ps_strings *);
+
+__asm(" .text;"
+"      .align  2;"
+"      .globl  _start;"
+"      .globl  __start;"
+"__start:;"
+"_start:;"
+"      .word   0x0101;"
+"      pushl   %r9;"           /* ps_strings */
+"      pushl   %r8;"           /* obj */
+"      pushl   %r7;"           /* cleanup */
+"      movl    (%r6),%r0;"     /* argc */
+"      pushal  8(%r6)[%r0];"   /* envp = &argv[argc + 1] */
+"      pushal  4(%r6);"        /* argv */
+"      pushl   %r0;"           /* argc */
+"      calls   $6,___start;"
+       );
+
+void
+___start(int argc, char **argv, char **envp,
+    void (*cleanup)(void),                     /* from shared loader */
+    const Obj_Entry *obj,                      /* from shared loader */
+    struct ps_strings *ps_strings)
+{
+       environ = envp;
+
+       if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
+               if ((__progname = _strrchr(__progname, '/')) == NULL)
+                       __progname = argv[0];
+               else
+                       __progname++;
+       }
+
+       if (ps_strings != (struct ps_strings *)0)
+               __ps_strings = ps_strings;
+
+#ifdef DYNAMIC
+       if (&_DYNAMIC != NULL)
+               _rtld_setup(cleanup, obj);
+#endif
+
+#ifdef MCRT0
+       atexit(_mcleanup);
+       monstartup((u_long)&_eprol, (u_long)&_etext);
+#endif
+
+       atexit(_fini);
+       _init();
+
+       exit(main(argc, argv, environ));
+}
+
+/*
+ * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: crt0.c,v 1.10 2004/08/26 21:24:09 thorpej Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "common.c"
diff --git a/lib/csu/vax_elf/dot_init.h b/lib/csu/vax_elf/dot_init.h
new file mode 100644 (file)
index 0000000..97c5082
--- /dev/null
@@ -0,0 +1,66 @@
+/* $NetBSD: dot_init.h,v 1.7 2008/05/10 15:31:04 martin Exp $ */
+
+/*-
+ * Copyright (c) 2001 Ross Harvey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
+#include <machine/asm.h>
+
+#define        MD_SECTION_PROLOGUE(sect, entry_pt)                     \
+               __asm (                                         \
+               "       .section "#sect",\"ax\",@progbits\n"    \
+               "       .globl  " #entry_pt "\n"                \
+               "       .type   " #entry_pt "@function\n"       \
+               "       .align  1\n"                            \
+               #entry_pt":\n"                                  \
+               "       .word 0\n"                              \
+                       /* fall thru */                         \
+               "       .previous")
+
+#define        MD_SECTION_EPILOGUE(sect)                               \
+               __asm (                                         \
+               "       .section "#sect",\"ax\",@progbits\n"    \
+               "       ret\n"                                  \
+               "       .previous")
+
+#define        MD_CALL_STATIC_FUNCTION(sect, func)                     \
+               __asm (                                         \
+               "       .section "#sect",\"ax\",@progbits\n"    \
+               "       calls   $0,"#func"\n"                   \
+               "       .previous");
+
+#define        MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init)
+#define        MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini)
+
+#define        MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init)
+#define        MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini)
index 3def5d19d726c2079bad20074a751f130be95543..2a3536af685865d03f31bf7871bb59fcd6c4468c 100644 (file)
@@ -168,17 +168,15 @@ static LIST_HEAD(, _ns_drec) _ns_drec = LIST_HEAD_INITIALIZER(&_ns_drec);
 static mutex_t _ns_drec_lock = MUTEX_INITIALIZER;
 #endif /* _REENTRANT */
 
-
-/*
- * Runtime determination of whether we are dynamically linked or not.
- */
-#ifdef __ELF__
-extern int                     _DYNAMIC __weak_reference(_DYNAMIC);
-#define        is_dynamic()            (&_DYNAMIC != NULL)
-#else
+#ifndef __ELF__
 #define        is_dynamic()            (0)     /* don't bother - switch to ELF! */
-#endif /* __ELF__ */
-
+#elif __GNUC_PREREQ__(4,2)
+static int rtld_DYNAMIC __attribute__((__weakref__, __alias__("_DYNAMIC")));
+#define        is_dynamic()            (&rtld_DYNAMIC != NULL)
+#else
+extern int _DYNAMIC __weak_reference(_DYNAMIC);
+#define        is_dynamic()            (&_DYNAMIC != NULL)
+#endif
 
 /*
  * size of dynamic array chunk for _nsmap and _nsmap[x].srclist (and other
diff --git a/libexec/ld.elf_so/Makefile b/libexec/ld.elf_so/Makefile
new file mode 100644 (file)
index 0000000..42feec0
--- /dev/null
@@ -0,0 +1,133 @@
+#      $NetBSD: Makefile,v 1.102 2011/01/16 02:36:05 matt Exp $
+#
+# NOTE: when changing ld.so, ensure that ldd still compiles.
+#
+
+WARNS?=4
+
+# This needs to be before bsd.init.mk
+.if defined(BSD_MK_COMPAT_FILE)
+.include <${BSD_MK_COMPAT_FILE}>
+.endif
+
+# We are not building this with PIE
+PIE_CFLAGS=
+PIE_LDFLAGS=
+.include <bsd.init.mk>                 # for MKPIC definition
+.include <bsd.shlib.mk>                        # for SHLINKINSTALLDIR definition
+
+.if defined(LDELFSO_MACHINE_CPU) && !empty(LDELFSO_MACHINE_CPU) && \
+    exists(${.CURDIR}/arch/${LDELFSO_MACHINE_CPU})
+ARCHSUBDIR=    ${LDELFSO_MACHINE_CPU}
+.else
+ARCHSUBDIR=    ${MACHINE_CPU}
+.endif
+M=             ${.CURDIR}/arch/${ARCHSUBDIR}
+
+.if ((${MACHINE_ARCH} == "alpha") ||                                   \
+     (${MACHINE_CPU} == "arm") ||                                      \
+     (${MACHINE_ARCH} == "hppa") ||                                    \
+     (${MACHINE_ARCH} == "i386") ||                                    \
+     (${MACHINE_ARCH} == "m68k") ||                                    \
+     (${MACHINE_CPU} == "mips") ||                                     \
+     (${MACHINE_ARCH} == "powerpc") ||                                 \
+     (${MACHINE_CPU} == "sh3") ||                                      \
+     (${MACHINE_ARCH} == "sparc") ||                                   \
+     (${MACHINE_ARCH} == "sparc64") ||                                 \
+     (${MACHINE_ARCH} == "x86_64") ||                                  \
+     (${MACHINE_ARCH} == "vax")) &&                                    \
+    ${MKPIC} != "no"
+
+LDFLAGS+=      -shared -symbolic -nostartfiles
+LDFLAGS+=      -Wl,-static
+LDFLAGS+=      -Wl,--warn-shared-textrel
+
+CFLAGS+=       -fvisibility=hidden
+
+# Adds SRCS, CPPFLAGS, LDFLAGS, etc.  Must go first so MD startup source
+# is first.
+.if exists($M/Makefile.inc)
+.include "$M/Makefile.inc"
+.endif
+
+# Support compat ld.elf_so.
+.if defined(MLIBDIR)
+PROG=          ld.elf_so-${MLIBDIR}
+CPPFLAGS+=     -DRTLD_ARCH_SUBDIR=\"${MLIBDIR}\"
+.else
+PROG=          ld.elf_so
+.endif
+
+CLIBOBJ!=      cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR}
+
+SRCS+=         rtld.c reloc.c symbol.c xmalloc.c xprintf.c debug.c \
+               map_object.c load.c search.c headers.c paths.c expand.c
+
+.if ${USE_FORT} == "yes"
+.PATH.c: ${NETBSDSRCDIR}/lib/libc/misc
+SRCS+=         stack_protector.c
+.endif
+
+.PATH.c: ${NETBSDSRCDIR}/lib/libc/stdlib
+SRCS+=         exit.c
+
+errlist_concat.h: ${NETBSDSRCDIR}/lib/libc/gen/errlist.awk ${NETBSDSRCDIR}/sys/sys/errno.h
+       ${TOOL_AWK} -v concat=1 -f ${.ALLSRC} > ${.TARGET}.tmp && \
+       mv -f ${.TARGET}.tmp ${.TARGET}
+
+xprintf.c: errlist_concat.h
+
+CLEANFILES+=   errlist_concat.h
+
+BINDIR=                ${SHLINKINSTALLDIR}
+
+CPPFLAGS+=     -DLIBDIR=\"${LIBDIR}\" -D_PATH_RTLD=\"${BINDIR}/${PROG}\"
+CPPFLAGS+=     -I${.CURDIR} -I.
+CPPFLAGS+=     -DRTLD_LOADER
+CPPFLAGS+=     -D_RTLD_SOURCE
+CPPFLAGS+=     -DCOMBRELOC
+#CPPFLAGS+=    -DDEBUG
+#CPPFLAGS+=    -DRTLD_DEBUG
+#CPPFLAGS+=    -DRTLD_DEBUG_RELOC
+#DBG=          -g
+DBG=           -O3 -fomit-frame-pointer
+
+.if ${SHLIBDIR} != ${LIBDIR}
+CPPFLAGS+=     -DRTLD_DEFAULT_LIBRARY_PATH=\"${SHLIBDIR}:${LIBDIR}\"
+.endif
+
+# rtld.c and symbol.c use alloca, so disable SSP warnings.
+COPTS.rtld.c+= -Wno-stack-protector
+COPTS.symbol.c+=-Wno-stack-protector
+
+LDADD+=                -L${CLIBOBJ} -L${DESTDIR}${LIBDIR}
+.if ${MKPICLIB} != "no"
+LDADD+=                -lc_pic
+.if ${MKPICINSTALL} != "no"
+DPADD+=                ${LIBC_PIC}
+.endif
+DPADD+=                ${CLIBOBJ}/libc_pic.a
+.else
+LDADD+=                -lc
+DPADD+=                ${CLIBOBJ}/libc.a
+.endif
+
+STRIPFLAG=
+
+.PATH: $M
+
+${PROG}: ${OBJS} ${DPADD}
+       ${_MKMSG_LINK} ${PROG}
+       ${CC} ${LDFLAGS} -o ${PROG} ${OBJS} ${LDADD}
+
+.if ${SHLINKINSTALLDIR} != "/usr/libexec"
+SYMLINKS+=     ${SHLINKINSTALLDIR}/${PROG} /usr/libexec/${PROG}
+.endif
+
+.include <bsd.prog.mk>
+.else
+
+MAN=           ld.elf_so.1
+
+.include <bsd.man.mk>
+.endif
diff --git a/libexec/ld.elf_so/README b/libexec/ld.elf_so/README
new file mode 100644 (file)
index 0000000..9bf3423
--- /dev/null
@@ -0,0 +1,6 @@
+$NetBSD: README,v 1.11 2006/11/24 22:52:16 wiz Exp $
+
+TO DO:
+
+* Support for coexistence of 32-bit and 64-bit ELF on platforms that can
+  do that.
diff --git a/libexec/ld.elf_so/TODO b/libexec/ld.elf_so/TODO
new file mode 100644 (file)
index 0000000..55ecf74
--- /dev/null
@@ -0,0 +1,33 @@
+rtld:
+* resolve MIPS binding lossage
+
+binutils/gcc:
+* alpha: why are there GLOB_DAT relocs in ld.elf_so?
+* alpha: bogus textrels in rtti info
+* mips: why are there global GOT relocs in ld.elf_so?
+* mips: bogus textrels in .rel.dyn
+* powerpc: make sure the .got section is always executable
+* powerpc: fix ld scripts so that .rodata is still used for PIC
+
+machine-specific:
+* #ifdefs:
+headers.c:#ifndef __mips__
+headers.c:#ifdef __mips__
+reloc.c:#if defined(__hppa__)
+rtld.c:#if !defined(__hppa__)
+rtld.c:#if !defined(__mips__) && !defined(__hppa__)
+rtld.c:#if !defined(__arm__) && !defined(__mips__) && !defined(__sh__)
+rtld.c:#ifdef __mips__
+rtld.h:#ifdef __mips__
+symbol.c:#ifndef __mips__
+
+issues to research:
+* sh, x86_64 have different absolute and GLOB_DAT relocs; nothing else does
+* sh, vax, x86_64 use addend on PLT; nothing else does
+
+
+rela: alpha hppa m68k powerpc sh sparc sparc64 vax x86_64
+rel: arm i386 mips
+
+- mycroft
+  2003/09/24
diff --git a/libexec/ld.elf_so/arch/alpha/Makefile.inc b/libexec/ld.elf_so/arch/alpha/Makefile.inc
new file mode 100644 (file)
index 0000000..b20689f
--- /dev/null
@@ -0,0 +1,11 @@
+#      $NetBSD: Makefile.inc,v 1.12 2005/06/04 16:17:17 lukem Exp $
+
+SRCS+=         rtld_start.S alpha_reloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic -mno-fp-regs
+
+CPPFLAGS+=     -DELFSIZE=64
+#CPPFLAGS+=    -DRTLD_DEBUG_ALPHA
+
+LDFLAGS+=      -Wl,-e,_rtld_start
diff --git a/libexec/ld.elf_so/arch/alpha/alpha_reloc.c b/libexec/ld.elf_so/arch/alpha/alpha_reloc.c
new file mode 100644 (file)
index 0000000..357adc7
--- /dev/null
@@ -0,0 +1,503 @@
+/*     $NetBSD: alpha_reloc.c,v 1.38 2010/09/30 09:11:18 skrll Exp $   */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed for the NetBSD Project by
+ *     Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright 1996, 1997, 1998, 1999 John D. Polstra.   
+ * All rights reserved.
+ *           
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *          
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: alpha_reloc.c,v 1.38 2010/09/30 09:11:18 skrll Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+#include "rtld.h"
+#include "debug.h"
+
+#ifdef RTLD_DEBUG_ALPHA
+#define        adbg(x)         xprintf x
+#else
+#define        adbg(x)         /* nothing */
+#endif
+
+void _rtld_bind_start(void);
+void _rtld_bind_start_old(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Addr);
+static inline int _rtld_relocate_plt_object(const Obj_Entry *,
+    const Elf_Rela *, Elf_Addr *);
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       uint32_t word0;
+
+       /*
+        * The PLTGOT on the Alpha looks like this:
+        *
+        *      PLT HEADER
+        *      .
+        *      . 32 bytes
+        *      .
+        *      PLT ENTRY #0
+        *      .
+        *      . 12 bytes
+        *      .
+        *      PLT ENTRY #1
+        *      .
+        *      . 12 bytes
+        *      .
+        *      etc.
+        *
+        * The old-format entries look like (displacements filled in
+        * by the linker):
+        *
+        *      ldah    $28, 0($31)             # 0x279f0000
+        *      lda     $28, 0($28)             # 0x239c0000
+        *      br      $31, plt0               # 0xc3e00000
+        *
+        * The new-format entries look like:
+        *
+        *      br      $28, plt0               # 0xc3800000
+        *                                      # 0x00000000
+        *                                      # 0x00000000
+        *
+        * What we do is fetch the first PLT entry and check to
+        * see the first word of it matches the first word of the
+        * old format.  If so, we use a binding routine that can
+        * handle the old format, otherwise we use a binding routine
+        * that handles the new format.
+        *
+        * Note that this is done on a per-object basis, we can mix
+        * and match shared objects build with both the old and new
+        * linker.
+        */
+       word0 = *(uint32_t *)(((char *) obj->pltgot) + 32);
+       if ((word0 & 0xffff0000) == 0x279f0000) {
+               /* Old PLT entry format. */
+               adbg(("ALPHA: object %p has old PLT format\n", obj));
+               obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start_old;
+               obj->pltgot[3] = (Elf_Addr) obj;
+       } else {
+               /* New PLT entry format. */
+               adbg(("ALPHA: object %p has new PLT format\n", obj));
+               obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
+               obj->pltgot[3] = (Elf_Addr) obj;
+       }
+
+       __asm volatile("imb");
+}
+
+/*
+ * It is possible for the compiler to emit relocations for unaligned data.
+ * We handle this situation with these inlines.
+ */
+#define        RELOC_ALIGNED_P(x) \
+       (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
+
+static inline Elf_Addr
+load_ptr(void *where)
+{
+       Elf_Addr res;
+
+       memcpy(&res, where, sizeof(res));
+
+       return (res);
+}
+
+static inline void
+store_ptr(void *where, Elf_Addr val)
+{
+
+       memcpy(where, &val, sizeof(val));
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rela *rela = 0, *relalim;
+       Elf_Addr relasz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_RELA:
+                       rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
+       for (; rela < relalim; rela++) {
+               where = (Elf_Addr *)(relocbase + rela->r_offset);
+               /* XXX For some reason I see a few GLOB_DAT relocs here. */
+               *where += (Elf_Addr)relocbase;
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+       Elf_Addr target = -1;
+
+       for (rela = obj->rela; rela < obj->relalim; rela++) {
+               Elf_Addr        *where;
+               const Elf_Sym   *def;
+               const Obj_Entry *defobj;
+               Elf_Addr         tmp;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+               symnum = ELF_R_SYM(rela->r_info);
+
+               switch (ELF_R_TYPE(rela->r_info)) {
+               case R_TYPE(NONE):
+                       break;
+
+               case R_TYPE(REFQUAD):
+               case R_TYPE(GLOB_DAT):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       target = (Elf_Addr)(defobj->relocbase +
+                           def->st_value);
+
+                       tmp = target + rela->r_addend;
+                       if (__predict_true(RELOC_ALIGNED_P(where))) {
+                               if (*where != tmp)
+                                       *where = tmp;
+                       } else {
+                               if (load_ptr(where) != tmp)
+                                       store_ptr(where, tmp);
+                       }
+                       rdbg(("REFQUAD/GLOB_DAT %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)tmp, defobj->path));
+                       break;
+
+               case R_TYPE(RELATIVE):
+                       if (__predict_true(RELOC_ALIGNED_P(where)))
+                               *where += (Elf_Addr)obj->relocbase;
+                       else
+                               store_ptr(where,
+                                   load_ptr(where) + (Elf_Addr)obj->relocbase);
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)*where));
+                       break;
+
+               case R_TYPE(COPY):
+                       /*
+                        * These are deferred until all other relocations have
+                        * been done.  All we do here is make sure that the
+                        * COPY relocation is not in a shared library.  They
+                        * are allowed only in executable files.
+                        */
+                       if (obj->isdynamic) {
+                               _rtld_error(
+                       "%s: Unexpected R_COPY relocation in shared library",
+                                   obj->path);
+                               return -1;
+                       }
+                       rdbg(("COPY (avoid in main)"));
+                       break;
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "addend = %p, contents = %p, symbol = %s",
+                           symnum, (u_long)ELF_R_TYPE(rela->r_info),
+                           (void *)rela->r_offset, (void *)rela->r_addend,
+                           (void *)load_ptr(where),
+                           obj->strtab + obj->symtab[symnum].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rela->r_info));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       if (!obj->relocbase)
+               return 0;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
+               Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+
+               assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
+
+               /* Just relocate the GOT slots pointing into the PLT */
+               *where += (Elf_Addr)obj->relocbase;
+               rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
+       }
+
+       return 0;
+}
+
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
+    Elf_Addr *tp)
+{
+       Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+       Elf_Addr new_value;
+       const Elf_Sym *def;
+       const Obj_Entry *defobj;
+       Elf_Addr stubaddr; 
+       unsigned long info = rela->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       rdbg(("bind now/fixup in %s --> old=%p new=%p",
+           defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
+
+       if ((stubaddr = *where) != new_value) {
+               int64_t delta, idisp;
+               uint32_t insn[3], *stubptr;
+               int insncnt;
+               Elf_Addr pc;
+
+               /* Point this GOT entry at the target. */
+               *where = new_value;
+
+               /*
+                * Alpha shared objects may have multiple GOTs, each
+                * of which may point to this entry in the PLT.  But,
+                * we only have a reference to the first GOT entry which
+                * points to this PLT entry.  In order to avoid having to
+                * re-bind this call every time a non-first GOT entry is
+                * used, we will attempt to patch up the PLT entry to
+                * reference the target, rather than the binder.
+                *
+                * When the PLT stub gets control, PV contains the address
+                * of the PLT entry.  Each PLT entry has room for 3 insns.
+                * If the displacement of the target from PV fits in a signed
+                * 32-bit integer, we can simply add it to PV.  Otherwise,
+                * we must load the GOT entry itself into PV.
+                *
+                * Note if the shared object uses the old PLT format, then
+                * we cannot patch up the PLT safely, and so we skip it
+                * in that case[*].
+                *
+                * [*] Actually, if we're not doing lazy-binding, then
+                * we *can* (and do) patch up this PLT entry; the PLTGOT
+                * thunk won't yet point to any binder entry point, and
+                * so this test will fail as it would for the new PLT
+                * entry format.
+                */
+               if (obj->pltgot[2] == (Elf_Addr) &_rtld_bind_start_old) {
+                       rdbg(("  old PLT format"));
+                       goto out;
+               }
+
+               delta = new_value - stubaddr;
+               rdbg(("  stubaddr=%p, where-stubaddr=%ld, delta=%ld",
+                   (void *)stubaddr, (long)where - (long)stubaddr,
+                   (long)delta));
+               insncnt = 0;
+               if ((int32_t)delta == delta) {
+                       /*
+                        * We can adjust PV with an LDA, LDAH sequence.
+                        *
+                        * First, build an LDA insn to adjust the low 16
+                        * bits.
+                        */
+                       insn[insncnt++] = 0x08 << 26 | 27 << 21 | 27 << 16 |
+                           (delta & 0xffff);
+                       rdbg(("  LDA  $27,%d($27)", (int16_t)delta));
+                       /*
+                        * Adjust the delta to account for the effects of
+                        * the LDA, including sign-extension.
+                        */
+                       delta -= (int16_t)delta;
+                       if (delta != 0) {
+                               /*
+                                * Build an LDAH instruction to adjust the
+                                * high 16 bits.
+                                */
+                               insn[insncnt++] = 0x09 << 26 | 27 << 21 |
+                                   27 << 16 | ((delta >> 16) & 0xffff);
+                               rdbg(("  LDAH $27,%d($27)",
+                                   (int16_t)(delta >> 16)));
+                       }
+               } else {
+                       int64_t dhigh;
+
+                       /* We must load the GOT entry. */
+                       delta = (Elf_Addr)where - stubaddr;
+
+                       /*
+                        * If the GOT entry is too far away from the PLT
+                        * entry, then we can't patch up the PLT entry.
+                        * This PLT entry will have to be bound for each
+                        * GOT entry except for the first one.  This program
+                        * will still run, albeit very slowly.  It is very
+                        * unlikely that this case will ever happen in
+                        * practice.
+                        */
+                       if ((int32_t)delta != delta) {
+                               rdbg(("  PLT stub too far from GOT to relocate"));
+                               goto out;
+                       }
+                       dhigh = delta - (int16_t)delta;
+                       if (dhigh != 0) {
+                               /*
+                                * Build an LDAH instruction to adjust the
+                                * high 16 bits.
+                                */
+                               insn[insncnt++] = 0x09 << 26 | 27 << 21 |
+                                   27 << 16 | ((dhigh >> 16) & 0xffff);
+                               rdbg(("  LDAH $27,%d($27)",
+                                   (int16_t)(dhigh >> 16)));
+                       }
+                       /* Build an LDQ to load the GOT entry. */
+                       insn[insncnt++] = 0x29 << 26 | 27 << 21 |
+                           27 << 16 | (delta & 0xffff);
+                       rdbg(("  LDQ  $27,%d($27)",
+                           (int16_t)delta));
+               }
+
+               /*
+                * Now, build a JMP or BR insn to jump to the target.  If
+                * the displacement fits in a sign-extended 21-bit field,
+                * we can use the more efficient BR insn.  Otherwise, we
+                * have to jump indirect through PV.
+                */
+               pc = stubaddr + (4 * (insncnt + 1));
+               idisp = (int64_t)(new_value - pc) >> 2;
+               if (-0x100000 <= idisp && idisp < 0x100000) {
+                       insn[insncnt++] = 0x30 << 26 | 31 << 21 |
+                           (idisp & 0x1fffff);
+                       rdbg(("  BR   $31,%p", (void *)new_value));
+               } else {
+                       insn[insncnt++] = 0x1a << 26 | 31 << 21 |
+                           27 << 16 | (idisp & 0x3fff);
+                       rdbg(("  JMP  $31,($27),%d",
+                           (int)(idisp & 0x3fff)));
+               }
+
+               /*
+                * Fill in the tail of the PLT entry first, for reentrancy.
+                * Until we have overwritten the first insn (an unconditional
+                * branch), the remaining insns have no effect.
+                */
+               stubptr = (uint32_t *)stubaddr;
+               while (insncnt > 1) {
+                       insncnt--;
+                       stubptr[insncnt] = insn[insncnt];
+               }
+               /*
+                * Commit the tail of the insn sequence to memory
+                * before overwriting the first insn.
+                */
+               __asm volatile("wmb" ::: "memory");
+               stubptr[0] = insn[0];
+               /*
+                * I-stream will be sync'd when we either return from
+                * the binder (lazy bind case) or when the PLTGOT thunk
+                * is patched up (bind-now case).
+                */
+       }
+out:
+       if (tp)
+               *tp = new_value;
+
+       return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Addr reloff)
+{
+       const Elf_Rela *rela = 
+           (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff);
+       Elf_Addr result = 0; /* XXX gcc */
+       int err;
+
+       err = _rtld_relocate_plt_object(obj, rela, &result);
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)result;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++)
+               if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
+                       return -1;
+
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/alpha/rtld_start.S b/libexec/ld.elf_so/arch/alpha/rtld_start.S
new file mode 100644 (file)
index 0000000..22d18ce
--- /dev/null
@@ -0,0 +1,194 @@
+/*     $NetBSD: rtld_start.S,v 1.16 2004/02/18 23:04:49 enami Exp $    */
+
+/*
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * Portions copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+/*
+ * Note: we can call ourselves LEAF even though we use callee-saved
+ * registers because we're the root of the call graph.
+ */
+LEAF_NOPROFILE(_rtld_start, 0)
+       .set    noreorder
+       br      pv, 1f
+1:     LDGP(pv)
+
+       /*
+        * Relocate ourself.
+        */
+       br      s2, 2f          /* get our PC */
+2:     ldiq    s3, 2b          /* get where the linker thought we were */
+
+       subq    s2, s3, a1      /* relocbase */
+       lda     t5, _DYNAMIC
+       addq    a1, t5, a0      /* &_DYNAMIC */
+
+       /* Squirrel away ps_strings. */
+       mov     a3, s0
+
+       bsr     ra, _rtld_relocate_nonplt_self
+       LDGP(ra)
+
+       /*
+        * Allocate space on the stack for the cleanup and obj_main
+        * entries that _rtld() will provide for us.
+        */
+       lda     sp, -16(sp)
+
+       subq    s2, s3, a1      /* relocbase */
+       mov     sp, a0          /* sp */
+       CALL(_rtld)             /* v0 = _rtld(sp, relocbase); */
+
+       ldq     a1, 0(sp)       /* cleanup */
+       ldq     a2, 8(sp)       /* obj_main */
+       lda     sp, 16(sp)      /* pop stack */
+
+       mov     sp, a0          /* stack pointer */
+       mov     s0, a3          /* ps_strings */
+
+       mov     v0, pv          /* set up PV for entry point */
+
+       jsr     ra, (v0), 0     /* (*_start)(sp, cleanup, obj, ps_strings); */
+       ldgp    gp, 0(ra)
+
+       CALL(exit)
+       halt
+END(_rtld_start)
+
+#define        RTLD_BIND_START_PROLOGUE                                        \
+       /* at_reg already used by PLT code. */                          \
+       .set    noat                                            ;       \
+                                                                       \
+       /*                                                              \
+        * Allocate stack frame and preserve all registers that the     \
+        * caller would have normally saved themselves.                 \
+        */                                                             \
+       lda     sp, -168(sp)                                    ;       \
+       stq     ra, 0(sp)                                       ;       \
+       stq     v0, 8(sp)                                       ;       \
+       stq     t0, 16(sp)                                      ;       \
+       stq     t1, 24(sp)                                      ;       \
+       stq     t2, 32(sp)                                      ;       \
+       stq     t3, 40(sp)                                      ;       \
+       stq     t4, 48(sp)                                      ;       \
+       stq     t5, 56(sp)                                      ;       \
+       stq     t6, 64(sp)                                      ;       \
+       stq     t7, 72(sp)                                      ;       \
+       stq     a0, 80(sp)                                      ;       \
+       stq     a1, 88(sp)                                      ;       \
+       stq     a2, 96(sp)                                      ;       \
+       stq     a3, 104(sp)                                     ;       \
+       stq     a4, 112(sp)                                     ;       \
+       stq     a5, 120(sp)                                     ;       \
+       stq     t8, 128(sp)                                     ;       \
+       stq     t9, 136(sp)                                     ;       \
+       stq     t10, 144(sp)                                    ;       \
+       stq     t11, 152(sp)                                    ;       \
+       stq     gp, 160(sp)                                     ;       \
+                                                                       \
+       /*                                                              \
+        * Load our global pointer.  Note, can't use pv, since it is    \
+        * already used by the PLT code.                                \
+        */                                                             \
+       br      t0, 1f                                          ;       \
+1:     LDGP(t0)
+
+#define        RTLD_BIND_START_EPILOGUE                                        \
+       /* Move the destination address into position. */               \
+       mov     v0, pv                                          ;       \
+                                                                       \
+       /* Restore program registers. */                                \
+       ldq     ra, 0(sp)                                       ;       \
+       ldq     v0, 8(sp)                                       ;       \
+       ldq     t0, 16(sp)                                      ;       \
+       ldq     t1, 24(sp)                                      ;       \
+       ldq     t2, 32(sp)                                      ;       \
+       ldq     t3, 40(sp)                                      ;       \
+       ldq     t4, 48(sp)                                      ;       \
+       ldq     t5, 56(sp)                                      ;       \
+       ldq     t6, 64(sp)                                      ;       \
+       ldq     t7, 72(sp)                                      ;       \
+       ldq     a0, 80(sp)                                      ;       \
+       ldq     a1, 88(sp)                                      ;       \
+       ldq     a2, 96(sp)                                      ;       \
+       ldq     a3, 104(sp)                                     ;       \
+       ldq     a4, 112(sp)                                     ;       \
+       ldq     a5, 120(sp)                                     ;       \
+       ldq     t8, 128(sp)                                     ;       \
+       ldq     t9, 136(sp)                                     ;       \
+       ldq     t10, 144(sp)                                    ;       \
+       ldq     t11, 152(sp)                                    ;       \
+       ldq     gp, 160(sp)                                     ;       \
+       /* XXX LDGP? */                                                 \
+                                                                       \
+       /*                                                              \
+        * We've patched the PLT; sync the I-stream.                    \
+        */                                                             \
+       imb                                                     ;       \
+                                                                       \
+       /* Pop the stack frame and turn control to the destination. */  \
+       lda     sp, 168(sp)                                     ;       \
+       jmp     zero, (pv)
+
+/*
+ * Lazy binding entry point, called via PLT.
+ */
+NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0)
+
+       RTLD_BIND_START_PROLOGUE
+
+       /* Set up the arguments for _rtld_bind. */
+       subq    at_reg, pv, a1          /* calculate offset of reloc entry */
+       ldq     a0, 8(pv)               /* object structure */
+       subq    a1, 20, a1              /* = (at - pv - 20) / 12 * 24 */
+       addq    a1, a1, a1
+
+       CALL(_rtld_bind)
+
+       RTLD_BIND_START_EPILOGUE
+
+END(_rtld_bind_start)
+
+/*
+ * Lazy binding entry point, called via PLT.  This version is for the
+ * old PLT entry format.
+ */
+NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0)
+
+       RTLD_BIND_START_PROLOGUE
+
+       /* Set up the arguments for _rtld_bind. */
+       ldq     a0, 8(pv)               /* object structure */
+       mov     at_reg, a1              /* offset of reloc entry */
+
+       CALL(_rtld_bind)
+
+       RTLD_BIND_START_EPILOGUE
+
+END(_rtld_bind_start_old)
diff --git a/libexec/ld.elf_so/arch/arm/Makefile.inc b/libexec/ld.elf_so/arch/arm/Makefile.inc
new file mode 100644 (file)
index 0000000..280a20d
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile.inc,v 1.11 2005/06/04 16:17:17 lukem Exp $
+
+SRCS+=         rtld_start.S mdreloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic
+
+CPPFLAGS+=     -DELFSIZE=32
+
+LDFLAGS+=      -Wl,-e,_rtld_start
diff --git a/libexec/ld.elf_so/arch/arm/mdreloc.c b/libexec/ld.elf_so/arch/arm/mdreloc.c
new file mode 100644 (file)
index 0000000..d62c690
--- /dev/null
@@ -0,0 +1,276 @@
+/*     $NetBSD: mdreloc.c,v 1.34 2010/08/06 16:33:17 joerg Exp $       */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.34 2010/08/06 16:33:17 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+void _rtld_bind_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       obj->pltgot[1] = (Elf_Addr) obj;
+       obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rel *rel = 0, *rellim;
+       Elf_Addr relsz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_REL:
+                       rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELSZ:
+                       relsz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       rellim = (const Elf_Rel *)((const uint8_t *)rel + relsz);
+       for (; rel < rellim; rel++) {
+               where = (Elf_Addr *)(relocbase + rel->r_offset);
+               *where += (Elf_Addr)relocbase;
+       }
+}
+
+/*
+ * It is possible for the compiler to emit relocations for unaligned data.
+ * We handle this situation with these inlines.
+ */
+#define        RELOC_ALIGNED_P(x) \
+       (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
+
+static inline Elf_Addr
+load_ptr(void *where)
+{
+       Elf_Addr res;
+
+       memcpy(&res, where, sizeof(res));
+
+       return (res);
+}
+
+static inline void
+store_ptr(void *where, Elf_Addr val)
+{
+
+       memcpy(where, &val, sizeof(val));
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rel *rel;
+
+       for (rel = obj->rel; rel < obj->rellim; rel++) {
+               Elf_Addr        *where;
+               const Elf_Sym   *def;
+               const Obj_Entry *defobj;
+               Elf_Addr         tmp;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+               symnum = ELF_R_SYM(rel->r_info);
+
+               switch (ELF_R_TYPE(rel->r_info)) {
+               case R_TYPE(NONE):
+                       break;
+
+#if 1 /* XXX should not occur */
+               case R_TYPE(PC24): {    /* word32 S - P + A */
+                       Elf32_Sword addend;
+
+                       /*
+                        * Extract addend and sign-extend if needed.
+                        */
+                       addend = *where;
+                       if (addend & 0x00800000)
+                               addend |= 0xff000000;
+
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       tmp = (Elf_Addr)obj->relocbase + def->st_value
+                           - (Elf_Addr)where + (addend << 2);
+                       if ((tmp & 0xfe000000) != 0xfe000000 &&
+                           (tmp & 0xfe000000) != 0) {
+                               _rtld_error(
+                               "%s: R_ARM_PC24 relocation @ %p to %s failed "
+                               "(displacement %ld (%#lx) out of range)",
+                                   obj->path, where,
+                                   obj->strtab + obj->symtab[symnum].st_name,
+                                   (long) tmp, (long) tmp);
+                               return -1;
+                       }
+                       tmp >>= 2;
+                       *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
+                       rdbg(("PC24 %s in %s --> %p @ %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, where, defobj->path));
+                       break;
+               }
+#endif
+
+               case R_TYPE(ABS32):     /* word32 B + S + A */
+               case R_TYPE(GLOB_DAT):  /* word32 B + S */
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       if (__predict_true(RELOC_ALIGNED_P(where))) {
+                               tmp = *where + (Elf_Addr)defobj->relocbase +
+                                   def->st_value;
+                               /* Set the Thumb bit, if needed.  */
+                               if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC)
+                                   tmp |= 1;
+                               *where = tmp;
+                       } else {
+                               tmp = load_ptr(where) +
+                                   (Elf_Addr)defobj->relocbase +
+                                   def->st_value;
+                               /* Set the Thumb bit, if needed.  */
+                               if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC)
+                                   tmp |= 1;
+                               store_ptr(where, tmp);
+                       }
+                       rdbg(("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)tmp, where, defobj->path));
+                       break;
+
+               case R_TYPE(RELATIVE):  /* word32 B + A */
+                       if (__predict_true(RELOC_ALIGNED_P(where))) {
+                               tmp = *where + (Elf_Addr)obj->relocbase;
+                               *where = tmp;
+                       } else {
+                               tmp = load_ptr(where) +
+                                   (Elf_Addr)obj->relocbase;
+                               store_ptr(where, tmp);
+                       }
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)tmp));
+                       break;
+
+               case R_TYPE(COPY):
+                       /*
+                        * These are deferred until all other relocations have
+                        * been done.  All we do here is make sure that the
+                        * COPY relocation is not in a shared library.  They
+                        * are allowed only in executable files.
+                        */
+                       if (obj->isdynamic) {
+                               _rtld_error(
+                       "%s: Unexpected R_COPY relocation in shared library",
+                                   obj->path);
+                               return -1;
+                       }
+                       rdbg(("COPY (avoid in main)"));
+                       break;
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "contents = %p, symbol = %s",
+                           symnum, (u_long)ELF_R_TYPE(rel->r_info),
+                           (void *)rel->r_offset, (void *)load_ptr(where),
+                           obj->strtab + obj->symtab[symnum].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rel->r_info));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       const Elf_Rel *rel;
+
+       if (!obj->relocbase)
+               return 0;
+
+       for (rel = obj->pltrel; rel < obj->pltrellim; rel++) {
+               Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+
+               assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT));
+
+               /* Just relocate the GOT slots pointing into the PLT */
+               *where += (Elf_Addr)obj->relocbase;
+               rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
+       }
+
+       return 0;
+}
+
+static int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel,
+       Elf_Addr *tp)
+{
+       Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+       Elf_Addr new_value;
+       const Elf_Sym  *def;
+       const Obj_Entry *defobj;
+       unsigned long info = rel->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JUMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       /* Set the Thumb bit, if needed.  */
+       if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC)
+               new_value |= 1;
+       rdbg(("bind now/fixup in %s --> old=%p new=%p",
+           defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
+       if (*where != new_value)
+               *where = new_value;
+       if (tp)
+               *tp = new_value;
+
+       return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rel *rel = (const Elf_Rel *)((const uint8_t *)obj->pltrel + reloff);
+       Elf_Addr new_value = 0; /* XXX gcc */
+       int err;
+
+       err = _rtld_relocate_plt_object(obj, rel, &new_value);
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)new_value;
+}
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rel *rel;
+       int err = 0;
+       
+       for (rel = obj->pltrel; rel < obj->pltrellim; rel++) {
+               err = _rtld_relocate_plt_object(obj, rel, NULL);
+               if (err)
+                       break;
+       }
+
+       return err;
+}
diff --git a/libexec/ld.elf_so/arch/arm/rtld_start.S b/libexec/ld.elf_so/arch/arm/rtld_start.S
new file mode 100644 (file)
index 0000000..41a599c
--- /dev/null
@@ -0,0 +1,104 @@
+/*     $NetBSD: rtld_start.S,v 1.10 2009/11/11 14:15:41 skrll Exp $    */
+
+/*-
+ * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas and by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: rtld_start.S,v 1.10 2009/11/11 14:15:41 skrll Exp $")
+
+       .text
+       .align  0
+       .globl  _rtld_start
+       .type   _rtld_start,%function
+_rtld_start:
+       sub     sp, sp, #8              /* make room for obj_main & exit proc */
+       mov     r4, r0                  /* save ps_strings */
+
+       ldr     sl, .L2
+       ldr     r5, .L2+4
+       ldr     r0, .L2+8
+.L1:
+       add     sl, pc, sl
+       ldr     r5, [sl, r5]
+       ldr     r0, [sl, r0]
+
+       sub     r1, sl, r5              /* relocbase */
+       add     r0, r1, r0              /* &_DYNAMIC */
+       bl      _rtld_relocate_nonplt_self
+
+       sub     r1, sl, r5              /* relocbase */
+       mov     r0, sp                  /* sp */
+       bl      _rtld                   /* call the shared loader */
+       mov     r3, r0                  /* save entry point */
+
+       ldr     r2, [sp, #0]            /* r2 = cleanup */
+       ldr     r1, [sp, #4]            /* r1 = obj_main */
+       add     sp, sp, #8              /* restore stack */
+       mov     r0, r4                  /* restore ps_strings */
+#ifdef _ARM_ARCH_4T
+       bx      r3                      /* jump to the entry point */
+#else
+       mov     pc, r3                  /* jump to the entry point */
+#endif
+.L2:
+       .word   _GLOBAL_OFFSET_TABLE_ - (.L1+8)
+       .word   _GLOBAL_OFFSET_TABLE_(GOT)
+       .word   _DYNAMIC(GOT)
+
+       .align  0
+       .globl  _rtld_bind_start
+       .type   _rtld_bind_start,%function
+/*
+ *     stack[0] = RA
+ *     ip = &GOT[n+3]
+ *     lr = &GOT[2]
+ */
+_rtld_bind_start:
+       stmdb   sp!,{r0-r4,sl,fp}
+
+       sub     r1, ip, lr              /* r1 = 4 * (n + 1) */
+       sub     r1, r1, #4              /* r1 = 4 * n */
+       add     r1, r1, r1              /* r1 = 8 * n */
+
+       ldr     r0, [lr, #-4]           /* get obj ptr from GOT[1] */
+       mov     r4, ip                  /* save GOT location */
+
+       bl      _rtld_bind              /* Call the binder */
+
+       str     r0, [r4]                /* save address in GOT */
+       mov     ip, r0                  /* save new address */
+
+       ldmia   sp!,{r0-r4,sl,fp,lr}    /* restore the stack */
+#ifdef _ARM_ARCH_4T
+       bx      ip                      /* jump to the new address */
+#else
+       mov     pc, ip                  /* jump to the new address */
+#endif
+
diff --git a/libexec/ld.elf_so/arch/hppa/Makefile.inc b/libexec/ld.elf_so/arch/hppa/Makefile.inc
new file mode 100644 (file)
index 0000000..6f6c7f8
--- /dev/null
@@ -0,0 +1,14 @@
+#      $NetBSD: Makefile.inc,v 1.8 2009/09/12 07:22:16 skrll Exp $
+
+SRCS+=         rtld_start.S hppa_reloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic
+
+CPPFLAGS+=     -DELFSIZE=32
+#CPPFLAGS+=    -DDEBUG
+#CPPFLAGS+=    -DRTLD_DEBUG
+#CPPFLAGS+=    -DRTLD_DEBUG_RELOC
+#CPPFLAGS+=    -DRTLD_DEBUG_HPPA
+
+LDFLAGS+=      -Wl,-e,'$$rtld_start'
diff --git a/libexec/ld.elf_so/arch/hppa/hppa_reloc.c b/libexec/ld.elf_so/arch/hppa/hppa_reloc.c
new file mode 100644 (file)
index 0000000..ef1cdf1
--- /dev/null
@@ -0,0 +1,617 @@
+/*     $NetBSD: hppa_reloc.c,v 1.34 2010/09/24 11:41:46 skrll Exp $    */
+
+/*-
+ * Copyright (c) 2002, 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Fredette and Nick Hudson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: hppa_reloc.c,v 1.34 2010/09/24 11:41:46 skrll Exp $");
+#endif /* not lint */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <string.h>
+
+#include "rtld.h"
+#include "debug.h"
+
+#ifdef RTLD_DEBUG_HPPA
+#define        hdbg(x)         xprintf x
+#else
+#define        hdbg(x)         /* nothing */
+#endif
+
+caddr_t _rtld_bind(const Obj_Entry *, const Elf_Addr);
+void _rtld_bind_start(void);
+void __rtld_setup_hppa_pltgot(const Obj_Entry *, Elf_Addr *);
+
+/*
+ * It is possible for the compiler to emit relocations for unaligned data.
+ * We handle this situation with these inlines.
+ */
+#define        RELOC_ALIGNED_P(x) \
+       (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
+
+static inline Elf_Addr
+load_ptr(void *where)
+{
+       if (__predict_true(RELOC_ALIGNED_P(where)))
+               return *(Elf_Addr *)where;
+       else {
+               Elf_Addr res;
+
+               (void)memcpy(&res, where, sizeof(res));
+               return res;
+       }
+}
+
+static inline void
+store_ptr(void *where, Elf_Addr val)
+{
+       if (__predict_true(RELOC_ALIGNED_P(where)))
+               *(Elf_Addr *)where = val;
+       else
+               (void)memcpy(where, &val, sizeof(val));
+}
+
+/*
+ * In the runtime architecture (ABI), PLABEL function pointers are
+ * distinguished from normal function pointers by having the next-least-
+ * significant bit set.  (This bit is referred to as the L field in HP
+ * documentation).  The $$dyncall millicode is aware of this.
+ */
+#define        RTLD_MAKE_PLABEL(plabel)        (((Elf_Addr)(plabel)) | (1 << 1))
+#define RTLD_IS_PLABEL(addr)           (((Elf_Addr)(addr)) & (1 << 1))
+#define        RTLD_GET_PLABEL(addr)   ((hppa_plabel *) (((Elf_Addr)addr) & ~3))
+
+/*
+ * This is the PLABEL structure.  The function PC and
+ * shared linkage members must come first, as they are
+ * the actual PLABEL.
+ */
+typedef struct _hppa_plabel {
+       Elf_Addr        hppa_plabel_pc;
+       Elf_Addr        hppa_plabel_sl;
+       SLIST_ENTRY(_hppa_plabel)       hppa_plabel_next;
+} hppa_plabel;
+
+/*
+ * For now allocated PLABEL structures are tracked on a 
+ * singly linked list.  This maybe should be revisited.
+ */
+static SLIST_HEAD(hppa_plabel_head, _hppa_plabel) hppa_plabel_list
+    = SLIST_HEAD_INITIALIZER(hppa_plabel_list);
+
+/*
+ * Because I'm hesitant to use NEW while relocating self,
+ * this is a small pool of preallocated PLABELs.
+ */
+#define        HPPA_PLABEL_PRE (14)
+static hppa_plabel hppa_plabel_pre[HPPA_PLABEL_PRE];
+static int hppa_plabel_pre_next = 0;
+
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+int _rtld_relocate_plt_objects(const Obj_Entry *);
+static inline int _rtld_relocate_plt_object(const Obj_Entry *,
+    const Elf_Rela *, Elf_Addr *);
+
+/*
+ * This bootstraps the dynamic linker by relocating its GOT.
+ * On the hppa, unlike on other architectures, static strings
+ * are found through the GOT.  Static strings are essential
+ * for RTLD_DEBUG, and I suspect they're used early even when 
+ * !defined(RTLD_DEBUG), making relocating the GOT essential.
+ *
+ * It gets worse.  Relocating the GOT doesn't mean just walking
+ * it and adding the relocbase to all of the entries.  You must
+ * find and use the GOT relocations, since those RELA relocations 
+ * have the necessary addends - the GOT comes initialized as 
+ * zeroes.
+ */
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rela  *relafirst, *rela, *relalim;
+       Elf_Addr        relasz;
+       void            *where;
+       Elf_Addr        *pltgot;
+       const Elf_Rela  *plabel_relocs[HPPA_PLABEL_PRE];
+       int             nplabel_relocs = 0;
+       int             i;
+       const Elf_Sym   *symtab, *sym;
+       unsigned long   symnum;
+       hppa_plabel     *plabel;
+
+       /*
+        * Process the DYNAMIC section, looking for the non-PLT relocations.
+        */ 
+       relafirst = NULL;
+       relasz = 0;
+       symtab = NULL;
+       pltgot = NULL;
+       for (; dynp->d_tag != DT_NULL; ++dynp) {
+               switch (dynp->d_tag) {
+
+               case DT_RELA:
+                       relafirst = (const Elf_Rela *)
+                           (relocbase + dynp->d_un.d_ptr);
+                       break;
+
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+
+               case DT_SYMTAB:
+                       symtab = (const Elf_Sym *)
+                           (relocbase + dynp->d_un.d_ptr);
+                       break;
+
+               case DT_PLTGOT:
+                       pltgot = (Elf_Addr *)
+                           (relocbase + dynp->d_un.d_ptr);
+                        break;
+               }
+       }
+       relalim = (const Elf_Rela *)((const char *)relafirst + relasz);
+
+       for (rela = relafirst; rela < relalim; rela++) {
+               symnum = ELF_R_SYM(rela->r_info);
+               where = (void *)(relocbase + rela->r_offset);
+
+               switch (ELF_R_TYPE(rela->r_info)) {
+               case R_TYPE(DIR32):
+                       if (symnum == 0)
+                               store_ptr(where, 
+                                   relocbase + rela->r_addend);
+                       else {
+                               sym = symtab + symnum;
+                               store_ptr(where, 
+                                   relocbase + rela->r_addend + sym->st_value);
+                       }
+                       break;
+
+               case R_TYPE(PLABEL32):
+                       /*
+                        * PLABEL32 relocation processing is done in two phases
+                        *
+                        *  i) local function relocations (symbol number == 0)
+                        *     can be resolved immediately.
+                        *
+                        * ii) external function relocations are deferred until
+                        *     we finish all other relocations so that global
+                        *     data isn't accessed until all other non-PLT
+                        *     relocations have been done.
+                        */
+                       if (symnum == 0)
+                               *((Elf_Addr *)where) = 
+                                   relocbase + rela->r_addend;
+                       else
+                               plabel_relocs[nplabel_relocs++] = rela;
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       assert(nplabel_relocs < HPPA_PLABEL_PRE);
+       for (i = 0; i < nplabel_relocs; i++) {
+               rela = plabel_relocs[i];
+               where = (void *)(relocbase + rela->r_offset);
+               sym = symtab + ELF_R_SYM(rela->r_info);
+               
+               plabel = &hppa_plabel_pre[hppa_plabel_pre_next++];
+
+               plabel->hppa_plabel_pc = (Elf_Addr)
+                   (relocbase + sym->st_value + rela->r_addend);
+               plabel->hppa_plabel_sl = (Elf_Addr)pltgot;
+
+               SLIST_INSERT_HEAD(&hppa_plabel_list, plabel, hppa_plabel_next);
+               *((Elf_Addr *)where) = (Elf_Addr)(RTLD_MAKE_PLABEL(plabel));
+       }
+       
+#if defined(RTLD_DEBUG_HPPA)
+       for (rela = relafirst; rela < relalim; rela++) {
+               where = (void *)(relocbase + rela->r_offset);
+
+               switch (ELF_R_TYPE(rela->r_info)) {
+               case R_TYPE(DIR32):
+                       hdbg(("DIR32 rela @%p(%p) -> %p(%p)\n",
+                           (void *)rela->r_offset,
+                           (void *)where,
+                           (void *)rela->r_addend,
+                           (void *)*((Elf_Addr *)where) ));
+                       break;
+
+               case R_TYPE(PLABEL32):
+                       symnum = ELF_R_SYM(rela->r_info);
+                       if (symnum == 0) {
+                               hdbg(("PLABEL rela @%p(%p) -> %p(%p)\n",
+                                   (void *)rela->r_offset,
+                                   (void *)where,
+                                   (void *)rela->r_addend,
+                                   (void *)*((Elf_Addr *)where) ));
+                       } else {
+                               sym = symtab + symnum;
+
+                               hdbg(("PLABEL32 rela @%p(%p), symnum=%ld(%p) -> %p(%p)\n",
+                                   (void *)rela->r_offset,
+                                   (void *)where,
+                                   symnum,
+                                   (void *)sym->st_value,
+                                   (void *)rela->r_addend,
+                                   (void *)*((Elf_Addr *)where) ));
+                       }
+                       break;
+               default:
+                       hdbg(("rela XXX reloc\n"));
+                       break;
+               }
+       }
+#endif /* RTLD_DEBUG_HPPA */
+}
+
+/*
+ * This allocates a PLABEL.  If called with a non-NULL def, the 
+ * plabel is for the function associated with that definition
+ * in the defining object defobj, plus the given addend.  If 
+ * called with a NULL def, the plabel is for the function at
+ * the (unrelocated) address in addend in the object defobj.
+ */
+Elf_Addr
+_rtld_function_descriptor_alloc(const Obj_Entry *defobj, const Elf_Sym *def,
+    Elf_Addr addend)
+{
+       Elf_Addr        func_pc, func_sl;
+       hppa_plabel     *plabel;
+
+       if (def != NULL) {
+       
+               /*
+                * We assume that symbols of type STT_NOTYPE
+                * are undefined.  Return NULL for these.
+                */
+               if (ELF_ST_TYPE(def->st_info) == STT_NOTYPE)
+                       return (Elf_Addr)NULL;
+
+               /* Otherwise assert that this symbol must be a function. */
+               assert(ELF_ST_TYPE(def->st_info) == STT_FUNC);
+
+               func_pc = (Elf_Addr)(defobj->relocbase + def->st_value + 
+                   addend);
+       } else
+               func_pc = (Elf_Addr)(defobj->relocbase + addend);
+
+       /*
+        * Search the existing PLABELs for one matching
+        * this function.  If there is one, return it.
+        */
+       func_sl = (Elf_Addr)(defobj->pltgot);
+       SLIST_FOREACH(plabel, &hppa_plabel_list, hppa_plabel_next)
+               if (plabel->hppa_plabel_pc == func_pc &&
+                   plabel->hppa_plabel_sl == func_sl)
+                       return RTLD_MAKE_PLABEL(plabel);
+
+       /*
+        * Once we've used up the preallocated set, we start
+        * using NEW to allocate plabels.
+        */
+       if (hppa_plabel_pre_next < HPPA_PLABEL_PRE)
+               plabel = &hppa_plabel_pre[hppa_plabel_pre_next++];
+       else {
+               plabel = NEW(hppa_plabel);
+               if (plabel == NULL)
+                       return (Elf_Addr)-1;
+       }
+
+       /* Fill the new entry and insert it on the list. */
+       plabel->hppa_plabel_pc = func_pc;
+       plabel->hppa_plabel_sl = func_sl;
+       SLIST_INSERT_HEAD(&hppa_plabel_list, plabel, hppa_plabel_next);
+
+       return RTLD_MAKE_PLABEL(plabel);
+}
+
+/*
+ * If a pointer is a PLABEL, this unwraps it.
+ */
+const void *
+_rtld_function_descriptor_function(const void *addr)
+{
+       return (RTLD_IS_PLABEL(addr) ? 
+           (const void *) RTLD_GET_PLABEL(addr)->hppa_plabel_pc :
+           addr);
+}
+
+/* This sets up an object's GOT. */
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       __rtld_setup_hppa_pltgot(obj, obj->pltgot);
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->rela; rela < obj->relalim; rela++) {
+               Elf_Addr        *where;
+               const Elf_Sym   *def;
+               const Obj_Entry *defobj;
+               Elf_Addr         tmp;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+               symnum = ELF_R_SYM(rela->r_info);
+
+               switch (ELF_R_TYPE(rela->r_info)) {
+               case R_TYPE(NONE):
+                       break;
+
+               case R_TYPE(DIR32):
+                       if (symnum) {
+                               /*
+                                * This is either a DIR32 against a symbol
+                                * (def->st_name != 0), or against a local
+                                * section (def->st_name == 0).
+                                */
+                               def = obj->symtab + symnum;
+                               defobj = obj;
+                               if (def->st_name != 0)
+                                       def = _rtld_find_symdef(symnum, obj,
+                                           &defobj, false);
+                               if (def == NULL)
+                                       return -1;
+
+                               tmp = (Elf_Addr)(defobj->relocbase +
+                                   def->st_value + rela->r_addend);
+
+                               if (load_ptr(where) != tmp)
+                                       store_ptr(where, tmp);
+                               rdbg(("DIR32 %s in %s --> %p in %s",
+                                   obj->strtab + obj->symtab[symnum].st_name,
+                                   obj->path, (void *)load_ptr(where),
+                                   defobj->path));
+                       } else {
+                               tmp = (Elf_Addr)(obj->relocbase +
+                                   rela->r_addend);
+
+                               if (load_ptr(where) != tmp)
+                                       store_ptr(where, tmp);
+                               rdbg(("DIR32 in %s --> %p", obj->path,
+                                           (void *)load_ptr(where)));
+                       }
+                       break;
+
+               case R_TYPE(PLABEL32):
+                       if (symnum) {
+                               def = _rtld_find_symdef(symnum, obj, &defobj,
+                                   false);
+                               if (def == NULL)
+                                       return -1;
+
+                               tmp = _rtld_function_descriptor_alloc(defobj,
+                                   def, rela->r_addend);
+                               if (tmp == (Elf_Addr)-1)
+                                       return -1;
+
+                               if (*where != tmp)
+                                       *where = tmp;
+                               rdbg(("PLABEL32 %s in %s --> %p in %s",
+                                   obj->strtab + obj->symtab[symnum].st_name,
+                                   obj->path, (void *)*where, defobj->path));
+                       } else {
+                               /*
+                                * This is a PLABEL for a static function, and
+                                * the dynamic linker has both allocated a PLT
+                                * entry for this function and told us where it
+                                * is.  We can safely use the PLT entry as the
+                                * PLABEL because there should be no other
+                                * PLABEL reloc referencing this function.
+                                * This object should also have an IPLT
+                                * relocation to initialize the PLT entry.
+                                *
+                                * The dynamic linker should also have ensured
+                                * that the addend has the
+                                * next-least-significant bit set; the
+                                * $$dyncall millicode uses this to distinguish
+                                * a PLABEL pointer from a plain function
+                                * pointer.
+                                */
+                               tmp = (Elf_Addr)
+                                   (obj->relocbase + rela->r_addend);
+
+                               if (*where != tmp)
+                                       *where = tmp;
+                               rdbg(("PLABEL32 in %s --> %p", obj->path,
+                                   (void *)*where));
+                       }
+                       break;
+
+               case R_TYPE(COPY):
+                       /*
+                        * These are deferred until all other relocations have
+                        * been done.  All we do here is make sure that the
+                        * COPY relocation is not in a shared library.  They
+                        * are allowed only in executable files.
+                        */
+                       if (obj->isdynamic) {
+                               _rtld_error(
+                       "%s: Unexpected R_COPY relocation in shared library",
+                                   obj->path);
+                               return -1;
+                       }
+                       rdbg(("COPY (avoid in main)"));
+                       break;
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "addend = %p, contents = %p, symbol = %s",
+                           symnum, (u_long)ELF_R_TYPE(rela->r_info),
+                           (void *)rela->r_offset, (void *)rela->r_addend,
+                           (void *)load_ptr(where),
+                           obj->strtab + obj->symtab[symnum].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rela->r_info));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
+               Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+               Elf_Addr func_pc, func_sl;
+
+               assert(ELF_R_TYPE(rela->r_info) == R_TYPE(IPLT));
+
+               /*
+                * If this is an IPLT reloc for a static function,
+                * fully resolve the PLT entry now.
+                */
+               if (ELF_R_SYM(rela->r_info) == 0) {
+                       func_pc = (Elf_Addr)(obj->relocbase + rela->r_addend);
+                       func_sl = (Elf_Addr)(obj->pltgot);
+               }
+
+               /*
+                * Otherwise set up for lazy binding.
+                */
+               else {
+                       /*
+                        * This function pointer points to the PLT
+                        * stub added by the linker, and instead of
+                        * a shared linkage value, we stash this
+                        * relocation's offset.  The PLT stub has
+                        * already been set up to transfer to
+                        * _rtld_bind_start.
+                        */
+                       func_pc = ((Elf_Addr)(obj->pltgot)) - 16;
+                       func_sl = (Elf_Addr)
+                           ((const char *)rela - (const char *)(obj->pltrela));
+               }
+               rdbg(("lazy bind %s(%p) --> old=(%p,%p) new=(%p,%p)",
+                   obj->path,
+                   (void *)where,
+                   (void *)where[0], (void *)where[1], 
+                   (void *)func_pc, (void *)func_sl));
+
+               /*
+                * Fill this PLT entry and return.
+                */
+               where[0] = func_pc;
+               where[1] = func_sl;
+       }
+       return 0;
+}
+
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
+    Elf_Addr *tp)
+{
+       Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
+       const Elf_Sym *def;
+       const Obj_Entry *defobj;
+       Elf_Addr        func_pc, func_sl;
+       unsigned long info = rela->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(IPLT));
+
+       if (ELF_R_SYM(info) == 0) {
+               func_pc = (Elf_Addr)(obj->relocbase + rela->r_addend);
+               func_sl = (Elf_Addr)(obj->pltgot);
+       } else {
+               def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj,
+                   tp != NULL);
+               if (__predict_false(def == NULL))
+                       return -1;
+               if (__predict_false(def == &_rtld_sym_zero))
+                       return 0;
+
+               func_pc = (Elf_Addr)(defobj->relocbase + def->st_value +
+                   rela->r_addend);
+               func_sl = (Elf_Addr)(defobj->pltgot);
+
+               rdbg(("bind now/fixup in %s --> old=(%p,%p) new=(%p,%p)",
+                   defobj->strtab + def->st_name,
+                   (void *)where[0], (void *)where[1], 
+                   (void *)func_pc, (void *)func_sl));
+       }
+       /*
+        * Fill this PLT entry and return.
+        */
+       if (where[0] != func_pc)
+               where[0] = func_pc;
+       if (where[1] != func_sl)
+               where[1] = func_sl;
+
+       if (tp)
+               *tp = (Elf_Addr)where;
+
+       return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rela *rela;
+       Elf_Addr new_value = 0; /* XXX gcc */
+       int err;
+
+       rela = (const Elf_Rela *)((const char *)obj->pltrela + reloff);
+       
+       assert(ELF_R_SYM(rela->r_info) != 0);
+
+       err = _rtld_relocate_plt_object(obj, rela, &new_value); 
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)new_value;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela = obj->pltrela;
+       
+       for (; rela < obj->pltrelalim; rela++) {
+               if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
+                       return -1;
+       }
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/hppa/rtld_start.S b/libexec/ld.elf_so/arch/hppa/rtld_start.S
new file mode 100644 (file)
index 0000000..ce2f229
--- /dev/null
@@ -0,0 +1,231 @@
+/*     $NetBSD: rtld_start.S,v 1.9 2010/09/30 19:32:40 skrll Exp $     */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Fredette.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <machine/frame.h>
+
+       .import _GLOBAL_OFFSET_TABLE_
+
+ENTRY($rtld_start,HPPA_FRAME_SIZE)
+
+       /* Start stack calling convention. */
+       copy    %r3, %r1 
+       copy    %sp, %r3
+       stw,ma  %r1, HPPA_FRAME_SIZE(%sp)
+       /*
+        * Save our single argument, the ps_strings pointer. We'll need this
+        * twice later: once to call _rtld, and again to transfer to the
+        * program's entry point.
+        */
+        stw     %arg0, HPPA_FRAME_ARG(0)(%r3)
+
+       /*
+        * We can't move to C until we relocate at least the 
+        * Global Offset Table.  Even finding the GOT is tricky
+        * without inadvertently causing the linker to make
+        * relocations for this part of the text segment.
+        */
+
+       bl      L$lpc1, %r19
+       depi    0, 31, 2, %r19
+L$lpc1:        addil   L'_DYNAMIC - ($PIC_pcrel$0 - 8), %r19
+       ldo     R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%r1),%arg0
+
+       /*
+        * Load the absolute address of the beginning of the GOT into %r19, the
+        * shared library linkage table register, leaving it ready-to-use by
+        * the dynamic linker C code.
+        */
+       addil   L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16), %r19
+       ldo     R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%r1),%r19
+
+       /*
+        * The linker sets the first entry in the GOT to the unrelocated
+        *  address of _DYNAMIC.  Subtract this from the absolute address of
+        * _DYNAMIC to get our relocbase.
+        */
+       ldw     0(%r19), %arg1
+       sub     %arg0, %arg1, %arg1     ; %arg1 = relocbase
+       bl      _rtld_relocate_nonplt_self, %rp
+       copy    %arg1, %r4              ; save for later
+
+       /*
+        * Recover the ps_strings pointer, and take out the
+        * ps_argvstr member.
+        */
+       ldw     HPPA_FRAME_ARG(0)(%r3), %arg0   ; ps_strings
+       ldw     0(%arg0), %arg0         ; ps_argvstr member first in struct
+
+       /*
+        * ps_argvstr - 4 would get us a pointer to argc, comparable to the
+        * initial stack pointer on architectures where the stack grows down.
+        * Subtracting an additional eight creates the storage for obj and
+        * cleanup that _rtld needs.
+        */
+       ldo     -12(%arg0), %arg0
+       stw     %arg0, HPPA_FRAME_ARG(1)(%r3)
+
+       /* Call _rtld, copying relocbase into arg1. */
+       bl      _rtld, %rp
+       copy    %r4, %arg1              ; %arg1 = relocbase
+
+       /* Prepare the arguments for the entry point. */
+       ldw     HPPA_FRAME_ARG(1)(%r3), %r1
+       ldw     HPPA_FRAME_ARG(0)(%r3), %arg0   ; ps_strings
+       ldw     0(%r1), %arg1                   ; cleanup
+       ldw     4(%r1), %arg2                   ; obj
+
+       /* End stack calling convention. */
+       ldo     HPPA_FRAME_SIZE(%r3), %sp
+       ldw,mb  -HPPA_FRAME_SIZE(%sp), %r3
+
+       /* Go for it. */
+       bv      %r0(%ret0)
+       copy    %r0, %rp
+EXIT($rtld_start)
+
+/*
+ * This does our setup for an object's GOT.  %arg0 is the Obj_Entry * for the
+ * object, and %arg1 is its GOT pointer.
+ */
+LEAF_ENTRY(__rtld_setup_hppa_pltgot)
+
+       /*
+        * The second entry of the GOT is reserved for the dynamic linker.  We
+        * put the Obj_Entry * for the object in there.
+        */
+       stw     %arg0, 4(%arg1)
+
+       /*
+        * Fill the fixup_func and fixup_ltp members of the PLT stub.  This
+        * stub is inserted by the linker immediately before the GOT.  We use
+        * this stub to enter our binder.
+        */
+
+       bl      L$lpc2, %arg0
+       depi    0, 31, 2, %arg0
+L$lpc2:        addil   L'_rtld_bind_start - ($PIC_pcrel$0 - 8), %arg0
+       ldo     R'_rtld_bind_start - ($PIC_pcrel$0 - 12)(%r1),%arg0
+
+       stw     %arg0, -8(%arg1)
+       bv      %r0(%rp)
+       stw     %r19, -4(%arg1)
+EXIT(__rtld_hppa_setup_pltgot)
+
+/*
+ * In order to support lazy binding, this implementation of _rtld_bind_start is
+ * very closely tied to the shared-library call stub and the PLT stub, both
+ * inserted by the linker.
+ */
+
+/*
+ * This is a magic branch instruction that is used by GCC's
+ * __canonicalize_funcptr_for_compare() function to fixup relocations
+ * in order to do function pointer comparisons.
+ */
+
+       bl      _rtld_bind, %rp
+
+ENTRY(_rtld_bind_start,HPPA_FRAME_SIZE)
+
+       /* Start stack calling convention.  */
+       copy    %r3, %r1 
+       copy    %sp, %r3
+
+       stw,ma  %r1, HPPA_FRAME_SIZE(%sp)
+
+       /*
+        * We have to save all calling convention registers that are set by the
+        * caller, because we have to restore them before transferring to the
+        * bound function.  Note that this includes %ret0, %ret1, and %t1.
+        *
+        * %ret0 and %ret1 because they can have meaning on entry to a
+        * function.
+        *
+        * %t1 because it's used by libc to pass on errno values to cerror.
+        */
+       stw     %rp, HPPA_FRAME_CRP(%r3)
+       stw     %arg0, HPPA_FRAME_ARG(0)(%r3)
+       stw     %arg1, HPPA_FRAME_ARG(1)(%r3)
+       stw     %arg2, HPPA_FRAME_ARG(2)(%r3)
+       stw     %arg3, HPPA_FRAME_ARG(3)(%r3)
+       /* 0(%r3) is filled with the saved %r3 above */
+       stw     %ret0, 4(%r3)
+       stw     %ret1, 8(%r3)
+
+       /*
+        * The linker PLT stub loads %r20 with (GOT - 8) for the object that
+        * needs binding done.  The second entry of the GOT is reserved for the
+        * dynamic linker's use, and we previously stashed the object's
+        * Obj_Entry * there.
+        */
+       ldw     12(%r20), %arg0
+
+       /*
+        * The linker shared-library call stub loads %r19 from the shared
+        * linkage member of the PLT entry.  We previously stashed the reloff
+        * of the relocation there.
+        */
+       copy    %r19, %arg1
+
+       /*
+        * The linker PLT stub loads %r21 with the fixup_ltp word in itself.
+        * We previously stashed our %r19 value there.
+        */
+       bl      _rtld_bind, %rp
+       copy    %r21, %r19
+
+       /*
+        * Our hppa version of _rtld_bind returns to us the address of the PLT
+        * entry that it fixed up.  Load the function address and shared
+        * linkage for the newly bound function.
+        */
+       ldw     0(%ret0), %r21
+       ldw     4(%ret0), %r19
+
+       /* Restore registers saved above. */
+       ldw     HPPA_FRAME_CRP(%r3), %rp
+       ldw     HPPA_FRAME_ARG(0)(%r3), %arg0
+       ldw     HPPA_FRAME_ARG(1)(%r3), %arg1
+       ldw     HPPA_FRAME_ARG(2)(%r3), %arg2
+       ldw     HPPA_FRAME_ARG(3)(%r3), %arg3
+       ldw     4(%r3), %ret0
+       ldw     8(%r3), %ret1
+
+       /* End stack calling convention. */
+       ldo     HPPA_FRAME_SIZE(%r3), %sp
+       ldw,mb  -HPPA_FRAME_SIZE(%sp), %r3
+
+       /* Transfer to the function. */
+       bv      %r0(%r21)
+       nop
+EXIT(_rtld_bind_start)
diff --git a/libexec/ld.elf_so/arch/i386/Makefile.inc b/libexec/ld.elf_so/arch/i386/Makefile.inc
new file mode 100644 (file)
index 0000000..14cbaed
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile.inc,v 1.14 2009/12/13 09:31:47 mrg Exp $
+
+SRCS+=         rtld_start.S mdreloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic
+
+CPPFLAGS+=     -DELFSIZE=32
+
+LDFLAGS+=      -Wl,-e,.rtld_start
diff --git a/libexec/ld.elf_so/arch/i386/mdreloc.c b/libexec/ld.elf_so/arch/i386/mdreloc.c
new file mode 100644 (file)
index 0000000..b1657c6
--- /dev/null
@@ -0,0 +1,216 @@
+/*     $NetBSD: mdreloc.c,v 1.32 2010/08/06 16:33:18 joerg Exp $       */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.32 2010/08/06 16:33:18 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+void _rtld_bind_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       obj->pltgot[1] = (Elf_Addr) obj;
+       obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rel *rel = 0, *rellim;
+       Elf_Addr relsz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_REL:
+                       rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELSZ:
+                       relsz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       if (rel == 0 || relsz == 0)
+               return;
+       rellim = (const Elf_Rel *)((const uint8_t *)rel + relsz);
+       for (; rel < rellim; rel++) {
+               where = (Elf_Addr *)(relocbase + rel->r_offset);
+               *where += (Elf_Addr)relocbase;
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rel *rel;
+       Elf_Addr target = 0;
+
+       for (rel = obj->rel; rel < obj->rellim; rel++) {
+               Elf_Addr        *where;
+               const Elf_Sym   *def;
+               const Obj_Entry *defobj;
+               Elf_Addr         tmp;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+               symnum = ELF_R_SYM(rel->r_info);
+
+               switch (ELF_R_TYPE(rel->r_info)) {
+               case R_TYPE(NONE):
+                       break;
+
+#if 1 /* XXX should not occur */
+               case R_TYPE(PC32):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       target = (Elf_Addr)(defobj->relocbase + def->st_value);
+
+                       *where += target - (Elf_Addr)where;
+                       rdbg(("PC32 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(GOT32):
+#endif
+               case R_TYPE(32):
+               case R_TYPE(GLOB_DAT):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       target = (Elf_Addr)(defobj->relocbase + def->st_value);
+
+                       tmp = target + *where;
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("32/GLOB_DAT %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(RELATIVE):
+                       *where += (Elf_Addr)obj->relocbase;
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)*where));
+                       break;
+
+               case R_TYPE(COPY):
+                       /*
+                        * These are deferred until all other relocations have
+                        * been done.  All we do here is make sure that the
+                        * COPY relocation is not in a shared library.  They
+                        * are allowed only in executable files.
+                        */
+                       if (obj->isdynamic) {
+                               _rtld_error(
+                       "%s: Unexpected R_COPY relocation in shared library",
+                                   obj->path);
+                               return -1;
+                       }
+                       rdbg(("COPY (avoid in main)"));
+                       break;
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "contents = %p, symbol = %s",
+                           symnum, (u_long)ELF_R_TYPE(rel->r_info),
+                           (void *)rel->r_offset, (void *)*where,
+                           obj->strtab + obj->symtab[symnum].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rel->r_info));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       const Elf_Rel *rel;
+
+       if (!obj->relocbase)
+               return 0;
+
+       for (rel = obj->pltrel; rel < obj->pltrellim; rel++) {
+               Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+
+               assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JMP_SLOT));
+
+               /* Just relocate the GOT slots pointing into the PLT */
+               *where += (Elf_Addr)obj->relocbase;
+               rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
+       }
+
+       return 0;
+}
+
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel,
+       Elf_Addr *tp)
+{
+       Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+       Elf_Addr target;
+       const Elf_Sym *def;
+       const Obj_Entry *defobj;
+       unsigned long info = rel->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       target = (Elf_Addr)(defobj->relocbase + def->st_value);
+       rdbg(("bind now/fixup in %s --> old=%p new=%p",
+           defobj->strtab + def->st_name, (void *)*where, 
+           (void *)target));
+       if (*where != target)
+               *where = target;
+       if (tp)
+               *tp = target;
+       return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rel *rel = (const Elf_Rel *)((const uint8_t *)obj->pltrel
+           + reloff);
+       Elf_Addr new_value;
+       int err;
+
+       new_value = 0;  /* XXX gcc */
+
+       err = _rtld_relocate_plt_object(obj, rel, &new_value);
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)new_value;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rel *rel;
+       int err = 0;
+       
+       for (rel = obj->pltrel; rel < obj->pltrellim; rel++) {
+               err = _rtld_relocate_plt_object(obj, rel, NULL);
+               if (err)
+                       break;
+       }
+       return err;
+}
diff --git a/libexec/ld.elf_so/arch/i386/rtld_start.S b/libexec/ld.elf_so/arch/i386/rtld_start.S
new file mode 100644 (file)
index 0000000..211649f
--- /dev/null
@@ -0,0 +1,88 @@
+/*     $NetBSD: rtld_start.S,v 1.11 2010/12/05 00:56:07 joerg Exp $    */
+
+/*-
+ * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas and by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+       .text
+       .align  4
+       .globl  .rtld_start
+       .hidden .rtld_start
+       .type   .rtld_start,@function
+.rtld_start:
+       subl    $8,%esp                 # make room of obj_main and exit proc
+       pushl   %ebx                    # save ps_strings
+
+       call    1f
+1:
+       popl    %edx
+       leal    _DYNAMIC-1b(%edx),%ecx  # &_DYNAMIC
+       movl    %ecx,%ebx
+       subl    _GLOBAL_OFFSET_TABLE_-1b(%edx),%ebx
+
+       pushl   %ebx                    # relocbase
+       pushl   %ecx                    # &_DYNAMIC
+       call    _rtld_relocate_nonplt_self
+
+       leal    12(%esp),%eax           # &cleanup
+       pushl   %ebx                    # relocbase
+       pushl   %eax                    # sp
+       call    _rtld                   # _rtld(sp, relocbase)
+
+       addl    $16,%esp                # pop args
+
+       popl    %ebx                    # %ebx = ps_strings
+       popl    %edx                    # %edx = cleanup
+       popl    %ecx                    # %ecx = obj_main
+       jmp     *%eax
+
+       .align  4
+       .globl  _rtld_bind_start
+       .hidden _rtld_bind_start
+       .type   _rtld_bind_start,@function
+_rtld_bind_start:      # (obj, reloff)
+       pushf                           # save registers
+       pushl   %eax
+       pushl   %ecx
+       pushl   %edx
+
+       pushl   20(%esp)                # Copy of reloff
+       pushl   20(%esp)                # Copy of obj
+       call    _rtld_bind              # Call the binder
+       addl    $8,%esp                 # pop binder args
+       movl    %eax,20(%esp)           # Store function to be called in obj
+
+       popl    %edx
+       popl    %ecx
+       popl    %eax
+       popf
+
+       leal    4(%esp),%esp            # Discard reloff, do not change eflags
+       ret
diff --git a/libexec/ld.elf_so/arch/m68k/Makefile.inc b/libexec/ld.elf_so/arch/m68k/Makefile.inc
new file mode 100644 (file)
index 0000000..42257ce
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile.inc,v 1.10 2005/06/04 16:17:17 lukem Exp $
+
+SRCS+=         rtld_start.S mdreloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic
+
+CPPFLAGS+=     -DELFSIZE=32
+
+LDFLAGS+=      -Wl,-e,.rtld_start
diff --git a/libexec/ld.elf_so/arch/m68k/mdreloc.c b/libexec/ld.elf_so/arch/m68k/mdreloc.c
new file mode 100644 (file)
index 0000000..ea18f03
--- /dev/null
@@ -0,0 +1,224 @@
+/*     $NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:18 joerg Exp $       */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:18 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:18 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+void _rtld_bind_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+static inline int _rtld_relocate_plt_object(const Obj_Entry *,
+    const Elf_Rela *, Elf_Addr *);
+
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       obj->pltgot[1] = (Elf_Addr) obj;
+       obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rela *rela = 0, *relalim;
+       Elf_Addr relasz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_RELA:
+                       rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
+       for (; rela < relalim; rela++) {
+               where = (Elf_Addr *)(relocbase + rela->r_offset);
+               *where += (Elf_Addr)relocbase;
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->rela; rela < obj->relalim; rela++) {
+               Elf_Addr        *where;
+               const Elf_Sym   *def;
+               const Obj_Entry *defobj;
+               Elf_Addr         tmp;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+               symnum = ELF_R_SYM(rela->r_info);
+
+               switch (ELF_R_TYPE(rela->r_info)) {
+               case R_TYPE(NONE):
+                       break;
+
+#if 1 /* XXX should not occur */
+               case R_TYPE(PC32):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
+                           rela->r_addend) - (Elf_Addr)where;
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("PC32 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(GOT32):
+#endif
+               case R_TYPE(32):
+               case R_TYPE(GLOB_DAT):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
+                           rela->r_addend);
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("32/GLOB_DAT %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(RELATIVE):
+                       *where += (Elf_Addr)obj->relocbase;
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)*where));
+                       break;
+
+               case R_TYPE(COPY):
+                       /*
+                        * These are deferred until all other relocations have
+                        * been done.  All we do here is make sure that the
+                        * COPY relocation is not in a shared library.  They
+                        * are allowed only in executable files.
+                        */
+                       if (obj->isdynamic) {
+                               _rtld_error(
+                       "%s: Unexpected R_COPY relocation in shared library",
+                                   obj->path);
+                               return -1;
+                       }
+                       rdbg(("COPY (avoid in main)"));
+                       break;
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "addend = %p, contents = %p, symbol = %s",
+                           symnum, (u_long)ELF_R_TYPE(rela->r_info),
+                           (void *)rela->r_offset, (void *)rela->r_addend,
+                           (void *)*where,
+                           obj->strtab + obj->symtab[symnum].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rela->r_info));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       if (!obj->relocbase)
+               return 0;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
+               Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+
+               assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
+
+               /* Just relocate the GOT slots pointing into the PLT */
+               *where += (Elf_Addr)obj->relocbase;
+               rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
+       }
+
+       return 0;
+}
+
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
+    Elf_Addr *tp)
+{
+       Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+       Elf_Addr new_value;
+       const Elf_Sym  *def;
+       const Obj_Entry *defobj;
+       unsigned long info = rela->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       assert(rela->r_addend == 0);
+       new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
+           rela->r_addend);
+       rdbg(("bind now/fixup in %s --> old=%p new=%p",
+           defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
+       if (*where != new_value)
+               *where = new_value;
+
+       if (tp)
+               *tp = new_value - rela->r_addend;
+
+       return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff);
+       Elf_Addr result;
+       int err;
+
+       result = 0;     /* XXX gcc */
+
+       err = _rtld_relocate_plt_object(obj, rela, &result);
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)result;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++)
+               if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
+                       return -1;
+
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/m68k/rtld_start.S b/libexec/ld.elf_so/arch/m68k/rtld_start.S
new file mode 100644 (file)
index 0000000..d6e6549
--- /dev/null
@@ -0,0 +1,79 @@
+/*     $NetBSD: rtld_start.S,v 1.9 2008/04/28 20:23:03 martin Exp $    */
+
+/*-
+ * Copyright (c) 1999, 2002, 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein and by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+       .text
+       .align  4
+       .globl  .rtld_start
+       .type   .rtld_start,@function
+.rtld_start:
+       subql   #8,%sp                  | storage for obj and cleanup
+
+       lea     (%pc,_GLOBAL_OFFSET_TABLE_@GOTPC),%a0
+       lea     (%pc,_DYNAMIC),%a1
+       movel   %a1,%a5
+       subl    (%a0),%a5
+
+       movel   %a5,-(%sp)              | relocbase
+       movel   %a1,-(%sp)              | &_DYNAMIC
+       jbsr    _rtld_relocate_nonplt_self@PLTPC
+       addql   #8,%sp                  | pop arguments
+
+       movel   %a5,-(%sp)              | relocbase
+       pea     4(%sp)                  | sp
+       jbsr    _rtld@PLTPC             | entry = _rtld(sp, relocbase)
+       addql   #8,%sp                  | pop arguments
+
+       moveal  (%sp)+,%a1              | cleanup
+       moveal  (%sp)+,%a0              | obj
+       moveal  %d0,%a3
+       jmp     (%a3)                   | Go for it!
+       .size   .rtld_start,.-.rtld_start
+
+       .align  4
+       .globl  _rtld_bind_start
+       .type   _rtld_bind_start,@function
+_rtld_bind_start:
+       moveml  %d0-%d1/%a0-%a1,-(%sp)  | preserve caller-saved registers
+       movel   20(%sp),-(%sp)          | push reloff
+       movel   (16+4)(%sp),-(%sp)      | push obj
+       jbsr    _rtld_bind@PLTPC        | %a0 = _rtld_bind(obj, reloff)
+       addql   #8,%sp                  | pop args
+#ifdef __SVR4_ABI__
+       movel   %a0,(16+4)(%sp)         | write fake `return' address over obj
+#else
+       movel   %d0,(16+4)(%sp)         | write fake `return' address over obj
+#endif
+       moveml  (%sp)+,%d0-%d1/%a0-%a1  | restore caller-saved registers
+       addql   #4,%sp                  | skip reloff
+       rts                             | `return' right into function
+       .size   _rtld_bind_start,.-_rtld_bind_start
diff --git a/libexec/ld.elf_so/arch/mips/Makefile.inc b/libexec/ld.elf_so/arch/mips/Makefile.inc
new file mode 100644 (file)
index 0000000..d5169f9
--- /dev/null
@@ -0,0 +1,17 @@
+#      $NetBSD: Makefile.inc,v 1.19 2010/07/11 07:43:12 mrg Exp $
+
+SRCS+=         rtld_start.S mips_reloc.c
+
+COPTS+=                -G0
+
+ABI64?= ${CFLAGS:M-mabi=64} ${CPPFLAGS:M-mabi=64} ${COPTS:M-mabi=64}
+ABIO64?= ${CFLAGS:M-mabi=o64} ${CPPFLAGS:M-mabi=o64} ${COPTS:M-mabi=o64}
+.if !empty(ABI64) || !empty(ABIO64)
+CPPFLAGS+=     -DELFSIZE=64
+.else
+CPPFLAGS+=     -DELFSIZE=32
+.endif
+CPPFLAGS+=     -DRTLD_INHIBIT_COPY_RELOCS
+AFLAGS+=       -Wa,--fatal-warnings
+
+LDFLAGS+=      -Wl,-e,rtld_start
diff --git a/libexec/ld.elf_so/arch/mips/mips_reloc.c b/libexec/ld.elf_so/arch/mips/mips_reloc.c
new file mode 100644 (file)
index 0000000..a77e5a9
--- /dev/null
@@ -0,0 +1,454 @@
+/*     $NetBSD: mips_reloc.c,v 1.60 2010/09/24 15:20:52 matt Exp $     */
+
+/*
+ * Copyright 1997 Michael L. Hitch <mhitch@montana.edu>
+ * Portions copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mips_reloc.c,v 1.60 2010/09/24 15:20:52 matt Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/endian.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+#ifdef __mips_o32
+#define SUPPORT_OLD_BROKEN_LD
+#endif
+
+void _rtld_bind_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(Elf_Word, Elf_Addr, Elf_Addr, Elf_Addr);
+
+/*
+ * It is possible for the compiler to emit relocations for unaligned data.
+ * We handle this situation with these inlines.
+ */
+
+#if ELFSIZE == 64
+/*
+ * ELF64 MIPS encodes the relocs uniquely.  The first 32-bits of info contain
+ * the symbol index.  The top 32-bits contain three relocation types encoded
+ * in big-endian integer with first relocation in LSB.  This means for little
+ * endian we have to byte swap that interger (r_type).
+ */
+#define        Elf_Sxword                      Elf64_Sxword
+#define        ELF_R_NXTTYPE_64_P(r_type)      ((((r_type) >> 8) & 0xff) == R_TYPE(64))
+#if BYTE_ORDER == LITTLE_ENDIAN
+#undef ELF_R_SYM
+#undef ELF_R_TYPE
+#define ELF_R_SYM(r_info)              ((r_info) & 0xffffffff)
+#define ELF_R_TYPE(r_info)             bswap32((r_info) >> 32)
+#endif
+#else
+#define        ELF_R_NXTTYPE_64_P(r_type)      (0)
+#define        Elf_Sxword                      Elf32_Sword
+#endif
+#define        GOT1_MASK                       (~(Elf_Addr)0 >> 1)
+
+static inline Elf_Sxword
+load_ptr(void *where, size_t len)
+{
+       Elf_Sxword val;
+
+       if (__predict_true(((uintptr_t)where & (len - 1)) == 0)) {
+#if ELFSIZE == 64
+               if (len == sizeof(Elf_Sxword))
+                       return *(Elf_Sxword *)where;
+#endif
+               return *(Elf_Sword *)where;
+       }
+
+       val = 0;
+#if BYTE_ORDER == LITTLE_ENDIAN
+       (void)memcpy(&val, where, len);
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+       (void)memcpy((uint8_t *)((&val)+1) - len, where, len);
+#endif
+       return (len == sizeof(Elf_Sxword)) ? val : (Elf_Sword)val;
+}
+
+static inline void
+store_ptr(void *where, Elf_Sxword val, size_t len)
+{
+       if (__predict_true(((uintptr_t)where & (len - 1)) == 0)) {
+#if ELFSIZE == 64
+               if (len == sizeof(Elf_Sxword)) {
+                       *(Elf_Sxword *)where = val;
+                       return;
+               }
+#endif
+               *(Elf_Sword *)where = val;
+               return;
+       }
+#if BYTE_ORDER == LITTLE_ENDIAN
+       (void)memcpy(where, &val, len);
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+       (void)memcpy(where, (const uint8_t *)((&val)+1) - len, len);
+#endif
+}
+
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       obj->pltgot[0] = (Elf_Addr) &_rtld_bind_start;
+       /* XXX only if obj->pltgot[1] & 0x80000000 ?? */
+       obj->pltgot[1] |= (Elf_Addr) obj;
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rel *rel = 0, *rellim;
+       Elf_Addr relsz = 0;
+       void *where;
+       const Elf_Sym *symtab = NULL, *sym;
+       Elf_Addr *got = NULL;
+       Elf_Word local_gotno = 0, symtabno = 0, gotsym = 0;
+       size_t i;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_REL:
+                       rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELSZ:
+                       relsz = dynp->d_un.d_val;
+                       break;
+               case DT_SYMTAB:
+                       symtab = (const Elf_Sym *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_PLTGOT:
+                       got = (Elf_Addr *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_MIPS_LOCAL_GOTNO:
+                       local_gotno = dynp->d_un.d_val;
+                       break;
+               case DT_MIPS_SYMTABNO:
+                       symtabno = dynp->d_un.d_val;
+                       break;
+               case DT_MIPS_GOTSYM:
+                       gotsym = dynp->d_un.d_val;
+                       break;
+               }
+       }
+
+       i = (got[1] & 0x80000000) ? 2 : 1;
+       /* Relocate the local GOT entries */
+       got += i;
+       for (; i < local_gotno; i++)
+               *got++ += relocbase;
+       sym = symtab + gotsym;
+       /* Now do the global GOT entries */
+       for (i = gotsym; i < symtabno; i++) {
+               *got = sym->st_value + relocbase;
+               ++sym;
+               ++got;
+       }
+
+       rellim = (const Elf_Rel *)((uintptr_t)rel + relsz);
+       for (; rel < rellim; rel++) {
+               Elf_Word r_symndx, r_type;
+
+               where = (void *)(relocbase + rel->r_offset);
+
+               r_symndx = ELF_R_SYM(rel->r_info);
+               r_type = ELF_R_TYPE(rel->r_info);
+
+               switch (r_type & 0xff) {
+               case R_TYPE(REL32): {
+                       const size_t rlen =
+                           ELF_R_NXTTYPE_64_P(r_type)
+                               ? sizeof(Elf_Sxword)
+                               : sizeof(Elf_Sword);
+                       Elf_Sxword old = load_ptr(where, rlen);
+                       Elf_Sxword val = old;
+#if ELFSIZE == 64
+                       assert(r_type == R_TYPE(REL32)
+                           || r_type == (R_TYPE(REL32)|(R_TYPE(64) << 8)));
+#endif
+                       assert(r_symndx < gotsym);
+                       sym = symtab + r_symndx;
+                       assert(ELF_ST_BIND(sym->st_info) == STB_LOCAL);
+                       val += relocbase;
+                       store_ptr(where, val, sizeof(Elf_Sword));
+                       rdbg(("REL32/L(%p) %p -> %p in <self>",
+                           where, (void *)old, (void *)val));
+                       store_ptr(where, val, rlen);
+                       break;
+               }
+
+               case R_TYPE(GPREL32):
+               case R_TYPE(NONE):
+                       break;
+
+
+               default:
+                       abort();
+               }
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rel *rel;
+       Elf_Addr *got = obj->pltgot;
+       const Elf_Sym *sym, *def;
+       const Obj_Entry *defobj;
+       Elf_Word i;
+#ifdef SUPPORT_OLD_BROKEN_LD
+       int broken;
+#endif
+
+#ifdef SUPPORT_OLD_BROKEN_LD
+       broken = 0;
+       sym = obj->symtab;
+       for (i = 1; i < 12; i++)
+               if (sym[i].st_info == ELF_ST_INFO(STB_LOCAL, STT_NOTYPE))
+                       broken = 1;
+       dbg(("%s: broken=%d", obj->path, broken));
+#endif
+
+       i = (got[1] & 0x80000000) ? 2 : 1;
+       /* Relocate the local GOT entries */
+       got += i;
+       for (; i < obj->local_gotno; i++)
+               *got++ += (Elf_Addr)obj->relocbase;
+       sym = obj->symtab + obj->gotsym;
+       /* Now do the global GOT entries */
+       for (i = obj->gotsym; i < obj->symtabno; i++) {
+               rdbg((" doing got %d sym %p (%s, %lx)", i - obj->gotsym, sym,
+                   sym->st_name + obj->strtab, (u_long) *got));
+
+#ifdef SUPPORT_OLD_BROKEN_LD
+               if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
+                   broken && sym->st_shndx == SHN_UNDEF) {
+                       /*
+                        * XXX DANGER WILL ROBINSON!
+                        * You might think this is stupid, as it intentionally
+                        * defeats lazy binding -- and you'd be right.
+                        * Unfortunately, for lazy binding to work right, we
+                        * need to a way to force the GOT slots used for
+                        * function pointers to be resolved immediately.  This
+                        * is supposed to be done automatically by the linker,
+                        * by not outputting a PLT slot and setting st_value
+                        * to 0 if there are non-PLT references, but older
+                        * versions of GNU ld do not do this.
+                        */
+                       def = _rtld_find_symdef(i, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       *got = def->st_value + (Elf_Addr)defobj->relocbase;
+               } else
+#endif
+               if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
+                   sym->st_value != 0 && sym->st_shndx == SHN_UNDEF) {
+                       /*
+                        * If there are non-PLT references to the function,
+                        * st_value should be 0, forcing us to resolve the
+                        * address immediately.
+                        *
+                        * XXX DANGER WILL ROBINSON!
+                        * The linker is not outputting PLT slots for calls to
+                        * functions that are defined in the same shared
+                        * library.  This is a bug, because it can screw up
+                        * link ordering rules if the symbol is defined in
+                        * more than one module.  For now, if there is a
+                        * definition, we fail the test above and force a full
+                        * symbol lookup.  This means that all intra-module
+                        * calls are bound immediately.  - mycroft, 2003/09/24
+                        */
+                       *got = sym->st_value + (Elf_Addr)obj->relocbase;
+               } else if (sym->st_info == ELF_ST_INFO(STB_GLOBAL, STT_SECTION)) {
+                       /* Symbols with index SHN_ABS are not relocated. */
+                       if (sym->st_shndx != SHN_ABS)
+                               *got = sym->st_value +
+                                   (Elf_Addr)obj->relocbase;
+               } else {
+                       def = _rtld_find_symdef(i, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       *got = def->st_value + (Elf_Addr)defobj->relocbase;
+               }
+
+               rdbg(("  --> now %lx", (u_long) *got));
+               ++sym;
+               ++got;
+       }
+
+       got = obj->pltgot;
+       for (rel = obj->rel; rel < obj->rellim; rel++) {
+               Elf_Word        r_symndx, r_type;
+               void            *where;
+
+               where = obj->relocbase + rel->r_offset;
+               r_symndx = ELF_R_SYM(rel->r_info);
+               r_type = ELF_R_TYPE(rel->r_info);
+
+               switch (r_type & 0xff) {
+               case R_TYPE(NONE):
+                       break;
+
+               case R_TYPE(REL32): {
+                       /* 32-bit PC-relative reference */
+                       const size_t rlen =
+                           ELF_R_NXTTYPE_64_P(r_type)
+                               ? sizeof(Elf_Sxword)
+                               : sizeof(Elf_Sword);
+                       Elf_Sxword old = load_ptr(where, rlen);
+                       Elf_Sxword val = old;
+
+                       def = obj->symtab + r_symndx;
+
+                       if (r_symndx >= obj->gotsym) {
+                               val += got[obj->local_gotno + r_symndx - obj->gotsym];
+                               rdbg(("REL32/G(%p) %p --> %p (%s) in %s",
+                                   where, (void *)old, (void *)val,
+                                   obj->strtab + def->st_name,
+                                   obj->path));
+                       } else {
+                               /*
+                                * XXX: ABI DIFFERENCE!
+                                *
+                                * Old NetBSD binutils would generate shared
+                                * libs with section-relative relocations being
+                                * already adjusted for the start address of
+                                * the section.
+                                *
+                                * New binutils, OTOH, generate shared libs
+                                * with the same relocations being based at
+                                * zero, so we need to add in the start address
+                                * of the section.
+                                *
+                                * --rkb, Oct 6, 2001
+                                */
+
+                               if (def->st_info ==
+                                   ELF_ST_INFO(STB_LOCAL, STT_SECTION)
+#ifdef SUPPORT_OLD_BROKEN_LD
+                                   && !broken
+#endif
+                                   )
+                                       val += (Elf_Addr)def->st_value;
+
+                               val += (Elf_Addr)obj->relocbase;
+
+                               rdbg(("REL32/L(%p) %p -> %p (%s) in %s",
+                                   where, (void *)old, (void *)val,
+                                   obj->strtab + def->st_name, obj->path));
+                       }
+                       store_ptr(where, val, rlen);
+                       break;
+               }
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "contents = %p, symbol = %s",
+                           (u_long)r_symndx, (u_long)ELF_R_TYPE(rel->r_info),
+                           (void *)rel->r_offset,
+                           (void *)load_ptr(where, sizeof(Elf_Sword)),
+                           obj->strtab + obj->symtab[r_symndx].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rel->r_info));
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       /* PLT fixups were done above in the GOT relocation. */
+       return 0;
+}
+
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, Elf_Word sym, Elf_Addr *tp)
+{
+       Elf_Addr *got = obj->pltgot;
+       const Elf_Sym *def;
+       const Obj_Entry *defobj;
+       Elf_Addr new_value;
+
+       def = _rtld_find_plt_symdef(sym, obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       rdbg(("bind now/fixup in %s --> new=%p",
+           defobj->strtab + def->st_name, (void *)new_value));
+       got[obj->local_gotno + sym - obj->gotsym] = new_value;
+
+       if (tp)
+               *tp = new_value;
+       return 0;
+}
+
+caddr_t
+_rtld_bind(Elf_Word a0, Elf_Addr a1, Elf_Addr a2, Elf_Addr a3)
+{
+       Elf_Addr *got = (Elf_Addr *)(a2 - 0x7ff0);
+       const Obj_Entry *obj = (Obj_Entry *)(got[1] & GOT1_MASK);
+       Elf_Addr new_value = 0; /* XXX gcc */
+       int err;
+
+       err = _rtld_relocate_plt_object(obj, a0, &new_value);
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)new_value;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Sym *sym = obj->symtab + obj->gotsym;
+       Elf_Word i;
+
+       for (i = obj->gotsym; i < obj->symtabno; i++, sym++) {
+               if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
+                       if (_rtld_relocate_plt_object(obj, i, NULL) < 0)
+                               return -1;
+       }
+
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/mips/rtld_start.S b/libexec/ld.elf_so/arch/mips/rtld_start.S
new file mode 100644 (file)
index 0000000..e7de196
--- /dev/null
@@ -0,0 +1,140 @@
+/*     $NetBSD: rtld_start.S,v 1.10 2009/12/14 00:41:19 matt Exp $     */
+
+/*
+ * Copyright 1997 Michael L. Hitch <mhitch@montana.edu>
+ * Portions copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mips/asm.h>
+
+.globl _C_LABEL(_rtld_relocate_nonplt_self)
+.globl _C_LABEL(_rtld)
+
+#define        PTR_SIZE        (1<<PTR_SCALESHIFT)
+
+LEAF(rtld_start)
+       .frame  sp, 4*PTR_SIZE, ra
+       .mask   0x10090000,-PTR_SIZE
+       .set    noreorder
+       SETUP_GP
+       PTR_SUBU sp, 4*PTR_SIZE         # adjust stack pointer
+       SETUP_GP64(s4, rtld_start)
+       SAVE_GP(0)
+                                       # -> 1*PTR_SIZE(sp) for atexit
+                                       # -> 2*PTR_SIZE(sp) for obj_main
+       move    s0, a0                  # save stack pointer from a0
+       move    s3, a3                  # save ps_strings pointer
+
+       PTR_LA  a1, 1f
+       bal     1f
+        PTR_LA t0, _C_LABEL(_rtld_relocate_nonplt_self)
+1:     PTR_SUBU a1, ra, a1             # relocbase
+       move    s2, a1                  # save for _rtld
+       PTR_LA  a0, _DYNAMIC
+       PTR_ADDU t9, a1, t0
+       jalr    t9                      # _rtld_relocate_nonplt_self(dynp, relocabase)
+        PTR_ADDU a0, a1, a0            # &_DYNAMIC
+
+       move    a1, s2                  # relocbase
+       PTR_ADDU a0, sp, 2*PTR_SIZE     # sp
+       jal     _C_LABEL(_rtld)         # v0 = _rtld(sp, relocbase)
+        nop
+
+       PTR_L   a1, 2*PTR_SIZE(sp)      # our atexit function
+       PTR_L   a2, 3*PTR_SIZE(sp)      # obj_main entry
+       PTR_ADDU sp, 4*PTR_SIZE         # readjust stack
+       move    a0, s0                  # stack pointer
+       move    t9, v0
+       jr      t9                      # _start(sp, cleanup, obj);
+        move   a3, s3                  # restore ps_strings
+
+END(rtld_start)
+
+#define        XCALLFRAME_SIZ          (12*SZREG)
+#define        XCALLFRAME_RA           (10*SZREG)
+#define        XCALLFRAME_GP           (9*SZREG)
+#define        XCALLFRAME_S0           (8*SZREG)
+#define        XCALLFRAME_A3           (7*SZREG)
+#define        XCALLFRAME_A2           (6*SZREG)
+#define        XCALLFRAME_A1           (5*SZREG)
+#define        XCALLFRAME_A0           (4*SZREG)
+#if defined(__mips_n32) || defined(__mips_n64)
+#define        XCALLFRAME_A7           (3*SZREG)
+#define        XCALLFRAME_A6           (2*SZREG)
+#define        XCALLFRAME_A5           (1*SZREG)
+#define        XCALLFRAME_A4           (0*SZREG)
+#endif
+
+       .globl  _rtld_bind_start
+       .ent    _rtld_bind_start
+_rtld_bind_start:
+       .frame  sp, XCALLFRAME_SIZ, $15
+       move    v1, gp                  # save old GP
+#if defined(__mips_o32) || defined(__mips_o64)
+       PTR_ADDU t9, 8                  # modify T9 to point at .cpload
+#endif
+       SETUP_GP
+       PTR_SUBU sp, XCALLFRAME_SIZ     # save arguments and sp value in stack
+       SETUP_GP64(XCALLFRAME_GP, _rtld_bind_start)
+       SAVE_GP(XCALLFRAME_GP)
+#if defined(__mips_n32) || defined(__mips_n64)
+       REG_S   a4,  XCALLFRAME_A4(sp)
+       REG_S   a5,  XCALLFRAME_A5(sp)
+       REG_S   a6,  XCALLFRAME_A6(sp)
+       REG_S   a7,  XCALLFRAME_A7(sp)
+#endif
+       REG_S   a0,  XCALLFRAME_A0(sp)
+       REG_S   a1,  XCALLFRAME_A1(sp)
+       REG_S   a2,  XCALLFRAME_A2(sp)
+       REG_S   a3,  XCALLFRAME_A3(sp)
+       REG_S   $15,  XCALLFRAME_RA(sp) # ra is in t7/t3
+       REG_S   s0,  XCALLFRAME_S0(sp)
+       move    s0, sp
+       move    a0, t8                  # symbol index
+       move    a1, $15                 # old RA
+       move    a2, v1                  # old GP
+       move    a3, ra                  # current RA
+       jal     _C_LABEL(_rtld_bind)
+        nop
+       move    sp, s0
+       REG_L   ra, XCALLFRAME_RA(sp)           
+       REG_L   s0, XCALLFRAME_S0(sp)
+       REG_L   a0, XCALLFRAME_A0(sp)
+       REG_L   a1, XCALLFRAME_A1(sp)
+       REG_L   a2, XCALLFRAME_A2(sp)
+       REG_L   a3, XCALLFRAME_A3(sp)
+#if defined(__mips_n32) || defined(__mips_n64)
+       REG_L   a4, XCALLFRAME_A4(sp)
+       REG_L   a5, XCALLFRAME_A5(sp)
+       REG_L   a6, XCALLFRAME_A6(sp)
+       REG_L   a7, XCALLFRAME_A7(sp)
+#endif
+       RESTORE_GP64
+       PTR_ADDU sp, XCALLFRAME_SIZ
+       move    t9, v0
+       jr      t9
+        nop
+END(_rtld_bind_start)
diff --git a/libexec/ld.elf_so/arch/powerpc/Makefile.inc b/libexec/ld.elf_so/arch/powerpc/Makefile.inc
new file mode 100644 (file)
index 0000000..49264ea
--- /dev/null
@@ -0,0 +1,11 @@
+#      $NetBSD: Makefile.inc,v 1.11 2009/10/22 21:56:13 skrll Exp $
+
+SRCS+=         rtld_start.S ppc_reloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic -msoft-float
+
+CPPFLAGS+=     -DELFSIZE=32
+
+LDFLAGS+=      -Wl,-e,_rtld_start
+LDFLAGS+=      -Wl,--script,${.CURDIR}/arch/powerpc/ld.so.script
diff --git a/libexec/ld.elf_so/arch/powerpc/ld.so.script b/libexec/ld.elf_so/arch/powerpc/ld.so.script
new file mode 100644 (file)
index 0000000..0ca2300
--- /dev/null
@@ -0,0 +1,271 @@
+OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc",
+             "elf32-powerpc")
+OUTPUT_ARCH(powerpc)
+ENTRY(_start)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+PROVIDE (__stack = 0); PROVIDE (___stack = 0);
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0 + SIZEOF_HEADERS;
+  .hash          : { *(.hash)          }
+  .dynsym        : { *(.dynsym)                }
+  .dynstr        : { *(.dynstr)                }
+  .gnu.version   : { *(.gnu.version)   }
+  .gnu.version_d   : { *(.gnu.version_d)       }
+  .gnu.version_r   : { *(.gnu.version_r)       }
+  .rel.init      : { *(.rel.init)      }
+  .rela.init     : { *(.rela.init)     }
+  .rel.text      :
+    {
+      *(.rel.text)
+      *(.rel.text.*)
+      *(.rel.gnu.linkonce.t.*)
+    }
+  .rela.text     :
+    {
+      *(.rela.text)
+      *(.rela.text.*)
+      *(.rela.gnu.linkonce.t.*)
+    }
+  .rel.fini      : { *(.rel.fini)      }
+  .rela.fini     : { *(.rela.fini)     }
+  .rel.rodata    :
+    {
+      *(.rel.rodata)
+      *(.rel.rodata.*)
+      *(.rel.gnu.linkonce.r.*)
+    }
+  .rela.rodata   :
+    {
+      *(.rela.rodata)
+      *(.rela.rodata.*)
+      *(.rela.gnu.linkonce.r.*)
+    }
+  .rel.data      :
+    {
+      *(.rel.data)
+      *(.rel.data.*)
+      *(.rel.gnu.linkonce.d.*)
+    }
+  .rela.data     :
+    {
+      *(.rela.data)
+      *(.rela.data.*)
+      *(.rela.gnu.linkonce.d.*)
+    }
+  .rel.ctors     : { *(.rel.ctors)     }
+  .rela.ctors    : { *(.rela.ctors)    }
+  .rel.dtors     : { *(.rel.dtors)     }
+  .rela.dtors    : { *(.rela.dtors)    }
+  .rel.got       : { *(.rel.got)               }
+  .rela.got      : { *(.rela.got)              }
+  .rel.sdata     :
+    {
+      *(.rel.sdata)
+      *(.rel.sdata.*)
+      *(.rel.gnu.linkonce.s.*)
+    }
+  .rela.sdata     :
+    {
+      *(.rela.sdata)
+      *(.rela.sdata.*)
+      *(.rela.gnu.linkonce.s.*)
+    }
+  .rel.sbss      :
+    { 
+      *(.rel.sbss)
+      *(.rel.sbss.*)
+      *(.rel.gnu.linkonce.sb.*)
+    }
+  .rela.sbss     :
+    {
+      *(.rela.sbss)
+      *(.rela.sbss.*)
+      *(.rel.gnu.linkonce.sb.*)
+    }
+  .rel.sdata2    : 
+    { 
+      *(.rel.sdata2)
+      *(.rel.sdata2.*)
+      *(.rel.gnu.linkonce.s2.*)
+    }
+  .rela.sdata2   : 
+    {
+      *(.rela.sdata2)
+      *(.rela.sdata2.*)
+      *(.rela.gnu.linkonce.s2.*)
+    }
+  .rel.sbss2     : 
+    { 
+      *(.rel.sbss2)    
+      *(.rel.sbss2.*)
+      *(.rel.gnu.linkonce.sb2.*)
+    }
+  .rela.sbss2    : 
+    { 
+      *(.rela.sbss2)   
+      *(.rela.sbss2.*)
+      *(.rela.gnu.linkonce.sb2.*)
+    }
+  .rel.bss       : 
+    { 
+      *(.rel.bss)
+      *(.rel.bss.*)
+      *(.rel.gnu.linkonce.b.*)
+    }
+  .rela.bss      : 
+    { 
+      *(.rela.bss)
+      *(.rela.bss.*)
+      *(.rela.gnu.linkonce.b.*)
+    }
+  .rel.plt       : { *(.rel.plt)               }
+  .rela.plt      : { *(.rela.plt)              }
+  .init          : 
+  { 
+    KEEP (*(.init))
+  } =0
+  .text      :
+  {
+    *(.text)
+    *(.text.*)
+    *(.stub)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+    *(.gnu.linkonce.t.*)
+  } =0
+  .fini      :
+  {
+    KEEP (*(.fini))
+  } =0
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata   : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }
+  .rodata1   : { *(.rodata1) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN(8);
+  .data    :
+  {
+    *(.data)
+    *(.data.*)
+    *(.gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1   : { *(.data1) }
+  .eh_frame : { KEEP (*(.eh_frame)) }
+  .gcc_except_table : { *(.gcc_except_table) }
+  .fixup       : { *(.fixup) }
+  .got1                : { *(.got1) }
+  .got2                : { *(.got2) }
+  .ctors   : 
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    /* We don't want to include the .ctor section from
+       from the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+   .dtors         :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .got           : { *(.got.plt) *(.got) }
+  PROVIDE (_GOT_END_ = .);
+  .sdata2   : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }
+  .sbss2   : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : 
+  {
+    *(.sdata) 
+    *(.sdata.*)
+    *(.gnu.linkonce.s.*)
+  }
+  _edata = .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .sbss      :
+  {
+    PROVIDE (__sbss_start = .);
+    PROVIDE (___sbss_start = .);
+    *(.dynsbss)
+    *(.sbss)
+    *(.sbss.*)
+    *(.gnu.linkonce.sb.*)
+    *(.scommon)
+    PROVIDE (__sbss_end = .);
+    PROVIDE (___sbss_end = .);
+  }
+  .plt      : { *(.plt)        }
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(.bss.*)
+   *(.gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(8);
+  }
+  . = ALIGN(8);
+  _end = .;
+  __end = .;
+  PROVIDE (end = .);
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* These must appear regardless of  .  */
+}
diff --git a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
new file mode 100644 (file)
index 0000000..88b93a7
--- /dev/null
@@ -0,0 +1,370 @@
+/*     $NetBSD: ppc_reloc.c,v 1.46 2011/01/16 01:22:29 matt Exp $      */
+
+/*-
+ * Copyright (C) 1998  Tsubai Masanari
+ * Portions copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: ppc_reloc.c,v 1.46 2011/01/16 01:22:29 matt Exp $");
+#endif /* not lint */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <machine/cpu.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+void _rtld_powerpc_pltcall(Elf_Word);
+void _rtld_powerpc_pltresolve(Elf_Word, Elf_Word);
+
+#define ha(x) ((((u_int32_t)(x) & 0x8000) ? \
+                       ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
+#define l(x) ((u_int32_t)(x) & 0xffff)
+
+void _rtld_bind_bssplt_start(void);
+void _rtld_bind_secureplt_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+static int _rtld_relocate_plt_object(const Obj_Entry *,
+    const Elf_Rela *, int, Elf_Addr *);
+
+/*
+ * The PPC PLT format consists of three sections:
+ * (1) The "pltcall" and "pltresolve" glue code.  This is always 18 words.
+ * (2) The code part of the PLT entries.  There are 2 words per entry for
+ *     up to 8192 entries, then 4 words per entry for any additional entries.
+ * (3) The data part of the PLT entries, comprising a jump table.
+ *     This section is half the size of the second section (ie. 1 or 2 words
+ *     per entry).
+ */
+
+/*
+ * Setup the plt glue routines (for bss-plt).
+ */
+#define PLTCALL_SIZE   20
+#define PLTRESOLVE_SIZE        24
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       /*
+        * Secure-PLT is much more sane.
+        */
+       if (obj->gotptr != NULL) {
+               obj->gotptr[1] = (Elf_Addr) _rtld_bind_secureplt_start;
+               obj->gotptr[2] = (Elf_Addr) obj;
+       } else {
+               Elf_Word *pltcall, *pltresolve;
+               Elf_Word *jmptab;
+               int N = obj->pltrelalim - obj->pltrela;
+
+               /* Entries beyond 8192 take twice as much space. */
+               if (N > 8192)
+                       N += N-8192;
+
+               pltcall = obj->pltgot;
+               jmptab = pltcall + 18 + N * 2;
+
+               memcpy(pltcall, _rtld_powerpc_pltcall, PLTCALL_SIZE);
+               pltcall[1] |= ha(jmptab);
+               pltcall[2] |= l(jmptab);
+
+               pltresolve = obj->pltgot + 8;
+
+               memcpy(pltresolve, _rtld_powerpc_pltresolve, PLTRESOLVE_SIZE);
+               pltresolve[0] |= ha(_rtld_bind_bssplt_start);
+               pltresolve[1] |= l(_rtld_bind_bssplt_start);
+               pltresolve[3] |= ha(obj);
+               pltresolve[4] |= l(obj);
+
+               /*
+                * Invalidate the icache for only the code part of the PLT
+                * (and not the jump table at the end).
+                */
+               __syncicache(pltcall, (char *)jmptab - (char *)pltcall);
+       }
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rela *rela = 0, *relalim;
+       Elf_Addr relasz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_RELA:
+                       rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
+       for (; rela < relalim; rela++) {
+               where = (Elf_Addr *)(relocbase + rela->r_offset);
+               *where = (Elf_Addr)(relocbase + rela->r_addend);
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->rela; rela < obj->relalim; rela++) {
+               Elf_Addr        *where;
+               const Elf_Sym   *def;
+               const Obj_Entry *defobj;
+               Elf_Addr         tmp;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+               symnum = ELF_R_SYM(rela->r_info);
+
+               switch (ELF_R_TYPE(rela->r_info)) {
+#if 1 /* XXX Should not be necessary. */
+               case R_TYPE(JMP_SLOT):
+#endif
+               case R_TYPE(NONE):
+                       break;
+
+               case R_TYPE(32):        /* word32 S + A */
+               case R_TYPE(GLOB_DAT):  /* word32 S + A */
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
+                           rela->r_addend);
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("32/GLOB_DAT %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(RELATIVE):  /* word32 B + A */
+                       *where = (Elf_Addr)(obj->relocbase + rela->r_addend);
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)*where));
+                       break;
+
+               case R_TYPE(COPY):
+                       /*
+                        * These are deferred until all other relocations have
+                        * been done.  All we do here is make sure that the
+                        * COPY relocation is not in a shared library.  They
+                        * are allowed only in executable files.
+                        */
+                       if (obj->isdynamic) {
+                               _rtld_error(
+                       "%s: Unexpected R_COPY relocation in shared library",
+                                   obj->path);
+                               return -1;
+                       }
+                       rdbg(("COPY (avoid in main)"));
+                       break;
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "addend = %p, contents = %p, symbol = %s",
+                           symnum, (u_long)ELF_R_TYPE(rela->r_info),
+                           (void *)rela->r_offset, (void *)rela->r_addend,
+                           (void *)*where,
+                           obj->strtab + obj->symtab[symnum].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rela->r_info));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       Elf_Addr * const pltresolve = obj->pltgot + 8;
+       const Elf_Rela *rela;
+       int reloff;
+
+       for (rela = obj->pltrela, reloff = 0;
+            rela < obj->pltrelalim;
+            rela++, reloff++) {
+               Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
+
+               assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
+
+               if (obj->gotptr != NULL) {
+                       /*
+                        * For now, simply treat then as relative.
+                        */
+                       *where += (Elf_Addr)obj->relocbase;
+               } else {
+                       int distance;
+
+                       if (reloff < 32768) {
+                               /* li   r11,reloff */
+                               *where++ = 0x39600000 | reloff;
+                       } else {
+                               /* lis  r11,ha(reloff) */
+                               /* addi r11,l(reloff) */
+                               *where++ = 0x3d600000 | ha(reloff);
+                               *where++ = 0x396b0000 | l(reloff);
+                       }
+                       /* b    pltresolve */
+                       distance = (Elf_Addr)pltresolve - (Elf_Addr)where;
+                       *where++ = 0x48000000 | (distance & 0x03fffffc);
+
+                       /*
+                        * Icache invalidation is not done for each entry here
+                        * because we sync the entire code part of the PLT once
+                        * in _rtld_setup_pltgot() after all the entries have been
+                        * initialized.
+                        */
+                       /* __syncicache(where - 3, 12); */
+               }
+       }
+
+       return 0;
+}
+
+static int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff, Elf_Addr *tp)
+{
+       Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
+       Elf_Addr value;
+       const Elf_Sym *def;
+       const Obj_Entry *defobj;
+       int distance;
+       unsigned long info = rela->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       distance = value - (Elf_Addr)where;
+       rdbg(("bind now/fixup in %s --> new=%p", 
+           defobj->strtab + def->st_name, (void *)value));
+
+       if (obj->gotptr != NULL) {
+               /*
+                * For Secure-PLT we simply replace the entry in GOT with the address
+                * of the routine.
+                */
+               assert(where >= (Elf_Word *)obj->pltgot);
+               assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela));
+               *where = value;
+       } else if (abs(distance) < 32*1024*1024) {      /* inside 32MB? */
+               /* b    value   # branch directly */
+               *where = 0x48000000 | (distance & 0x03fffffc);
+               __syncicache(where, 4);
+       } else {
+               Elf_Addr *pltcall, *jmptab;
+               int N = obj->pltrelalim - obj->pltrela;
+       
+               /* Entries beyond 8192 take twice as much space. */
+               if (N > 8192)
+                       N += N-8192;
+
+               pltcall = obj->pltgot;
+               jmptab = pltcall + 18 + N * 2;
+       
+               jmptab[reloff] = value;
+
+               if (reloff < 32768) {
+                       /* li   r11,reloff */
+                       *where++ = 0x39600000 | reloff;
+               } else {
+#ifdef notyet
+                       /* lis  r11,ha(value) */
+                       /* addi r11,l(value) */
+                       /* mtctr r11 */
+                       /* bctr */
+                       *where++ = 0x3d600000 | ha(value);
+                       *where++ = 0x396b0000 | l(value);
+                       *where++ = 0x7d6903a6;
+                       *where++ = 0x4e800420;
+#else
+                       /* lis  r11,ha(reloff) */
+                       /* addi r11,l(reloff) */
+                       *where++ = 0x3d600000 | ha(reloff);
+                       *where++ = 0x396b0000 | l(reloff);
+#endif
+               }
+               /* b    pltcall */
+               distance = (Elf_Addr)pltcall - (Elf_Addr)where;
+               *where++ = 0x48000000 | (distance & 0x03fffffc);
+               __syncicache(where - 3, 12);
+       }
+
+       if (tp)
+               *tp = value;
+       return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rela *rela = (const void *)((const char *)obj->pltrela + reloff);
+       Elf_Addr new_value;
+       int err;
+
+       new_value = 0;  /* XXX gcc */
+
+       err = _rtld_relocate_plt_object(obj, rela, reloff, &new_value); 
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)new_value;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+       int reloff;
+       
+       for (rela = obj->pltrela, reloff = 0; rela < obj->pltrelalim; rela++, reloff++) {
+               if (_rtld_relocate_plt_object(obj, rela, reloff, NULL) < 0)
+                       return -1;
+       }
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/powerpc/rtld_start.S b/libexec/ld.elf_so/arch/powerpc/rtld_start.S
new file mode 100644 (file)
index 0000000..aa57681
--- /dev/null
@@ -0,0 +1,133 @@
+/*     $NetBSD: rtld_start.S,v 1.14 2011/01/16 01:22:29 matt Exp $     */
+
+/*-
+ * Copyright (C) 1998  Tsubai Masanari
+ * Portions copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+       .globl  _rtld_start
+       .globl  _rtld
+
+       .text
+
+_rtld_start:
+       stwu    %r1,-48(%r1)
+       stw     %r3,12(%r1)             # argc
+       stw     %r4,16(%r1)             # argv
+       stw     %r5,20(%r1)             # envp
+/*     stw     %r6,24(%r1)             # obj           (always 0) */
+/*     stw     %r7,28(%r1)             # cleanup       (always 0) */
+       stw     %r8,32(%r1)             # ps_strings
+
+       bcl     20,31,1f
+1:     mflr    %r30
+       mr      %r3,%r30                # save for _DYNAMIC
+       addis   %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha
+       addi    %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l
+       addis   %r3,%r3,_DYNAMIC-1b@ha  # get _DYNAMIC actual address
+       addi    %r3,%r3,_DYNAMIC-1b@l
+       lwz     %r28,0(%r30)            # get base-relative &_DYNAMIC
+       sub     %r28,%r3,%r28           # r28 = relocbase
+       mr      %r4,%r28                # r4 = relocbase
+       bl      _rtld_relocate_nonplt_self
+
+       lwz     %r3,16(%r1)
+       addi    %r3,%r3,-12             # sp = &argv[-3]        /* XXX */
+       mr      %r4,%r28                # r4 = relocbase
+       bl      _rtld                   # _start = _rtld(sp, relocbase)
+       mtlr    %r3
+
+       lwz     %r3,12(%r1)             # argc
+       lwz     %r4,16(%r1)             # argv
+       lwz     %r5,20(%r1)             # envp
+       lwz     %r6,-8(%r4)             # obj = sp[1] (== argv[-2])
+       lwz     %r7,-12(%r4)            # cleanup = sp[0] (== argv[-3])
+       lwz     %r8,32(%r1)             # ps_strings
+
+       addi    %r1,%r1,48
+       blrl            # _start(argc, argv, envp, obj, cleanup, ps_strings)
+
+       li      %r0,1                   # _exit()
+       sc
+
+END(_rtld_start)
+
+       .globl  _rtld_bind
+
+/*
+ * secure-plt expects %r11 to be the offset to the rela entry.
+ * bss-plt expects %r11 to be index of the rela entry.
+ * So for bss-plt, we multiply the index by 12 to get the offset.
+ */
+ENTRY_NOPROFILE(_rtld_bind_bssplt_start)
+       slwi    %r11,%r11,2
+       add     %r0,%r11,%r11
+       add     %r11,%r11,%r0
+ENTRY_NOPROFILE(_rtld_bind_secureplt_start)
+       stwu    %r1,-160(%r1)
+
+       stw     %r0,20(%r1)
+       mflr    %r0
+       stw     %r0,16(%r1)             # save lr
+       mfcr    %r0
+       stw     %r0,12(%r1)             # save cr
+       stmw    %r3,24(%r1)             # save r3-r31
+
+       mr      %r3,%r12                # obj
+       mr      %r4,%r11                # reloff
+       bl      _rtld_bind              # _rtld_bind(obj, reloff)
+       mtctr   %r3
+
+       lmw     %r3,24(%r1)             # load r3-r31
+       lwz     %r0,12(%r1)             # restore cr
+       mtcr    %r0
+       lwz     %r0,16(%r1)             # restore lr
+       mtlr    %r0
+       lwz     %r0,20(%r1)
+
+       addi    %r1,%r1,160
+       bctr
+END(_rtld_bind_start)
+
+       .globl  _rtld_powerpc_pltcall
+       .globl  _rtld_powerpc_pltresolve
+
+_rtld_powerpc_pltcall:
+       slwi    %r11,%r11,2
+       addis   %r11,%r11,0             # addis 11,11,jmptab@ha
+       lwz     %r11,0(%r11)            # lwz   11,jmptab@l(11)
+       mtctr   %r11
+       bctr
+
+_rtld_powerpc_pltresolve:
+       lis     %r12,0                  # lis   12,_rtld_bind_bssplt_start@ha
+       addi    %r12,%r12,0             # addi  12,12,_rtld_bind_bssplt_start@l
+       mtctr   %r12
+       lis     %r12,0                  # lis   12,obj@ha
+       addi    %r12,%r12,0             # addi  12,12,obj@l
+       bctr
diff --git a/libexec/ld.elf_so/arch/sh3/Makefile.inc b/libexec/ld.elf_so/arch/sh3/Makefile.inc
new file mode 100644 (file)
index 0000000..2bb9e96
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile.inc,v 1.7 2005/06/04 16:17:17 lukem Exp $
+
+SRCS+=         rtld_start.S mdreloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic
+
+CPPFLAGS+=     -DELFSIZE=32
+
+LDFLAGS+=      -Wl,-e,.rtld_start
diff --git a/libexec/ld.elf_so/arch/sh3/mdreloc.c b/libexec/ld.elf_so/arch/sh3/mdreloc.c
new file mode 100644 (file)
index 0000000..6ceb4ca
--- /dev/null
@@ -0,0 +1,249 @@
+/*     $NetBSD: mdreloc.c,v 1.28 2010/08/06 16:33:18 joerg Exp $       */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.28 2010/08/06 16:33:18 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.28 2010/08/06 16:33:18 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+void _rtld_bind_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+static inline int _rtld_relocate_plt_object(const Obj_Entry *,
+    const Elf_Rela *, Elf_Addr *);
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       obj->pltgot[1] = (Elf_Addr) obj;
+       obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rela *rela = 0, *relalim;
+       Elf_Addr relasz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_RELA:
+                       rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
+       for (; rela < relalim; rela++) {
+               where = (Elf_Addr *)(relocbase + rela->r_offset);
+               *where = (Elf_Addr)(relocbase + rela->r_addend);
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->rela; rela < obj->relalim; rela++) {
+               Elf_Addr        *where;
+               const Elf_Sym   *def;
+               const Obj_Entry *defobj;
+               Elf_Addr         tmp;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+               symnum = ELF_R_SYM(rela->r_info);
+
+               switch (ELF_R_TYPE(rela->r_info)) {
+               case R_TYPE(NONE):
+                       break;
+
+#if 1 /* XXX should not occur */
+               case R_TYPE(GOT32):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
+                           rela->r_addend);
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("GOT32 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(REL32):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
+                           rela->r_addend) - (Elf_Addr)where;
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("PC32 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+#endif
+
+               case R_TYPE(DIR32):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
+                           rela->r_addend);
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("32 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(GLOB_DAT):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       tmp = (Elf_Addr)(defobj->relocbase + def->st_value) +
+                           rela->r_addend;
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("GLOB_DAT %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(RELATIVE):
+                       if (rela->r_addend)
+                               *where = (Elf_Addr)obj->relocbase + rela->r_addend;
+                       else
+                               *where += (Elf_Addr)obj->relocbase;
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)*where));
+                       break;
+
+               case R_TYPE(COPY):
+                       /*
+                        * These are deferred until all other relocations have
+                        * been done.  All we do here is make sure that the
+                        * COPY relocation is not in a shared library.  They
+                        * are allowed only in executable files.
+                        */
+                       if (obj->isdynamic) {
+                               _rtld_error(
+                       "%s: Unexpected R_COPY relocation in shared library",
+                                   obj->path);
+                               return -1;
+                       }
+                       rdbg(("COPY (avoid in main)"));
+                       break;
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "addend = %p, contents = %p, symbol = %s",
+                           symnum, (u_long)ELF_R_TYPE(rela->r_info),
+                           (void *)rela->r_offset, (void *)rela->r_addend,
+                           (void *)*where,
+                           obj->strtab + obj->symtab[symnum].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rela->r_info));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       if (!obj->relocbase)
+               return 0;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
+               Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+
+               assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
+
+               /* Just relocate the GOT slots pointing into the PLT */
+               *where += (Elf_Addr)obj->relocbase;
+               rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
+       }
+
+       return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff);
+       Elf_Addr new_value;
+       int err;
+
+       new_value = 0;  /* XXX gcc */
+
+       err = _rtld_relocate_plt_object(obj, rela, &new_value);
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)new_value;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela = obj->pltrela;
+
+       for (; rela < obj->pltrelalim; rela++)
+               if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
+                       return -1;
+
+       return 0;
+}
+
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp)
+{
+       Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+       Elf_Addr new_value;
+       const Elf_Sym  *def;
+       const Obj_Entry *defobj;
+       unsigned long info = rela->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       rdbg(("bind now/fixup in %s --> old=%p new=%p",
+           defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
+       if (*where != new_value)
+               *where = new_value;
+
+       if (tp)
+               *tp = new_value;
+
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/sh3/rtld_start.S b/libexec/ld.elf_so/arch/sh3/rtld_start.S
new file mode 100644 (file)
index 0000000..9ac5b13
--- /dev/null
@@ -0,0 +1,117 @@
+/*     $NetBSD: rtld_start.S,v 1.7 2008/04/28 20:23:03 martin Exp $    */
+
+/*-
+ * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Marcus Comstedt.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+       .text
+       .align  2
+       .globl  .rtld_start
+       .type   .rtld_start,@function
+
+.rtld_start:
+       mova    2f,r0
+       mov.l   @r0,r2
+       add     r0,r2           /* GOT */
+       mov.l   @(4,r0),r4      /* _DYNAMIC@GOTOFF */
+       add     r2,r4           /* _DYNAMIC */
+       mov.l   @(12,r0),r1     /* _rtld_relocate_nonplt_self offset */
+       mov.l   @(8,r0),r0      /* _DYNAMIC@GOT */
+       mov     r4,r5
+       mov.l   @(r0,r2),r0     /* where linker thinks _DYNAMIC is */
+       sub     r0,r5           /* compute relocation base */
+       bsrf    r1              /* _rtld_relocate_nonplt_self(dynp, relocbase) */
+        mov.l  r5,@-r15        /* save relocbase */
+
+4:
+       mov.l   @r15+,r5        /* restore relocbase */
+       add     #-8,r15         /* room for values returned by _rtld */
+       mov     r15,r4
+       mov.l   1f,r0
+       bsrf    r0              /* _rtld(sp, relocbase) */
+        mov.l  r9,@-r15        /* save ps_strings */
+3:
+       mov.l   @r15+,r9        /* restore ps_strings */
+
+       mov.l   @r15+,r7        /* from _rtld: exit procedure */
+       mov.l   @r15+,r8        /* from _rtld: main object */
+
+       mov.l   @r15,r4         /* restore argc */
+
+       mov     r15,r5          /* restore argv */
+       add     #4,r5
+
+       mov     r4,r6           /* restore envp */
+       shll2   r6
+       add     r15,r6
+       jmp     @r0             /* entry point returned by _rtld */
+        add    #8,r6
+       .align  2
+1:     .long   _rtld-3b
+2:     .long   _GLOBAL_OFFSET_TABLE_
+       .long   _DYNAMIC@GOTOFF
+       .long   _DYNAMIC@GOT
+       .long   _rtld_relocate_nonplt_self-4b
+       .size   .rtld_start,.-.rtld_start
+
+       .align  2
+       .globl  _rtld_bind_start
+       .type   _rtld_bind_start,@function
+_rtld_bind_start:              /* r0 = obj, r1 = reloff */
+       mov.l   r2,@-r15        /* save registers */
+       mov.l   r3,@-r15
+       mov.l   r4,@-r15
+       mov.l   r5,@-r15
+       mov.l   r6,@-r15
+       mov.l   r7,@-r15
+       sts.l   mach,@-r15
+       sts.l   macl,@-r15
+       sts.l   pr,@-r15
+
+       mov     r0,r4           /* copy of obj */
+       mov.l   2f,r0
+       bsrf    r0              /* call the binder */
+        mov    r1,r5           /* copy of reloff */
+4:
+       lds.l   @r15+,pr        /* restore registers */
+       lds.l   @r15+,macl
+       lds.l   @r15+,mach
+       mov.l   @r15+,r7
+       mov.l   @r15+,r6
+       mov.l   @r15+,r5
+       mov.l   @r15+,r4
+       mov.l   @r15+,r3
+       jmp     @r0
+        mov.l  @r15+,r2
+       .align  2
+2:     .long   _rtld_bind-4b
+       .size   _rtld_bind_start,.-_rtld_bind_start
+
+       .end
diff --git a/libexec/ld.elf_so/arch/sparc/Makefile.inc b/libexec/ld.elf_so/arch/sparc/Makefile.inc
new file mode 100644 (file)
index 0000000..e13e6e0
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile.inc,v 1.14 2009/12/13 09:31:47 mrg Exp $
+
+SRCS+=         rtld_start.S mdreloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic
+
+CPPFLAGS+=     -DELFSIZE=32
+
+LDFLAGS+=      -Wl,-e,_rtld_start
diff --git a/libexec/ld.elf_so/arch/sparc/mdreloc.c b/libexec/ld.elf_so/arch/sparc/mdreloc.c
new file mode 100644 (file)
index 0000000..6b10b58
--- /dev/null
@@ -0,0 +1,394 @@
+/*     $NetBSD: mdreloc.c,v 1.44 2010/08/06 16:33:18 joerg Exp $       */
+
+/*-
+ * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg and by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.44 2010/08/06 16:33:18 joerg Exp $");
+#endif /* not lint */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "rtldenv.h"
+#include "debug.h"
+#include "rtld.h"
+
+/*
+ * The following table holds for each relocation type:
+ *     - the width in bits of the memory location the relocation
+ *       applies to (not currently used)
+ *     - the number of bits the relocation value must be shifted to the
+ *       right (i.e. discard least significant bits) to fit into
+ *       the appropriate field in the instruction word.
+ *     - flags indicating whether
+ *             * the relocation involves a symbol
+ *             * the relocation is relative to the current position
+ *             * the relocation is for a GOT entry
+ *             * the relocation is relative to the load address
+ *
+ */
+#define _RF_S          0x80000000              /* Resolve symbol */
+#define _RF_A          0x40000000              /* Use addend */
+#define _RF_P          0x20000000              /* Location relative */
+#define _RF_G          0x10000000              /* GOT offset */
+#define _RF_B          0x08000000              /* Load address relative */
+#define _RF_U          0x04000000              /* Unaligned */
+#define _RF_SZ(s)      (((s) & 0xff) << 8)     /* memory target size */
+#define _RF_RS(s)      ( (s) & 0xff)           /* right shift */
+static const int reloc_target_flags[] = {
+       0,                                                      /* NONE */
+       _RF_S|_RF_A|            _RF_SZ(8)  | _RF_RS(0),         /* RELOC_8 */
+       _RF_S|_RF_A|            _RF_SZ(16) | _RF_RS(0),         /* RELOC_16 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* RELOC_32 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(8)  | _RF_RS(0),         /* DISP_8 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(16) | _RF_RS(0),         /* DISP_16 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(0),         /* DISP_32 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(2),         /* WDISP_30 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(2),         /* WDISP_22 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(10),        /* HI22 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* 22 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* 13 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* LO10 */
+       _RF_G|                  _RF_SZ(32) | _RF_RS(0),         /* GOT10 */
+       _RF_G|                  _RF_SZ(32) | _RF_RS(0),         /* GOT13 */
+       _RF_G|                  _RF_SZ(32) | _RF_RS(10),        /* GOT22 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(0),         /* PC10 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(10),        /* PC22 */
+             _RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(2),         /* WPLT30 */
+                               _RF_SZ(32) | _RF_RS(0),         /* COPY */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* GLOB_DAT */
+                               _RF_SZ(32) | _RF_RS(0),         /* JMP_SLOT */
+             _RF_A|    _RF_B|  _RF_SZ(32) | _RF_RS(0),         /* RELATIVE */
+       _RF_S|_RF_A|    _RF_U|  _RF_SZ(32) | _RF_RS(0),         /* UA_32 */
+};
+
+#ifdef RTLD_DEBUG_RELOC
+static const char *reloc_names[] = {
+       "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8",
+       "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22",
+       "22", "13", "LO10", "GOT10", "GOT13",
+       "GOT22", "PC10", "PC22", "WPLT30", "COPY",
+       "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32"
+};
+#endif
+
+#define RELOC_RESOLVE_SYMBOL(t)                ((reloc_target_flags[t] & _RF_S) != 0)
+#define RELOC_PC_RELATIVE(t)           ((reloc_target_flags[t] & _RF_P) != 0)
+#define RELOC_BASE_RELATIVE(t)         ((reloc_target_flags[t] & _RF_B) != 0)
+#define RELOC_UNALIGNED(t)             ((reloc_target_flags[t] & _RF_U) != 0)
+#define RELOC_USE_ADDEND(t)            ((reloc_target_flags[t] & _RF_A) != 0)
+#define RELOC_TARGET_SIZE(t)           ((reloc_target_flags[t] >> 8) & 0xff)
+#define RELOC_VALUE_RIGHTSHIFT(t)      (reloc_target_flags[t] & 0xff)
+
+static const int reloc_target_bitmask[] = {
+#define _BM(x) (~(-(1ULL << (x))))
+       0,                              /* NONE */
+       _BM(8), _BM(16), _BM(32),       /* RELOC_8, _16, _32 */
+       _BM(8), _BM(16), _BM(32),       /* DISP8, DISP16, DISP32 */
+       _BM(30), _BM(22),               /* WDISP30, WDISP22 */
+       _BM(22), _BM(22),               /* HI22, _22 */
+       _BM(13), _BM(10),               /* RELOC_13, _LO10 */
+       _BM(10), _BM(13), _BM(22),      /* GOT10, GOT13, GOT22 */
+       _BM(10), _BM(22),               /* _PC10, _PC22 */  
+       _BM(30), 0,                     /* _WPLT30, _COPY */
+       -1, -1, -1,                     /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
+       _BM(32)                         /* _UA32 */
+#undef _BM
+};
+#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
+
+void _rtld_bind_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+static inline int _rtld_relocate_plt_object(const Obj_Entry *,
+    const Elf_Rela *, Elf_Addr *);
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       /*
+        * PLTGOT is the PLT on the sparc.
+        * The first entry holds the call the dynamic linker.
+        * We construct a `call' sequence that transfers
+        * to `_rtld_bind_start()'.
+        * The second entry holds the object identification.
+        * Note: each PLT entry is three words long.
+        */
+#define SAVE   0x9de3bfa0      /* i.e. `save %sp,-96,%sp' */
+#define CALL   0x40000000
+#define NOP    0x01000000
+       obj->pltgot[0] = SAVE;
+       obj->pltgot[1] = CALL |
+           ((Elf_Addr) &_rtld_bind_start - (Elf_Addr) &obj->pltgot[1]) >> 2;
+       obj->pltgot[2] = NOP;
+       obj->pltgot[3] = (Elf_Addr) obj;
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rela *rela = 0, *relalim;
+       Elf_Addr relasz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_RELA:
+                       rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
+       for (; rela < relalim; rela++) {
+               where = (Elf_Addr *)(relocbase + rela->r_offset);
+               *where += (Elf_Addr)(relocbase + rela->r_addend);
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->rela; rela < obj->relalim; rela++) {
+               Elf_Addr *where;
+               Elf_Word type, value, mask;
+               const Elf_Sym *def = NULL;
+               const Obj_Entry *defobj = NULL;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
+               symnum = ELF_R_SYM(rela->r_info);
+
+               type = ELF_R_TYPE(rela->r_info);
+               if (type == R_TYPE(NONE))
+                       continue;
+
+               /* We do JMP_SLOTs in _rtld_bind() below */
+               if (type == R_TYPE(JMP_SLOT))
+                       continue;
+
+               /* COPY relocs are also handled elsewhere */
+               if (type == R_TYPE(COPY))
+                       continue;
+
+               /*
+                * We use the fact that relocation types are an `enum'
+                * Note: R_SPARC_6 is currently numerically largest.
+                */
+               if (type > R_TYPE(6))
+                       return (-1);
+
+               value = rela->r_addend;
+
+               /*
+                * Handle relative relocs here, as an optimization.
+                */
+               if (type == R_TYPE(RELATIVE)) {
+                       *where += (Elf_Addr)(obj->relocbase + value);
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)*where));
+                       continue;
+               }
+
+               if (RELOC_RESOLVE_SYMBOL(type)) {
+
+                       /* Find the symbol */
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return (-1);
+
+                       /* Add in the symbol's absolute address */
+                       value += (Elf_Word)(defobj->relocbase + def->st_value);
+               }
+
+               if (RELOC_PC_RELATIVE(type)) {
+                       value -= (Elf_Word)where;
+               }
+
+               if (RELOC_BASE_RELATIVE(type)) {
+                       /*
+                        * Note that even though sparcs use `Elf_rela'
+                        * exclusively we still need the implicit memory addend
+                        * in relocations referring to GOT entries.
+                        * Undoubtedly, someone f*cked this up in the distant
+                        * past, and now we're stuck with it in the name of
+                        * compatibility for all eternity..
+                        *
+                        * In any case, the implicit and explicit should be
+                        * mutually exclusive. We provide a check for that
+                        * here.
+                        */
+#define DIAGNOSTIC
+#ifdef DIAGNOSTIC
+                       if (value != 0 && *where != 0) {
+                               xprintf("BASE_REL(%s): where=%p, *where 0x%x, "
+                                       "addend=0x%x, base %p\n",
+                                       obj->path, where, *where,
+                                       rela->r_addend, obj->relocbase);
+                       }
+#endif
+                       value += (Elf_Word)(obj->relocbase + *where);
+               }
+
+               mask = RELOC_VALUE_BITMASK(type);
+               value >>= RELOC_VALUE_RIGHTSHIFT(type);
+               value &= mask;
+
+               if (RELOC_UNALIGNED(type)) {
+                       /* Handle unaligned relocations. */
+                       Elf_Addr tmp = 0;
+                       char *ptr = (char *)where;
+                       int i, size = RELOC_TARGET_SIZE(type)/8;
+
+                       /* Read it in one byte at a time. */
+                       for (i=0; i<size; i++)
+                               tmp = (tmp << 8) | ptr[i];
+
+                       tmp &= ~mask;
+                       tmp |= value;
+
+                       /* Write it back out. */
+                       for (i=0; i<size; i++)
+                               ptr[i] = ((tmp >> (8*i)) & 0xff);
+#ifdef RTLD_DEBUG_RELOC
+                       value = (Elf_Word)tmp;
+#endif
+
+               } else {
+                       *where &= ~mask;
+                       *where |= value;
+#ifdef RTLD_DEBUG_RELOC
+                       value = (Elf_Word)*where;
+#endif
+               }
+#ifdef RTLD_DEBUG_RELOC
+               if (RELOC_RESOLVE_SYMBOL(type)) {
+                       rdbg(("%s %s in %s --> %p in %s", reloc_names[type],
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)value, defobj->path));
+               } else {
+                       rdbg(("%s in %s --> %p", reloc_names[type],
+                           obj->path, (void *)value));
+               }
+#endif
+       }
+       return (0);
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       return (0);
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff);
+       Elf_Addr value;
+       int err;
+
+       value = 0;      /* XXX gcc */
+
+       err = _rtld_relocate_plt_object(obj, rela, &value);
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)value;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela = obj->pltrela;
+
+       for (; rela < obj->pltrelalim; rela++)
+               if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
+                       return -1;
+
+       return 0;
+}
+
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp)
+{
+       const Elf_Sym *def;
+       const Obj_Entry *defobj;
+       Elf_Word *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+       Elf_Addr value;
+       unsigned long info = rela->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       rdbg(("bind now/fixup in %s --> new=%p", 
+           defobj->strtab + def->st_name, (void *)value));
+
+       /*
+        * At the PLT entry pointed at by `where', we now construct
+        * a direct transfer to the now fully resolved function
+        * address.  The resulting code in the jump slot is:
+        *
+        *      sethi   %hi(roffset), %g1
+        *      sethi   %hi(addr), %g1
+        *      jmp     %g1+%lo(addr)
+        *
+        * We write the third instruction first, since that leaves the
+        * previous `b,a' at the second word in place. Hence the whole
+        * PLT slot can be atomically change to the new sequence by
+        * writing the `sethi' instruction at word 2.
+        */
+#define SETHI  0x03000000
+#define JMP    0x81c06000
+#define NOP    0x01000000
+       where[2] = JMP   | (value & 0x000003ff);
+       where[1] = SETHI | ((value >> 10) & 0x003fffff);
+       __asm volatile("iflush %0+8" : : "r" (where));
+       __asm volatile("iflush %0+4" : : "r" (where));
+
+       if (tp)
+               *tp = value;
+
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/sparc/rtld_start.S b/libexec/ld.elf_so/arch/sparc/rtld_start.S
new file mode 100644 (file)
index 0000000..67761cd
--- /dev/null
@@ -0,0 +1,81 @@
+/*     $NetBSD: rtld_start.S,v 1.16 2008/04/28 20:23:03 martin Exp $   */
+
+/*-
+ * Copyright (c) 1999, 2002, 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas, Paul Kranenburg, and by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+       .section        ".text"
+       .align  4
+       .global _rtld_start
+       .type   _rtld_start,@function
+_rtld_start:
+       mov     0, %fp                  /* Erect a fence post for ourselves */
+       mov     %g1, %l1                /* save ps_strings */
+       sub     %sp, 32+8, %sp          /* room for return args and save area */
+
+       sethi   %hi(_GLOBAL_OFFSET_TABLE_-4), %l7
+       call    0f
+        add    %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7
+       call    _DYNAMIC+8
+0:     add     %l7, %o7, %l7           /* real &_GLOBAL_OFFSET_TABLE_ */
+       ld      [%o7+8], %o0            /* load stub call instruction */
+       ld      [%l7], %l0              /* base-relative &_DYNAMIC */
+       sll     %o0, 2, %o0             /* extract PC offset */
+
+       add     %o0, %o7, %o0           /* real &_DYNAMIC */
+       sub     %o0, %l0, %l0           /* relocbase */
+       call    _rtld_relocate_nonplt_self
+        mov    %l0, %o1                /* relocbase */
+
+       mov     %l0, %o1                /* relocbase */
+       call    _rtld
+        add    %sp, 96, %o0            /* &argc - 8 */
+
+       ld      [%sp + 96], %g3 /* arg: cleanup */
+       ld      [%sp + 96 + 4], %g2     /* arg: obj */
+       add     %sp, 32+8, %sp          /* restore stack pointer */
+
+       jmp     %o0
+        mov    %l1, %g1                /* restore ps_strings */
+
+
+       .section        ".text"
+       .align  4
+       .global _rtld_bind_start
+       .type   _rtld_bind_start,@function
+_rtld_bind_start:      # (obj, reloff)
+       ld      [%o7 + 8], %o0          /* obj id is in second PLT slot */
+       srl     %g1, 10, %o1            /* offset is in high 22 bits */
+       call    _rtld_bind              /* Call _rtld_bind(obj, offset) */
+        sub    %o1, 12*4, %o1          /* first 4 `pltrel' entries missing! */
+
+       jmp     %o0                     /* return value == function address */
+        restore
+
diff --git a/libexec/ld.elf_so/arch/sparc64/Makefile.inc b/libexec/ld.elf_so/arch/sparc64/Makefile.inc
new file mode 100644 (file)
index 0000000..a7527c0
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile.inc,v 1.8 2005/06/04 16:17:17 lukem Exp $
+
+SRCS+=         rtld_start.S mdreloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic
+
+CPPFLAGS+=     -DELFSIZE=64
+
+LDFLAGS+=      -Wl,-e,_rtld_start
diff --git a/libexec/ld.elf_so/arch/sparc64/mdreloc.c b/libexec/ld.elf_so/arch/sparc64/mdreloc.c
new file mode 100644 (file)
index 0000000..0dc7e82
--- /dev/null
@@ -0,0 +1,732 @@
+/*     $NetBSD: mdreloc.c,v 1.50 2010/09/24 12:00:10 skrll Exp $       */
+
+/*-
+ * Copyright (c) 2000 Eduardo Horvath.
+ * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg and by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.50 2010/09/24 12:00:10 skrll Exp $");
+#endif /* not lint */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "rtldenv.h"
+#include "debug.h"
+#include "rtld.h"
+
+/*
+ * The following table holds for each relocation type:
+ *     - the width in bits of the memory location the relocation
+ *       applies to (not currently used)
+ *     - the number of bits the relocation value must be shifted to the
+ *       right (i.e. discard least significant bits) to fit into
+ *       the appropriate field in the instruction word.
+ *     - flags indicating whether
+ *             * the relocation involves a symbol
+ *             * the relocation is relative to the current position
+ *             * the relocation is for a GOT entry
+ *             * the relocation is relative to the load address
+ *
+ */
+#define _RF_S          0x80000000              /* Resolve symbol */
+#define _RF_A          0x40000000              /* Use addend */
+#define _RF_P          0x20000000              /* Location relative */
+#define _RF_G          0x10000000              /* GOT offset */
+#define _RF_B          0x08000000              /* Load address relative */
+#define _RF_U          0x04000000              /* Unaligned */
+#define _RF_SZ(s)      (((s) & 0xff) << 8)     /* memory target size */
+#define _RF_RS(s)      ( (s) & 0xff)           /* right shift */
+static const int reloc_target_flags[] = {
+       0,                                                      /* NONE */
+       _RF_S|_RF_A|            _RF_SZ(8)  | _RF_RS(0),         /* RELOC_8 */
+       _RF_S|_RF_A|            _RF_SZ(16) | _RF_RS(0),         /* RELOC_16 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* RELOC_32 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(8)  | _RF_RS(0),         /* DISP_8 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(16) | _RF_RS(0),         /* DISP_16 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(0),         /* DISP_32 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(2),         /* WDISP_30 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(2),         /* WDISP_22 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(10),        /* HI22 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* 22 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* 13 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* LO10 */
+       _RF_G|                  _RF_SZ(32) | _RF_RS(0),         /* GOT10 */
+       _RF_G|                  _RF_SZ(32) | _RF_RS(0),         /* GOT13 */
+       _RF_G|                  _RF_SZ(32) | _RF_RS(10),        /* GOT22 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(0),         /* PC10 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(10),        /* PC22 */
+             _RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(2),         /* WPLT30 */
+                               _RF_SZ(32) | _RF_RS(0),         /* COPY */
+       _RF_S|_RF_A|            _RF_SZ(64) | _RF_RS(0),         /* GLOB_DAT */
+                               _RF_SZ(32) | _RF_RS(0),         /* JMP_SLOT */
+             _RF_A|    _RF_B|  _RF_SZ(64) | _RF_RS(0),         /* RELATIVE */
+       _RF_S|_RF_A|    _RF_U|  _RF_SZ(32) | _RF_RS(0),         /* UA_32 */
+
+             _RF_A|            _RF_SZ(32) | _RF_RS(0),         /* PLT32 */
+             _RF_A|            _RF_SZ(32) | _RF_RS(10),        /* HIPLT22 */
+             _RF_A|            _RF_SZ(32) | _RF_RS(0),         /* LOPLT10 */
+             _RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(0),         /* PCPLT32 */
+             _RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(10),        /* PCPLT22 */
+             _RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(0),         /* PCPLT10 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* 10 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* 11 */
+       _RF_S|_RF_A|            _RF_SZ(64) | _RF_RS(0),         /* 64 */
+       _RF_S|_RF_A|/*extra*/   _RF_SZ(32) | _RF_RS(0),         /* OLO10 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(42),        /* HH22 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(32),        /* HM10 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(10),        /* LM22 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(42),        /* PC_HH22 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(32),        /* PC_HM10 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(10),        /* PC_LM22 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(2),         /* WDISP16 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(32) | _RF_RS(2),         /* WDISP19 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* GLOB_JMP */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* 7 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* 5 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* 6 */
+       _RF_S|_RF_A|_RF_P|      _RF_SZ(64) | _RF_RS(0),         /* DISP64 */
+             _RF_A|            _RF_SZ(64) | _RF_RS(0),         /* PLT64 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(10),        /* HIX22 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* LOX10 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(22),        /* H44 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(12),        /* M44 */
+       _RF_S|_RF_A|            _RF_SZ(32) | _RF_RS(0),         /* L44 */
+       _RF_S|_RF_A|            _RF_SZ(64) | _RF_RS(0),         /* REGISTER */
+       _RF_S|_RF_A|    _RF_U|  _RF_SZ(64) | _RF_RS(0),         /* UA64 */
+       _RF_S|_RF_A|    _RF_U|  _RF_SZ(16) | _RF_RS(0),         /* UA16 */
+};
+
+#ifdef RTLD_DEBUG_RELOC
+static const char *reloc_names[] = {
+       "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8",
+       "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22",
+       "22", "13", "LO10", "GOT10", "GOT13",
+       "GOT22", "PC10", "PC22", "WPLT30", "COPY",
+       "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32", "PLT32",
+       "HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32",
+       "10", "11", "64", "OLO10", "HH22",
+       "HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22", 
+       "WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6",
+       "DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44", 
+       "L44", "REGISTER", "UA64", "UA16"
+};
+#endif
+
+#define RELOC_RESOLVE_SYMBOL(t)                ((reloc_target_flags[t] & _RF_S) != 0)
+#define RELOC_PC_RELATIVE(t)           ((reloc_target_flags[t] & _RF_P) != 0)
+#define RELOC_BASE_RELATIVE(t)         ((reloc_target_flags[t] & _RF_B) != 0)
+#define RELOC_UNALIGNED(t)             ((reloc_target_flags[t] & _RF_U) != 0)
+#define RELOC_USE_ADDEND(t)            ((reloc_target_flags[t] & _RF_A) != 0)
+#define RELOC_TARGET_SIZE(t)           ((reloc_target_flags[t] >> 8) & 0xff)
+#define RELOC_VALUE_RIGHTSHIFT(t)      (reloc_target_flags[t] & 0xff)
+
+static const long reloc_target_bitmask[] = {
+#define _BM(x) (~(-(1ULL << (x))))
+       0,                              /* NONE */
+       _BM(8), _BM(16), _BM(32),       /* RELOC_8, _16, _32 */
+       _BM(8), _BM(16), _BM(32),       /* DISP8, DISP16, DISP32 */
+       _BM(30), _BM(22),               /* WDISP30, WDISP22 */
+       _BM(22), _BM(22),               /* HI22, _22 */
+       _BM(13), _BM(10),               /* RELOC_13, _LO10 */
+       _BM(10), _BM(13), _BM(22),      /* GOT10, GOT13, GOT22 */
+       _BM(10), _BM(22),               /* _PC10, _PC22 */  
+       _BM(30), 0,                     /* _WPLT30, _COPY */
+       _BM(32), _BM(32), _BM(32),      /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
+       _BM(32), _BM(32),               /* _UA32, PLT32 */
+       _BM(22), _BM(10),               /* _HIPLT22, LOPLT10 */
+       _BM(32), _BM(22), _BM(10),      /* _PCPLT32, _PCPLT22, _PCPLT10 */
+       _BM(10), _BM(11), -1,           /* _10, _11, _64 */
+       _BM(10), _BM(22),               /* _OLO10, _HH22 */
+       _BM(10), _BM(22),               /* _HM10, _LM22 */
+       _BM(22), _BM(10), _BM(22),      /* _PC_HH22, _PC_HM10, _PC_LM22 */
+       _BM(16), _BM(19),               /* _WDISP16, _WDISP19 */
+       -1,                             /* GLOB_JMP */
+       _BM(7), _BM(5), _BM(6)          /* _7, _5, _6 */
+       -1, -1,                         /* DISP64, PLT64 */
+       _BM(22), _BM(13),               /* HIX22, LOX10 */
+       _BM(22), _BM(10), _BM(13),      /* H44, M44, L44 */
+       -1, -1, _BM(16),                /* REGISTER, UA64, UA16 */
+#undef _BM
+};
+#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
+
+/*
+ * Instruction templates:
+ */
+#define        BAA     0x10400000      /*      ba,a    %xcc, 0 */
+#define        SETHI   0x03000000      /*      sethi   %hi(0), %g1 */
+#define        JMP     0x81c06000      /*      jmpl    %g1+%lo(0), %g0 */
+#define        NOP     0x01000000      /*      sethi   %hi(0), %g0 */
+#define        OR      0x82806000      /*      or      %g1, 0, %g1 */
+#define        XOR     0x82c06000      /*      xor     %g1, 0, %g1 */
+#define        MOV71   0x8283a000      /*      or      %o7, 0, %g1 */
+#define        MOV17   0x9c806000      /*      or      %g1, 0, %o7 */
+#define        CALL    0x40000000      /*      call    0 */
+#define        SLLX    0x8b407000      /*      sllx    %g1, 0, %g1 */
+#define        SETHIG5 0x0b000000      /*      sethi   %hi(0), %g5 */
+#define        ORG5    0x82804005      /*      or      %g1, %g5, %g1 */
+
+
+/* %hi(v)/%lo(v) with variable shift */
+#define        HIVAL(v, s)     (((v) >> (s)) & 0x003fffff)
+#define LOVAL(v, s)    (((v) >> (s)) & 0x000003ff)
+
+void _rtld_bind_start_0(long, long);
+void _rtld_bind_start_1(long, long);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+
+/*
+ * Install rtld function call into this PLT slot.
+ */
+#define        SAVE            0x9de3bf50      /* i.e. `save %sp,-176,%sp' */
+#define        SETHI_l0        0x21000000
+#define        SETHI_l1        0x23000000
+#define        OR_l0_l0        0xa0142000
+#define        SLLX_l0_32_l0   0xa12c3020
+#define        OR_l0_l1_l0     0xa0140011
+#define        JMPL_l0_o0      0x91c42000
+#define        MOV_g1_o1       0x92100001
+
+void _rtld_install_plt(Elf_Word *, Elf_Addr);
+static inline int _rtld_relocate_plt_object(const Obj_Entry *,
+    const Elf_Rela *, Elf_Addr *);
+
+void
+_rtld_install_plt(Elf_Word *pltgot, Elf_Addr proc)
+{
+       pltgot[0] = SAVE;
+       pltgot[1] = SETHI_l0  | HIVAL(proc, 42);
+       pltgot[2] = SETHI_l1  | HIVAL(proc, 10);
+       pltgot[3] = OR_l0_l0  | LOVAL(proc, 32);
+       pltgot[4] = SLLX_l0_32_l0;
+       pltgot[5] = OR_l0_l1_l0;
+       pltgot[6] = JMPL_l0_o0 | LOVAL(proc, 0);
+       pltgot[7] = MOV_g1_o1;
+}
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       /*
+        * On sparc64 we got troubles.
+        *
+        * Instructions are 4 bytes long.
+        * Elf[64]_Addr is 8 bytes long, so are our pltglot[]
+        * array entries.
+        * Each PLT entry jumps to PLT0 to enter the dynamic
+        * linker.
+        * Loading an arbitrary 64-bit pointer takes 6
+        * instructions and 2 registers.
+        *
+        * Somehow we need to issue a save to get a new stack
+        * frame, load the address of the dynamic linker, and
+        * jump there, in 8 instructions or less.
+        *
+        * Oh, we need to fill out both PLT0 and PLT1.
+        */
+       {
+               Elf_Word *entry = (Elf_Word *)obj->pltgot;
+
+               /* Install in entries 0 and 1 */
+               _rtld_install_plt(&entry[0], (Elf_Addr) &_rtld_bind_start_0);
+               _rtld_install_plt(&entry[8], (Elf_Addr) &_rtld_bind_start_1);
+
+               /* 
+                * Install the object reference in first slot
+                * of entry 2.
+                */
+               obj->pltgot[8] = (Elf_Addr) obj;
+       }
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rela *rela = 0, *relalim;
+       Elf_Addr relasz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_RELA:
+                       rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
+       for (; rela < relalim; rela++) {
+               where = (Elf_Addr *)(relocbase + rela->r_offset);
+               *where = (Elf_Addr)(relocbase + rela->r_addend);
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+       const Elf_Sym *def = NULL;
+       const Obj_Entry *defobj = NULL;
+
+       for (rela = obj->rela; rela < obj->relalim; rela++) {
+               Elf_Addr *where;
+               Elf_Word type;
+               Elf_Addr value = 0, mask;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
+               symnum = ELF_R_SYM(rela->r_info);
+
+               type = ELF_R_TYPE(rela->r_info);
+               if (type == R_TYPE(NONE))
+                       continue;
+
+               /* We do JMP_SLOTs in _rtld_bind() below */
+               if (type == R_TYPE(JMP_SLOT))
+                       continue;
+
+               /* COPY relocs are also handled elsewhere */
+               if (type == R_TYPE(COPY))
+                       continue;
+
+               /*
+                * We use the fact that relocation types are an `enum'
+                * Note: R_SPARC_UA16 is currently numerically largest.
+                */
+               if (type > R_TYPE(UA16))
+                       return (-1);
+
+               value = rela->r_addend;
+
+               /*
+                * Handle relative relocs here, as an optimization.
+                */
+               if (type == R_TYPE(RELATIVE)) {
+                       *where = (Elf_Addr)(obj->relocbase + value);
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)*where));
+                       continue;
+               }
+
+               if (RELOC_RESOLVE_SYMBOL(type)) {
+
+                       /* Find the symbol */
+                       def = _rtld_find_symdef(symnum, obj, &defobj,
+                           false);
+                       if (def == NULL)
+                               return -1;
+
+                       /* Add in the symbol's absolute address */
+                       value += (Elf_Addr)(defobj->relocbase + def->st_value);
+               }
+
+               if (RELOC_PC_RELATIVE(type)) {
+                       value -= (Elf_Addr)where;
+               }
+
+               if (RELOC_BASE_RELATIVE(type)) {
+                       /*
+                        * Note that even though sparcs use `Elf_rela'
+                        * exclusively we still need the implicit memory addend
+                        * in relocations referring to GOT entries.
+                        * Undoubtedly, someone f*cked this up in the distant
+                        * past, and now we're stuck with it in the name of
+                        * compatibility for all eternity..
+                        *
+                        * In any case, the implicit and explicit should be
+                        * mutually exclusive. We provide a check for that
+                        * here.
+                        */
+#ifdef DIAGNOSTIC
+                       if (value != 0 && *where != 0) {
+                               xprintf("BASE_REL(%s): where=%p, *where 0x%lx, "
+                                       "addend=0x%lx, base %p\n",
+                                       obj->path, where, *where,
+                                       rela->r_addend, obj->relocbase);
+                       }
+#endif
+                       /* XXXX -- apparently we ignore the preexisting value */
+                       value += (Elf_Addr)(obj->relocbase);
+               }
+
+               mask = RELOC_VALUE_BITMASK(type);
+               value >>= RELOC_VALUE_RIGHTSHIFT(type);
+               value &= mask;
+
+               if (RELOC_UNALIGNED(type)) {
+                       /* Handle unaligned relocations. */
+                       Elf_Addr tmp = 0;
+                       char *ptr = (char *)where;
+                       int i, size = RELOC_TARGET_SIZE(type)/8;
+
+                       /* Read it in one byte at a time. */
+                       for (i=0; i<size; i++)
+                               tmp = (tmp << 8) | ptr[i];
+
+                       tmp &= ~mask;
+                       tmp |= value;
+
+                       /* Write it back out. */
+                       for (i=0; i<size; i++)
+                               ptr[i] = ((tmp >> (8*i)) & 0xff);
+#ifdef RTLD_DEBUG_RELOC
+                       value = (Elf_Addr)tmp;
+#endif
+
+               } else if (RELOC_TARGET_SIZE(type) > 32) {
+                       *where &= ~mask;
+                       *where |= value;
+#ifdef RTLD_DEBUG_RELOC
+                       value = (Elf_Addr)*where;
+#endif
+               } else {
+                       Elf32_Addr *where32 = (Elf32_Addr *)where;
+
+                       *where32 &= ~mask;
+                       *where32 |= value;
+#ifdef RTLD_DEBUG_RELOC
+                       value = (Elf_Addr)*where32;
+#endif
+               }
+
+#ifdef RTLD_DEBUG_RELOC
+               if (RELOC_RESOLVE_SYMBOL(type)) {
+                       rdbg(("%s %s in %s --> %p in %s", reloc_names[type],
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)value, defobj->path));
+               } else {
+                       rdbg(("%s in %s --> %p", reloc_names[type],
+                           obj->path, (void *)value));
+               }
+#endif
+       }
+       return (0);
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       return (0);
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rela *rela = obj->pltrela + reloff;
+       Elf_Addr result;
+       int err;
+
+       result = 0;     /* XXX gcc */
+
+       if (ELF_R_TYPE(obj->pltrela->r_info) == R_TYPE(JMP_SLOT)) {
+               /*
+                * XXXX
+                *
+                * The first four PLT entries are reserved.  There is some
+                * disagreement whether they should have associated relocation
+                * entries.  Both the SPARC 32-bit and 64-bit ELF
+                * specifications say that they should have relocation entries,
+                * but the 32-bit SPARC binutils do not generate them, and now
+                * the 64-bit SPARC binutils have stopped generating them too.
+                * 
+                * So, to provide binary compatibility, we will check the first
+                * entry, if it is reserved it should not be of the type
+                * JMP_SLOT.  If it is JMP_SLOT, then the 4 reserved entries
+                * were not generated and our index is 4 entries too far.
+                */
+               rela -= 4;
+       }
+
+       err = _rtld_relocate_plt_object(obj, rela, &result);
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)result;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       rela = obj->pltrela;
+
+       /*
+        * Check for first four reserved entries - and skip them.
+        * See above for details.
+        */
+       if (ELF_R_TYPE(obj->pltrela->r_info) != R_TYPE(JMP_SLOT))
+               rela += 4;
+
+       for (; rela < obj->pltrelalim; rela++)
+               if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
+                       return -1;
+
+       return 0;
+}
+
+/*
+ * New inline function that is called by _rtld_relocate_plt_object and
+ * _rtld_bind
+ */
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
+    Elf_Addr *tp)
+{
+       Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
+       const Elf_Sym *def;
+       const Obj_Entry *defobj;
+       Elf_Addr value, offset;
+       unsigned long info = rela->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       rdbg(("bind now/fixup in %s --> new=%p", 
+           defobj->strtab + def->st_name, (void *)value));
+
+       /*
+        * At the PLT entry pointed at by `where', we now construct a direct
+        * transfer to the now fully resolved function address.
+        *
+        * A PLT entry is supposed to start by looking like this:
+        *
+        *      sethi   %hi(. - .PLT0), %g1
+        *      ba,a    %xcc, .PLT1
+        *      nop
+        *      nop
+        *      nop
+        *      nop
+        *      nop
+        *      nop
+        *
+        * When we replace these entries we start from the last instruction
+        * and do it in reverse order so the last thing we do is replace the
+        * branch.  That allows us to change this atomically.
+        *
+        * We now need to find out how far we need to jump.  We have a choice
+        * of several different relocation techniques which are increasingly
+        * expensive.
+        */
+
+       offset = ((Elf_Addr)where) - value;
+       if (rela->r_addend) {
+               Elf_Addr *ptr = (Elf_Addr *)where;
+               /*
+                * This entry is >= 32768.  The relocations points to a
+                * PC-relative pointer to the bind_0 stub at the top of the
+                * PLT section.  Update it to point to the target function.
+                */
+               ptr[0] += value - (Elf_Addr)obj->pltgot;
+
+       } else if (offset <= (1L<<20) && (Elf_SOff)offset >= -(1L<<20)) {
+               /* 
+                * We're within 1MB -- we can use a direct branch insn.
+                *
+                * We can generate this pattern:
+                *
+                *      sethi   %hi(. - .PLT0), %g1
+                *      ba,a    %xcc, addr
+                *      nop
+                *      nop
+                *      nop
+                *      nop
+                *      nop
+                *      nop
+                *
+                */
+               where[1] = BAA | ((offset >> 2) & 0x3fffff);
+               __asm volatile("iflush %0+4" : : "r" (where));
+       } else if (value < (1L<<32)) {
+               /* 
+                * We're within 32-bits of address zero.
+                *
+                * The resulting code in the jump slot is:
+                *
+                *      sethi   %hi(. - .PLT0), %g1
+                *      sethi   %hi(addr), %g1
+                *      jmp     %g1+%lo(addr)
+                *      nop
+                *      nop
+                *      nop
+                *      nop
+                *      nop
+                *
+                */
+               where[2] = JMP   | LOVAL(value, 0);
+               where[1] = SETHI | HIVAL(value, 10);
+               __asm volatile("iflush %0+8" : : "r" (where));
+               __asm volatile("iflush %0+4" : : "r" (where));
+
+       } else if ((Elf_SOff)value <= 0 && (Elf_SOff)value > -(1L<<32)) {
+               /* 
+                * We're within 32-bits of address -1.
+                *
+                * The resulting code in the jump slot is:
+                *
+                *      sethi   %hi(. - .PLT0), %g1
+                *      sethi   %hix(addr), %g1
+                *      xor     %g1, %lox(addr), %g1
+                *      jmp     %g1
+                *      nop
+                *      nop
+                *      nop
+                *      nop
+                *
+                */
+               where[3] = JMP;
+               where[2] = XOR | ((~value) & 0x00001fff);
+               where[1] = SETHI | HIVAL(~value, 10);
+               __asm volatile("iflush %0+12" : : "r" (where));
+               __asm volatile("iflush %0+8" : : "r" (where));
+               __asm volatile("iflush %0+4" : : "r" (where));
+
+       } else if (offset <= (1L<<32) && (Elf_SOff)offset >= -((1L<<32) - 4)) {
+               /* 
+                * We're within 32-bits -- we can use a direct call insn 
+                *
+                * The resulting code in the jump slot is:
+                *
+                *      sethi   %hi(. - .PLT0), %g1
+                *      mov     %o7, %g1
+                *      call    (.+offset)
+                *       mov    %g1, %o7
+                *      nop
+                *      nop
+                *      nop
+                *      nop
+                *
+                */
+               where[3] = MOV17;
+               where[2] = CALL   | ((offset >> 4) & 0x3fffffff);
+               where[1] = MOV71;
+               __asm volatile("iflush %0+12" : : "r" (where));
+               __asm volatile("iflush %0+8" : : "r" (where));
+               __asm volatile("iflush %0+4" : : "r" (where));
+
+       } else if (offset < (1L<<44)) {
+               /* 
+                * We're within 44 bits.  We can generate this pattern:
+                *
+                * The resulting code in the jump slot is:
+                *
+                *      sethi   %hi(. - .PLT0), %g1
+                *      sethi   %h44(addr), %g1
+                *      or      %g1, %m44(addr), %g1
+                *      sllx    %g1, 12, %g1    
+                *      jmp     %g1+%l44(addr)  
+                *      nop
+                *      nop
+                *      nop
+                *
+                */
+               where[4] = JMP   | LOVAL(offset, 0);
+               where[3] = SLLX  | 12;
+               where[2] = OR    | (((offset) >> 12) & 0x00001fff);
+               where[1] = SETHI | HIVAL(offset, 22);
+               __asm volatile("iflush %0+16" : : "r" (where));
+               __asm volatile("iflush %0+12" : : "r" (where));
+               __asm volatile("iflush %0+8" : : "r" (where));
+               __asm volatile("iflush %0+4" : : "r" (where));
+
+       } else if ((Elf_SOff)offset < 0 && (Elf_SOff)offset > -(1L<<44)) {
+               /* 
+                * We're within 44 bits.  We can generate this pattern:
+                *
+                * The resulting code in the jump slot is:
+                *
+                *      sethi   %hi(. - .PLT0), %g1
+                *      sethi   %h44(-addr), %g1
+                *      xor     %g1, %m44(-addr), %g1
+                *      sllx    %g1, 12, %g1    
+                *      jmp     %g1+%l44(addr)  
+                *      nop
+                *      nop
+                *      nop
+                *
+                */
+               where[4] = JMP   | LOVAL(offset, 0);
+               where[3] = SLLX  | 12;
+               where[2] = XOR   | (((~offset) >> 12) & 0x00001fff);
+               where[1] = SETHI | HIVAL(~offset, 22);
+               __asm volatile("iflush %0+16" : : "r" (where));
+               __asm volatile("iflush %0+12" : : "r" (where));
+               __asm volatile("iflush %0+8" : : "r" (where));
+               __asm volatile("iflush %0+4" : : "r" (where));
+
+       } else {
+               /* 
+                * We need to load all 64-bits
+                *
+                * The resulting code in the jump slot is:
+                *
+                *      sethi   %hi(. - .PLT0), %g1
+                *      sethi   %hh(addr), %g1
+                *      sethi   %lm(addr), %g5
+                *      or      %g1, %hm(addr), %g1
+                *      sllx    %g1, 32, %g1
+                *      or      %g1, %g5, %g1
+                *      jmp     %g1+%lo(addr)
+                *      nop
+                *
+                */
+               where[6] = JMP     | LOVAL(value, 0);
+               where[5] = ORG5;
+               where[4] = SLLX    | 32;
+               where[3] = OR      | LOVAL(value, 32);
+               where[2] = SETHIG5 | HIVAL(value, 10);
+               where[1] = SETHI   | HIVAL(value, 42);
+               __asm volatile("iflush %0+24" : : "r" (where));
+               __asm volatile("iflush %0+20" : : "r" (where));
+               __asm volatile("iflush %0+16" : : "r" (where));
+               __asm volatile("iflush %0+12" : : "r" (where));
+               __asm volatile("iflush %0+8" : : "r" (where));
+               __asm volatile("iflush %0+4" : : "r" (where));
+
+       }
+
+       if (tp)
+               *tp = value;
+
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/sparc64/rtld_start.S b/libexec/ld.elf_so/arch/sparc64/rtld_start.S
new file mode 100644 (file)
index 0000000..79171cc
--- /dev/null
@@ -0,0 +1,172 @@
+/*     $NetBSD: rtld_start.S,v 1.17 2008/04/28 20:23:04 martin Exp $   */
+
+/*-
+ * Copyright (c) 2000 Eduardo Horvath.
+ * Copyright (c) 1999, 2002, 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas, Paul Kranenburg and by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#define        _LOCORE
+#include <machine/frame.h>
+
+/*
+ * ELF:
+ *     On startup the stack should contain 16 extended word register save area,
+ *     followed by the arg count, etc.
+ *
+ * _rtld() expects the stack pointer to point to two longwords for argument
+ *     return followed by argc, etc.  We need to create a pointer to
+ *     &argc + 16 and pass that in.  The return args will be in those locations.
+ * 
+ * NB: We are violating the ELF spec by passing a pointer to the ps strings in
+ *     %g1 instead of a termination routine.
+ */
+
+       .register       %g2,#scratch
+       .register       %g3,#scratch
+
+/* Offset of ARGC from bottom of stack */
+#define        ARGC    176
+       
+       .section        ".text"
+       .align  4
+       .global _rtld_start
+       .type   _rtld_start,@function
+_rtld_start:
+       mov     0, %fp                  /* Erect a fence post for ourselves */
+       mov     %g1, %l1                /* save ps_strings */
+       sub     %sp, 48+16, %sp         /* Make room for return args */
+
+       sethi   %hi(_GLOBAL_OFFSET_TABLE_-4), %l7
+       call    0f
+        add    %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7
+       call    _DYNAMIC+8
+0:     add     %l7, %o7, %l7           /* real &_GLOBAL_OFFSET_TABLE_ */
+       ld      [%o7+8], %o0            /* load stub call instruction */
+       ldx     [%l7], %l0              /* base-relative &_DYNAMIC */
+       sll     %o0, 2, %o0             /* extract PC offset */
+       sra     %o0, 0, %o0             /* sign-extend */
+
+       add     %o0, %o7, %o0           /* real &_DYNAMIC */
+       sub     %o0, %l0, %l0           /* relocbase */
+       call    _rtld_relocate_nonplt_self
+        mov    %l0, %o1                /* relocbase */
+
+       mov     %l0, %o1                /* relocbase */
+       call    _rtld
+        add    %sp, BIAS + ARGC, %o0   /* &argc - 16 */
+
+       ldx     [%sp + BIAS + ARGC], %g3        /* arg: cleanup */
+       ldx     [%sp + BIAS + ARGC + 8], %g2    /* arg: obj */
+       add     %sp, 48+16, %sp         /* restore stack pointer */
+
+       jmp     %o0
+        mov    %l1, %g1                /* restore ps_strings */
+
+
+       /*
+        * We have two separate entry points to the runtime linker.
+        * I'm implementing this following the SPARC v9 ABI spec.
+        *
+        * _rtld_bind_start_0(y, x) is called from .PLT0, and is used for
+        * PLT entries above 32768.
+        *
+        * _rtld_bind_start_1(y, x) is called from .PLT1, and is used for
+        * PLT entries below 32768.
+        *
+        * The first two entries of PLT2 contain the xword object pointer.
+        *
+        * These routines are called with two longword arguments, 
+        * x and y.  To calculate the address of the entry,
+        * _rtld_bind_start_1(y, x) does:
+        *
+        *      n = x >> 15;
+        *
+        * and _rtld_bind_start_0(y, x) does:
+        *
+        *      i = x - y + 8 - 32768*32;
+        *      n = 32768 + (i/5120)*160 + (i%5120)/24;
+        *
+        * Neither routine needs to issue a save since it's already been
+        * done in the PLT entry.
+        */
+
+       .section        ".text"
+       .align  4
+       .global _rtld_bind_start_0
+       .type   _rtld_bind_start_0,@function
+_rtld_bind_start_0:    # (y, x)
+       /* %o0 = obj->pltgot[6] */
+       /* %o1 = plt[4] */
+       /* %o1 - %o0 + 8 == offset of plt[] from obj->pltgot[] */
+       /* -32768*32 to get offset from beginning of upper PLT section */
+
+       sethi   %hi(32768*32-8), %l1
+       sub     %o1, %o0, %l0           /* i = x - y */
+       or      %l1, %lo(32768*32-8), %l1
+       sub     %l0, %l1, %l0           /* i = x - y + 8 - 32768*32 */
+
+       ldx     [%o0 + (10*4)], %o0     /* Load object pointer from PLT2 */
+
+       sethi   %hi(5120), %l1
+       sdivx   %l0, %l1, %l1           /* Calculate i/5120 */
+       sllx    %l1, 2, %l2
+       add     %l2, %l1, %l2
+       sllx    %l2, 10, %l2
+       sub     %l0, %l2, %l2           /* And i%5120 */
+       
+       /* Let the division churn for a bit. */
+       sdivx   %l2, 24, %l4            /* (i%5120)/24 */
+
+       /* 160 is (32 * 5) or (32 * (4 + 1)) */
+       sllx    %l1, 2, %l3             /* 4 * (i/5120) */
+       add     %l1, %l3, %l3           /* 5 * (i/5120) */
+       sllx    %l3, 5, %l3             /* 32 * 5 * (i/5120) */
+
+       sethi   %hi(32768), %l6
+       add     %l3, %l4, %l5           /* %l5 = (i/5120)*160 + (i%5120)/24; */
+       
+       call    _rtld_bind              /* Call _rtld_bind(obj, offset) */
+        add    %l5, %l6, %o1           /* %o1 = 32768 + ... */
+
+       jmp     %o0                     /* return value == function address */
+        restore                        /* Dump our stack frame */
+       
+       .section        ".text"
+       .align  4
+       .global _rtld_bind_start_1
+       .type   _rtld_bind_start_1,@function
+_rtld_bind_start_1:    # (y, x)
+       ldx     [%o0 + (2*4)], %o0      /* Load object pointer from PLT2 */
+       
+       call    _rtld_bind              /* Call _rtld_bind(obj, offset) */
+        srax   %o1, 15, %o1            /* %o1 is the index to our PLT slot */
+
+       jmp     %o0                     /* return value == function address */
+        restore                        /* Dump our stack frame */
+
diff --git a/libexec/ld.elf_so/arch/vax/Makefile.inc b/libexec/ld.elf_so/arch/vax/Makefile.inc
new file mode 100644 (file)
index 0000000..bf52eb7
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile.inc,v 1.11 2009/09/19 14:54:17 skrll Exp $
+
+SRCS+=         rtld_start.S mdreloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fpic
+
+CPPFLAGS+=     -DELFSIZE=32
+
+LDFLAGS+=      -Wl,-Bsymbolic -Wl,-e,_rtld_start
diff --git a/libexec/ld.elf_so/arch/vax/mdreloc.c b/libexec/ld.elf_so/arch/vax/mdreloc.c
new file mode 100644 (file)
index 0000000..a7b99e6
--- /dev/null
@@ -0,0 +1,207 @@
+/*     $NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:19 joerg Exp $       */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:19 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:19 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+void _rtld_bind_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+static inline int _rtld_relocate_plt_object(const Obj_Entry *,
+    const Elf_Rela *, Elf_Addr *);
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       obj->pltgot[1] = (Elf_Addr) obj;
+       obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rela *rela = 0, *relalim;
+       Elf_Addr relasz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_RELA:
+                       rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
+       for (; rela < relalim; rela++) {
+               where = (Elf_Addr *)(relocbase + rela->r_offset);
+               *where = (Elf_Addr)(relocbase + rela->r_addend);
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->rela; rela < obj->relalim; rela++) {
+               Elf_Addr        *where;
+               const Elf_Sym   *def;
+               const Obj_Entry *defobj;
+               Elf_Addr         tmp;
+               unsigned long    symnum;
+
+               where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+               symnum = ELF_R_SYM(rela->r_info);
+
+               switch (ELF_R_TYPE(rela->r_info)) {
+               case R_TYPE(NONE):
+                       break;
+
+               case R_TYPE(32):        /* word32 S + A */
+               case R_TYPE(GLOB_DAT):  /* word32 S + A */
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
+                           rela->r_addend);
+
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("32/GLOB_DAT %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(RELATIVE):  /* word32 B + A */
+                       tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
+                       if (*where != tmp)
+                               *where = tmp;
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)*where));
+                       break;
+
+               case R_TYPE(COPY):
+                       /*
+                        * These are deferred until all other relocations have
+                        * been done.  All we do here is make sure that the
+                        * COPY relocation is not in a shared library.  They
+                        * are allowed only in executable files.
+                        */
+                       if (obj->isdynamic) {
+                               _rtld_error(
+                       "%s: Unexpected R_COPY relocation in shared library",
+                                   obj->path);
+                               return -1;
+                       }
+                       rdbg(("COPY (avoid in main)"));
+                       break;
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "addend = %p, contents = %p, symbol = %s",
+                           symnum, (u_long)ELF_R_TYPE(rela->r_info),
+                           (void *)rela->r_offset, (void *)rela->r_addend,
+                           (void *)*where,
+                           obj->strtab + obj->symtab[symnum].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rela->r_info));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       if (!obj->relocbase)
+               return 0;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
+               Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+
+               assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
+
+               /* Just relocate the GOT slots pointing into the PLT */
+               *where += (Elf_Addr)obj->relocbase;
+               rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
+       }
+
+       return 0;
+}
+
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp)
+{
+       Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+       Elf_Addr new_value;
+       const Elf_Sym  *def;
+       const Obj_Entry *defobj;
+       unsigned long info = rela->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
+           rela->r_addend);
+       rdbg(("bind now/fixup in %s --> old=%p new=%p",
+           defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
+       if (*where != new_value)
+               *where = new_value;
+
+       if (tp)
+               *tp = new_value - rela->r_addend;
+
+       return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff);
+       Elf_Addr result;
+       int err;
+
+       result = 0;     /* XXX gcc */
+
+       err = _rtld_relocate_plt_object(obj, rela, &result);
+       if (err)
+               _rtld_die();
+
+       return (caddr_t)result;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++)
+               if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
+                       return -1;
+
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/vax/rtld_start.S b/libexec/ld.elf_so/arch/vax/rtld_start.S
new file mode 100644 (file)
index 0000000..6f5fc70
--- /dev/null
@@ -0,0 +1,78 @@
+/*     $NetBSD: rtld_start.S,v 1.16 2003/03/02 22:03:40 mycroft Exp $  */
+
+/*
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * Portions copyright 2002, 2003 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+/* R9 contains the address of PS_STRINGS and since its caller saved,
+ * we can just use it.  R6 has a backup copy of the stack pointer which
+ * we can use as well.
+ */
+ENTRY(_rtld_start, 0)
+       /* Allocate space on the stack for the cleanup and obj_main
+        * entries that _rtld() will provide for us.
+        */
+       clrl    %fp
+       subl2   $8,%sp
+
+       movab   _DYNAMIC,%r0
+       subl3   _GLOBAL_OFFSET_TABLE_,%r0,%r10
+       pushl   %r10            /* relocbase */
+       pushl   %r0             /* &_DYNAMIC */
+       calls   $2,_rtld_relocate_nonplt_self
+
+       pushl   %r10            /* relocbase */
+       pushal  4(%sp)          /* sp */
+       calls   $2,_rtld        /* entry = _rtld(sp, relocbase) */
+
+       movq    (%sp)+,%r7      /* grab cleanup and obj_main into %r7/%r8 */
+       jmp     2(%r0)          /* jump to entry point + 2 */
+
+/*
+ * Lazy binding entry point, called via PLT.
+ *
+ * Note: Some functions rely on there not being an additional call frame;
+ * hence the `optimization' to avoid the callg opportunistically.
+ */
+ALTENTRY(_rtld_bind_start)
+       pushr   $0x3f           /* save R0-R5 */
+       movq    24(%sp),%r0     /* get addresses of plt.got & reloc index */
+       pushl   (%r1)           /* push relocation index */
+       pushl   %r0             /* push address of obj entry */
+       calls   $2,_rtld_bind
+       movl    %r0,28(%sp)     /* save return address onto stack */
+       bicw3   6(%fp),(%r0),%r0/* does the entry mask save any additional regs */
+       popr    $0x3f           /* restore R0-R5 (cond flags not modified) */
+       bneq    4f              /* yes? do it the hard way */
+       addl2   $4,%sp          /* no? skip past plt.got on stack */
+       addl2   $2,(%sp)                /*    skip past the mask */
+       rsb                     /*    and jump to it */
+4:     addl2   $4,%sp
+       callg   (%ap),*(%sp)+   /* return value from _rtld_bind() == actual */
+       ret
diff --git a/libexec/ld.elf_so/arch/x86_64/Makefile.inc b/libexec/ld.elf_so/arch/x86_64/Makefile.inc
new file mode 100644 (file)
index 0000000..96d3660
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile.inc,v 1.7 2005/06/04 16:17:17 lukem Exp $
+
+SRCS+=         rtld_start.S mdreloc.c
+
+# XXX Should not be in CPPFLAGS!
+CPPFLAGS+=     -fPIC
+
+CPPFLAGS+=     -DELFSIZE=64
+
+LDFLAGS+=      -Wl,-e,.rtld_start
diff --git a/libexec/ld.elf_so/arch/x86_64/mdreloc.c b/libexec/ld.elf_so/arch/x86_64/mdreloc.c
new file mode 100644 (file)
index 0000000..b0ea285
--- /dev/null
@@ -0,0 +1,311 @@
+/*     $NetBSD: mdreloc.c,v 1.38 2010/08/06 16:33:19 joerg Exp $       */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed for the NetBSD Project by
+ *      Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.38 2010/08/06 16:33:19 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <elf.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+void _rtld_bind_start(void);
+void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
+caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+static inline int _rtld_relocate_plt_object(const Obj_Entry *,
+    const Elf_Rela *, Elf_Addr *);
+
+void
+_rtld_setup_pltgot(const Obj_Entry *obj)
+{
+       obj->pltgot[1] = (Elf_Addr) obj;
+       obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
+}
+
+void
+_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
+{
+       const Elf_Rela *rela = 0, *relalim;
+       Elf_Addr relasz = 0;
+       Elf_Addr *where;
+
+       for (; dynp->d_tag != DT_NULL; dynp++) {
+               switch (dynp->d_tag) {
+               case DT_RELA:
+                       rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
+                       break;
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+               }
+       }
+       /*
+        * Assume only 64-bit relocations here, which should always
+        * be true for the dynamic linker.
+        */
+       relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
+       for (; rela < relalim; rela++) {
+               where = (Elf_Addr *)(relocbase + rela->r_offset);
+               *where = (Elf_Addr)(relocbase + rela->r_addend);
+       }
+}
+
+int
+_rtld_relocate_nonplt_objects(Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+       const Elf_Sym *def = NULL;
+       const Obj_Entry *defobj =NULL;
+
+       for (rela = obj->rela; rela < obj->relalim; rela++) {
+               Elf64_Addr *where64;
+               Elf32_Addr *where32;
+               Elf64_Addr tmp64;
+               Elf32_Addr tmp32;
+               unsigned long    symnum;
+
+               where64 = (Elf64_Addr *)(obj->relocbase + rela->r_offset);
+               where32 = (Elf32_Addr *)where64;
+               symnum = ELF_R_SYM(rela->r_info);
+
+               switch (ELF_R_TYPE(rela->r_info)) {
+               case R_TYPE(NONE):
+                       break;
+
+               case R_TYPE(32):        /* word32 S + A, truncate */
+               case R_TYPE(32S):       /* word32 S + A, signed truncate */
+               case R_TYPE(GOT32):     /* word32 G + A (XXX can we see these?) */
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase +
+                           def->st_value + rela->r_addend);
+
+                       if (*where32 != tmp32)
+                               *where32 = tmp32;
+                       rdbg(("32/32S %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)(unsigned long)*where32,
+                           defobj->path));
+                       break;
+               case R_TYPE(64):        /* word64 S + A */
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value +
+                           rela->r_addend);
+
+                       if (*where64 != tmp64)
+                               *where64 = tmp64;
+                       rdbg(("64 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where64, defobj->path));
+                       break;
+               case R_TYPE(PC32):      /* word32 S + A - P */
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase +
+                           def->st_value + rela->r_addend -
+                           (Elf64_Addr)where64);
+                       if (*where32 != tmp32)
+                               *where32 = tmp32;
+                       rdbg(("PC32 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)(unsigned long)*where32,
+                           defobj->path));
+                       break;
+               case R_TYPE(GLOB_DAT):  /* word64 S */
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+                       tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value);
+
+                       if (*where64 != tmp64)
+                               *where64 = tmp64;
+                       rdbg(("64 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where64, defobj->path));
+                       break;
+               case R_TYPE(RELATIVE):  /* word64 B + A */
+                       tmp64 = (Elf64_Addr)(obj->relocbase + rela->r_addend);
+                       if (*where64 != tmp64)
+                               *where64 = tmp64;
+                       rdbg(("RELATIVE in %s --> %p", obj->path,
+                           (void *)*where64));
+                               break;
+
+               case R_TYPE(COPY):
+                       rdbg(("COPY"));
+                       break;
+
+               default:
+                       rdbg(("sym = %lu, type = %lu, offset = %p, "
+                           "addend = %p, contents = %p, symbol = %s",
+                           symnum, (u_long)ELF_R_TYPE(rela->r_info),
+                           (void *)rela->r_offset, (void *)rela->r_addend,
+                           (void *)*where64,
+                           obj->strtab + obj->symtab[symnum].st_name));
+                       _rtld_error("%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           obj->path, (u_long) ELF_R_TYPE(rela->r_info));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+_rtld_relocate_plt_lazy(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       if (!obj->relocbase)
+               return 0;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
+               Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+
+               assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT));
+
+               /* Just relocate the GOT slots pointing into the PLT */
+               *where += (Elf_Addr)obj->relocbase;
+               rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
+       }
+
+       return 0;
+}
+
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp)
+{
+       Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+       Elf_Addr new_value;
+       const Elf_Sym  *def;
+       const Obj_Entry *defobj;
+       unsigned long info = rela->r_info;
+
+       assert(ELF_R_TYPE(info) == R_TYPE(JUMP_SLOT));
+
+       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
+       if (__predict_false(def == NULL))
+               return -1;
+       if (__predict_false(def == &_rtld_sym_zero))
+               return 0;
+
+       new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
+           rela->r_addend);
+       rdbg(("bind now/fixup in %s --> old=%p new=%p", 
+           defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
+       if (*where != new_value)
+               *where = new_value;
+
+       if (tp)
+               *tp = new_value - rela->r_addend;
+
+       return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+       const Elf_Rela *rela = obj->pltrela + reloff;
+       Elf_Addr new_value;
+       int error;
+
+       new_value = 0; /* XXX GCC4 */
+
+       error = _rtld_relocate_plt_object(obj, rela, &new_value);
+       if (error)
+               _rtld_die();
+
+       return (caddr_t)new_value;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+       const Elf_Rela *rela;
+
+       for (rela = obj->pltrela; rela < obj->pltrelalim; rela++)
+               if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
+                       return -1;
+
+       return 0;
+}
diff --git a/libexec/ld.elf_so/arch/x86_64/rtld_start.S b/libexec/ld.elf_so/arch/x86_64/rtld_start.S
new file mode 100644 (file)
index 0000000..d154e94
--- /dev/null
@@ -0,0 +1,105 @@
+/*     $NetBSD: rtld_start.S,v 1.8 2010/12/05 00:56:07 joerg Exp $     */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed for the NetBSD Project by
+ *      Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+       .text
+       .align  16
+       .globl  .rtld_start
+       .hidden .rtld_start
+       .type   .rtld_start,@function
+.rtld_start:
+       subq    $16,%rsp                # make room of obj_main and exit proc
+       movq    %rsp,%r12               # stack pointer arg to _rtld
+       pushq   %rbx                    # save ps_strings
+
+       leaq    _GLOBAL_OFFSET_TABLE_(%rip),%rax
+       leaq    _DYNAMIC(%rip),%rdi     # &_DYNAMIC
+       movq    %rdi,%rbx
+       subq    (%rax),%rbx             # relocbase
+
+       movq    %rbx,%rsi
+       call    _rtld_relocate_nonplt_self
+
+       movq    %r12,%rdi
+       movq    %rbx,%rsi
+       call    _rtld                   # _rtld(sp, relocbase)
+
+       popq    %rbx                    # %rbx = ps_strings
+       popq    %rdx                    # %rdx = cleanup
+       popq    %rcx                    # %rcx = obj_main
+       jmp     *%rax
+
+       .align  4
+       .globl  _rtld_bind_start
+       .hidden _rtld_bind_start
+       .type   _rtld_bind_start,@function
+_rtld_bind_start:      # (obj, reloff)
+       # This function is called with a misaligned stack from the PLT
+       # due to the additional argument pushed.
+       # At this point %rsp % 16 == 8.
+       pushfq                          # save caller-saved registers
+       pushq   %rax
+       pushq   %rcx
+       pushq   %rdx
+       pushq   %rsi
+       pushq   %rdi
+       pushq   %r8
+       pushq   %r9
+       pushq   %r10
+       pushq   %r11
+
+       movq    80(%rsp),%rdi
+       movq    88(%rsp),%rsi
+
+       call    _rtld_bind              # call the binder
+       movq    %rax,88(%rsp)           # store function in obj
+
+       popq    %r11
+       popq    %r10
+       popq    %r9
+       popq    %r8
+       popq    %rdi
+       popq    %rsi
+       popq    %rdx
+       popq    %rcx
+       popq    %rax
+       popfq
+
+       leaq    8(%rsp),%rsp
+
+       ret
similarity index 52%
rename from lib/csu/i386-elf/crt1_c.c
rename to libexec/ld.elf_so/debug.c
index f60e8b64f1d5b7ee265807c3f2249499e25c9fec..e8af26ec51e505675e3f11467d755237dc304c6a 100644 (file)
@@ -1,6 +1,8 @@
-/* LINTLIBRARY */
-/*-
- * Copyright 1996-1998 John D. Polstra.
+/*     $NetBSD: debug.c,v 1.6 2004/10/22 05:39:56 skrll Exp $  */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
  */
 
-#ifndef lint
-#ifndef __GNUC__
-#error "GCC is needed to compile this file"
-#endif
-#endif /* lint */
-
-#include <stdlib.h>
-
-extern int _DYNAMIC;
-#pragma weak _DYNAMIC
-
-typedef void (*fptr)(void);
-
-extern void _fini(void);
-extern void _init(void);
-extern int main(int, char **, char **);
-extern void _start(char *, ...);
+/*
+ * Support for printing debugging messages.
+ */
 
-#ifdef GCRT
-extern void _mcleanup(void);
-extern void monstartup(void *, void *);
-extern int eprol;
-extern int etext;
-#endif
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: debug.c,v 1.6 2004/10/22 05:39:56 skrll Exp $");
+#endif /* not lint */
 
-char **environ;
-const char *__progname = "";
+#include <stdarg.h>
 
-char ***_penviron;
+#include "debug.h"
+#include "rtldenv.h"
 
-__dead void _start1(fptr, int, char *[]);
+#ifdef DEBUG
+int debug = 0;
 
-/* The entry function, C part. */
-__dead void
-_start1(fptr cleanup, int argc, char *argv[])
+void
+debug_printf(const char *format, ...)
 {
-       char **env;
-       const char *s;
 
-       _penviron = &environ;
+       if (debug) {
+               va_list ap;
 
-       env = argv + argc + 1;
-       environ = env;
-       if (argc > 0 && argv[0] != NULL) {
-               __progname = argv[0];
-               for (s = __progname; *s != '\0'; s++)
-                       if (*s == '/')
-                               __progname = s + 1;
+               va_start(ap, format);
+               xvprintf(format, ap);
+               va_end(ap);
+               xprintf("\n");
        }
-
-#if 0
-       if (&_DYNAMIC != NULL)
-               atexit(cleanup);
-       else
-               _init_tls();
-#endif
-
-#ifdef GCRT
-       atexit(_mcleanup);
-#endif
-       atexit(_fini);
-#ifdef GCRT
-       monstartup(&eprol, &etext);
-__asm__("eprol:");
-#endif
-       _init();
-       exit( main(argc, argv, env) );
 }
-
-__asm(".hidden _start1");
+#endif
similarity index 58%
rename from lib/csu/i386-elf/crt1_s.S
rename to libexec/ld.elf_so/debug.h
index e101330e29a5b52dbd4d1955607e8c5953db71f5..f4abc12a4d643d609ad201f2d960f799457c6eb0 100644 (file)
@@ -1,5 +1,8 @@
-/*-
- * Copyright 2009 Konstantin Belousov.
+/*     $NetBSD: debug.h,v 1.5 2002/09/12 22:56:28 mycroft Exp $        */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
  */
 
+/*
+ * Support for printing debugging messages.
+ */
+
+#ifndef DEBUG_H 
+#define DEBUG_H
+
+
+#ifdef DEBUG
+
+extern void debug_printf __P((const char *, ...))
+    __attribute__((__format__(__printf__, 1, 2)));
+extern int debug;
+
+# define dbg(a)                debug_printf a
+#else 
+# define dbg(a)                ((void) 0)
+#endif
+#ifdef RTLD_DEBUG_RELOC
+# define rdbg(a)       debug_printf a
+#else
+# define rdbg(a)       ((void) 0)
+#endif
 
-       .text
-       .align  4
-       .globl  _start
-       .type   _start, @function
-_start:
-       .cfi_startproc
-       xorl    %ebp,%ebp
-       pushl   %ebp
-       .cfi_def_cfa_offset 4
-       movl    %esp,%ebp
-       .cfi_offset %ebp,-8
-       .cfi_def_cfa_register %ebp
-       andl    $0xfffffff0,%esp # align stack
-       leal    8(%ebp),%eax
-       pushl   %eax            # argv
-       pushl   4(%ebp)         # argc
-       pushl   %edx            # rtld cleanup
-       call    _start1
-       int3
-       .cfi_endproc
-       .size   _start, . - _start
-
-       .ident  "$MINIX$"
+#endif
diff --git a/libexec/ld.elf_so/expand.c b/libexec/ld.elf_so/expand.c
new file mode 100644 (file)
index 0000000..3be194d
--- /dev/null
@@ -0,0 +1,172 @@
+/*     $NetBSD: expand.c,v 1.5 2008/04/28 20:23:03 martin Exp $        */
+
+/*-
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: expand.c,v 1.5 2008/04/28 20:23:03 martin Exp $");
+#endif /* not lint */
+
+#include <ctype.h>
+#include <string.h>
+#include <sys/sysctl.h>
+
+#ifdef DEBUG_EXPAND
+#include <stdio.h>
+#include <err.h>
+#define xwarn warn
+#define xerr err
+size_t _rtld_expand_path(char *, size_t, const char *, const char *,
+    const char *);
+#else
+#include <sys/stat.h>
+#include "rtld.h"
+#endif
+
+static const struct {
+       const char *name;
+       size_t namelen;
+} bltn[] = {
+#define ADD(a) { #a, sizeof(#a) - 1 },
+       ADD(HWCAP)      /* SSE, MMX, etc */
+       ADD(ISALIST)    /* XXX */
+       ADD(ORIGIN)     /* dirname argv[0] */
+       ADD(OSNAME)     /* uname -s */
+       ADD(OSREL)      /* uname -r */
+       ADD(PLATFORM)   /* uname -p */
+};
+
+static int mib[3][2] = {
+       { CTL_KERN, KERN_OSTYPE },
+       { CTL_KERN, KERN_OSRELEASE },
+       { CTL_HW, HW_MACHINE_ARCH },
+};
+
+static size_t
+expand(char *buf, const char *execname, int what, size_t bl)
+{
+       const char *p, *ep;
+       char *bp = buf;
+       size_t len;
+       char name[32];
+
+       switch (what) {
+       case 0: /* HWCAP XXX: Not yet */
+       case 1: /* ISALIST XXX: Not yet */
+               return 0;
+
+       case 2: /* ORIGIN */
+               if (execname == NULL)
+                       xerr(1, "execname not specified in AUX vector");
+               if ((ep = strrchr(p = execname, '/')) == NULL)
+                       xerr(1, "bad execname `%s' in AUX vector", execname);
+               break;
+
+       case 3: /* OSNAME */
+       case 4: /* OSREL */
+       case 5: /* PLATFORM */
+               len = sizeof(name);     
+               if (sysctl(mib[what - 3], 2, name, &len, NULL, 0) == -1) {
+                       xwarn("sysctl");
+                       return 0;
+               }
+               ep = (p = name) + len - 1;
+               break;
+       default:
+               return 0;
+       }
+
+       while (p != ep && bl)
+               *bp++ = *p++, bl--;
+
+       return bp - buf;
+}
+               
+
+size_t
+_rtld_expand_path(char *buf, size_t bufsize, const char *execname,
+    const char *bp, const char *ep)
+{
+       size_t i, ds = bufsize;
+       char *dp = buf;
+       const char *p;
+       int br;
+
+       for (p = bp; p < ep;) {
+               if (*p == '$') {
+                       br = *++p == '{';
+
+                       if (br)
+                               p++;
+
+                       for (i = 0; i < sizeof(bltn) / sizeof(bltn[0]); i++) {
+                               size_t s = bltn[i].namelen;
+                               const char *es = p + s;
+
+                               if ((br && *es != '}') ||
+                                   (!br && (es != ep &&
+                                       isalpha((unsigned char)*es))))
+                                       continue;
+
+                               if (strncmp(bltn[i].name, p, s) == 0) {
+                                       size_t ls = expand(dp, execname, i, ds);
+                                       if (ls >= ds)
+                                               return bufsize;
+                                       ds -= ls;
+                                       dp += ls;
+                                       p = es + br;
+                                       goto done;
+                               }
+                       }
+                       p -= br + 1;
+
+               }
+               *dp++ = *p++;
+               ds--;
+done:;
+       }
+       *dp = '\0';
+       return dp - buf;
+}
+
+#ifdef DEBUG_EXPAND
+int
+main(int argc, char *argv[])
+{
+       char buf[1024];
+       size_t i;
+
+       for (i = 1; i < argc; i++) {
+               char *p = argv[i], *ep = argv[i] + strlen(p);
+               size_t n = _rtld_expand_path(buf, sizeof(buf), argv[0], p, ep);
+               printf("%s\n", buf);
+       }
+       return 0;
+}
+#endif
diff --git a/libexec/ld.elf_so/headers.c b/libexec/ld.elf_so/headers.c
new file mode 100644 (file)
index 0000000..0725530
--- /dev/null
@@ -0,0 +1,369 @@
+/*     $NetBSD: headers.c,v 1.39 2011/01/16 01:22:29 matt Exp $         */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * Copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp@polstra.com>.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: headers.c,v 1.39 2011/01/16 01:22:29 matt Exp $");
+#endif /* not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/bitops.h>
+#include <dirent.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+/*
+ * Process a shared object's DYNAMIC section, and save the important
+ * information in its Obj_Entry structure.
+ */
+void
+_rtld_digest_dynamic(const char *execname, Obj_Entry *obj)
+{
+       Elf_Dyn        *dynp;
+       Needed_Entry  **needed_tail = &obj->needed;
+       const Elf_Dyn  *dyn_rpath = NULL;
+       bool            use_pltrel = false;
+       bool            use_pltrela = false;
+       Elf_Addr        relsz = 0, relasz = 0;
+       Elf_Addr        pltrel = 0, pltrelsz = 0;
+       Elf_Addr        init = 0, fini = 0;
+
+       for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) {
+               switch (dynp->d_tag) {
+
+               case DT_REL:
+                       obj->rel = (const Elf_Rel *)
+                           (obj->relocbase + dynp->d_un.d_ptr);
+                       break;
+
+               case DT_RELSZ:
+                       relsz = dynp->d_un.d_val;
+                       break;
+
+               case DT_RELENT:
+                       assert(dynp->d_un.d_val == sizeof(Elf_Rel));
+                       break;
+
+               case DT_JMPREL:
+                       pltrel = dynp->d_un.d_ptr;
+                       break;
+
+               case DT_PLTRELSZ:
+                       pltrelsz = dynp->d_un.d_val;
+                       break;
+
+               case DT_RELA:
+                       obj->rela = (const Elf_Rela *)
+                           (obj->relocbase + dynp->d_un.d_ptr);
+                       break;
+
+               case DT_RELASZ:
+                       relasz = dynp->d_un.d_val;
+                       break;
+
+               case DT_RELAENT:
+                       assert(dynp->d_un.d_val == sizeof(Elf_Rela));
+                       break;
+
+               case DT_PLTREL:
+                       use_pltrel = dynp->d_un.d_val == DT_REL;
+                       use_pltrela = dynp->d_un.d_val == DT_RELA;
+                       assert(use_pltrel || use_pltrela);
+                       break;
+
+               case DT_SYMTAB:
+                       obj->symtab = (const Elf_Sym *)
+                               (obj->relocbase + dynp->d_un.d_ptr);
+                       break;
+
+               case DT_SYMENT:
+                       assert(dynp->d_un.d_val == sizeof(Elf_Sym));
+                       break;
+
+               case DT_STRTAB:
+                       obj->strtab = (const char *)
+                           (obj->relocbase + dynp->d_un.d_ptr);
+                       break;
+
+               case DT_STRSZ:
+                       obj->strsize = dynp->d_un.d_val;
+                       break;
+
+               case DT_HASH:
+                       {
+                               const Elf_Symindx *hashtab = (const Elf_Symindx *)
+                                   (obj->relocbase + dynp->d_un.d_ptr);
+
+                               if (hashtab[0] > UINT32_MAX)
+                                       obj->nbuckets = UINT32_MAX;
+                               else
+                                       obj->nbuckets = hashtab[0];
+                               obj->nchains = hashtab[1];
+                               obj->buckets = hashtab + 2;
+                               obj->chains = obj->buckets + obj->nbuckets;
+                               /*
+                                * Should really be in _rtld_relocate_objects,
+                                * but _rtld_symlook_obj might be used before.
+                                */
+                               if (obj->nbuckets) {
+                                       fast_divide32_prepare(obj->nbuckets,
+                                           &obj->nbuckets_m,
+                                           &obj->nbuckets_s1,
+                                           &obj->nbuckets_s2);
+                               }
+                       }
+                       break;
+
+               case DT_NEEDED:
+                       {
+                               Needed_Entry *nep = NEW(Needed_Entry);
+
+                               nep->name = dynp->d_un.d_val;
+                               nep->obj = NULL;
+                               nep->next = NULL;
+
+                               *needed_tail = nep;
+                               needed_tail = &nep->next;
+                       }
+                       break;
+
+               case DT_PLTGOT:
+                       obj->pltgot = (Elf_Addr *)
+                           (obj->relocbase + dynp->d_un.d_ptr);
+                       break;
+
+               case DT_TEXTREL:
+                       obj->textrel = true;
+                       break;
+
+               case DT_SYMBOLIC:
+                       obj->symbolic = true;
+                       break;
+
+               case DT_RPATH:
+                       /*
+                        * We have to wait until later to process this, because
+                        * we might not have gotten the address of the string
+                        * table yet.
+                        */
+                       dyn_rpath = dynp;
+                       break;
+
+               case DT_SONAME:
+                       /* Not used by the dynamic linker. */
+                       break;
+
+               case DT_INIT:
+                       init = dynp->d_un.d_ptr;
+                       break;
+
+               case DT_FINI:
+                       fini = dynp->d_un.d_ptr;
+                       break;
+
+               /*
+                * Don't process DT_DEBUG on MIPS as the dynamic section
+                * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
+                * XXX: n32/n64 may use DT_DEBUG, not sure yet.
+                */
+#ifndef __mips__
+               case DT_DEBUG:
+#ifdef RTLD_LOADER
+                       dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug;
+#endif
+                       break;
+#endif
+
+#ifdef __mips__
+               case DT_MIPS_LOCAL_GOTNO:
+                       obj->local_gotno = dynp->d_un.d_val;
+                       break;
+
+               case DT_MIPS_SYMTABNO:
+                       obj->symtabno = dynp->d_un.d_val;
+                       break;
+
+               case DT_MIPS_GOTSYM:
+                       obj->gotsym = dynp->d_un.d_val;
+                       break;
+
+               case DT_MIPS_RLD_MAP:
+#ifdef RTLD_LOADER
+                       *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr)
+                           &_rtld_debug;
+#endif
+                       break;
+#endif
+#ifdef __powerpc__
+               case DT_PPC_GOT:
+                       obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
+                       break;
+#endif
+               case DT_FLAGS_1:
+                       obj->z_now =
+                           ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0);
+                       obj->z_nodelete =
+                           ((dynp->d_un.d_val & DF_1_NODELETE) != 0);
+                       obj->z_initfirst =
+                           ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
+                       obj->z_noopen =
+                           ((dynp->d_un.d_val & DF_1_NOOPEN) != 0);
+                       break;
+               }
+       }
+
+       obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz);
+       obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz);
+       if (use_pltrel) {
+               obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel);
+               obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz);
+               obj->pltrelalim = 0;
+               /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
+                  Trim rel(a)lim to save time later. */
+               if (obj->rellim && obj->pltrel &&
+                   obj->rellim > obj->pltrel &&
+                   obj->rellim <= obj->pltrellim)
+                       obj->rellim = obj->pltrel;
+       } else if (use_pltrela) {
+               obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel);
+               obj->pltrellim = 0;
+               obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz);
+               /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
+                  Trim rel(a)lim to save time later. */
+               if (obj->relalim && obj->pltrela &&
+                   obj->relalim > obj->pltrela &&
+                   obj->relalim <= obj->pltrelalim)
+                       obj->relalim = obj->pltrela;
+       }
+
+#if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS)
+       if (init != 0)
+               obj->init = (void (*)(void))
+                   _rtld_function_descriptor_alloc(obj, NULL, init);
+       if (fini != 0)
+               obj->fini = (void (*)(void))
+                   _rtld_function_descriptor_alloc(obj, NULL, fini);
+#else
+       if (init != 0)
+               obj->init = (void (*)(void))
+                   (obj->relocbase + init);
+       if (fini != 0)
+               obj->fini = (void (*)(void))
+                   (obj->relocbase + fini);
+#endif
+
+       if (dyn_rpath != NULL) {
+               _rtld_add_paths(execname, &obj->rpaths, obj->strtab +
+                   dyn_rpath->d_un.d_val);
+       }
+}
+
+/*
+ * Process a shared object's program header.  This is used only for the
+ * main program, when the kernel has already loaded the main program
+ * into memory before calling the dynamic linker.  It creates and
+ * returns an Obj_Entry structure.
+ */
+Obj_Entry *
+_rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
+{
+       Obj_Entry      *obj;
+       const Elf_Phdr *phlimit = phdr + phnum;
+       const Elf_Phdr *ph;
+       int             nsegs = 0;
+       Elf_Addr        vaddr;
+
+       obj = _rtld_obj_new();
+
+       for (ph = phdr; ph < phlimit; ++ph) {
+               if (ph->p_type != PT_PHDR)
+                       continue;
+               
+               obj->phdr = (void *)(uintptr_t)phdr->p_vaddr;
+               obj->phsize = phdr->p_memsz;
+               obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr);
+               dbg(("headers: phdr %p phsize %zu relocbase %lx", obj->phdr,
+                   obj->phsize, (long)obj->relocbase));
+               break;
+       }
+       assert(obj->phdr == phdr);
+       
+       for (ph = phdr; ph < phlimit; ++ph) {
+               vaddr = (Elf_Addr)(uintptr_t)(obj->relocbase + ph->p_vaddr);
+               switch (ph->p_type) {
+
+               case PT_INTERP:
+                       obj->interp = (const char *)(uintptr_t)vaddr;
+                       break;
+
+               case PT_LOAD:
+                       assert(nsegs < 2);
+                       if (nsegs == 0) {       /* First load segment */
+                               obj->vaddrbase = round_down(vaddr);
+                               obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase;
+                               obj->textsize = round_up(vaddr + ph->p_memsz) -
+                                   obj->vaddrbase;
+                       } else {                /* Last load segment */
+                               obj->mapsize = round_up(vaddr + ph->p_memsz) -
+                                   obj->vaddrbase;
+                       }
+                       ++nsegs;
+                       break;
+
+               case PT_DYNAMIC:
+                       obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr;
+                       break;
+               }
+       }
+       assert(nsegs == 2);
+
+       obj->entry = entry;
+       return obj;
+}
diff --git a/libexec/ld.elf_so/ld.elf_so.1 b/libexec/ld.elf_so/ld.elf_so.1
new file mode 100644 (file)
index 0000000..e8bb619
--- /dev/null
@@ -0,0 +1,224 @@
+.\"    $NetBSD: ld.elf_so.1,v 1.15 2010/12/17 08:50:26 wiz Exp $
+.\"
+.\" Copyright (c) 2001 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Nick Hudson.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd December 17, 2010
+.Dt LD.ELF_SO 1
+.Os
+.Sh NAME
+.Nm ld.elf_so
+.Nd run-time link-editor (linker)
+.Sh DESCRIPTION
+.Nm
+is a self-contained, position independent program
+image providing run-time support for loading and
+link-editing shared objects into a process' address space.
+It uses information stored in data structures within the binary (see
+.Xr elf 5 )
+and environment variables to determine which shared objects are needed.
+These shared objects are loaded at a convenient virtual address using the
+.Xr mmap 2
+system call.
+After all shared objects have been successfully loaded,
+.Nm
+proceeds to resolve external references from both
+the main program and all objects loaded.
+Once all required references are resolved control is
+passed to the program via its entry point.
+.Ss Startup
+On the execution of a dynamically linked binary the kernel will load
+the program and its run-time linker as specified in the PT_INTERP
+section in the program header.
+At this point, instead of passing control directly to the program,
+the kernel passes control to the specified linker.
+An auxiliary vector of information is passed that includes
+the address of the program header, the size of each entry in the header,
+and the number of entries.
+The entry point of the program and the base address of where
+.Nm
+is loaded is also supplied.
+.Ss Finding objects
+Each
+.Xr elf 5
+object file may contain information in its dynamic (PT_DYNAMIC) section
+about which shared objects it requires (often referred to as dependencies).
+These dependencies are specified in the optional DT_NEEDED entry within
+the dynamic section.
+Each DT_NEEDED entry refers to a filename string of
+the shared object that is to be searched for.
+.Pp
+The linker will search for libraries in three lists of paths:
+.Bl -enum
+.It
+A user defined list of paths as specified in LD_LIBRARY_PATH and
+.Xr ld.so.conf 5 .
+.Pp
+The use of ld.so.conf should be avoided as the setting of a global search
+path can present a security risk.
+.It
+A list of paths specified within a shared object using a DT_RPATH entry in
+the dynamic section.
+This is defined at shared object link time.
+.It
+The list of default paths which is set to
+.Pa /usr/lib .
+.El
+.Pp
+.Nm
+will expand the following variables if present in the paths:
+.Bl -tag -width $PLATFORM
+.It $HWCAP
+Processor hardware capabilities, for example FPU, MMX, SSE.
+Currently unimplemented.
+.It $ISALIST
+List of instructions sets this processor can execute.
+Currently unimplemented.
+.It $ORIGIN
+The directory of the main object.
+Implemented in
+.Nm
+but the kernel support is currently disabled.
+.It $OSNAME
+The value of the
+.Dv kern.ostype
+.Xr sysctl 3 .
+.It $OSREL
+The value of the
+.Dv kern.osrelease
+.Xr sysctl 3 .
+.It $PLATFORM
+The value of the
+.Dv hw.machine_arch
+.Xr sysctl 3 .
+.El
+.Pp
+Both
+.Dv ${VARIABLE}
+and
+.Dv $VARIABLE
+are recognized.
+.Pp
+The filename string can be considered free form, however, it will almost
+always take the form lib\*[Lt]name\*[Gt].so.\*[Lt]number\*[Gt],
+where name specifies the
+.Sq library
+name and number is conceptually the library's major version number.
+.Pp
+This name and another of the form lib\*[Lt]name\*[Gt].so are normally
+symbolic links to the real shared object which has a filename of the form
+lib\*[Lt]name\*[Gt].so.\*[Lt]major\*[Gt].\*[Lt]minor\*[Gt][.\*[Lt]teeny\*[Gt]].
+This naming convention allows a versioning scheme similar to
+.Xr a.out 5 .
+.Ss Relocation
+.Nm
+will perform all necessary relocations immediately except for relocations
+relating to the Procedure Linkage Table (PLT).
+The PLT is used as a indirection method for procedure
+calls to globally defined functions.
+It allows, through the use of intermediate code, the delayed binding of
+a call to a globally defined function to be performed at procedure call time.
+This
+.Sq lazy
+method is the default (see LD_BIND_NOW).
+.Ss Initialization
+A mechanism is provided for initialization and termination routines
+to be called, on a per-object basis before execution of the program proper
+begins or after the program has completed.
+This gives a shared object an opportunity to perform
+any extra set-up or completion work.
+.Pp
+The DT_INIT and DT_FINI entries in the dynamic section specify the addresses
+of the initialization and termination functions, respectively, for
+the shared object.
+.Nm
+arranges for each initialization function to be called before control is passed
+to the program and for the termination functions to be called by using
+.Xr atexit 3 .
+.Pp
+This mechanism is exploited by the system-supplied constructor
+initialization and destructor code located in
+.Pa /usr/lib/crtbeginS.o
+and
+.Pa /usr/lib/crtendS.o .
+These files are automatically included by
+.Xr cc 1
+and
+.Xr c++ 1
+in the list of object-code files passed to
+.Xr ld 1
+when building a shared C or C++ object.
+.Sh ENVIRONMENT
+If the following environment variables exist they will be used by
+.Nm .
+.Bl -tag -width "LD_LIBRARY_PATH"
+.It Ev LD_LIBRARY_PATH
+A colon separated list of directories, overriding the default search path
+for shared libraries.
+.It Ev LD_PRELOAD
+A colon or space separated list of shared object filenames to be loaded
+.Em after
+the main program but
+.Em before
+its shared object dependencies.
+Space is allowed as a separator for backwards compatibility only.
+Support may be removed in a future release and should not be relied upon.
+.It Ev LD_BIND_NOW
+If defined immediate binding of Procedure Link Table (PLT) entries is
+performed instead of the default lazy method.
+.It Ev LD_DEBUG
+If defined a variety of debug information will be written to the standard
+error of an dynamically linked executed when it is run.
+This variable is only recognized if
+.Nm
+was compiled with debugging support
+.Sy ( -DDEBUG ) .
+.El
+.Sh FILES
+.Bl -tag -width /etc/ld.so.conf -compact
+.It Pa /etc/ld.so.conf
+library location hints supplied by the system administrator.
+.El
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr ld.aout_so 1 ,
+.Xr dlfcn 3 ,
+.Xr elf 5
+.Sh HISTORY
+The ELF shared library model employed first appeared in Sys V R4.
+.Pp
+The path expansion variables first appeared in Solaris 10, and
+in
+.Nx 5.0 .
+.Sh SECURITY CONSIDERATIONS
+The environment variables
+.Ev LD_LIBRARY_PATH
+and
+.Ev LD_PRELOAD
+are not honored when executing in a set-user-ID or set-group-ID environment.
+This action is taken to prevent malicious substitution of shared object
+dependencies or interposition of symbols.
diff --git a/libexec/ld.elf_so/load.c b/libexec/ld.elf_so/load.c
new file mode 100644 (file)
index 0000000..cefda1e
--- /dev/null
@@ -0,0 +1,350 @@
+/*     $NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $   */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * Copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp@polstra.com>.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $");
+#endif /* not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/sysctl.h>
+#include <dirent.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+static bool _rtld_load_by_name(const char *, Obj_Entry *, Needed_Entry **,
+    int);
+
+#ifdef RTLD_LOADER
+Objlist _rtld_list_main =      /* Objects loaded at program startup */
+  SIMPLEQ_HEAD_INITIALIZER(_rtld_list_main);
+Objlist _rtld_list_global =    /* Objects dlopened with RTLD_GLOBAL */
+  SIMPLEQ_HEAD_INITIALIZER(_rtld_list_global);
+  
+void
+_rtld_objlist_push_head(Objlist *list, Obj_Entry *obj)
+{
+       Objlist_Entry *elm;
+
+       elm = NEW(Objlist_Entry);
+       elm->obj = obj;
+       SIMPLEQ_INSERT_HEAD(list, elm, link);
+}
+
+void
+_rtld_objlist_push_tail(Objlist *list, Obj_Entry *obj)
+{
+       Objlist_Entry *elm;
+
+       elm = NEW(Objlist_Entry);
+       elm->obj = obj;
+       SIMPLEQ_INSERT_TAIL(list, elm, link);
+}
+
+Objlist_Entry *
+_rtld_objlist_find(Objlist *list, const Obj_Entry *obj)
+{
+       Objlist_Entry *elm;
+
+       SIMPLEQ_FOREACH(elm, list, link) {
+               if (elm->obj == obj)
+                       return elm;
+       }
+       return NULL;
+}
+#endif
+
+/*
+ * Load a shared object into memory, if it is not already loaded.
+ *
+ * Returns a pointer to the Obj_Entry for the object.  Returns NULL
+ * on failure.
+ */
+Obj_Entry *
+_rtld_load_object(const char *filepath, int flags)
+{
+       Obj_Entry *obj;
+       int fd = -1;
+       struct stat sb;
+       size_t pathlen = strlen(filepath);
+
+       for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next)
+               if (pathlen == obj->pathlen && !strcmp(obj->path, filepath)) 
+                       break;
+
+       /*
+        * If we didn't find a match by pathname, open the file and check
+        * again by device and inode.  This avoids false mismatches caused
+        * by multiple links or ".." in pathnames.
+        *
+        * To avoid a race, we open the file and use fstat() rather than
+        * using stat().
+        */
+       if (obj == NULL) {
+               if ((fd = open(filepath, O_RDONLY)) == -1) {
+                       _rtld_error("Cannot open \"%s\"", filepath);
+                       return NULL;
+               }
+               if (fstat(fd, &sb) == -1) {
+                       _rtld_error("Cannot fstat \"%s\"", filepath);
+                       close(fd);
+                       return NULL;
+               }
+               for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next) {
+                       if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) {
+                               close(fd);
+                               break;
+                       }
+               }
+       }
+
+       if (obj == NULL) { /* First use of this object, so we must map it in */
+               obj = _rtld_map_object(filepath, fd, &sb);
+               (void)close(fd);
+               if (obj == NULL)
+                       return NULL;
+               _rtld_digest_dynamic(filepath, obj);
+
+               if (flags & _RTLD_DLOPEN) {
+                       if (obj->z_noopen || (flags & _RTLD_NOLOAD)) {
+                               dbg(("refusing to load non-loadable \"%s\"",
+                                   obj->path));
+                               _rtld_error("Cannot dlopen non-loadable %s",
+                                   obj->path);
+                               munmap(obj->mapbase, obj->mapsize);
+                               _rtld_obj_free(obj);
+                               return OBJ_ERR;
+                       }
+               }
+
+               *_rtld_objtail = obj;
+               _rtld_objtail = &obj->next;
+               _rtld_objcount++;
+               _rtld_objloads++;
+#ifdef RTLD_LOADER
+               _rtld_linkmap_add(obj); /* for GDB */
+#endif
+               dbg(("  %p .. %p: %s", obj->mapbase,
+                   obj->mapbase + obj->mapsize - 1, obj->path));
+               if (obj->textrel)
+                       dbg(("  WARNING: %s has impure text", obj->path));
+       }
+
+       ++obj->refcount;
+#ifdef RTLD_LOADER
+       if (flags & _RTLD_MAIN && !obj->mainref) {
+               obj->mainref = 1;
+               dbg(("adding %p (%s) to _rtld_list_main", obj, obj->path));
+               _rtld_objlist_push_tail(&_rtld_list_main, obj);
+       }
+       if (flags & _RTLD_GLOBAL && !obj->globalref) {
+               obj->globalref = 1;
+               dbg(("adding %p (%s) to _rtld_list_global", obj, obj->path));
+               _rtld_objlist_push_tail(&_rtld_list_global, obj);
+       }
+#endif
+       return obj;
+}
+
+static bool
+_rtld_load_by_name(const char *name, Obj_Entry *obj, Needed_Entry **needed,
+    int flags)
+{
+       Library_Xform *x = _rtld_xforms;
+       Obj_Entry *o = NULL;
+       size_t j;
+       ssize_t i;
+       bool got = false;
+       union {
+               int i;
+               u_quad_t q;
+               char s[16];
+       } val;
+
+       dbg(("load by name %s %p", name, x));
+       for (; x; x = x->next) {
+               if (strcmp(x->name, name) != 0)
+                       continue;
+
+               j = sizeof(val);
+               if ((i = _rtld_sysctl(x->ctlname, &val, &j)) == -1) {
+                       xwarnx(_PATH_LD_HINTS ": invalid/unknown sysctl for %s (%d)",
+                           name, errno);
+                       break;
+               }
+
+               switch (i) {
+               case CTLTYPE_QUAD:
+                       xsnprintf(val.s, sizeof(val.s), "%" PRIu64, val.q);
+                       break;
+               case CTLTYPE_INT:
+                       xsnprintf(val.s, sizeof(val.s), "%d", val.i);
+                       break;
+               case CTLTYPE_STRING:
+                       break;
+               default:
+                       xwarnx("unsupported sysctl type %d", (int)i);
+                       break;
+               }
+
+               dbg(("sysctl returns %s", val.s));
+
+               for (i = 0; i < RTLD_MAX_ENTRY && x->entry[i].value != NULL;
+                   i++) {
+                       dbg(("entry %ld", (unsigned long)i));
+                       if (strcmp(x->entry[i].value, val.s) == 0)
+                               break;
+               }
+
+               if (i == RTLD_MAX_ENTRY) {
+                       xwarnx("sysctl value %s not found for lib%s",
+                           val.s, name);
+                       break;
+               }
+
+               for (j = 0; j < RTLD_MAX_LIBRARY &&
+                   x->entry[i].library[j] != NULL; j++) {
+                       o = _rtld_load_library(x->entry[i].library[j], obj,
+                           flags);
+                       if (o == NULL) {
+                               xwarnx("could not load %s for %s",
+                                   x->entry[i].library[j], name);
+                               continue;
+                       }
+                       got = true;
+                       if (j == 0)
+                               (*needed)->obj = o;
+                       else {
+                               /* make a new one and put it in the chain */
+                               Needed_Entry *ne = xmalloc(sizeof(*ne));
+                               ne->name = (*needed)->name;
+                               ne->obj = o;
+                               ne->next = (*needed)->next;
+                               (*needed)->next = ne;
+                               *needed = ne;
+                       }
+                               
+               }
+               
+       }
+
+       if (got)
+               return true;
+
+       return ((*needed)->obj = _rtld_load_library(name, obj, flags)) != NULL;
+}
+
+
+/*
+ * Given a shared object, traverse its list of needed objects, and load
+ * each of them.  Returns 0 on success.  Generates an error message and
+ * returns -1 on failure.
+ */
+int
+_rtld_load_needed_objects(Obj_Entry *first, int flags)
+{
+       Obj_Entry *obj;
+       int status = 0;
+
+       for (obj = first; obj != NULL; obj = obj->next) {
+               Needed_Entry *needed;
+
+               for (needed = obj->needed; needed != NULL;
+                   needed = needed->next) {
+                       const char *name = obj->strtab + needed->name;
+#ifdef RTLD_LOADER
+                       Obj_Entry *nobj;
+#endif
+                       if (!_rtld_load_by_name(name, obj, &needed,
+                           flags & ~_RTLD_NOLOAD))
+                               status = -1;    /* FIXME - cleanup */
+#ifdef RTLD_LOADER
+                       if (status == -1)
+                               return status;
+
+                       if (flags & _RTLD_MAIN)
+                               continue;
+
+                       nobj = needed->obj;
+                       if (nobj->z_nodelete && !obj->ref_nodel) {
+                               dbg(("obj %s nodelete", nobj->path));
+                               _rtld_ref_dag(nobj);
+                               nobj->ref_nodel = true;
+                       }
+#endif
+               }
+       }
+
+       return status;
+}
+
+#ifdef RTLD_LOADER
+int
+_rtld_preload(const char *preload_path)
+{
+       const char *path;
+       char *cp, *buf;
+       int status = 0;
+
+       if (preload_path != NULL && *preload_path != '\0') {
+               cp = buf = xstrdup(preload_path);
+               while ((path = strsep(&cp, " :")) != NULL && status == 0) {
+                       if (!_rtld_load_object(path, _RTLD_MAIN))
+                               status = -1;
+                       else
+                               dbg((" preloaded \"%s\"", path));
+               }
+               xfree(buf);
+       }
+
+       return status;
+}
+#endif
diff --git a/libexec/ld.elf_so/map_object.c b/libexec/ld.elf_so/map_object.c
new file mode 100644 (file)
index 0000000..71cc853
--- /dev/null
@@ -0,0 +1,422 @@
+/*     $NetBSD: map_object.c,v 1.41 2010/10/16 10:27:07 skrll Exp $     */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * Copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: map_object.c,v 1.41 2010/10/16 10:27:07 skrll Exp $");
+#endif /* not lint */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+static int protflags(int);     /* Elf flags -> mmap protection */
+
+#define EA_UNDEF               (~(Elf_Addr)0)
+
+/*
+ * Map a shared object into memory.  The argument is a file descriptor,
+ * which must be open on the object and positioned at its beginning.
+ *
+ * The return value is a pointer to a newly-allocated Obj_Entry structure
+ * for the shared object.  Returns NULL on failure.
+ */
+Obj_Entry *
+_rtld_map_object(const char *path, int fd, const struct stat *sb)
+{
+       Obj_Entry       *obj;
+       Elf_Ehdr        *ehdr;
+       Elf_Phdr        *phdr;
+       size_t           phsize;
+       Elf_Phdr        *phlimit;
+       Elf_Phdr        *segs[2];
+       int              nsegs;
+       caddr_t          mapbase = MAP_FAILED;
+       size_t           mapsize = 0;
+       int              mapflags;
+       Elf_Off          base_offset;
+#ifdef MAP_ALIGNED
+       Elf_Addr         base_alignment;
+#endif
+       Elf_Addr         base_vaddr;
+       Elf_Addr         base_vlimit;
+       Elf_Addr         text_vlimit;
+       int              text_flags;
+       caddr_t          base_addr;
+       Elf_Off          data_offset;
+       Elf_Addr         data_vaddr;
+       Elf_Addr         data_vlimit;
+       int              data_flags;
+       caddr_t          data_addr;
+       Elf_Addr         phdr_vaddr;
+       size_t           phdr_memsz;
+       caddr_t          gap_addr;
+       size_t           gap_size;
+       int i;
+#ifdef RTLD_LOADER
+       Elf_Addr         clear_vaddr;
+       caddr_t          clear_addr;
+       size_t           nclear;
+#endif
+
+       if (sb != NULL && sb->st_size < (off_t)sizeof (Elf_Ehdr)) {
+               _rtld_error("%s: unrecognized file format1", path);
+               return NULL;
+       }
+
+       obj = _rtld_obj_new();
+       obj->path = xstrdup(path);
+       obj->pathlen = strlen(path);
+       if (sb != NULL) {
+               obj->dev = sb->st_dev;
+               obj->ino = sb->st_ino;
+       }
+
+       ehdr = mmap(NULL, _rtld_pagesz, PROT_READ, MAP_FILE | MAP_SHARED, fd,
+           (off_t)0);
+       obj->ehdr = ehdr;
+       if (ehdr == MAP_FAILED) {
+               _rtld_error("%s: read error: %s", path, xstrerror(errno));
+               goto bad;
+       }
+       /* Make sure the file is valid */
+       if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 ||
+           ehdr->e_ident[EI_CLASS] != ELFCLASS) {
+               _rtld_error("%s: unrecognized file format2 [%x != %x]", path,
+                   ehdr->e_ident[EI_CLASS], ELFCLASS);
+               goto bad;
+       }
+       /* Elf_e_ident includes class */
+       if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
+           ehdr->e_version != EV_CURRENT ||
+           ehdr->e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) {
+               _rtld_error("%s: unsupported file version", path);
+               goto bad;
+       }
+       if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
+               _rtld_error("%s: unsupported file type", path);
+               goto bad;
+       }
+       switch (ehdr->e_machine) {
+               ELFDEFNNAME(MACHDEP_ID_CASES)
+       default:
+               _rtld_error("%s: unsupported machine", path);
+               goto bad;
+       }
+
+       /*
+         * We rely on the program header being in the first page.  This is
+         * not strictly required by the ABI specification, but it seems to
+         * always true in practice.  And, it simplifies things considerably.
+         */
+       assert(ehdr->e_phentsize == sizeof(Elf_Phdr));
+       assert(ehdr->e_phoff + ehdr->e_phnum * sizeof(Elf_Phdr) <=
+           _rtld_pagesz);
+
+       /*
+         * Scan the program header entries, and save key information.
+         *
+         * We rely on there being exactly two load segments, text and data,
+         * in that order.
+         */
+       phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff);
+       phsize = ehdr->e_phnum * sizeof(phdr[0]);
+       obj->phdr = NULL;
+       phdr_vaddr = EA_UNDEF;
+       phdr_memsz = 0;
+       phlimit = phdr + ehdr->e_phnum;
+       nsegs = 0;
+       while (phdr < phlimit) {
+               switch (phdr->p_type) {
+               case PT_INTERP:
+                       obj->interp = (void *)(uintptr_t)phdr->p_vaddr;
+                       dbg(("%s: PT_INTERP %p", obj->path, obj->interp));
+                       break;
+
+               case PT_LOAD:
+                       if (nsegs < 2)
+                               segs[nsegs] = phdr;
+                       ++nsegs;
+                       dbg(("%s: PT_LOAD %p", obj->path, phdr));
+                       break;
+
+               case PT_PHDR:
+                       phdr_vaddr = phdr->p_vaddr;
+                       phdr_memsz = phdr->p_memsz;
+                       dbg(("%s: PT_PHDR %p phsize %zu", obj->path,
+                           (void *)(uintptr_t)phdr_vaddr, phdr_memsz));
+                       break;
+               
+               case PT_DYNAMIC:
+                       obj->dynamic = (void *)(uintptr_t)phdr->p_vaddr;
+                       dbg(("%s: PT_DYNAMIC %p", obj->path, obj->dynamic));
+                       break;
+               }
+
+               ++phdr;
+       }
+       phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff);
+       obj->entry = (void *)(uintptr_t)ehdr->e_entry;
+       if (!obj->dynamic) {
+               _rtld_error("%s: not dynamically linked", path);
+               goto bad;
+       }
+       if (nsegs != 2) {
+               _rtld_error("%s: wrong number of segments (%d != 2)", path,
+                   nsegs);
+               goto bad;
+       }
+
+       /*
+        * Map the entire address space of the object as a file
+        * region to stake out our contiguous region and establish a
+        * base for relocation.  We use a file mapping so that
+        * the kernel will give us whatever alignment is appropriate
+        * for the platform we're running on.
+        *
+        * We map it using the text protection, map the data segment
+        * into the right place, then map an anon segment for the bss
+        * and unmap the gaps left by padding to alignment.
+        */
+
+#ifdef MAP_ALIGNED
+       base_alignment = segs[0]->p_align;
+#endif
+       base_offset = round_down(segs[0]->p_offset);
+       base_vaddr = round_down(segs[0]->p_vaddr);
+       base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz);
+       text_vlimit = round_up(segs[0]->p_vaddr + segs[0]->p_memsz);
+       text_flags = protflags(segs[0]->p_flags);
+       data_offset = round_down(segs[1]->p_offset);
+       data_vaddr = round_down(segs[1]->p_vaddr);
+       data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz);
+       data_flags = protflags(segs[1]->p_flags);
+#ifdef RTLD_LOADER
+       clear_vaddr = segs[1]->p_vaddr + segs[1]->p_filesz;
+#endif
+
+       obj->textsize = text_vlimit - base_vaddr;
+       obj->vaddrbase = base_vaddr;
+       obj->isdynamic = ehdr->e_type == ET_DYN;
+
+       obj->phdr_loaded = false;
+       for (i = 0; i < nsegs; i++) {
+               if (phdr_vaddr != EA_UNDEF &&
+                   segs[i]->p_vaddr <= phdr_vaddr &&
+                   segs[i]->p_memsz >= phdr_memsz) {
+                       obj->phdr_loaded = true;
+                       break;
+               }
+               if (segs[i]->p_offset <= ehdr->e_phoff &&
+                   segs[i]->p_memsz >= phsize) {
+                       phdr_vaddr = segs[i]->p_vaddr + ehdr->e_phoff;
+                       phdr_memsz = phsize;
+                       obj->phdr_loaded = true;
+                       break;
+               }
+       }
+       if (obj->phdr_loaded) {
+               obj->phdr = (void *)(uintptr_t)phdr_vaddr;
+               obj->phsize = phdr_memsz;
+       } else {
+               Elf_Phdr *buf;
+               buf = xmalloc(phsize);
+               if (buf == NULL) {
+                       _rtld_error("%s: cannot allocate program header", path);
+                       goto bad;
+               }
+               memcpy(buf, phdr, phsize);
+               obj->phdr = buf;
+               obj->phsize = phsize;
+       }
+       dbg(("%s: phdr %p phsize %zu (%s)", obj->path, obj->phdr, obj->phsize,
+            obj->phdr_loaded ? "loaded" : "allocated"));
+
+       /* Unmap header if it overlaps the first load section. */
+       if (base_offset < _rtld_pagesz) {
+               munmap(ehdr, _rtld_pagesz);
+               obj->ehdr = MAP_FAILED;
+       }
+
+       /*
+        * Calculate log2 of the base section alignment.
+        */
+       mapflags = 0;
+#ifdef MAP_ALIGNED
+       if (base_alignment > _rtld_pagesz) {
+               unsigned int log2 = 0;
+               for (; base_alignment > 1; base_alignment >>= 1)
+                       log2++;
+               mapflags = MAP_ALIGNED(log2);
+       }
+#endif
+
+#ifdef RTLD_LOADER
+       base_addr = obj->isdynamic ? NULL : (caddr_t)base_vaddr;
+#else
+       base_addr = NULL;
+#endif
+       mapsize = base_vlimit - base_vaddr;
+       mapbase = mmap(base_addr, mapsize, text_flags,
+           mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset);
+       if (mapbase == MAP_FAILED) {
+               _rtld_error("mmap of entire address space failed: %s",
+                   xstrerror(errno));
+               goto bad;
+       }
+
+       /* Overlay the data segment onto the proper region. */
+       data_addr = mapbase + (data_vaddr - base_vaddr);
+       if (mmap(data_addr, data_vlimit - data_vaddr, data_flags,
+           MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, data_offset) ==
+           MAP_FAILED) {
+               _rtld_error("mmap of data failed: %s", xstrerror(errno));
+               goto bad;
+       }
+
+       /* Overlay the bss segment onto the proper region. */
+       if (mmap(mapbase + data_vlimit - base_vaddr, base_vlimit - data_vlimit,
+           data_flags, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) ==
+           MAP_FAILED) {
+               _rtld_error("mmap of bss failed: %s", xstrerror(errno));
+               goto bad;
+       }
+
+       /* Unmap the gap between the text and data. */
+       gap_addr = mapbase + round_up(text_vlimit - base_vaddr);
+       gap_size = data_addr - gap_addr;
+       if (gap_size != 0 && mprotect(gap_addr, gap_size, PROT_NONE) == -1) {
+               _rtld_error("mprotect of text -> data gap failed: %s",
+                   xstrerror(errno));
+               goto bad;
+       }
+
+#ifdef RTLD_LOADER
+       /* Clear any BSS in the last page of the data segment. */
+       clear_addr = mapbase + (clear_vaddr - base_vaddr);
+       if ((nclear = data_vlimit - clear_vaddr) > 0)
+               memset(clear_addr, 0, nclear);
+
+       /* Non-file portion of BSS mapped above. */
+#endif
+
+       obj->mapbase = mapbase;
+       obj->mapsize = mapsize;
+       obj->relocbase = mapbase - base_vaddr;
+
+       if (obj->dynamic)
+               obj->dynamic = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->dynamic);
+       if (obj->entry)
+               obj->entry = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->entry);
+       if (obj->interp)
+               obj->interp = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->interp);
+       if (obj->phdr_loaded)
+               obj->phdr =  (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->phdr);
+
+       return obj;
+
+bad:
+       if (obj->ehdr != MAP_FAILED)
+               munmap(obj->ehdr, _rtld_pagesz);
+       if (mapbase != MAP_FAILED)
+               munmap(mapbase, mapsize);
+       _rtld_obj_free(obj);
+       return NULL;
+}
+
+void
+_rtld_obj_free(Obj_Entry *obj)
+{
+       Objlist_Entry *elm;
+
+       xfree(obj->path);
+       while (obj->needed != NULL) {
+               Needed_Entry *needed = obj->needed;
+               obj->needed = needed->next;
+               xfree(needed);
+       }
+       while ((elm = SIMPLEQ_FIRST(&obj->dldags)) != NULL) {
+               SIMPLEQ_REMOVE_HEAD(&obj->dldags, link);
+               xfree(elm);
+       }
+       while ((elm = SIMPLEQ_FIRST(&obj->dagmembers)) != NULL) {
+               SIMPLEQ_REMOVE_HEAD(&obj->dagmembers, link);
+               xfree(elm);
+       }
+       if (!obj->phdr_loaded)
+               xfree((void *)(uintptr_t)obj->phdr);
+       xfree(obj);
+#ifdef COMBRELOC
+       _rtld_combreloc_reset(obj);
+#endif
+}
+
+Obj_Entry *
+_rtld_obj_new(void)
+{
+       Obj_Entry *obj;
+
+       obj = CNEW(Obj_Entry);
+       SIMPLEQ_INIT(&obj->dldags);
+       SIMPLEQ_INIT(&obj->dagmembers);
+       return obj;
+}
+
+/*
+ * Given a set of ELF protection flags, return the corresponding protection
+ * flags for MMAP.
+ */
+static int
+protflags(int elfflags)
+{
+       int prot = 0;
+
+       if (elfflags & PF_R)
+               prot |= PROT_READ;
+#ifdef RTLD_LOADER
+       if (elfflags & PF_W)
+               prot |= PROT_WRITE;
+#endif
+       if (elfflags & PF_X)
+               prot |= PROT_EXEC;
+       return prot;
+}
diff --git a/libexec/ld.elf_so/paths.c b/libexec/ld.elf_so/paths.c
new file mode 100644 (file)
index 0000000..6ccffbc
--- /dev/null
@@ -0,0 +1,478 @@
+/*     $NetBSD: paths.c,v 1.40 2009/05/19 20:44:52 christos Exp $       */
+
+/*
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * Copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: paths.c,v 1.40 2009/05/19 20:44:52 christos Exp $");
+#endif /* not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/gmon.h>
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <sys/mbuf.h>
+#include <sys/resource.h>
+#include <machine/cpu.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+static Search_Path *_rtld_find_path(Search_Path *, const char *, size_t);
+static Search_Path **_rtld_append_path(Search_Path **, Search_Path **,
+    const char *, const char *, const char *);
+static void _rtld_process_mapping(Library_Xform **, const char *,
+    const char *);
+static char *exstrdup(const char *, const char *);
+static const char *getstr(const char **, const char *, const char *);
+static const char *getcstr(const char **, const char *, const char *);
+static const char *getword(const char **, const char *, const char *);
+static int matchstr(const char *, const char *, const char *);
+
+static const char WS[] = " \t\n";
+
+/*
+ * Like xstrdup(), but takes end of string as a argument.
+ */
+static char *
+exstrdup(const char *bp, const char *ep)
+{
+       char *cp;
+       size_t len = ep - bp;
+
+       cp = xmalloc(len + 1);
+       memcpy(cp, bp, len);
+       cp[len] = '\0';
+       return (cp);
+}
+
+/*
+ * Like strsep(), but takes end of string and doesn't put any NUL.  To
+ * detect empty string, compare `*p' and return value.
+ */
+static const char *
+getstr(const char **p, const char *ep, const char *delim)
+{
+       const char *cp = *p, *q, *r;
+
+       if (ep < cp)
+               /* End of string */
+               return (NULL);
+
+       for (q = cp; q < ep; q++)
+               for (r = delim; *r != 0; r++)
+                       if (*r == *q)
+                               goto done;
+
+done:
+       *p = q;
+       return (cp);
+}
+
+/*
+ * Like getstr() above, but delim[] is complemented.
+ */
+static const char *
+getcstr(const char **p, const char *ep, const char *delim)
+{
+       const char *cp = *p, *q, *r;
+
+       if (ep < cp)
+               /* End of string */
+               return (NULL);
+
+       for (q = cp; q < ep; q++)
+               for (r = delim; *r != *q; r++)
+                       if (*r == 0)
+                               goto done;
+
+done:
+       *p = q;
+       return (cp);
+}
+
+static const char *
+getword(const char **p, const char *ep, const char *delim)
+{
+
+       (void)getcstr(p, ep, delim);
+
+       /*
+        * Now, we're looking non-delim, or end of string.
+        */
+
+       return (getstr(p, ep, delim));
+}
+
+/*
+ * Match `bp' against NUL terminated string pointed by `p'.
+ */
+static int
+matchstr(const char *p, const char *bp, const char *ep)
+{
+       int c;
+
+       while (bp < ep)
+               if ((c = *p++) == 0 || c != *bp++)
+                       return (0);
+
+       return (*p == 0);
+}
+
+static Search_Path *
+_rtld_find_path(Search_Path *path, const char *pathstr, size_t pathlen)
+{
+
+       for (; path != NULL; path = path->sp_next) {
+               if (pathlen == path->sp_pathlen &&
+                   memcmp(path->sp_path, pathstr, pathlen) == 0)
+                       return path;
+       }
+       return NULL;
+}
+
+static Search_Path **
+_rtld_append_path(Search_Path **head_p, Search_Path **path_p,
+    const char *execname, const char *bp, const char *ep)
+{
+       Search_Path *path;
+       char epath[MAXPATHLEN];
+       size_t len;
+
+       len = _rtld_expand_path(epath, sizeof(epath), execname, bp, ep);
+       if (len == 0)
+               return path_p;
+
+       if (_rtld_find_path(*head_p, bp, ep - bp) != NULL)
+               return path_p;
+
+       path = NEW(Search_Path);
+       path->sp_pathlen = len;
+       path->sp_path = exstrdup(epath, epath + len);
+       path->sp_next = (*path_p);
+       (*path_p) = path;
+       path_p = &path->sp_next;
+
+       dbg((" added path \"%s\"", path->sp_path));
+       return path_p;
+}
+
+void
+_rtld_add_paths(const char *execname, Search_Path **path_p, const char *pathstr)
+{
+       Search_Path **head_p = path_p;
+
+       if (pathstr == NULL)
+               return;
+
+       if (pathstr[0] == ':') {
+               /*
+                * Leading colon means append to current path
+                */
+               while ((*path_p) != NULL)
+                       path_p = &(*path_p)->sp_next;
+               pathstr++;
+       }
+
+       for (;;) {
+               const char *bp = pathstr;
+               const char *ep = strchr(bp, ':');
+               if (ep == NULL)
+                       ep = &pathstr[strlen(pathstr)];
+
+               path_p = _rtld_append_path(head_p, path_p, execname, bp, ep);
+
+               if (ep[0] == '\0')
+                       break;
+               pathstr = ep + 1;
+       }
+}
+
+/*
+ * Process library mappings of the form:
+ *     <library_name>  <machdep_variable> <value,...:library_name,...> ... 
+ */
+static void
+_rtld_process_mapping(Library_Xform **lib_p, const char *bp, const char *ep)
+{
+       Library_Xform *hwptr = NULL;
+       const char *ptr, *key, *ekey, *lib, *elib, *l;
+       int i, j;
+       
+       dbg((" processing mapping \"%.*s\"", (int)(ep - bp), bp));
+
+       if ((ptr = getword(&bp, ep, WS)) == NULL || ptr == bp)
+               return;
+
+       dbg((" library \"%.*s\"", (int)(bp - ptr), ptr));
+
+       hwptr = xmalloc(sizeof(*hwptr));
+       memset(hwptr, 0, sizeof(*hwptr));
+       hwptr->name = exstrdup(ptr, bp);
+
+       bp++;
+
+       if ((ptr = getword(&bp, ep, WS)) == NULL || ptr == bp) {
+               xwarnx("missing sysctl variable name");
+               goto cleanup;
+       }
+
+       dbg((" sysctl \"%.*s\"", (int)(bp - ptr), ptr));
+
+       hwptr->ctlname = exstrdup(ptr, bp);
+
+       for (i = 0; bp++, (ptr = getword(&bp, ep, WS)) != NULL;) {
+               dbg((" ptr = %.*s", (int)(bp - ptr), ptr));
+               if (ptr == bp)
+                       continue;
+
+               if (i == RTLD_MAX_ENTRY) {
+no_more:
+                       xwarnx("maximum library entries exceeded `%s'",
+                           hwptr->name);
+                       goto cleanup;
+               }
+               if ((key = getstr(&ptr, bp, ":")) == NULL) {
+                       xwarnx("missing sysctl variable value for `%s'",
+                           hwptr->name);
+                       goto cleanup;
+               }
+               ekey = ptr++;
+               if ((lib = getstr(&ptr, bp, ":")) == NULL) {
+                       xwarnx("missing sysctl library list for `%s'",
+                           hwptr->name);
+                       goto cleanup;
+               }
+               elib = ptr;             /* No need to advance */
+               for (j = 0; (l = getstr(&lib, elib, ",")) != NULL;
+                   j++, lib++) {
+                       if (j == RTLD_MAX_LIBRARY) {
+                               xwarnx("maximum library entries exceeded `%s'",
+                                   hwptr->name);
+                               goto cleanup;
+                       }
+                       dbg((" library \"%.*s\"", (int)(lib - l), l));
+                       hwptr->entry[i].library[j] = exstrdup(l, lib);
+               }
+               if (j == 0) {
+                       xwarnx("No library map entries for `%s/%.*s'",
+                           hwptr->name, (int)(bp - ptr), ptr);
+                       goto cleanup;
+               }
+               j = i;
+               for (; (l = getstr(&key, ekey, ",")) != NULL; i++, key++) {
+                       /*
+                        * Allow empty key (it is valid as string
+                        * value).  Thus, we loop at least once and
+                        * `i' is incremented.
+                        */
+
+                       dbg((" key \"%.*s\"", (int)(key - l), l));
+                       if (i == RTLD_MAX_ENTRY)
+                               goto no_more;
+                       if (i != j)
+                               (void)memcpy(hwptr->entry[i].library, 
+                                   hwptr->entry[j].library,
+                                   sizeof(hwptr->entry[j].library));
+                       hwptr->entry[i].value = exstrdup(l, key);
+               }
+       }
+
+       if (i == 0) {
+               xwarnx("No library entries for `%s'", hwptr->name);
+               goto cleanup;
+       }
+
+       hwptr->next = *lib_p;
+       *lib_p = hwptr;
+
+       return;
+
+cleanup:
+       if (hwptr->name)
+               xfree(hwptr->name);
+       xfree(hwptr);
+}
+
+void
+_rtld_process_hints(const char *execname, Search_Path **path_p,
+    Library_Xform **lib_p, const char *fname)
+{
+       int fd;
+       char *buf, small[128];
+       const char *b, *ep, *ptr;
+       struct stat st;
+       ssize_t sz;
+       Search_Path **head_p = path_p;
+
+       if ((fd = open(fname, O_RDONLY)) == -1) {
+               /* Don't complain */
+               return;
+       }
+
+       /* Try to avoid mmap/stat on the file. */
+       buf = small;
+       buf[0] = '\0';
+       sz = read(fd, buf, sizeof(small));
+       if (sz == -1) {
+               xwarn("read: %s", fname);
+               (void)close(fd);
+               return;
+       }
+       if (sz >= (ssize_t)sizeof(small)) {
+               if (fstat(fd, &st) == -1) {
+                       /* Complain */
+                       xwarn("fstat: %s", fname);
+                       (void)close(fd);
+                       return;
+               }
+
+               sz = (ssize_t) st.st_size;
+
+               buf = mmap(0, sz, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
+               if (buf == MAP_FAILED) {
+                       xwarn("mmap: %s", fname);
+                       (void)close(fd);
+                       return;
+               }
+       }
+       (void)close(fd);
+
+       while ((*path_p) != NULL)
+               path_p = &(*path_p)->sp_next;
+
+       for (b = buf, ep = buf + sz; b < ep; b++) {
+               (void)getcstr(&b, ep, WS);
+               if (b == ep)
+                       break;
+
+               ptr = getstr(&b, ep, "\n#");
+               if (*ptr == '/') {
+                       /*
+                        * Since '/' != '\n' and != '#', we know ptr <
+                        * b.  And we will stop when b[-1] == '/'.
+                        */
+                       while (b[-1] == ' ' || b[-1] == '\t')
+                               b--;
+                       path_p = _rtld_append_path(head_p, path_p, execname,
+                           ptr, b);
+               } else
+                       _rtld_process_mapping(lib_p, ptr, b);
+
+               /*
+                * b points one of ' ', \t, \n, # or equal to ep.  So,
+                * make sure we are at newline or end of string.
+                */
+               (void)getstr(&b, ep, "\n");
+       }
+
+       if (buf != small)
+               (void)munmap(buf, sz);
+}
+
+/* Basic name -> sysctl MIB translation */
+int
+_rtld_sysctl(const char *name, void *oldp, size_t *oldlen)
+{
+       const char *node, *ep;
+       struct sysctlnode query, *result, *newresult;
+       int mib[CTL_MAXNAME], r;
+       size_t res_size, n, i;
+       u_int miblen = 0;
+
+       /* Start with 16 entries, will grow it up as needed. */
+       res_size = 16 * sizeof(struct sysctlnode);
+       result = xmalloc(res_size);
+       if (result == NULL)
+               return (-1);
+
+       ep = name + strlen(name);
+       do {
+               i = ~0ul;
+               while (*name == '/' || *name == '.')
+                       name++;
+               if (name >= ep)
+                       break;
+
+               mib[miblen] = CTL_QUERY;
+               memset(&query, 0, sizeof(query));
+               query.sysctl_flags = SYSCTL_VERSION;
+
+               n = res_size;
+               if (sysctl(mib, miblen + 1, result, &n, &query,
+                   sizeof(query)) == -1) {
+                       if (errno != ENOMEM)
+                               goto bad;
+                       /* Grow up result */
+                       res_size = n;
+                       newresult = xrealloc(result, res_size);
+                       if (newresult == NULL)
+                               goto bad;
+                       result = newresult;
+                       if (sysctl(mib, miblen + 1, result, &n, &query,
+                           sizeof(query)) == -1)
+                               goto bad;
+               }
+               n /= sizeof(struct sysctlnode);
+
+               node = getstr(&name, ep, "./");
+
+               for (i = 0; i < n; i++)
+                       if (matchstr(result[i].sysctl_name, node, name)) {
+                               mib[miblen] = result[i].sysctl_num;
+                               miblen++;
+                               break;
+                       }
+       } while (name < ep && miblen <= CTL_MAXNAME);
+
+       if (name < ep || i == ~0ul)
+               goto bad;
+       r = SYSCTL_TYPE(result[i].sysctl_flags);
+
+       xfree(result);
+       if (sysctl(mib, miblen, oldp, oldlen, NULL, 0) == -1)
+               return (-1);
+       return r;
+
+bad:
+       xfree(result);
+       return (-1);
+}
diff --git a/libexec/ld.elf_so/reloc.c b/libexec/ld.elf_so/reloc.c
new file mode 100644 (file)
index 0000000..c0666b2
--- /dev/null
@@ -0,0 +1,224 @@
+/*     $NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $         */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp@polstra.com>.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $");
+#endif /* not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/bitops.h>
+#include <dirent.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+#ifndef RTLD_INHIBIT_COPY_RELOCS
+static int _rtld_do_copy_relocation(const Obj_Entry *, const Elf_Rela *);
+
+static int
+_rtld_do_copy_relocation(const Obj_Entry *dstobj, const Elf_Rela *rela)
+{
+       void           *dstaddr = (void *)(dstobj->relocbase + rela->r_offset);
+       const Elf_Sym  *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
+       const char     *name = dstobj->strtab + dstsym->st_name;
+       unsigned long   hash = _rtld_elf_hash(name);
+       size_t          size = dstsym->st_size;
+       const void     *srcaddr;
+       const Elf_Sym  *srcsym = NULL;
+       Obj_Entry      *srcobj;
+
+       for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
+               if ((srcsym = _rtld_symlook_obj(name, hash, srcobj, false)) != NULL)
+                       break;
+
+       if (srcobj == NULL) {
+               _rtld_error("Undefined symbol \"%s\" referenced from COPY"
+                   " relocation in %s", name, dstobj->path);
+               return (-1);
+       }
+       srcaddr = (const void *)(srcobj->relocbase + srcsym->st_value);
+       (void)memcpy(dstaddr, srcaddr, size);
+       rdbg(("COPY %s %s %s --> src=%p dst=%p size %ld",
+           dstobj->path, srcobj->path, name, srcaddr,
+           (void *)dstaddr, (long)size));
+       return (0);
+}
+#endif /* RTLD_INHIBIT_COPY_RELOCS */
+
+
+/*
+ * Process the special R_xxx_COPY relocations in the main program.  These
+ * copy data from a shared object into a region in the main program's BSS
+ * segment.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+_rtld_do_copy_relocations(const Obj_Entry *dstobj)
+{
+#ifndef RTLD_INHIBIT_COPY_RELOCS
+
+       /* COPY relocations are invalid elsewhere */
+       assert(!dstobj->isdynamic);
+
+       if (dstobj->rel != NULL) {
+               const Elf_Rel  *rel;
+               for (rel = dstobj->rel; rel < dstobj->rellim; ++rel) {
+                       if (ELF_R_TYPE(rel->r_info) == R_TYPE(COPY)) {
+                               Elf_Rela        ourrela;
+                               ourrela.r_info = rel->r_info;
+                               ourrela.r_offset = rel->r_offset;
+                               ourrela.r_addend = 0;
+                               if (_rtld_do_copy_relocation(dstobj,
+                                   &ourrela) < 0)
+                                       return (-1);
+                       }
+               }
+       }
+       if (dstobj->rela != NULL) {
+               const Elf_Rela *rela;
+               for (rela = dstobj->rela; rela < dstobj->relalim; ++rela) {
+                       if (ELF_R_TYPE(rela->r_info) == R_TYPE(COPY)) {
+                               if (_rtld_do_copy_relocation(dstobj, rela) < 0)
+                                       return (-1);
+                       }
+               }
+       }
+#endif /* RTLD_INHIBIT_COPY_RELOCS */
+
+       return (0);
+}
+
+/*
+ * Relocate newly-loaded shared objects.  The argument is a pointer to
+ * the Obj_Entry for the first such object.  All objects from the first
+ * to the end of the list of objects are relocated.  Returns 0 on success,
+ * or -1 on failure.
+ */
+int
+_rtld_relocate_objects(Obj_Entry *first, bool bind_now)
+{
+       Obj_Entry *obj;
+       int ok = 1;
+
+       for (obj = first; obj != NULL; obj = obj->next) {
+               if (obj->nbuckets == 0 || obj->nchains == 0 ||
+                   obj->buckets == NULL || obj->symtab == NULL ||
+                   obj->strtab == NULL) {
+                       _rtld_error("%s: Shared object has no run-time"
+                           " symbol table", obj->path);
+                       return -1;
+               }
+               if (obj->nbuckets == UINT32_MAX) {
+                       _rtld_error("%s: Symbol table too large", obj->path);
+                       return -1;
+               }
+               rdbg((" relocating %s (%ld/%ld rel/rela, %ld/%ld plt rel/rela)",
+                   obj->path,
+                   (long)(obj->rellim - obj->rel),
+                   (long)(obj->relalim - obj->rela),
+                   (long)(obj->pltrellim - obj->pltrel),
+                   (long)(obj->pltrelalim - obj->pltrela)));
+
+               if (obj->textrel) {
+                       /*
+                        * There are relocations to the write-protected text
+                        * segment.
+                        */
+                       if (mprotect(obj->mapbase, obj->textsize,
+                               PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {
+                               _rtld_error("%s: Cannot write-enable text "
+                                   "segment: %s", obj->path, xstrerror(errno));
+                               return -1;
+                       }
+               }
+               dbg(("doing non-PLT relocations"));
+               if (_rtld_relocate_nonplt_objects(obj) < 0)
+                       ok = 0;
+               if (obj->textrel) {     /* Re-protected the text segment. */
+                       if (mprotect(obj->mapbase, obj->textsize,
+                                    PROT_READ | PROT_EXEC) == -1) {
+                               _rtld_error("%s: Cannot write-protect text "
+                                   "segment: %s", obj->path, xstrerror(errno));
+                               return -1;
+                       }
+               }
+               dbg(("doing lazy PLT binding"));
+               if (_rtld_relocate_plt_lazy(obj) < 0)
+                       ok = 0;
+#if defined(__hppa__)
+               bind_now = 1;
+#endif
+               if (obj->z_now || bind_now) {
+                       dbg(("doing immediate PLT binding"));
+                       if (_rtld_relocate_plt_objects(obj) < 0)
+                               ok = 0;
+               }
+               if (!ok)
+                       return -1;
+
+               /* Set some sanity-checking numbers in the Obj_Entry. */
+               obj->magic = RTLD_MAGIC;
+               obj->version = RTLD_VERSION;
+
+               /* Fill in the dynamic linker entry points. */
+               obj->dlopen = dlopen;
+               obj->dlsym = dlsym;
+               obj->dlerror = dlerror;
+               obj->dlclose = dlclose;
+               obj->dladdr = dladdr;
+
+               dbg(("fixing up PLTGOT"));
+               /* Set the special PLTGOT entries. */
+               if (obj->pltgot != NULL)
+                       _rtld_setup_pltgot(obj);
+       }
+
+       return 0;
+}
diff --git a/libexec/ld.elf_so/rtld.c b/libexec/ld.elf_so/rtld.c
new file mode 100644 (file)
index 0000000..24528c3
--- /dev/null
@@ -0,0 +1,1265 @@
+/*     $NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $  */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * Copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp@polstra.com>.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $");
+#endif /* not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <dirent.h>
+
+#include <ctype.h>
+
+#include <dlfcn.h>
+#include "debug.h"
+#include "rtld.h"
+
+#if !defined(lint)
+#include "sysident.h"
+#endif
+
+/*
+ * Function declarations.
+ */
+static void     _rtld_init(caddr_t, caddr_t, const char *);
+static void     _rtld_exit(void);
+
+Elf_Addr        _rtld(Elf_Addr *, Elf_Addr);
+
+
+/*
+ * Data declarations.
+ */
+static char    *error_message; /* Message for dlopen(), or NULL */
+
+struct r_debug  _rtld_debug;   /* for GDB; */
+bool            _rtld_trust;   /* False for setuid and setgid programs */
+Obj_Entry      *_rtld_objlist; /* Head of linked list of shared objects */
+Obj_Entry     **_rtld_objtail; /* Link field of last object in list */
+Obj_Entry      *_rtld_objmain; /* The main program shared object */
+Obj_Entry       _rtld_objself; /* The dynamic linker shared object */
+u_int          _rtld_objcount; /* Number of objects in _rtld_objlist */
+u_int          _rtld_objloads; /* Number of objects loaded in _rtld_objlist */
+const char     _rtld_path[] = _PATH_RTLD;
+
+/* Initialize a fake symbol for resolving undefined weak references. */
+Elf_Sym                _rtld_sym_zero = {
+    .st_info   = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+    .st_shndx  = SHN_ABS,
+};
+size_t _rtld_pagesz;   /* Page size, as provided by kernel */
+
+Search_Path    *_rtld_default_paths;
+Search_Path    *_rtld_paths;
+
+Library_Xform  *_rtld_xforms;
+
+/*
+ * Global declarations normally provided by crt0.
+ */
+char           *__progname;
+char          **environ;
+
+#if defined(RTLD_DEBUG)
+#ifndef __sh__
+extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
+#else  /* 32-bit SuperH */
+register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12");
+#endif
+#endif /* RTLD_DEBUG */
+extern Elf_Dyn  _DYNAMIC;
+
+static void _rtld_call_fini_functions(int);
+static void _rtld_call_init_functions(void);
+static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int);
+static void _rtld_initlist_tsort(Objlist *, int);
+static Obj_Entry *_rtld_dlcheck(void *);
+static void _rtld_init_dag(Obj_Entry *);
+static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *);
+static void _rtld_objlist_remove(Objlist *, Obj_Entry *);
+static void _rtld_objlist_clear(Objlist *);
+static void _rtld_unload_object(Obj_Entry *, bool);
+static void _rtld_unref_dag(Obj_Entry *);
+static Obj_Entry *_rtld_obj_from_addr(const void *);
+
+static void
+_rtld_call_fini_functions(int force)
+{
+       Objlist_Entry *elm;
+       Objlist finilist;
+       Obj_Entry *obj;
+
+       dbg(("_rtld_call_fini_functions(%d)", force));
+
+       SIMPLEQ_INIT(&finilist);
+       _rtld_initlist_tsort(&finilist, 1);
+
+       /* First pass: objects _not_ marked with DF_1_INITFIRST. */
+       SIMPLEQ_FOREACH(elm, &finilist, link) {
+               obj = elm->obj;
+               if (obj->refcount > 0 && !force) {
+                       continue;
+               }
+               if (obj->fini == NULL || obj->fini_called || obj->z_initfirst) {
+                       continue;
+               }
+               dbg (("calling fini function %s at %p",  obj->path,
+                   (void *)obj->fini));
+               obj->fini_called = 1;
+               (*obj->fini)();
+       }
+
+       /* Second pass: objects marked with DF_1_INITFIRST. */
+       SIMPLEQ_FOREACH(elm, &finilist, link) {
+               obj = elm->obj;
+               if (obj->refcount > 0 && !force) {
+                       continue;
+               }
+               if (obj->fini == NULL || obj->fini_called) {
+                       continue;
+               }
+               dbg (("calling fini function %s at %p (DF_1_INITFIRST)",
+                   obj->path, (void *)obj->fini));
+               obj->fini_called = 1;
+               (*obj->fini)();
+       }
+
+        _rtld_objlist_clear(&finilist);
+}
+
+static void
+_rtld_call_init_functions()
+{
+       Objlist_Entry *elm;
+       Objlist initlist;
+       Obj_Entry *obj;
+
+       dbg(("_rtld_call_init_functions()"));
+       SIMPLEQ_INIT(&initlist);
+       _rtld_initlist_tsort(&initlist, 0);
+
+       /* First pass: objects marked with DF_1_INITFIRST. */
+       SIMPLEQ_FOREACH(elm, &initlist, link) {
+               obj = elm->obj;
+               if (obj->init == NULL || obj->init_called || !obj->z_initfirst) {
+                       continue;
+               }
+               dbg (("calling init function %s at %p (DF_1_INITFIRST)",
+                   obj->path, (void *)obj->init));
+               obj->init_called = 1;
+               (*obj->init)();
+       }
+
+       /* Second pass: all other objects. */
+       SIMPLEQ_FOREACH(elm, &initlist, link) {
+               obj = elm->obj;
+               if (obj->init == NULL || obj->init_called) {
+                       continue;
+               }
+               dbg (("calling init function %s at %p",  obj->path,
+                   (void *)obj->init));
+               obj->init_called = 1;
+               (*obj->init)();
+       }
+
+        _rtld_objlist_clear(&initlist);
+}
+
+/*
+ * Initialize the dynamic linker.  The argument is the address at which
+ * the dynamic linker has been mapped into memory.  The primary task of
+ * this function is to create an Obj_Entry for the dynamic linker and
+ * to resolve the PLT relocation for platforms that need it (those that
+ * define __HAVE_FUNCTION_DESCRIPTORS
+ */
+static void
+_rtld_init(caddr_t mapbase, caddr_t relocbase, const char *execname)
+{
+
+       /* Conjure up an Obj_Entry structure for the dynamic linker. */
+       _rtld_objself.path = __UNCONST(_rtld_path);
+       _rtld_objself.pathlen = sizeof(_rtld_path)-1;
+       _rtld_objself.rtld = true;
+       _rtld_objself.mapbase = mapbase;
+       _rtld_objself.relocbase = relocbase;
+       _rtld_objself.dynamic = (Elf_Dyn *) &_DYNAMIC;
+       _rtld_objself.strtab = "_rtld_sym_zero";
+
+       /*
+        * Set value to -relocbase so that
+        *
+        *     _rtld_objself.relocbase + _rtld_sym_zero.st_value == 0
+        *
+        * This allows unresolved references to weak symbols to be computed
+        * to a value of 0.
+        */
+       _rtld_sym_zero.st_value = -(uintptr_t)relocbase;
+
+       _rtld_digest_dynamic(_rtld_path, &_rtld_objself);
+       assert(!_rtld_objself.needed);
+#if !defined(__hppa__)
+       assert(!_rtld_objself.pltrel && !_rtld_objself.pltrela);
+#else
+       _rtld_relocate_plt_objects(&_rtld_objself);
+#endif
+#if !defined(__mips__) && !defined(__hppa__)
+       assert(!_rtld_objself.pltgot);
+#endif
+#if !defined(__arm__) && !defined(__mips__) && !defined(__sh__)
+       /* ARM, MIPS and SH{3,5} have a bogus DT_TEXTREL. */
+       assert(!_rtld_objself.textrel);
+#endif
+
+       _rtld_add_paths(execname, &_rtld_default_paths,
+           RTLD_DEFAULT_LIBRARY_PATH);
+
+#ifdef RTLD_ARCH_SUBDIR
+       _rtld_add_paths(execname, &_rtld_default_paths,
+           RTLD_DEFAULT_LIBRARY_PATH "/" RTLD_ARCH_SUBDIR);
+#endif
+
+       /*
+        * Set up the _rtld_objlist pointer, so that rtld symbols can be found.
+        */
+       _rtld_objlist = &_rtld_objself;
+
+       /* Make the object list empty again. */
+       _rtld_objlist = NULL;
+       _rtld_objtail = &_rtld_objlist;
+       _rtld_objcount = 0;
+
+       _rtld_debug.r_brk = _rtld_debug_state;
+       _rtld_debug.r_state = RT_CONSISTENT;
+}
+
+/*
+ * Cleanup procedure.  It will be called (by the atexit() mechanism) just
+ * before the process exits.
+ */
+static void
+_rtld_exit(void)
+{
+       dbg(("rtld_exit()"));
+
+       _rtld_call_fini_functions(1);
+}
+
+/*
+ * Main entry point for dynamic linking.  The argument is the stack
+ * pointer.  The stack is expected to be laid out as described in the
+ * SVR4 ABI specification, Intel 386 Processor Supplement.  Specifically,
+ * the stack pointer points to a word containing ARGC.  Following that
+ * in the stack is a null-terminated sequence of pointers to argument
+ * strings.  Then comes a null-terminated sequence of pointers to
+ * environment strings.  Finally, there is a sequence of "auxiliary
+ * vector" entries.
+ *
+ * This function returns the entry point for the main program, the dynamic
+ * linker's exit procedure in sp[0], and a pointer to the main object in
+ * sp[1].
+ */
+Elf_Addr
+_rtld(Elf_Addr *sp, Elf_Addr relocbase)
+{
+       const AuxInfo  *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr,
+                      *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid,
+                      *pAUX_ruid, *pAUX_rgid;
+       const AuxInfo  *pAUX_pagesz;
+       char          **env, **oenvp;
+       const AuxInfo  *aux;
+       const AuxInfo  *auxp;
+       Elf_Addr       *const osp = sp;
+       bool            bind_now = 0;
+       const char     *ld_bind_now, *ld_preload, *ld_library_path;
+       const char    **argv;
+       const char     *execname;
+       long            argc;
+       const char **real___progname;
+       const Obj_Entry **real___mainprog_obj;
+       char ***real_environ;
+#ifdef DEBUG
+       int i = 0;
+       const char     *ld_debug;
+#endif
+
+       /*
+         * On entry, the dynamic linker itself has not been relocated yet.
+         * Be very careful not to reference any global data until after
+         * _rtld_init has returned.  It is OK to reference file-scope statics
+         * and string constants, and to call static and global functions.
+         */
+       /* Find the auxiliary vector on the stack. */
+       /* first Elf_Word reserved to address of exit routine */
+#if defined(RTLD_DEBUG)
+       debug = 1;
+       dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp,
+           (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase));
+       dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_,
+           &_DYNAMIC));
+       dbg(("_ctype_ is %p", _ctype_));
+#endif
+
+       sp += 2;                /* skip over return argument space */
+       argv = (const char **) &sp[1];
+       argc = *(long *)sp;
+       sp += 2 + argc;         /* Skip over argc, arguments, and NULL
+                                * terminator */
+       env = (char **) sp;
+       while (*sp++ != 0) {    /* Skip over environment, and NULL terminator */
+#if defined(RTLD_DEBUG)
+               dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1]));
+#endif
+       }
+       aux = (const AuxInfo *) sp;
+
+       pAUX_base = pAUX_entry = pAUX_execfd = NULL;
+       pAUX_phdr = pAUX_phent = pAUX_phnum = NULL;
+       pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL;
+       pAUX_pagesz = NULL;
+
+       execname = NULL;
+
+       /* Digest the auxiliary vector. */
+       for (auxp = aux; auxp->a_type != AT_NULL; ++auxp) {
+               switch (auxp->a_type) {
+               case AT_BASE:
+                       pAUX_base = auxp;
+                       break;
+               case AT_ENTRY:
+                       pAUX_entry = auxp;
+                       break;
+               case AT_EXECFD:
+                       pAUX_execfd = auxp;
+                       break;
+               case AT_PHDR:
+                       pAUX_phdr = auxp;
+                       break;
+               case AT_PHENT:
+                       pAUX_phent = auxp;
+                       break;
+               case AT_PHNUM:
+                       pAUX_phnum = auxp;
+                       break;
+#ifdef AT_EUID
+               case AT_EUID:
+                       pAUX_euid = auxp;
+                       break;
+               case AT_RUID:
+                       pAUX_ruid = auxp;
+                       break;
+               case AT_EGID:
+                       pAUX_egid = auxp;
+                       break;
+               case AT_RGID:
+                       pAUX_rgid = auxp;
+                       break;
+#endif
+#ifdef AT_SUN_EXECNAME
+               case AT_SUN_EXECNAME:
+                       execname = (const char *)(const void *)auxp->a_v;
+                       break;
+#endif
+               case AT_PAGESZ:
+                       pAUX_pagesz = auxp;
+                       break;
+               }
+       }
+
+       /* Initialize and relocate ourselves. */
+       if (pAUX_base == NULL) {
+               _rtld_error("Bad pAUX_base");
+               _rtld_die();
+       }
+       assert(pAUX_pagesz != NULL);
+       _rtld_pagesz = (int)pAUX_pagesz->a_v;
+       _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname);
+
+       __progname = _rtld_objself.path;
+       environ = env;
+
+       _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) ==
+           (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) &&
+           ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) ==
+           (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid()));
+
+#ifdef DEBUG
+       ld_debug = NULL;
+#endif
+       ld_bind_now = NULL;
+       ld_library_path = NULL;
+       ld_preload = NULL;
+       /*
+        * Inline avoid using normal getenv/unsetenv here as the libc
+        * code is quite a bit more complicated.
+        */
+       for (oenvp = env; *env != NULL; ++env) {
+               static const char bind_var[] = "LD_BIND_NOW=";
+               static const char debug_var[] =  "LD_DEBUG=";
+               static const char path_var[] = "LD_LIBRARY_PATH=";
+               static const char preload_var[] = "LD_PRELOAD=";
+#define LEN(x) (sizeof(x) - 1)
+
+               if ((*env)[0] != 'L' || (*env)[1] != 'D') {
+                       /*
+                        * Special case to skip most entries without
+                        * the more expensive calls to strncmp.
+                        */
+                       *oenvp++ = *env;
+               } else if (strncmp(*env, debug_var, LEN(debug_var)) == 0) {
+                       if (_rtld_trust) {
+#ifdef DEBUG
+                               ld_debug = *env + LEN(debug_var);
+#endif
+                               *oenvp++ = *env;
+                       }
+               } else if (strncmp(*env, bind_var, LEN(bind_var)) == 0) {
+                       ld_bind_now = *env + LEN(bind_var);
+               } else if (strncmp(*env, path_var, LEN(path_var)) == 0) {
+                       if (_rtld_trust) {
+                               ld_library_path = *env + LEN(path_var);
+                               *oenvp++ = *env;
+                       }
+               } else if (strncmp(*env, preload_var, LEN(preload_var)) == 0) {
+                       if (_rtld_trust) {
+                               ld_preload = *env + LEN(preload_var);
+                               *oenvp++ = *env;
+                       }
+               } else {
+                       *oenvp++ = *env;
+               }
+#undef LEN
+       }
+       *oenvp++ = NULL;
+
+       if (ld_bind_now != NULL && *ld_bind_now != '\0')
+               bind_now = true;
+       if (_rtld_trust) {
+#ifdef DEBUG
+#ifdef RTLD_DEBUG
+               debug = 0;
+#endif
+               if (ld_debug != NULL && *ld_debug != '\0')
+                       debug = 1;
+#endif
+               _rtld_add_paths(execname, &_rtld_paths, ld_library_path);
+       } else {
+               execname = NULL;
+       }
+       _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms,
+           _PATH_LD_HINTS);
+       dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p",
+            _rtld_objself.mapbase, _rtld_objself.relocbase));
+
+       /*
+         * Load the main program, or process its program header if it is
+         * already loaded.
+         */
+       if (pAUX_execfd != NULL) {      /* Load the main program. */
+               int             fd = pAUX_execfd->a_v;
+               const char *obj_name = argv[0] ? argv[0] : "main program";
+               dbg(("loading main program"));
+               _rtld_objmain = _rtld_map_object(obj_name, fd, NULL);
+               close(fd);
+               if (_rtld_objmain == NULL)
+                       _rtld_die();
+       } else {                /* Main program already loaded. */
+               const Elf_Phdr *phdr;
+               int             phnum;
+               caddr_t         entry;
+
+               dbg(("processing main program's program header"));
+               assert(pAUX_phdr != NULL);
+               phdr = (const Elf_Phdr *) pAUX_phdr->a_v;
+               assert(pAUX_phnum != NULL);
+               phnum = pAUX_phnum->a_v;
+               assert(pAUX_phent != NULL);
+               assert(pAUX_phent->a_v == sizeof(Elf_Phdr));
+               assert(pAUX_entry != NULL);
+               entry = (caddr_t) pAUX_entry->a_v;
+               _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
+               _rtld_objmain->path = xstrdup(argv[0] ? argv[0] :
+                   "main program");
+               _rtld_objmain->pathlen = strlen(_rtld_objmain->path);
+       }
+
+       _rtld_objmain->mainprog = true;
+       
+       /*
+        * Get the actual dynamic linker pathname from the executable if
+        * possible.  (It should always be possible.)  That ensures that
+        * gdb will find the right dynamic linker even if a non-standard
+        * one is being used.
+        */
+       if (_rtld_objmain->interp != NULL &&
+           strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0)
+               _rtld_objself.path = xstrdup(_rtld_objmain->interp);
+       dbg(("actual dynamic linker is %s", _rtld_objself.path));
+       
+       _rtld_digest_dynamic(execname, _rtld_objmain);
+
+       /* Link the main program into the list of objects. */
+       *_rtld_objtail = _rtld_objmain;
+       _rtld_objtail = &_rtld_objmain->next;
+       _rtld_objcount++;
+       _rtld_objloads++;
+
+       _rtld_linkmap_add(_rtld_objmain);
+       _rtld_linkmap_add(&_rtld_objself);
+
+       ++_rtld_objmain->refcount;
+       _rtld_objmain->mainref = 1;
+       _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain);
+
+       if (ld_preload) {
+               /*
+                * Pre-load user-specified objects after the main program
+                * but before any shared object dependencies.
+                */
+               dbg(("preloading objects"));
+               if (_rtld_preload(ld_preload) == -1)
+                       _rtld_die();
+       }
+
+       dbg(("loading needed objects"));
+       if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1)
+               _rtld_die();
+
+       dbg(("relocating objects"));
+       if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1)
+               _rtld_die();
+
+       dbg(("doing copy relocations"));
+       if (_rtld_do_copy_relocations(_rtld_objmain) == -1)
+               _rtld_die();
+
+       /*
+        * Set the __progname,  environ and, __mainprog_obj before
+        * calling anything that might use them.
+        */
+       real___progname = _rtld_objmain_sym("__progname");
+       if (real___progname) {
+               if (argv[0] != NULL) {
+                       if ((*real___progname = strrchr(argv[0], '/')) == NULL)
+                               (*real___progname) = argv[0];
+                       else
+                               (*real___progname)++;
+               } else {
+                       (*real___progname) = NULL;
+               }
+       }
+       real_environ = _rtld_objmain_sym("environ");
+       if (real_environ)
+               *real_environ = environ;
+       /*
+        * Set __mainprog_obj for old binaries.
+        */
+       real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj");
+       if (real___mainprog_obj)
+               *real___mainprog_obj = _rtld_objmain;
+
+       dbg(("calling _init functions"));
+       _rtld_call_init_functions();
+
+       dbg(("control at program entry point = %p, obj = %p, exit = %p",
+            _rtld_objmain->entry, _rtld_objmain, _rtld_exit));
+
+       /*
+        * Return with the entry point and the exit procedure in at the top
+        * of stack.
+        */
+
+       _rtld_debug_state();    /* say hello to gdb! */
+
+       ((void **) osp)[0] = _rtld_exit;
+       ((void **) osp)[1] = _rtld_objmain;
+       return (Elf_Addr) _rtld_objmain->entry;
+}
+
+void
+_rtld_die(void)
+{
+       const char *msg = dlerror();
+
+       if (msg == NULL)
+               msg = "Fatal error";
+       xerrx(1, "%s", msg);
+}
+
+static Obj_Entry *
+_rtld_dlcheck(void *handle)
+{
+       Obj_Entry *obj;
+
+       for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
+               if (obj == (Obj_Entry *) handle)
+                       break;
+
+       if (obj == NULL || obj->dl_refcount == 0) {
+               xwarnx("Invalid shared object handle %p", handle);
+               return NULL;
+       }
+       return obj;
+}
+
+static void
+_rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev)
+{
+       Needed_Entry* elm;
+
+       /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */
+
+       if (obj->init_done)
+               return;
+       obj->init_done = 1;
+
+       for (elm = obj->needed; elm != NULL; elm = elm->next) {
+               if (elm->obj != NULL) {
+                       _rtld_initlist_visit(list, elm->obj, rev);
+               }
+       }
+
+       if (rev) {
+               _rtld_objlist_push_head(list, obj);
+       } else {
+               _rtld_objlist_push_tail(list, obj);
+       }
+}
+
+static void
+_rtld_initlist_tsort(Objlist* list, int rev)
+{
+       dbg(("_rtld_initlist_tsort"));
+
+       Obj_Entry* obj;
+
+       for (obj = _rtld_objlist->next; obj; obj = obj->next) {
+               obj->init_done = 0;
+       }
+
+       for (obj = _rtld_objlist->next; obj; obj = obj->next) {
+               _rtld_initlist_visit(list, obj, rev);
+       }
+}
+
+static void
+_rtld_init_dag(Obj_Entry *root)
+{
+
+       _rtld_init_dag1(root, root);
+}
+
+static void
+_rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj)
+{
+       const Needed_Entry *needed;
+
+       if (!obj->mainref) {
+               if (_rtld_objlist_find(&obj->dldags, root))
+                       return;
+               dbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root,
+                   root->path));
+               _rtld_objlist_push_tail(&obj->dldags, root);
+               _rtld_objlist_push_tail(&root->dagmembers, obj);
+       }
+       for (needed = obj->needed; needed != NULL; needed = needed->next)
+               if (needed->obj != NULL)
+                       _rtld_init_dag1(root, needed->obj);
+}
+
+/*
+ * Note, this is called only for objects loaded by dlopen().
+ */
+static void
+_rtld_unload_object(Obj_Entry *root, bool do_fini_funcs)
+{
+
+       _rtld_unref_dag(root);
+       if (root->refcount == 0) { /* We are finished with some objects. */
+               Obj_Entry *obj;
+               Obj_Entry **linkp;
+               Objlist_Entry *elm;
+
+               /* Finalize objects that are about to be unmapped. */
+               if (do_fini_funcs)
+                       _rtld_call_fini_functions(0);
+
+               /* Remove the DAG from all objects' DAG lists. */
+               SIMPLEQ_FOREACH(elm, &root->dagmembers, link)
+                       _rtld_objlist_remove(&elm->obj->dldags, root);
+
+               /* Remove the DAG from the RTLD_GLOBAL list. */
+               if (root->globalref) {
+                       root->globalref = 0;
+                       _rtld_objlist_remove(&_rtld_list_global, root);
+               }
+
+               /* Unmap all objects that are no longer referenced. */
+               linkp = &_rtld_objlist->next;
+               while ((obj = *linkp) != NULL) {
+                       if (obj->refcount == 0) {
+                               dbg(("unloading \"%s\"", obj->path));
+                               if (obj->ehdr != MAP_FAILED)
+                                       munmap(obj->ehdr, _rtld_pagesz);
+                               munmap(obj->mapbase, obj->mapsize);
+                               _rtld_objlist_remove(&_rtld_list_global, obj);
+                               _rtld_linkmap_delete(obj);
+                               *linkp = obj->next;
+                               _rtld_objcount--;
+                               _rtld_obj_free(obj);
+                       } else
+                               linkp = &obj->next;
+               }
+               _rtld_objtail = linkp;
+       }
+}
+
+void
+_rtld_ref_dag(Obj_Entry *root)
+{
+       const Needed_Entry *needed;
+
+       assert(root);
+
+       ++root->refcount;
+
+       dbg(("incremented reference on \"%s\" (%d)", root->path,
+           root->refcount));
+       for (needed = root->needed; needed != NULL;
+            needed = needed->next) {
+               if (needed->obj != NULL)
+                       _rtld_ref_dag(needed->obj);
+       }
+}
+
+static void
+_rtld_unref_dag(Obj_Entry *root)
+{
+
+       assert(root);
+       assert(root->refcount != 0);
+
+       --root->refcount;
+       dbg(("decremented reference on \"%s\" (%d)", root->path,
+           root->refcount));
+
+       if (root->refcount == 0) {
+               const Needed_Entry *needed;
+
+               for (needed = root->needed; needed != NULL;
+                    needed = needed->next) {
+                       if (needed->obj != NULL)
+                               _rtld_unref_dag(needed->obj);
+               }
+       }
+}
+
+__strong_alias(__dlclose,dlclose)
+int
+dlclose(void *handle)
+{
+       Obj_Entry *root = _rtld_dlcheck(handle);
+
+       if (root == NULL)
+               return -1;
+
+       _rtld_debug.r_state = RT_DELETE;
+       _rtld_debug_state();
+
+       --root->dl_refcount;
+       _rtld_unload_object(root, true);
+
+       _rtld_debug.r_state = RT_CONSISTENT;
+       _rtld_debug_state();
+
+       return 0;
+}
+
+__strong_alias(__dlerror,dlerror)
+char *
+dlerror(void)
+{
+       char *msg = error_message;
+
+       error_message = NULL;
+       return msg;
+}
+
+__strong_alias(__dlopen,dlopen)
+void *
+dlopen(const char *name, int mode)
+{
+       Obj_Entry **old_obj_tail = _rtld_objtail;
+       Obj_Entry *obj = NULL;
+       int flags = _RTLD_DLOPEN;
+       bool nodelete;
+       bool now;
+
+       flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0;
+       flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0;
+       
+       nodelete = (mode & RTLD_NODELETE) ? true : false;
+       now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false;
+
+       _rtld_debug.r_state = RT_ADD;
+       _rtld_debug_state();
+
+       if (name == NULL) {
+               obj = _rtld_objmain;
+               obj->refcount++;
+       } else
+               obj = _rtld_load_library(name, _rtld_objmain, flags);
+
+
+       if (obj != NULL) {
+               ++obj->dl_refcount;
+               if (*old_obj_tail != NULL) {    /* We loaded something new. */
+                       assert(*old_obj_tail == obj);
+
+                       if (_rtld_load_needed_objects(obj, flags) == -1 ||
+                           (_rtld_init_dag(obj),
+                           _rtld_relocate_objects(obj,
+                           (now || obj->z_now))) == -1) {
+                               _rtld_unload_object(obj, false);
+                               obj->dl_refcount--;
+                               obj = NULL;
+                       } else {
+                               _rtld_call_init_functions();
+                       }
+               }
+               if (obj != NULL) {
+                       if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) {
+                               dbg(("dlopen obj %s nodelete", obj->path));
+                               _rtld_ref_dag(obj);
+                               obj->z_nodelete = obj->ref_nodel = true;
+                       }
+               }
+       }
+       _rtld_debug.r_state = RT_CONSISTENT;
+       _rtld_debug_state();
+
+       return obj;
+}
+
+/*
+ * Find a symbol in the main program.
+ */
+void *
+_rtld_objmain_sym(const char *name)
+{
+       unsigned long hash;
+       const Elf_Sym *def;
+       const Obj_Entry *obj;
+       DoneList donelist;
+
+       hash = _rtld_elf_hash(name);
+       obj = _rtld_objmain;
+       _rtld_donelist_init(&donelist);
+
+       def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, false,
+           &donelist);
+
+       if (def != NULL)
+               return obj->relocbase + def->st_value;
+       return NULL;
+}
+
+#ifdef __powerpc__
+static void *
+hackish_return_address(void)
+{
+       return __builtin_return_address(1);
+}
+#endif
+
+__strong_alias(__dlsym,dlsym)
+void *
+dlsym(void *handle, const char *name)
+{
+       const Obj_Entry *obj;
+       unsigned long hash;
+       const Elf_Sym *def;
+       const Obj_Entry *defobj;
+       void *retaddr;
+       DoneList donelist; 
+       
+       hash = _rtld_elf_hash(name);
+       def = NULL;
+       defobj = NULL;
+       
+       switch ((intptr_t)handle) {
+       case (intptr_t)NULL:
+       case (intptr_t)RTLD_NEXT:
+       case (intptr_t)RTLD_DEFAULT:
+       case (intptr_t)RTLD_SELF:
+#ifdef __powerpc__
+               retaddr = hackish_return_address();
+#else
+               retaddr = __builtin_return_address(0);
+#endif
+               if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
+                       _rtld_error("Cannot determine caller's shared object");
+                       return NULL;
+               }
+
+               switch ((intptr_t)handle) {
+               case (intptr_t)NULL:     /* Just the caller's shared object. */
+                       def = _rtld_symlook_obj(name, hash, obj, false);
+                       defobj = obj;
+                       break;
+
+               case (intptr_t)RTLD_NEXT:       /* Objects after callers */
+                       obj = obj->next;
+                       /*FALLTHROUGH*/
+
+               case (intptr_t)RTLD_SELF:       /* Caller included */
+                       for (; obj; obj = obj->next) {
+                               if ((def = _rtld_symlook_obj(name, hash, obj,
+                                   false)) != NULL) {
+                                       defobj = obj;
+                                       break;
+                               }
+                       }
+                       break;
+
+               case (intptr_t)RTLD_DEFAULT:
+                       def = _rtld_symlook_default(name, hash, obj, &defobj,
+                           false);
+                       break;
+
+               default:
+                       abort();
+               }
+               break;
+
+       default:
+               if ((obj = _rtld_dlcheck(handle)) == NULL)
+                       return NULL;
+               
+               _rtld_donelist_init(&donelist);
+
+               if (obj->mainprog) {
+                       /* Search main program and all libraries loaded by it */
+                       def = _rtld_symlook_list(name, hash, &_rtld_list_main,
+                           &defobj, false, &donelist);
+               } else {
+                       Needed_Entry fake;
+                       DoneList depth;
+
+                       /* Search the object and all the libraries loaded by it. */
+                       fake.next = NULL;
+                       fake.obj = __UNCONST(obj);
+                       fake.name = 0;
+
+                       _rtld_donelist_init(&depth);
+                       def = _rtld_symlook_needed(name, hash, &fake, &defobj,
+                           false, &donelist, &depth);
+               }
+
+               break;
+       }
+       
+       if (def != NULL) {
+#ifdef __HAVE_FUNCTION_DESCRIPTORS
+               if (ELF_ST_TYPE(def->st_info) == STT_FUNC)
+                       return (void *)_rtld_function_descriptor_alloc(defobj, 
+                           def, 0);
+#endif /* __HAVE_FUNCTION_DESCRIPTORS */
+               return defobj->relocbase + def->st_value;
+       }
+       
+       _rtld_error("Undefined symbol \"%s\"", name);
+       return NULL;
+}
+
+__strong_alias(__dladdr,dladdr)
+int
+dladdr(const void *addr, Dl_info *info)
+{
+       const Obj_Entry *obj;
+       const Elf_Sym *def, *best_def;
+       void *symbol_addr;
+       unsigned long symoffset;
+       
+#ifdef __HAVE_FUNCTION_DESCRIPTORS
+       addr = _rtld_function_descriptor_function(addr);
+#endif /* __HAVE_FUNCTION_DESCRIPTORS */
+
+       obj = _rtld_obj_from_addr(addr);
+       if (obj == NULL) {
+               _rtld_error("No shared object contains address");
+               return 0;
+       }
+       info->dli_fname = obj->path;
+       info->dli_fbase = obj->mapbase;
+       info->dli_saddr = (void *)0;
+       info->dli_sname = NULL;
+       
+       /*
+        * Walk the symbol list looking for the symbol whose address is
+        * closest to the address sent in.
+        */
+       best_def = NULL;
+       for (symoffset = 0; symoffset < obj->nchains; symoffset++) {
+               def = obj->symtab + symoffset;
+
+               /*
+                * For skip the symbol if st_shndx is either SHN_UNDEF or
+                * SHN_COMMON.
+                */
+               if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON)
+                       continue;
+
+               /*
+                * If the symbol is greater than the specified address, or if it
+                * is further away from addr than the current nearest symbol,
+                * then reject it.
+                */
+               symbol_addr = obj->relocbase + def->st_value;
+               if (symbol_addr > addr || symbol_addr < info->dli_saddr)
+                       continue;
+
+               /* Update our idea of the nearest symbol. */
+               info->dli_sname = obj->strtab + def->st_name;
+               info->dli_saddr = symbol_addr;
+               best_def = def;
+
+               /* Exact match? */
+               if (info->dli_saddr == addr)
+                       break;
+       }
+
+#ifdef __HAVE_FUNCTION_DESCRIPTORS
+       if (best_def != NULL && ELF_ST_TYPE(best_def->st_info) == STT_FUNC)
+               info->dli_saddr = (void *)_rtld_function_descriptor_alloc(obj, 
+                   best_def, 0);
+#endif /* __HAVE_FUNCTION_DESCRIPTORS */
+
+       return 1;
+}
+
+__strong_alias(__dlinfo,dlinfo)
+int
+dlinfo(void *handle, int req, void *v)
+{
+       const Obj_Entry *obj;
+       void *retaddr;
+
+       if (handle == RTLD_SELF) {
+#ifdef __powerpc__
+               retaddr = hackish_return_address();
+#else
+               retaddr = __builtin_return_address(0);
+#endif
+               if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
+                       _rtld_error("Cannot determine caller's shared object");
+                       return -1;
+               }
+       } else {
+               if ((obj = _rtld_dlcheck(handle)) == NULL) {
+                       _rtld_error("Invalid handle");
+                       return -1;
+               }
+       }
+
+       switch (req) {
+       case RTLD_DI_LINKMAP:
+               {
+               const struct link_map **map = v;
+
+               *map = &obj->linkmap;
+               break;
+               }
+
+       default:
+               _rtld_error("Invalid request");
+               return -1;
+       }
+
+       return 0;
+}
+
+__strong_alias(__dl_iterate_phdr,dl_iterate_phdr);
+int
+dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *param)
+{
+       struct dl_phdr_info phdr_info;
+       const Obj_Entry *obj;
+       int error = 0;
+
+       for (obj = _rtld_objlist;  obj != NULL;  obj = obj->next) {
+               phdr_info.dlpi_addr = (Elf_Addr)obj->relocbase;
+               phdr_info.dlpi_name = STAILQ_FIRST(&obj->names) ?
+                   STAILQ_FIRST(&obj->names)->name : obj->path;
+               phdr_info.dlpi_phdr = obj->phdr;
+               phdr_info.dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
+#if 1
+               phdr_info.dlpi_tls_modid = 0;
+               phdr_info.dlpi_tls_data = 0;
+#else
+               phdr_info.dlpi_tls_modid = obj->tlsindex;
+               phdr_info.dlpi_tls_data = obj->tlsinit;
+#endif
+               phdr_info.dlpi_adds = _rtld_objloads;
+               phdr_info.dlpi_subs = _rtld_objloads - _rtld_objcount;
+
+               error = callback(&phdr_info, sizeof(phdr_info), param);
+               if (error)
+                       break;
+       }
+
+       return error;
+}
+
+/*
+ * Error reporting function.  Use it like printf.  If formats the message
+ * into a buffer, and sets things up so that the next call to dlerror()
+ * will return the message.
+ */
+void
+_rtld_error(const char *fmt,...)
+{
+       static char     buf[512];
+       va_list         ap;
+
+       va_start(ap, fmt);
+       xvsnprintf(buf, sizeof buf, fmt, ap);
+       error_message = buf;
+       va_end(ap);
+}
+
+void
+_rtld_debug_state(void)
+{
+
+       /* do nothing */
+}
+
+void
+_rtld_linkmap_add(Obj_Entry *obj)
+{
+       struct link_map *l = &obj->linkmap;
+       struct link_map *prev;
+
+       obj->linkmap.l_name = obj->path;
+       obj->linkmap.l_addr = obj->relocbase;
+       obj->linkmap.l_ld = obj->dynamic;
+#ifdef __mips__
+       /* XXX This field is not standard and will be removed eventually. */
+       obj->linkmap.l_offs = obj->relocbase;
+#endif
+
+       if (_rtld_debug.r_map == NULL) {
+               _rtld_debug.r_map = l;
+               return;
+       }
+
+       /*
+        * Scan to the end of the list, but not past the entry for the
+        * dynamic linker, which we want to keep at the very end.
+        */
+       for (prev = _rtld_debug.r_map;
+           prev->l_next != NULL && prev->l_next != &_rtld_objself.linkmap;
+           prev = prev->l_next);
+
+       l->l_prev = prev;
+       l->l_next = prev->l_next;
+       if (l->l_next != NULL)
+               l->l_next->l_prev = l;
+       prev->l_next = l;
+}
+
+void
+_rtld_linkmap_delete(Obj_Entry *obj)
+{
+       struct link_map *l = &obj->linkmap;
+
+       if (l->l_prev == NULL) {
+               if ((_rtld_debug.r_map = l->l_next) != NULL)
+                       l->l_next->l_prev = NULL;
+               return;
+       }
+       if ((l->l_prev->l_next = l->l_next) != NULL)
+               l->l_next->l_prev = l->l_prev;
+}
+
+static Obj_Entry *
+_rtld_obj_from_addr(const void *addr)
+{
+       Obj_Entry *obj;
+       
+       for (obj = _rtld_objlist;  obj != NULL;  obj = obj->next) {
+               if (addr < (void *) obj->mapbase)
+                       continue;
+               if (addr < (void *) (obj->mapbase + obj->mapsize))
+                       return obj;
+       }
+       return NULL;
+}
+
+static void
+_rtld_objlist_clear(Objlist *list)
+{
+       while (!SIMPLEQ_EMPTY(list)) {
+               Objlist_Entry* elm = SIMPLEQ_FIRST(list);
+               SIMPLEQ_REMOVE_HEAD(list, link);
+               xfree(elm);
+       }
+}
+
+static void
+_rtld_objlist_remove(Objlist *list, Obj_Entry *obj)
+{
+       Objlist_Entry *elm;
+       
+       if ((elm = _rtld_objlist_find(list, obj)) != NULL) {
+               SIMPLEQ_REMOVE(list, elm, Struct_Objlist_Entry, link);
+               xfree(elm);
+       }
+}
diff --git a/libexec/ld.elf_so/rtld.h b/libexec/ld.elf_so/rtld.h
new file mode 100644 (file)
index 0000000..11f0a82
--- /dev/null
@@ -0,0 +1,362 @@
+/*     $NetBSD: rtld.h,v 1.99 2011/01/16 15:56:37 matt Exp $    */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RTLD_H
+#define RTLD_H
+
+#include <dlfcn.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/exec_elf.h>
+#include "rtldenv.h"
+#include "link.h"
+
+#if defined(_RTLD_SOURCE)
+
+#ifndef        RTLD_DEFAULT_LIBRARY_PATH
+#define        RTLD_DEFAULT_LIBRARY_PATH       "/usr/lib"
+#endif
+#define _PATH_LD_HINTS                 "/etc/ld.so.conf"
+
+extern size_t _rtld_pagesz;
+
+#define round_down(x)  ((x) & ~(_rtld_pagesz - 1))
+#define round_up(x)    round_down((x) + _rtld_pagesz - 1)
+
+#define NEW(type)      ((type *) xmalloc(sizeof(type)))
+#define CNEW(type)     ((type *) xcalloc(sizeof(type)))
+
+/*
+ * Fill in a DoneList with an allocation large enough to hold all of
+ * the currently-loaded objects. Keep this in a macro since it calls
+ * alloca and we want that to occur within the scope of the caller.
+ */
+#define _rtld_donelist_init(dlp)                                       \
+    ((dlp)->num_alloc = _rtld_objcount,                                        \
+    (dlp)->objs = alloca((dlp)->num_alloc * sizeof((dlp)->objs[0])),   \
+    assert((dlp)->objs != NULL),                                       \
+    (dlp)->num_used = 0)
+
+#endif /* _RTLD_SOURCE */
+
+/*
+ * C++ has mandated the use of the following keywords for its new boolean
+ * type.  We might as well follow their lead.
+ */
+struct Struct_Obj_Entry;
+
+typedef struct Struct_Objlist_Entry {
+       SIMPLEQ_ENTRY(Struct_Objlist_Entry) link;
+       struct Struct_Obj_Entry *obj;
+} Objlist_Entry;
+
+typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist;
+
+typedef struct Struct_Name_Entry {
+       STAILQ_ENTRY(Struct_Name_Entry) link;
+       char    name[1];
+} Name_Entry;
+
+typedef struct Struct_Needed_Entry {
+       struct Struct_Needed_Entry *next;
+       struct Struct_Obj_Entry *obj;
+       unsigned long   name;   /* Offset of name in string table */
+} Needed_Entry;
+
+typedef struct _rtld_search_path_t {
+       struct _rtld_search_path_t *sp_next;
+       const char     *sp_path;
+       size_t          sp_pathlen;
+} Search_Path;
+
+
+#define RTLD_MAX_ENTRY 10
+#define RTLD_MAX_LIBRARY 4
+#define RTLD_MAX_CTL 2
+typedef struct _rtld_library_xform_t {
+       struct _rtld_library_xform_t *next;
+       char *name;
+       const char *ctlname;
+       struct {
+               char *value;
+               char *library[RTLD_MAX_LIBRARY];
+       } entry[RTLD_MAX_ENTRY];
+} Library_Xform;
+
+/*
+ * Shared object descriptor.
+ *
+ * Items marked with "(%)" are dynamically allocated, and must be freed
+ * when the structure is destroyed.
+ *
+ * The layout of this structure needs to be preserved because pre-2.0 binaries
+ * hard-coded the location of dlopen() and friends.
+ */
+
+#define RTLD_MAGIC     0xd550b87a
+#define RTLD_VERSION   1
+
+typedef struct Struct_Obj_Entry {
+       Elf32_Word      magic;          /* Magic number (sanity check) */
+       Elf32_Word      version;        /* Version number of struct format */
+
+       struct Struct_Obj_Entry *next;
+       char           *path;           /* Pathname of underlying file (%) */
+       int             refcount;
+       int             dl_refcount;    /* Number of times loaded by dlopen */
+
+       /* These items are computed by map_object() or by digest_phdr(). */
+       caddr_t         mapbase;        /* Base address of mapped region */
+       size_t          mapsize;        /* Size of mapped region in bytes */
+       size_t          textsize;       /* Size of text segment in bytes */
+       Elf_Addr        vaddrbase;      /* Base address in shared object file */
+       caddr_t         relocbase;      /* Reloc const = mapbase - *vaddrbase */
+       Elf_Dyn        *dynamic;        /* Dynamic section */
+       caddr_t         entry;          /* Entry point */
+       const Elf_Phdr *phdr;           /* Program header (may be xmalloc'ed) */
+       size_t          phsize;         /* Size of program header in bytes */
+
+       /* Items from the dynamic section. */
+       Elf_Addr       *pltgot;         /* PLTGOT table */
+       const Elf_Rel  *rel;            /* Relocation entries */
+       const Elf_Rel  *rellim;         /* Limit of Relocation entries */
+       const Elf_Rela *rela;           /* Relocation entries */
+       const Elf_Rela *relalim;        /* Limit of Relocation entries */
+       const Elf_Rel  *pltrel;         /* PLT relocation entries */
+       const Elf_Rel  *pltrellim;      /* Limit of PLT relocation entries */
+       const Elf_Rela *pltrela;        /* PLT relocation entries */
+       const Elf_Rela *pltrelalim;     /* Limit of PLT relocation entries */
+       const Elf_Sym  *symtab;         /* Symbol table */
+       const char     *strtab;         /* String table */
+       unsigned long   strsize;        /* Size in bytes of string table */
+#ifdef __mips__
+       Elf_Word        local_gotno;    /* Number of local GOT entries */
+       Elf_Word        symtabno;       /* Number of dynamic symbols */
+       Elf_Word        gotsym;         /* First dynamic symbol in GOT */
+#endif
+
+       const Elf_Symindx *buckets;     /* Hash table buckets array */
+       unsigned long   unused1;        /* Used to be nbuckets */
+       const Elf_Symindx *chains;      /* Hash table chain array */
+       unsigned long   nchains;        /* Number of chains */
+
+       Search_Path    *rpaths;         /* Search path specified in object */
+       Needed_Entry   *needed;         /* Shared objects needed by this (%) */
+
+       void            (*init)(void);  /* Initialization function to call */
+       void            (*fini)(void);  /* Termination function to call */
+
+       /* Entry points for dlopen() and friends. */
+       void           *(*dlopen)(const char *, int);
+       void           *(*dlsym)(void *, const char *);
+       char           *(*dlerror)(void);
+       int             (*dlclose)(void *);
+       int             (*dladdr)(const void *, Dl_info *);
+
+       u_int32_t       mainprog:1,     /* True if this is the main program */
+                       rtld:1,         /* True if this is the dynamic linker */
+                       textrel:1,      /* True if there are relocations to
+                                        * text seg */
+                       symbolic:1,     /* True if generated with
+                                        * "-Bsymbolic" */
+                       printed:1,      /* True if ldd has printed it */
+                       isdynamic:1,    /* True if this is a pure PIC object */
+                       mainref:1,      /* True if on _rtld_list_main */
+                       globalref:1,    /* True if on _rtld_list_global */
+                       init_done:1,    /* True if .init has been added */
+                       init_called:1,  /* True if .init function has been 
+                                        * called */
+                       fini_called:1,  /* True if .fini function has been 
+                                        * called */
+                       z_now:1,        /* True if object's symbols should be
+                                          bound immediately */
+                       z_nodelete:1,   /* True if object should never be
+                                          unloaded */
+                       z_initfirst:1,  /* True if object's .init/.fini take
+                                        * priority over others */
+                       z_noopen:1,     /* True if object should never be
+                                          dlopen'ed */
+                       phdr_loaded:1,  /* Phdr is loaded and doesn't need to
+                                        * be freed. */
+                       ref_nodel:1;    /* Refcount increased to prevent dlclose */
+
+       struct link_map linkmap;        /* for GDB */
+
+       /* These items are computed by map_object() or by digest_phdr(). */
+       const char     *interp; /* Pathname of the interpreter, if any */
+       Objlist         dldags; /* Object belongs to these dlopened DAGs (%) */
+       Objlist         dagmembers;     /* DAG has these members (%) */
+       dev_t           dev;            /* Object's filesystem's device */
+       ino_t           ino;            /* Object's inode number */
+
+       void            *ehdr;
+
+       uint32_t        nbuckets;       /* Number of buckets */
+       uint32_t        nbuckets_m;     /* Precomputed for fast remainder */
+       uint8_t         nbuckets_s1;
+       uint8_t         nbuckets_s2;
+       size_t          pathlen;        /* Pathname length */
+       STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we
+                                                  know about. */
+#ifdef __powerpc__
+       Elf_Addr       *gotptr;         /* GOT table (secure-plt only) */
+#endif
+} Obj_Entry;
+
+typedef struct Struct_DoneList {
+       const Obj_Entry **objs;         /* Array of object pointers */
+       unsigned int num_alloc;         /* Allocated size of the array */
+       unsigned int num_used;          /* Number of array slots used */
+} DoneList;
+
+
+#if defined(_RTLD_SOURCE)
+
+extern struct r_debug _rtld_debug;
+extern Search_Path *_rtld_default_paths;
+extern Obj_Entry *_rtld_objlist;
+extern Obj_Entry **_rtld_objtail;
+extern u_int _rtld_objcount;
+extern u_int _rtld_objloads;
+extern Obj_Entry *_rtld_objmain;
+extern Obj_Entry _rtld_objself;
+extern Search_Path *_rtld_paths;
+extern Library_Xform *_rtld_xforms;
+extern bool _rtld_trust;
+extern Objlist _rtld_list_global;
+extern Objlist _rtld_list_main;
+extern Elf_Sym _rtld_sym_zero;
+
+#define        RTLD_MODEMASK 0x3
+
+/* Flags for _rtld_load_object() and friends. */
+#define        _RTLD_GLOBAL    0x01    /* Add object to global DAG. */
+#define        _RTLD_MAIN      0x02
+#define        _RTLD_NOLOAD    0x04    /* dlopen() specified RTLD_NOLOAD. */
+#define        _RTLD_DLOPEN    0x08    /* Load_object() called from dlopen(). */
+
+/* rtld.c */
+
+/* We export these symbols using _rtld_symbol_lookup and is_exported. */
+__dso_public char *dlerror(void);
+__dso_public void *dlopen(const char *, int);
+__dso_public void *dlsym(void *, const char *);
+__dso_public int dlclose(void *);
+__dso_public int dladdr(const void *, Dl_info *);
+__dso_public int dlinfo(void *, int, void *);
+__dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *),
+    void *);
+
+/* These aren't exported */
+void _rtld_error(const char *, ...)
+     __attribute__((__format__(__printf__,1,2)));
+void _rtld_die(void) __attribute__((__noreturn__));
+void *_rtld_objmain_sym(const char *);
+void _rtld_debug_state(void);
+void _rtld_linkmap_add(Obj_Entry *);
+void _rtld_linkmap_delete(Obj_Entry *);
+void _rtld_objlist_push_head(Objlist *, Obj_Entry *);
+void _rtld_objlist_push_tail(Objlist *, Obj_Entry *);
+Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *);
+void _rtld_ref_dag(Obj_Entry *);
+
+/* expand.c */
+size_t _rtld_expand_path(char *, size_t, const char *, const char *,\
+    const char *);
+
+/* headers.c */
+void _rtld_digest_dynamic(const char *, Obj_Entry *);
+Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t);
+
+/* load.c */
+Obj_Entry *_rtld_load_object(const char *, int);
+int _rtld_load_needed_objects(Obj_Entry *, int);
+int _rtld_preload(const char *);
+
+#define        OBJ_ERR (Obj_Entry *)(-1)
+/* path.c */
+void _rtld_add_paths(const char *, Search_Path **, const char *);
+void _rtld_process_hints(const char *, Search_Path **, Library_Xform **,
+    const char *);
+int _rtld_sysctl(const char *, void *, size_t *);
+
+/* reloc.c */
+int _rtld_do_copy_relocations(const Obj_Entry *);
+int _rtld_relocate_objects(Obj_Entry *, bool);
+int _rtld_relocate_nonplt_objects(Obj_Entry *);
+int _rtld_relocate_plt_lazy(const Obj_Entry *);
+int _rtld_relocate_plt_objects(const Obj_Entry *);
+void _rtld_setup_pltgot(const Obj_Entry *);
+
+/* search.c */
+Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int);
+
+/* symbol.c */
+unsigned long _rtld_elf_hash(const char *);
+const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long,
+    const Obj_Entry *, bool);
+const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *,
+    const Obj_Entry **, bool);
+const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *, 
+    const Obj_Entry **, bool);
+
+const Elf_Sym *_rtld_symlook_list(const char *, unsigned long,
+    const Objlist *, const Obj_Entry **, bool, DoneList *);
+const Elf_Sym *_rtld_symlook_default(const char *, unsigned long,
+    const Obj_Entry *, const Obj_Entry **, bool);
+const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long,
+    const Needed_Entry *, const Obj_Entry **, bool,
+    DoneList *, DoneList *);
+#ifdef COMBRELOC
+void _rtld_combreloc_reset(const Obj_Entry *);
+#endif
+
+/* map_object.c */
+struct stat;
+Obj_Entry *_rtld_map_object(const char *, int, const struct stat *);
+void _rtld_obj_free(Obj_Entry *);
+Obj_Entry *_rtld_obj_new(void);
+
+/* function descriptors */
+#ifdef __HAVE_FUNCTION_DESCRIPTORS
+Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, 
+    const Elf_Sym *, Elf_Addr);
+const void *_rtld_function_descriptor_function(const void *);
+#endif /* __HAVE_FUNCTION_DESCRIPTORS */
+
+#endif /* _RTLD_SOURCE */
+
+#endif /* RTLD_H */
diff --git a/libexec/ld.elf_so/rtldenv.h b/libexec/ld.elf_so/rtldenv.h
new file mode 100644 (file)
index 0000000..a1b3ba9
--- /dev/null
@@ -0,0 +1,86 @@
+/*     $NetBSD: rtldenv.h,v 1.10 2010/10/29 15:08:17 christos Exp $     */
+
+/*
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTLDENV_H
+#define        _RTLDENV_H
+
+#include <stddef.h>
+#include <stdarg.h>
+
+void    *xcalloc(size_t);
+void    *xmalloc(size_t);
+void    *xrealloc(void *, size_t);
+char    *xstrdup(const char *);
+void   xfree(void *);
+
+#ifdef RTLD_LOADER
+void xprintf(const char *, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
+void xvprintf(const char *, va_list)
+    __attribute__((__format__(__printf__, 1, 0)));
+void xsnprintf(char *, size_t, const char *, ...)
+    __attribute__((__format__(__printf__, 3, 4)));
+size_t xvsnprintf(char *, size_t, const char *, va_list)
+    __attribute__((__format__(__printf__, 3, 0)));
+void xwarn(const char *, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
+void xwarnx(const char *, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
+void xerr(int, const char *, ...)
+    __attribute__((__noreturn__, __format__(__printf__, 2, 3)));
+void xerrx(int, const char *, ...)
+    __attribute__((__noreturn__, __format__(__printf__, 2, 3)));
+
+void     xassert(const char *, int, const char *);
+const char *xstrerror(int);
+int    xunsetenv(const char *);
+
+# ifdef DEBUG
+#  define assert(cond) ((cond) ? (void) 0 : xassert(__FILE__, __LINE__, #cond))
+# else
+#  define assert(cond) (void) 0
+# endif
+#else
+# include <assert.h>
+# include <stdio.h>
+# include <err.h>
+# define xprintf       printf
+# define xvprintf      vprintf
+# define xsnprintf     snprintf
+# define xvsnprintf    vsnprintf
+# define xwarn         warn
+# define xwarnx                warnx
+# define xerr          err
+# define xerrx         errx
+# define xassert       assert
+# define xstrerror     strerror
+#endif
+
+#endif /* _RTLDENV_H */
diff --git a/libexec/ld.elf_so/search.c b/libexec/ld.elf_so/search.c
new file mode 100644 (file)
index 0000000..513f0ad
--- /dev/null
@@ -0,0 +1,192 @@
+/*     $NetBSD: search.c,v 1.23 2010/12/24 12:41:43 skrll Exp $         */
+
+/*
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp@polstra.com>.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: search.c,v 1.23 2010/12/24 12:41:43 skrll Exp $");
+#endif /* not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+/*
+ * Data declarations.
+ */
+Search_Path    *_rtld_invalid_paths;
+
+static Obj_Entry *_rtld_search_library_path(const char *, size_t,
+    const char *, size_t, int);
+
+static Obj_Entry *
+_rtld_search_library_path(const char *name, size_t namelen,
+    const char *dir, size_t dirlen, int flags)
+{
+       char pathname[MAXPATHLEN];
+       size_t pathnamelen;
+       Obj_Entry *obj;
+       Search_Path *sp;
+
+       pathnamelen = dirlen + 1 + namelen;
+       if (pathnamelen >= sizeof(pathname))
+               return NULL;
+
+       for (sp = _rtld_invalid_paths; sp != NULL; sp = sp->sp_next) {
+               if (sp->sp_pathlen == pathnamelen &&
+                   sp->sp_path[dirlen] == '/' &&
+                   !memcmp(name, sp->sp_path + dirlen + 1, namelen) &&
+                   !memcmp(dir, sp->sp_path, dirlen)) {
+                       return NULL;
+               }
+       }
+
+       memcpy(pathname, dir, dirlen);
+       pathname[dirlen] = '/';
+       memcpy(pathname + dirlen + 1, name, namelen);
+       pathname[pathnamelen] = '\0';
+
+       dbg(("  Trying \"%s\"", pathname));
+       obj = _rtld_load_object(pathname, flags);
+       if (obj == NULL) {
+               Search_Path *path;
+
+               path = NEW(Search_Path);
+               path->sp_pathlen = pathnamelen;
+               path->sp_path = xstrdup(pathname);
+               path->sp_next = _rtld_invalid_paths;
+               _rtld_invalid_paths = path;
+       }
+       return obj;
+}
+
+/*
+ * Find the library with the given name, and return its full pathname.
+ * The returned string is dynamically allocated.  Generates an error
+ * message and returns NULL if the library cannot be found.
+ *
+ * If the second argument is non-NULL, then it refers to an already-
+ * loaded shared object, whose library search path will be searched.
+ */
+Obj_Entry *
+_rtld_load_library(const char *name, const Obj_Entry *refobj, int flags)
+{
+       char tmperror[512], *tmperrorp;
+       Search_Path *sp;
+       const char *pathname;
+       int namelen;
+       Obj_Entry *obj;
+
+       if (strchr(name, '/') != NULL) {        /* Hard coded pathname */
+               if (name[0] != '/' && !_rtld_trust) {
+                       _rtld_error(
+                       "absolute pathname required for shared object \"%s\"",
+                           name);
+                       return NULL;
+               }
+               pathname = name;
+               goto found;
+       }
+       dbg((" Searching for \"%s\" (%p)", name, refobj));
+
+       tmperrorp = dlerror();
+       if (tmperrorp != NULL) {
+               strncpy(tmperror, tmperrorp, sizeof tmperror);
+               tmperrorp = tmperror;
+       }
+       
+       namelen = strlen(name);
+
+       for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next)
+               if ((obj = _rtld_search_library_path(name, namelen,
+                   sp->sp_path, sp->sp_pathlen, flags)) != NULL)
+                       goto pathfound;
+
+       if (refobj != NULL)
+               for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next)
+                       if ((obj = _rtld_search_library_path(name,
+                           namelen, sp->sp_path, sp->sp_pathlen, flags)) != NULL)
+                               goto pathfound;
+
+       for (sp = _rtld_default_paths; sp != NULL; sp = sp->sp_next)
+               if ((obj = _rtld_search_library_path(name, namelen,
+                   sp->sp_path, sp->sp_pathlen, flags)) != NULL)
+                       goto pathfound;
+
+       _rtld_error("Shared object \"%s\" not found", name);
+       return NULL;
+
+pathfound:
+       /*
+        * The library has been found, but it couldn't be loaded for some
+        * reason.
+        */
+       if (obj == OBJ_ERR)
+               return NULL;
+       /*
+        * Successfully found a library; restore the dlerror state as it was
+        * before _rtld_load_library() was called (any failed call to
+        * _rtld_search_library_path() will set the dlerror state, but if the
+        * library was eventually found, then the error state should not
+        * change.
+        */
+       if (tmperrorp)
+               _rtld_error("%s", tmperror);
+       else
+               (void)dlerror();
+       return obj;
+
+found:
+       obj = _rtld_load_object(pathname, flags);
+       if (obj == OBJ_ERR)
+               return NULL;
+
+       return obj;
+}
+
diff --git a/libexec/ld.elf_so/symbol.c b/libexec/ld.elf_so/symbol.c
new file mode 100644 (file)
index 0000000..f4979bb
--- /dev/null
@@ -0,0 +1,488 @@
+/*     $NetBSD: symbol.c,v 1.54 2010/10/16 10:27:07 skrll Exp $         */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * Copyright 2002 Charles M. Hannum <root@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp@polstra.com>.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: symbol.c,v 1.54 2010/10/16 10:27:07 skrll Exp $");
+#endif /* not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/bitops.h>
+#include <dirent.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+typedef void (*fptr_t)(void);
+
+/*
+ * If the given object is already in the donelist, return true.  Otherwise
+ * add the object to the list and return false.
+ */
+static bool
+_rtld_donelist_check(DoneList *dlp, const Obj_Entry *obj)
+{
+       unsigned int i;
+
+       for (i = 0;  i < dlp->num_used;  i++)
+               if (dlp->objs[i] == obj)
+                       return true;
+       /*
+        * Our donelist allocation may not always be sufficient as we're not
+        * thread safe. We'll handle it properly anyway.
+        */
+       if (dlp->num_used < dlp->num_alloc)
+               dlp->objs[dlp->num_used++] = obj;
+       return false;
+}
+
+static bool
+_rtld_is_exported(const Elf_Sym *def)
+{
+       static const fptr_t _rtld_exports[] = {
+               (fptr_t)dlopen,
+               (fptr_t)dlclose,
+               (fptr_t)dlsym,
+               (fptr_t)dlerror,
+               (fptr_t)dladdr,
+               (fptr_t)dlinfo,
+               (fptr_t)dl_iterate_phdr,
+               NULL
+       };
+       int i;
+       fptr_t value;
+
+       value = (fptr_t)(_rtld_objself.relocbase + def->st_value);
+       for (i = 0; _rtld_exports[i] != NULL; i++) {
+               if (value == _rtld_exports[i])
+                       return true;
+       }
+       return false;
+}
+
+/*
+ * Hash function for symbol table lookup.  Don't even think about changing
+ * this.  It is specified by the System V ABI.
+ */
+unsigned long
+_rtld_elf_hash(const char *name)
+{
+       const unsigned char *p = (const unsigned char *) name;
+       unsigned long   h = 0;
+       unsigned long   g;
+       unsigned long   c;
+
+       for (; __predict_true((c = *p) != '\0'); p++) {
+               h <<= 4;
+               h += c;
+               if ((g = h & 0xf0000000) != 0) {
+                       h ^= g;
+                       h ^= g >> 24;
+               }
+       }
+       return (h);
+}
+
+const Elf_Sym *
+_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist,
+    const Obj_Entry **defobj_out, bool in_plt, DoneList *dlp)
+{
+       const Elf_Sym *symp;
+       const Elf_Sym *def;
+       const Obj_Entry *defobj;
+       const Objlist_Entry *elm;
+       
+       def = NULL;
+       defobj = NULL;
+       SIMPLEQ_FOREACH(elm, objlist, link) {
+               if (_rtld_donelist_check(dlp, elm->obj))
+                       continue;
+               rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path,
+                   name));
+               if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt))
+                   != NULL) {
+                       if ((def == NULL) ||
+                           (ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
+                               def = symp;
+                               defobj = elm->obj;
+                               if (ELF_ST_BIND(def->st_info) != STB_WEAK)
+                                       break;
+                       }
+               }
+       }
+       if (def != NULL)
+               *defobj_out = defobj;
+       return def;
+}
+
+/*
+ * Search the symbol table of a shared object and all objects needed by it for
+ * a symbol of the given name. Search order is breadth-first. Returns a pointer
+ * to the symbol, or NULL if no definition was found.
+ */
+const Elf_Sym *
+_rtld_symlook_needed(const char *name, unsigned long hash,
+    const Needed_Entry *needed, const Obj_Entry **defobj_out, bool inplt,
+    DoneList *breadth, DoneList *depth)
+{
+       const Elf_Sym *def, *def_w;
+       const Needed_Entry *n;
+       const Obj_Entry *obj, *defobj, *defobj1;
+
+       def = def_w = NULL;
+       defobj = NULL;
+       for (n = needed; n != NULL; n = n->next) {
+               if ((obj = n->obj) == NULL)
+                       continue;
+               if (_rtld_donelist_check(breadth, obj))
+                       continue;
+               if ((def = _rtld_symlook_obj(name, hash, obj, inplt)) == NULL)
+                       continue;
+               defobj = obj;
+               if (ELF_ST_BIND(def->st_info) != STB_WEAK) {
+                       *defobj_out = defobj;
+
+                       return (def);
+               }
+       }
+       /*
+        * Either the symbol definition has not been found in directly needed
+        * objects, or the found symbol is weak.
+        */
+       for (n = needed; n != NULL; n = n->next) {
+               if ((obj = n->obj) == NULL)
+                       continue;
+               if (_rtld_donelist_check(depth, obj))
+                       continue;
+               def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1,
+                   inplt, breadth, depth);
+               if (def_w == NULL)
+                       continue;
+               if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) {
+                       def = def_w;
+                       defobj = defobj1;
+                       if (ELF_ST_BIND(def_w->st_info) != STB_WEAK)
+                               break;
+               }
+       }
+       if (def != NULL)
+               *defobj_out = defobj;
+
+       return def;
+}
+
+/*
+ * Search the symbol table of a single shared object for a symbol of
+ * the given name.  Returns a pointer to the symbol, or NULL if no
+ * definition was found.
+ *
+ * The symbol's hash value is passed in for efficiency reasons; that
+ * eliminates many recomputations of the hash value.
+ */
+const Elf_Sym *
+_rtld_symlook_obj(const char *name, unsigned long hash,
+    const Obj_Entry *obj, bool in_plt)
+{
+       unsigned long symnum;
+
+       for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets,
+            obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)];
+            symnum != ELF_SYM_UNDEFINED;
+            symnum = obj->chains[symnum]) {
+               const Elf_Sym  *symp;
+               const char     *strp;
+
+               assert(symnum < obj->nchains);
+               symp = obj->symtab + symnum;
+               strp = obj->strtab + symp->st_name;
+               rdbg(("check \"%s\" vs \"%s\" in %p", name, strp, obj));
+               if (name[1] == strp[1] && !strcmp(name, strp)) {
+                       if (symp->st_shndx != SHN_UNDEF)
+                               return symp;
+#ifndef __mips__
+                       /*
+                        * XXX DANGER WILL ROBINSON!
+                        * If we have a function pointer in the executable's
+                        * data section, it points to the executable's PLT
+                        * slot, and there is NO relocation emitted.  To make
+                        * the function pointer comparable to function pointers
+                        * in shared libraries, we must resolve data references
+                        * in the libraries to point to PLT slots in the
+                        * executable, if they exist.
+                        */
+                       else if (!in_plt && symp->st_value != 0 &&
+                            ELF_ST_TYPE(symp->st_info) == STT_FUNC)
+                               return symp;
+#endif
+                       else
+                               return NULL;
+               }
+       }
+
+       return NULL;
+}
+
+#ifdef COMBRELOC
+static const Obj_Entry *_rtld_last_refobj;
+
+/*
+ * Called when an object is freed. Reset the cached symbol look up if
+ * our last referencing or definition object just got unloaded.
+ */
+void
+_rtld_combreloc_reset(const Obj_Entry *obj)
+{
+       if (_rtld_last_refobj == obj)
+               _rtld_last_refobj = NULL;
+}
+#endif
+
+/*
+ * Given a symbol number in a referencing object, find the corresponding
+ * definition of the symbol.  Returns a pointer to the symbol, or NULL if
+ * no definition was found.  Returns a pointer to the Obj_Entry of the
+ * defining object via the reference parameter DEFOBJ_OUT.
+ */
+const Elf_Sym *
+_rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj,
+    const Obj_Entry **defobj_out, bool in_plt)
+{
+       const Elf_Sym  *ref;
+       const Elf_Sym  *def;
+       const Obj_Entry *defobj;
+       const char     *name;
+       unsigned long   hash;
+
+#ifdef COMBRELOC
+       /*
+        * COMBRELOC combines multiple reloc sections and sorts them to make
+        * dynamic symbol lookup caching possible.
+        *
+        * So if the lookup we are doing is the same as the previous lookup
+        * return the cached results.
+        */
+       static unsigned long last_symnum;
+       static const Obj_Entry *last_defobj;
+       static const Elf_Sym *last_def;
+
+       if (symnum == last_symnum && refobj == _rtld_last_refobj
+           && in_plt == false) {
+               *defobj_out = last_defobj;
+               return last_def;
+       }
+#endif
+
+       ref = refobj->symtab + symnum;
+       name = refobj->strtab + ref->st_name;
+
+       /*
+        * We don't have to do a full scale lookup if the symbol is local.
+        * We know it will bind to the instance in this load module; to
+        * which we already have a pointer (ie ref).
+        */
+       if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) {
+               if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) {
+                       _rtld_error("%s: Bogus symbol table entry %lu",
+                           refobj->path, symnum);
+               }
+
+               hash = _rtld_elf_hash(name);
+               defobj = NULL;
+               def = _rtld_symlook_default(name, hash, refobj, &defobj, in_plt);
+       } else {
+               rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path));
+               def = ref;
+               defobj = refobj;
+       }
+               
+       /*
+        * If we found no definition and the reference is weak, treat the
+        * symbol as having the value zero.
+        */
+       if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) {
+               rdbg(("  returning _rtld_sym_zero@_rtld_objself"));
+               def = &_rtld_sym_zero;
+               defobj = &_rtld_objself;
+       }
+
+       if (def != NULL) {
+               *defobj_out = defobj;
+#ifdef COMBRELOC
+               if (in_plt == false) {
+                       /*
+                        * Cache the lookup arguments and results if this was
+                        * non-PLT lookup.
+                        */
+                       last_symnum = symnum;
+                       _rtld_last_refobj = refobj;
+                       last_def = def;
+                       last_defobj = defobj;
+               }
+#endif
+       } else {
+               rdbg(("lookup failed"));
+               _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)",
+                   refobj->path, in_plt ? "PLT " : "", name, symnum);
+       }
+       return def;
+}
+
+const Elf_Sym *
+_rtld_find_plt_symdef(unsigned long symnum, const Obj_Entry *obj,
+    const Obj_Entry **defobj, bool imm)
+{
+       const Elf_Sym  *def = _rtld_find_symdef(symnum, obj, defobj, true);
+       if (__predict_false(def == NULL))
+               return NULL;
+
+       if (__predict_false(def == &_rtld_sym_zero)) {
+               /* tp is set during lazy binding. */
+               if (imm) {
+                       const Elf_Sym   *ref = obj->symtab + symnum;
+                       const char      *name = obj->strtab + ref->st_name;
+
+                       _rtld_error(
+                           "%s: Trying to call undefined weak symbol `%s'",
+                           obj->path, name);
+                       return NULL;
+               }
+       }
+       return def;
+}
+
+/*
+ * Given a symbol name in a referencing object, find the corresponding
+ * definition of the symbol.  Returns a pointer to the symbol, or NULL if
+ * no definition was found.  Returns a pointer to the Obj_Entry of the
+ * defining object via the reference parameter DEFOBJ_OUT.
+ */
+const Elf_Sym *
+_rtld_symlook_default(const char *name, unsigned long hash,
+    const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt)
+{
+       const Elf_Sym *def;
+       const Elf_Sym *symp;
+       const Obj_Entry *obj;
+       const Obj_Entry *defobj;
+       const Objlist_Entry *elm;
+       def = NULL;
+       defobj = NULL;
+       DoneList donelist;
+
+       _rtld_donelist_init(&donelist);
+
+       /* Look first in the referencing object if linked symbolically. */
+       if (refobj->symbolic && !_rtld_donelist_check(&donelist, refobj)) {
+               rdbg(("search referencing object for %s", name));
+               symp = _rtld_symlook_obj(name, hash, refobj, in_plt);
+               if (symp != NULL) {
+                       def = symp;
+                       defobj = refobj;
+               }
+       }
+
+       /* Search all objects loaded at program start up. */
+       if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
+               rdbg(("search _rtld_list_main for %s", name));
+               symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj,
+                   in_plt, &donelist);
+               if (symp != NULL &&
+                   (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
+                       def = symp;
+                       defobj = obj;
+               }
+       }
+
+       /* Search all RTLD_GLOBAL objects. */
+       if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
+               rdbg(("search _rtld_list_global for %s", name));
+               symp = _rtld_symlook_list(name, hash, &_rtld_list_global,
+                   &obj, in_plt, &donelist);
+               if (symp != NULL &&
+                   (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
+                       def = symp;
+                       defobj = obj;
+               }
+       }
+       
+       /* Search all dlopened DAGs containing the referencing object. */
+       SIMPLEQ_FOREACH(elm, &refobj->dldags, link) {
+               if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK)
+                       break;
+               rdbg(("search DAG with root %p (%s) for %s", elm->obj,
+                   elm->obj->path, name));
+               symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers,
+                   &obj, in_plt, &donelist);
+               if (symp != NULL &&
+                   (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
+                       def = symp;
+                       defobj = obj;
+               }
+       }
+
+       /*
+        * Search the dynamic linker itself, and possibly resolve the
+        * symbol from there.  This is how the application links to
+        * dynamic linker services such as dlopen.  Only the values listed
+        * in the "_rtld_exports" array can be resolved from the dynamic
+        * linker.
+        */
+       if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
+               rdbg(("Search the dynamic linker itself."));
+               symp = _rtld_symlook_obj(name, hash, &_rtld_objself, in_plt);
+               if (symp != NULL && _rtld_is_exported(symp)) {
+                       def = symp;
+                       defobj = &_rtld_objself;
+               }
+       }
+
+       if (def != NULL)
+               *defobj_out = defobj;
+       return def;
+}
diff --git a/libexec/ld.elf_so/sysident.h b/libexec/ld.elf_so/sysident.h
new file mode 100644 (file)
index 0000000..a710d8c
--- /dev/null
@@ -0,0 +1,91 @@
+/* $NetBSD: sysident.h,v 1.14 2007/06/24 20:35:36 christos Exp $ */
+
+/*
+ * Copyright (c) 1997 Christopher G. Demetriou
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *          This product includes software developed for the
+ *          NetBSD Project.  See http://www.NetBSD.org/ for
+ *          information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+/*
+ * Here we define the NetBSD OS Version in an ELF .note section, structured
+ * like:
+ *
+ * [NOTE HEADER]
+ *     long            name size
+ *     long            description size
+ *     long            note type
+ *
+ * [NOTE DATUM]
+ *     string          OS name
+ *
+ * OSVERSION notes also have:
+ *     long            OS version (__NetBSD_Version__ constant from param.h)
+ *
+ * The DATUM fields should be padded out such that their actual (not
+ * declared) sizes % 4 == 0.
+ *
+ * These are used by the kernel to determine if this binary is really a
+ * NetBSD binary, or some other OS's.
+ */
+
+/* XXX: NetBSD 1.5 compatibility only! */
+#if __NetBSD_Version__ < 105010000
+#define        ELF_NOTE_TYPE_NETBSD_TAG        1
+#endif
+
+#define        __S(x)  __STRING(x)
+__asm(
+       ".section\t\".note.netbsd.ident\", \"a\"\n"
+       "\t.p2align\t2\n\n"
+
+       "\t.long\t" __S(ELF_NOTE_NETBSD_NAMESZ) "\n"
+       "\t.long\t" __S(ELF_NOTE_NETBSD_DESCSZ) "\n"
+       "\t.long\t" __S(ELF_NOTE_TYPE_NETBSD_TAG) "\n"
+       "\t.ascii\t" __S(ELF_NOTE_NETBSD_NAME) "\n"
+       "\t.long\t" __S(__NetBSD_Version__) "\n\n"
+
+       "\t.previous\n"
+       "\t.p2align\t2\n"
+);
+
+__asm(
+       ".section\t\".note.netbsd.pax\", \"a\"\n"
+       "\t.p2align\t2\n\n"
+
+       "\t.long\t" __S(ELF_NOTE_PAX_NAMESZ) "\n"
+       "\t.long\t" __S(ELF_NOTE_PAX_DESCSZ) "\n"
+       "\t.long\t" __S(ELF_NOTE_TYPE_PAX_TAG) "\n"
+       "\t.ascii\t" __S(ELF_NOTE_PAX_NAME) "\n"
+       "\t.long\t" __S(0) "\n\n"
+
+       "\t.previous\n"
+       "\t.p2align\t2\n"
+);
diff --git a/libexec/ld.elf_so/xmalloc.c b/libexec/ld.elf_so/xmalloc.c
new file mode 100644 (file)
index 0000000..e80c03a
--- /dev/null
@@ -0,0 +1,486 @@
+/*     $NetBSD: xmalloc.c,v 1.10 2010/12/03 23:07:49 joerg Exp $       */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)malloc.c    5.11 (Berkeley) 2/23/91";*/
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * malloc.c (Caltech) 2/21/82
+ * Chris Kingsley, kingsley@cit-20.
+ *
+ * This is a very fast storage allocator.  It allocates blocks of a small
+ * number of different sizes, and keeps free lists of each size.  Blocks that
+ * don't exactly fit are passed up to the next larger size.  In this
+ * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long.
+ * This is designed for use in a virtual memory environment.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: xmalloc.c,v 1.10 2010/12/03 23:07:49 joerg Exp $");
+#endif /* not lint */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "rtld.h"
+
+/*
+ * Pre-allocate mmap'ed pages
+ */
+#define        NPOOLPAGES      (32*1024/pagesz)
+static char            *pagepool_start, *pagepool_end;
+static int             morepages(int);
+#define PAGEPOOL_SIZE  (size_t)(pagepool_end - pagepool_start)
+
+/*
+ * The overhead on a block is at least 4 bytes.  When free, this space
+ * contains a pointer to the next free block, and the bottom two bits must
+ * be zero.  When in use, the first byte is set to MAGIC, and the second
+ * byte is the size index.  The remaining bytes are for alignment.
+ * If range checking is enabled then a second word holds the size of the
+ * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
+ * The order of elements is critical: ov_magic must overlay the low order
+ * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
+ */
+union  overhead {
+       union   overhead *ov_next;      /* when free */
+       struct {
+               u_char  ovu_magic;      /* magic number */
+               u_char  ovu_index;      /* bucket # */
+#ifdef RCHECK
+               u_short ovu_rmagic;     /* range magic number */
+               u_int   ovu_size;       /* actual block size */
+#endif
+       } ovu;
+#define        ov_magic        ovu.ovu_magic
+#define        ov_index        ovu.ovu_index
+#define        ov_rmagic       ovu.ovu_rmagic
+#define        ov_size         ovu.ovu_size
+};
+
+static void morecore(size_t);
+static void *imalloc(size_t);
+
+#define        MAGIC           0xef            /* magic # on accounting info */
+#define RMAGIC         0x5555          /* magic # on range info */
+
+#ifdef RCHECK
+#define        RSLOP           (sizeof (u_short))
+#else
+#define        RSLOP           0
+#endif
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
+ * smallest allocatable block is 8 bytes.  The overhead information
+ * precedes the data area returned to the user.
+ */
+#define        NBUCKETS 30
+static union overhead *nextf[NBUCKETS];
+
+static size_t pagesz;                  /* page size */
+static size_t pagebucket;              /* page size bucket */
+
+#ifdef MSTATS
+/*
+ * nmalloc[i] is the difference between the number of mallocs and frees
+ * for a given block size.
+ */
+static u_int nmalloc[NBUCKETS];
+#endif
+
+#if defined(MALLOC_DEBUG) || defined(RCHECK)
+#define        ASSERT(p)   if (!(p)) botch("p")
+static void
+botch(const char *s)
+{
+    xwarnx("\r\nassertion botched: %s\r\n", s);
+    abort();
+}
+#else
+#define        ASSERT(p)
+#endif
+
+#define TRACE()        xprintf("TRACE %s:%d\n", __FILE__, __LINE__)
+
+static void *
+imalloc(size_t nbytes)
+{
+       union overhead *op;
+       size_t bucket;
+       size_t n, m;
+       unsigned amt;
+
+       /*
+        * First time malloc is called, setup page size and
+        * align break pointer so all data will be page aligned.
+        */
+       if (pagesz == 0) {
+               pagesz = n = _rtld_pagesz;
+               if (morepages(NPOOLPAGES) == 0)
+                       return NULL;
+               op = (union overhead *)(pagepool_start);
+               m = sizeof (*op) - (((char *)op - (char *)NULL) & (n - 1));
+               if (n < m)
+                       n += pagesz - m;
+               else
+                       n -= m;
+               if (n) {
+                       pagepool_start += n;
+               }
+               bucket = 0;
+               amt = sizeof(union overhead);
+               while (pagesz > amt) {
+                       amt <<= 1;
+                       bucket++;
+               }
+               pagebucket = bucket;
+       }
+       /*
+        * Convert amount of memory requested into closest block size
+        * stored in hash buckets which satisfies request.
+        * Account for space used per block for accounting.
+        */
+       if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) {
+               if (sizeof(union overhead) & (sizeof(union overhead) - 1)) {
+                   amt = sizeof(union overhead) * 2;
+                   bucket = 1;
+               } else {
+                   amt = sizeof(union overhead); /* size of first bucket */
+                   bucket = 0;
+               }
+               n = -(sizeof (*op) + RSLOP);
+       } else {
+               amt = pagesz;
+               bucket = pagebucket;
+       }
+       while (nbytes > amt + n) {
+               amt <<= 1;
+               if (amt == 0)
+                       return (NULL);
+               bucket++;
+       }
+       /*
+        * If nothing in hash bucket right now,
+        * request more memory from the system.
+        */
+       if ((op = nextf[bucket]) == NULL) {
+               morecore(bucket);
+               if ((op = nextf[bucket]) == NULL)
+                       return (NULL);
+       }
+       /* remove from linked list */
+       nextf[bucket] = op->ov_next;
+       op->ov_magic = MAGIC;
+       op->ov_index = bucket;
+#ifdef MSTATS
+       nmalloc[bucket]++;
+#endif
+#ifdef RCHECK
+       /*
+        * Record allocated size of block and
+        * bound space with magic numbers.
+        */
+       op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
+       op->ov_rmagic = RMAGIC;
+       *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
+#endif
+       return ((char *)(op + 1));
+}
+
+/*
+ * Allocate more memory to the indicated bucket.
+ */
+static void
+morecore(size_t bucket)
+{
+       union overhead *op;
+       size_t sz;              /* size of desired block */
+       size_t amt;             /* amount to allocate */
+       size_t nblks;           /* how many blocks we get */
+
+       /*
+        * sbrk_size <= 0 only for big, FLUFFY, requests (about
+        * 2^30 bytes on a VAX, I think) or for a negative arg.
+        */
+       sz = 1 << (bucket + 3);
+#ifdef MALLOC_DEBUG
+       ASSERT(sz > 0);
+#endif
+       if (sz < pagesz) {
+               amt = pagesz;
+               nblks = amt / sz;
+       } else {
+               amt = sz + pagesz;
+               nblks = 1;
+       }
+       if (amt > PAGEPOOL_SIZE)
+               if (morepages(amt/pagesz + NPOOLPAGES) == 0)
+                       return;
+       op = (union overhead *)pagepool_start;
+       pagepool_start += amt;
+
+       /*
+        * Add new memory allocated to that on
+        * free list for this hash bucket.
+        */
+       nextf[bucket] = op;
+       while (--nblks > 0) {
+               op->ov_next = (union overhead *)((caddr_t)op + sz);
+               op = (union overhead *)((caddr_t)op + sz);
+       }
+}
+
+void
+xfree(void *cp)
+{
+       int size;
+       union overhead *op;
+
+       if (cp == NULL)
+               return;
+       op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
+#ifdef MALLOC_DEBUG
+       ASSERT(op->ov_magic == MAGIC);          /* make sure it was in use */
+#else
+       if (op->ov_magic != MAGIC)
+               return;                         /* sanity */
+#endif
+#ifdef RCHECK
+       ASSERT(op->ov_rmagic == RMAGIC);
+       ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
+#endif
+       size = op->ov_index;
+       ASSERT(size < NBUCKETS);
+       op->ov_next = nextf[size];      /* also clobbers ov_magic */
+       nextf[size] = op;
+#ifdef MSTATS
+       nmalloc[size]--;
+#endif
+}
+
+static void *
+irealloc(void *cp, size_t nbytes)
+{
+       size_t onb;
+       size_t i;
+       union overhead *op;
+       char *res;
+
+       if (cp == NULL)
+               return (imalloc(nbytes));
+       op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
+       if (op->ov_magic != MAGIC) {
+               static const char *err_str =
+                   "memory corruption or double free in realloc\n";
+               extern char *__progname;
+               write(STDERR_FILENO, __progname, strlen(__progname));
+               write(STDERR_FILENO, err_str, strlen(err_str));
+               abort();
+       }
+
+       i = op->ov_index;
+       onb = 1 << (i + 3);
+       if (onb < pagesz)
+               onb -= sizeof (*op) + RSLOP;
+       else
+               onb += pagesz - sizeof (*op) - RSLOP;
+       /* avoid the copy if same size block */
+       if (i) {
+               i = 1 << (i + 2);
+               if (i < pagesz)
+                       i -= sizeof (*op) + RSLOP;
+               else
+                       i += pagesz - sizeof (*op) - RSLOP;
+       }
+       if (nbytes <= onb && nbytes > i) {
+#ifdef RCHECK
+               op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
+               *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
+#endif
+               return(cp);
+       } else
+               xfree(cp);
+       if ((res = imalloc(nbytes)) == NULL)
+               return (NULL);
+       if (cp != res)          /* common optimization if "compacting" */
+               memcpy(res, cp, (nbytes < onb) ? nbytes : onb);
+       return (res);
+}
+
+#ifdef MSTATS
+/*
+ * mstats - print out statistics about malloc
+ *
+ * Prints two lines of numbers, one showing the length of the free list
+ * for each size category, the second showing the number of mallocs -
+ * frees for each size category.
+ */
+void
+mstats(char *s)
+{
+       int i, j;
+       union overhead *p;
+       int totfree = 0,
+       totused = 0;
+
+       xprintf("Memory allocation statistics %s\nfree:\t", s);
+       for (i = 0; i < NBUCKETS; i++) {
+               for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
+                       ;
+               xprintf(" %d", j);
+               totfree += j * (1 << (i + 3));
+       }
+       xprintf("\nused:\t");
+       for (i = 0; i < NBUCKETS; i++) {
+               xprintf(" %d", nmalloc[i]);
+               totused += nmalloc[i] * (1 << (i + 3));
+       }
+       xprintf("\n\tTotal in use: %d, total free: %d\n",
+           totused, totfree);
+}
+#endif
+
+
+static int
+morepages(int n)
+{
+       int     fd = -1;
+       int     offset;
+
+#ifdef NEED_DEV_ZERO
+       fd = open("/dev/zero", O_RDWR, 0);
+       if (fd == -1)
+               xerr(1, "/dev/zero");
+#endif
+
+       if (PAGEPOOL_SIZE > pagesz) {
+               caddr_t addr = (caddr_t)
+                       (((long)pagepool_start + pagesz - 1) & ~(pagesz - 1));
+               if (munmap(addr, pagepool_end - addr) != 0)
+                       xwarn("morepages: munmap %p", addr);
+       }
+
+       offset = (long)pagepool_start - ((long)pagepool_start & ~(pagesz - 1));
+
+       if ((pagepool_start = mmap(0, n * pagesz,
+                       PROT_READ|PROT_WRITE,
+                       MAP_ANON|MAP_PRIVATE, fd, 0)) == (caddr_t)-1) {
+               xprintf("Cannot map anonymous memory");
+               return 0;
+       }
+       pagepool_end = pagepool_start + n * pagesz;
+       pagepool_start += offset;
+
+#ifdef NEED_DEV_ZERO
+       close(fd);
+#endif
+       return n;
+}
+
+void *
+xcalloc(size_t size)
+{
+
+       return memset(xmalloc(size), 0, size);
+}
+
+void *
+xmalloc(size_t size)
+{
+       void *p = imalloc(size);
+
+       if (p == NULL)
+               xerr(1, "%s", xstrerror(errno));
+       return p;
+}
+
+void *
+xrealloc(void *p, size_t size)
+{
+       p = irealloc(p, size);
+
+       if (p == NULL)
+               xerr(1, "%s", xstrerror(errno));
+       return p;
+}
+
+char *
+xstrdup(const char *str)
+{
+       size_t len;
+       char *copy;
+
+       len = strlen(str) + 1;
+       copy = xmalloc(len);
+       memcpy(copy, str, len);
+       return (copy);
+}
diff --git a/libexec/ld.elf_so/xprintf.c b/libexec/ld.elf_so/xprintf.c
new file mode 100644 (file)
index 0000000..77c9bbf
--- /dev/null
@@ -0,0 +1,323 @@
+/*     $NetBSD: xprintf.c,v 1.21 2010/12/16 22:52:32 joerg Exp $        */
+
+/*
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: xprintf.c,v 1.21 2010/12/16 22:52:32 joerg Exp $");
+#endif /* not lint */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "rtldenv.h"
+
+#ifdef RTLD_LOADER
+#define        SZ_LONG         0x01
+#define        SZ_UNSIGNED     0x02
+#define SZ_SIZE_T      0x04
+
+/*
+ * Non-mallocing printf, for use by malloc and rtld itself.
+ * This avoids putting in most of stdio.
+ *
+ * deals withs formats %x, %p, %s, and %d.
+ */
+size_t
+xvsnprintf(char *buf, size_t buflen, const char *fmt, va_list ap)
+{
+       char *bp = buf;
+       char *const ep = buf + buflen - 4;
+       int size, prec;
+
+       while (*fmt != '\0' && bp < ep) {
+               switch (*fmt) {
+               case '\\':{
+                       if (fmt[1] != '\0')
+                               *bp++ = *++fmt;
+                       continue;
+               }
+               case '%':{
+                       size = 0;
+                       prec = -1;
+       rflag:          switch (fmt[1]) {
+                       case '*':
+                               prec = va_arg(ap, int);
+                               /* FALLTHROUGH */
+                       case '.':
+                               fmt++;
+                               goto rflag;
+                       case 'l':
+                               size |= SZ_LONG;
+                               fmt++;
+                               goto rflag;
+                       case 'z':
+                               size |= SZ_SIZE_T;
+                               fmt++;
+                               goto rflag;
+                       case 'u':
+                               size |= SZ_UNSIGNED;
+                               /* FALLTHROUGH */
+                       case 'd':{
+                               long sval;
+                               unsigned long uval;
+                               char digits[sizeof(int) * 3], *dp = digits;
+#define        SARG() \
+(size & SZ_LONG ? va_arg(ap, long) : \
+((size & SZ_SIZE_T ? (long)va_arg(ap, size_t) : \
+va_arg(ap, int))))
+#define        UARG() \
+(size & SZ_LONG ? va_arg(ap, unsigned long) : \
+((size & SZ_SIZE_T ? va_arg(ap, size_t) : \
+va_arg(ap, unsigned int))))
+
+                               if (fmt[1] == 'd') {
+                                       if (size & SZ_UNSIGNED)
+                                               sval = UARG();
+                                       else
+                                               sval = SARG();
+                                       if (sval < 0) {
+                                               if ((sval << 1) == 0) {
+                                                       /*
+                                                        * We can't flip the
+                                                        * sign of this since
+                                                        * it can't be
+                                                        * represented as a
+                                                        * positive number in
+                                                        * two complement,
+                                                        * handle the first
+                                                        * digit. After that,
+                                                        * it can be flipped
+                                                        * since it is now not
+                                                        * 2^(n-1).
+                                                        */
+                                                       *dp++ = '0'-(sval % 10);
+                                                       sval /= 10;
+                                               }
+                                               *bp++ = '-';
+                                               uval = -sval;
+                                       } else {
+                                               uval = sval;
+                                       }
+                               } else {
+                                       if (size & SZ_UNSIGNED)
+                                               uval = UARG();
+                                       else
+                                               uval = SARG();
+                               }
+                               do {
+                                       *dp++ = '0' + (uval % 10);
+                                       uval /= 10;
+                               } while (uval != 0);
+                               do {
+                                       *bp++ = *--dp;
+                               } while (dp != digits && bp < ep);
+                               fmt += 2;
+                               break;
+                       }
+                       case 'x':
+                       case 'p':{
+                               unsigned long val = va_arg(ap, unsigned long);
+                               unsigned long mask = ~(~0UL >> 4);
+                               int bits = sizeof(val) * 8 - 4;
+                               const char hexdigits[] = "0123456789abcdef";
+                               if (fmt[1] == 'p') {
+                                       *bp++ = '0';
+                                       *bp++ = 'x';
+                               }
+                               /* handle the border case */
+                               if (val == 0) {
+                                       *bp++ = '0';
+                                       fmt += 2;
+                                       break;
+                               }
+                               /* suppress 0s */
+                               while ((val & mask) == 0)
+                                       bits -= 4, mask >>= 4;
+
+                               /* emit the hex digits */
+                               while (bits >= 0 && bp < ep) {
+                                       *bp++ = hexdigits[(val & mask) >> bits];
+                                       bits -= 4, mask >>= 4;
+                               }
+                               fmt += 2;
+                               break;
+                       }
+                       case 's':{
+                               const char *str = va_arg(ap, const char *);
+                               int len;
+
+                               if (str == NULL)
+                                       str = "(null)";
+
+                               if (prec < 0)
+                                       len = strlen(str);
+                               else
+                                       len = prec;
+                               if (ep - bp < len)
+                                       len = ep - bp;
+                               memcpy(bp, str, len);
+                               bp += len;
+                               fmt += 2;
+                               break;
+                       }
+                       case 'c':{
+                               int c = va_arg(ap, int);
+                               *bp++ = (char)c;
+                               fmt += 2;
+                               break;
+                       }
+                       default:
+                               *bp++ = *fmt;
+                               break;
+                       }
+                       break;
+               }
+               default:
+                       *bp++ = *fmt++;
+                       break;
+               }
+       }
+
+       *bp = '\0';
+       return bp - buf;
+}
+
+void
+xvprintf(const char *fmt, va_list ap)
+{
+       char buf[256];
+
+       (void) write(2, buf, xvsnprintf(buf, sizeof(buf), fmt, ap));
+}
+
+void
+xprintf(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+
+       xvprintf(fmt, ap);
+
+       va_end(ap);
+}
+
+void
+xsnprintf(char *buf, size_t buflen, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+
+       xvsnprintf(buf, buflen, fmt, ap);
+
+       va_end(ap);
+}
+
+#include "errlist_concat.h"
+
+const char *
+xstrerror(int error)
+{
+
+       if (error >= concat_nerr || error < 0) {
+               static char buf[128];
+               xsnprintf(buf, sizeof(buf), "Unknown error: %d", error);
+               return buf;
+       }
+       return concat_errlist + concat_offset[error];
+}
+
+void
+xerrx(int eval, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       xvprintf(fmt, ap);
+       va_end(ap);
+       (void) write(2, "\n", 1);
+
+       exit(eval);
+}
+
+void
+xerr(int eval, const char *fmt, ...)
+{
+       int saved_errno = errno;
+       va_list ap;
+
+       va_start(ap, fmt);
+       xvprintf(fmt, ap);
+       va_end(ap);
+
+       xprintf(": %s\n", xstrerror(saved_errno));
+       exit(eval);
+}
+
+void
+xwarn(const char *fmt, ...)
+{
+       int saved_errno = errno;
+       va_list ap;
+
+       va_start(ap, fmt);
+       xvprintf(fmt, ap);
+       va_end(ap);
+
+       xprintf(": %s\n", xstrerror(saved_errno));
+       errno = saved_errno;
+}
+
+void
+xwarnx(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       xvprintf(fmt, ap);
+       va_end(ap);
+       (void) write(2, "\n", 1);
+}
+
+#ifdef DEBUG
+void
+xassert(const char *file, int line, const char *failedexpr)
+{
+
+       xprintf("assertion \"%s\" failed: file \"%s\", line %d\n",
+               failedexpr, file, line);
+       abort();
+       /* NOTREACHED */
+}
+#endif
+#endif
index 7c04a89b5aa7f345ffe689b50e111de3ab7edd50..2add88faddfa67a3594ed70a30c5f60ca5f8843b 100644 (file)
@@ -58,6 +58,14 @@ TOOLCHAIN_MISSING?=  no
 HAVE_GCC=      4
 .endif
 
+.if \
+    ${MACHINE_ARCH} == "i386" || \
+    ${MACHINE_ARCH} == "powerpc" || \
+    ${MACHINE_ARCH} == "x86_64"
+USE_COMPILERCRTSTUFF?=  no
+.endif
+USE_COMPILERCRTSTUFF?=  yes
+
 # default to GDB6
 HAVE_GDB?=     6
 
index bfc950cfb36fdcc351067326eddd0592b4acc290..dfbd4412b1ce7a05bebf188f303a2ba61586d5ee 100644 (file)
@@ -3,6 +3,8 @@
 # minixpath:  path in Minix source tree (starting from /usr/src/)
 # netbsdpath: path in BSD source tree (starting from src/)
 2011/01/17 18:11:10,external/bsd/file
+2011/01/17 18:11:10,lib/csu
+2011/01/17 18:11:10,libexec/ld.elf_so
 2011/01/17 18:11:10,usr.bin/genassym
 2012/02/10 16:16:12,usr.bin/su
 2011/12/25 06:09:09,sys/arch/i386/stand