-/* $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.
/* 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
#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
#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 */
/* 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 */
} 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 {
} 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))
/*
#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
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
/* 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.
#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
#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
/*
* 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
/*
*/
#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.
#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
#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
#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 *,
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 \
#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))
--- /dev/null
+/* $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_ */
+# $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
--- /dev/null
+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.
--- /dev/null
+# $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
--- /dev/null
+/* $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"
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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");
--- /dev/null
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:33 joerg Exp $
+
+CPPFLAGS+= -DELFSIZE=32
+
+
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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}
--- /dev/null
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:33 joerg Exp $
+
+CPPFLAGS+= -DELFSIZE=32
+
+
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+= -DELFSIZE=32
+
+
--- /dev/null
+#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
--- /dev/null
+/* $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:
--- /dev/null
+/* $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
--- /dev/null
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+= -DELFSIZE=32
+
+
-/*-
- * 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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+= -DELFSIZE=32
+
+
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+= -DELFSIZE=32
+
+
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $
+
+CPPFLAGS+= -DELFSIZE=64
-/*-
- * 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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $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"
--- /dev/null
+/* $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"
+
--- /dev/null
+/* $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)
--- /dev/null
+# $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>
--- /dev/null
+/* $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));
+}
--- /dev/null
+/* $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
--- /dev/null
+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
--- /dev/null
+# $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>
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 **);
--- /dev/null
+/* $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;
--- /dev/null
+/* $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;
--- /dev/null
+/* $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
--- /dev/null
+/* $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__ */
--- /dev/null
+# $NetBSD: Makefile,v 1.3 2006/05/19 19:11:12 christos Exp $
+CPPFLAGS+= -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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)
+++ /dev/null
-.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>
--- /dev/null
+# $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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)
--- /dev/null
+# $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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)
--- /dev/null
+# $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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)
--- /dev/null
+# $NetBSD: Makefile,v 1.13 2006/05/19 19:11:12 christos Exp $
+
+CPPFLAGS+= -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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)
--- /dev/null
+# $NetBSD: Makefile,v 1.1 2006/06/30 22:49:50 ross Exp $
+
+CPPFLAGS+= -I- -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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)
--- /dev/null
+# $NetBSD: Makefile,v 1.3 2006/05/19 19:11:12 christos Exp $
+
+CPPFLAGS+= -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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")
--- /dev/null
+# $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"
--- /dev/null
+/* $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"
--- /dev/null
+# $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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)
--- /dev/null
+# $NetBSD: Makefile,v 1.3 2006/05/19 19:11:12 christos Exp $
+CPPFLAGS+= -I${.CURDIR}
+
+.include "${.CURDIR}/../common_elf/Makefile.inc"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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)
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
--- /dev/null
+# $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
--- /dev/null
+$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.
--- /dev/null
+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
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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)
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
+
--- /dev/null
+# $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'
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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)
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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)
--- /dev/null
+# $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
--- /dev/null
+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 . */
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
+
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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 */
+
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
-/* 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
-/*-
- * 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
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+.\" $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.
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+ }
+}
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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;
+}
+
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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"
+);
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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
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
# 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