From e83f7ba2c93894ce4409c1a9136af3d6d8ad48cf Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Sat, 31 Mar 2012 00:35:32 +0200 Subject: [PATCH] switch to netbsd csu . file- and functionality-compatible with previous situation (FreeBSD csu) (with a crt1.o -> crt0.o symlink in /usr/lib) . harmonizes source with netbsd . harmonizes linker invocation (e.g. clang) with netbsd . helpful to get some arm code in there for the arm port project --- common/include/sys/exec_elf.h | 214 ++- include/sys/Makefile | 2 +- include/sys/cdefs_elf.h | 2 +- include/sys/exec.h | 298 ++++ lib/csu/Makefile | 32 +- lib/csu/README | 63 + lib/csu/alpha/Makefile | 18 + lib/csu/alpha/crt0.c | 90 ++ lib/csu/alpha/crtfm.c | 68 + lib/csu/alpha/dot_init.h | 78 + lib/csu/arch/arm/Makefile.inc | 5 + lib/csu/arch/arm/crt0.S | 56 + lib/csu/arch/arm/crti.S | 56 + lib/csu/arch/arm/crtn.S | 44 + lib/csu/arch/i386/Makefile.inc | 5 + lib/csu/arch/i386/crt0.S | 53 + lib/csu/{i386-elf => arch/i386}/crtbegin.S | 0 lib/csu/{i386-elf => arch/i386}/crtend.S | 0 lib/csu/arch/i386/crti.S | 54 + lib/csu/arch/i386/crtn.S | 46 + lib/csu/arch/m68k/Makefile.inc | 5 + lib/csu/arch/m68k/crt0.S | 52 + lib/csu/arch/m68k/crti.S | 50 + lib/csu/arch/m68k/crtn.S | 44 + lib/csu/arch/sh3/Makefile.inc | 5 + lib/csu/{i386-elf/crtn.S => arch/sh3/crt0.S} | 36 +- lib/csu/arch/sh3/crti.S | 56 + lib/csu/arch/sh3/crtn.S | 50 + lib/csu/arch/sparc/Makefile.inc | 5 + lib/csu/arch/sparc/crt0.S | 56 + lib/csu/arch/sparc/crti.S | 78 + lib/csu/arch/sparc/crtn.S | 74 + lib/csu/arch/vax/Makefile.inc | 5 + lib/csu/arch/vax/crt0.S | 53 + lib/csu/arch/vax/crti.S | 52 + lib/csu/arch/vax/crtn.S | 44 + lib/csu/arch/x86_64/Makefile.inc | 3 + .../{i386-elf/crti.S => arch/x86_64/crt0.S} | 47 +- lib/csu/arch/x86_64/crtbegin.S | 156 ++ lib/csu/arch/x86_64/crtend.S | 52 + lib/csu/arch/x86_64/crti.S | 52 + lib/csu/arch/x86_64/crtn.S | 46 + lib/csu/arm_elf/Makefile | 8 + lib/csu/arm_elf/crt0.c | 109 ++ lib/csu/arm_elf/dot_init.h | 61 + lib/csu/common/Makefile.inc | 87 ++ lib/csu/common/crt0-common.c | 137 ++ lib/csu/common/sysident.S | 82 ++ lib/csu/common/sysident_assym.cf | 12 + lib/csu/common_elf/Makefile.inc | 74 + lib/csu/common_elf/common.c | 77 + lib/csu/common_elf/common.h | 95 ++ lib/csu/common_elf/crti.c | 40 + lib/csu/common_elf/crtn.c | 35 + lib/csu/common_elf/dot_init.h | 48 + lib/csu/common_elf/dwarf2_eh.h | 70 + lib/csu/hppa/Makefile | 4 + lib/csu/hppa/crt0.c | 158 ++ lib/csu/hppa/dot_init.h | 69 + lib/csu/i386-elf/Makefile | 29 - lib/csu/ia64/Makefile | 8 + lib/csu/ia64/crt0.c | 97 ++ lib/csu/ia64/dot_init.h | 74 + lib/csu/m68k_elf/Makefile | 6 + lib/csu/m68k_elf/crt0.c | 100 ++ lib/csu/m68k_elf/dot_init.h | 60 + lib/csu/mips/Makefile | 6 + lib/csu/mips/crt0.c | 169 +++ lib/csu/mips/dot_init.h | 137 ++ lib/csu/powerpc/Makefile | 5 + lib/csu/powerpc/crt0.c | 107 ++ lib/csu/powerpc/dot_init.h | 62 + lib/csu/powerpc64/Makefile | 5 + lib/csu/powerpc64/crt0.c | 99 ++ lib/csu/powerpc64/dot_init.h | 69 + lib/csu/sh3_elf/Makefile | 5 + lib/csu/sh3_elf/crt0.c | 94 ++ lib/csu/sh3_elf/dot_init.h | 91 ++ lib/csu/sparc64/Makefile | 8 + lib/csu/sparc64/crt0.c | 119 ++ lib/csu/sparc_elf/Makefile | 6 + lib/csu/sparc_elf/crt0.c | 104 ++ lib/csu/sparc_elf/dot_init.h | 92 ++ lib/csu/vax_elf/Makefile | 4 + lib/csu/vax_elf/crt0.c | 101 ++ lib/csu/vax_elf/dot_init.h | 66 + lib/libc/net/nsdispatch.c | 18 +- libexec/ld.elf_so/Makefile | 133 ++ libexec/ld.elf_so/README | 6 + libexec/ld.elf_so/TODO | 33 + libexec/ld.elf_so/arch/alpha/Makefile.inc | 11 + libexec/ld.elf_so/arch/alpha/alpha_reloc.c | 503 +++++++ libexec/ld.elf_so/arch/alpha/rtld_start.S | 194 +++ libexec/ld.elf_so/arch/arm/Makefile.inc | 10 + libexec/ld.elf_so/arch/arm/mdreloc.c | 276 ++++ libexec/ld.elf_so/arch/arm/rtld_start.S | 104 ++ libexec/ld.elf_so/arch/hppa/Makefile.inc | 14 + libexec/ld.elf_so/arch/hppa/hppa_reloc.c | 617 ++++++++ libexec/ld.elf_so/arch/hppa/rtld_start.S | 231 +++ libexec/ld.elf_so/arch/i386/Makefile.inc | 10 + libexec/ld.elf_so/arch/i386/mdreloc.c | 216 +++ libexec/ld.elf_so/arch/i386/rtld_start.S | 88 ++ libexec/ld.elf_so/arch/m68k/Makefile.inc | 10 + libexec/ld.elf_so/arch/m68k/mdreloc.c | 224 +++ libexec/ld.elf_so/arch/m68k/rtld_start.S | 79 + libexec/ld.elf_so/arch/mips/Makefile.inc | 17 + libexec/ld.elf_so/arch/mips/mips_reloc.c | 454 ++++++ libexec/ld.elf_so/arch/mips/rtld_start.S | 140 ++ libexec/ld.elf_so/arch/powerpc/Makefile.inc | 11 + libexec/ld.elf_so/arch/powerpc/ld.so.script | 271 ++++ libexec/ld.elf_so/arch/powerpc/ppc_reloc.c | 370 +++++ libexec/ld.elf_so/arch/powerpc/rtld_start.S | 133 ++ libexec/ld.elf_so/arch/sh3/Makefile.inc | 10 + libexec/ld.elf_so/arch/sh3/mdreloc.c | 249 ++++ libexec/ld.elf_so/arch/sh3/rtld_start.S | 117 ++ libexec/ld.elf_so/arch/sparc/Makefile.inc | 10 + libexec/ld.elf_so/arch/sparc/mdreloc.c | 394 +++++ libexec/ld.elf_so/arch/sparc/rtld_start.S | 81 ++ libexec/ld.elf_so/arch/sparc64/Makefile.inc | 10 + libexec/ld.elf_so/arch/sparc64/mdreloc.c | 732 ++++++++++ libexec/ld.elf_so/arch/sparc64/rtld_start.S | 172 +++ libexec/ld.elf_so/arch/vax/Makefile.inc | 10 + libexec/ld.elf_so/arch/vax/mdreloc.c | 207 +++ libexec/ld.elf_so/arch/vax/rtld_start.S | 78 + libexec/ld.elf_so/arch/x86_64/Makefile.inc | 10 + libexec/ld.elf_so/arch/x86_64/mdreloc.c | 311 ++++ libexec/ld.elf_so/arch/x86_64/rtld_start.S | 105 ++ .../crt1_c.c => libexec/ld.elf_so/debug.c | 96 +- .../crt1_s.S => libexec/ld.elf_so/debug.h | 61 +- libexec/ld.elf_so/expand.c | 172 +++ libexec/ld.elf_so/headers.c | 369 +++++ libexec/ld.elf_so/ld.elf_so.1 | 224 +++ libexec/ld.elf_so/load.c | 350 +++++ libexec/ld.elf_so/map_object.c | 422 ++++++ libexec/ld.elf_so/paths.c | 478 +++++++ libexec/ld.elf_so/reloc.c | 224 +++ libexec/ld.elf_so/rtld.c | 1265 +++++++++++++++++ libexec/ld.elf_so/rtld.h | 362 +++++ libexec/ld.elf_so/rtldenv.h | 86 ++ libexec/ld.elf_so/search.c | 192 +++ libexec/ld.elf_so/symbol.c | 488 +++++++ libexec/ld.elf_so/sysident.h | 91 ++ libexec/ld.elf_so/xmalloc.c | 486 +++++++ libexec/ld.elf_so/xprintf.c | 323 +++++ share/mk/bsd.own.mk | 8 + tools/nbsd_ports | 2 + 146 files changed, 17246 insertions(+), 216 deletions(-) create mode 100644 include/sys/exec.h create mode 100644 lib/csu/README create mode 100644 lib/csu/alpha/Makefile create mode 100644 lib/csu/alpha/crt0.c create mode 100644 lib/csu/alpha/crtfm.c create mode 100644 lib/csu/alpha/dot_init.h create mode 100644 lib/csu/arch/arm/Makefile.inc create mode 100644 lib/csu/arch/arm/crt0.S create mode 100644 lib/csu/arch/arm/crti.S create mode 100644 lib/csu/arch/arm/crtn.S create mode 100644 lib/csu/arch/i386/Makefile.inc create mode 100644 lib/csu/arch/i386/crt0.S rename lib/csu/{i386-elf => arch/i386}/crtbegin.S (100%) rename lib/csu/{i386-elf => arch/i386}/crtend.S (100%) create mode 100644 lib/csu/arch/i386/crti.S create mode 100644 lib/csu/arch/i386/crtn.S create mode 100644 lib/csu/arch/m68k/Makefile.inc create mode 100644 lib/csu/arch/m68k/crt0.S create mode 100644 lib/csu/arch/m68k/crti.S create mode 100644 lib/csu/arch/m68k/crtn.S create mode 100644 lib/csu/arch/sh3/Makefile.inc rename lib/csu/{i386-elf/crtn.S => arch/sh3/crt0.S} (60%) create mode 100644 lib/csu/arch/sh3/crti.S create mode 100644 lib/csu/arch/sh3/crtn.S create mode 100644 lib/csu/arch/sparc/Makefile.inc create mode 100644 lib/csu/arch/sparc/crt0.S create mode 100644 lib/csu/arch/sparc/crti.S create mode 100644 lib/csu/arch/sparc/crtn.S create mode 100644 lib/csu/arch/vax/Makefile.inc create mode 100644 lib/csu/arch/vax/crt0.S create mode 100644 lib/csu/arch/vax/crti.S create mode 100644 lib/csu/arch/vax/crtn.S create mode 100644 lib/csu/arch/x86_64/Makefile.inc rename lib/csu/{i386-elf/crti.S => arch/x86_64/crt0.S} (58%) create mode 100644 lib/csu/arch/x86_64/crtbegin.S create mode 100644 lib/csu/arch/x86_64/crtend.S create mode 100644 lib/csu/arch/x86_64/crti.S create mode 100644 lib/csu/arch/x86_64/crtn.S create mode 100644 lib/csu/arm_elf/Makefile create mode 100644 lib/csu/arm_elf/crt0.c create mode 100644 lib/csu/arm_elf/dot_init.h create mode 100644 lib/csu/common/Makefile.inc create mode 100644 lib/csu/common/crt0-common.c create mode 100644 lib/csu/common/sysident.S create mode 100644 lib/csu/common/sysident_assym.cf create mode 100644 lib/csu/common_elf/Makefile.inc create mode 100644 lib/csu/common_elf/common.c create mode 100644 lib/csu/common_elf/common.h create mode 100644 lib/csu/common_elf/crti.c create mode 100644 lib/csu/common_elf/crtn.c create mode 100644 lib/csu/common_elf/dot_init.h create mode 100644 lib/csu/common_elf/dwarf2_eh.h create mode 100644 lib/csu/hppa/Makefile create mode 100644 lib/csu/hppa/crt0.c create mode 100644 lib/csu/hppa/dot_init.h delete mode 100644 lib/csu/i386-elf/Makefile create mode 100644 lib/csu/ia64/Makefile create mode 100644 lib/csu/ia64/crt0.c create mode 100644 lib/csu/ia64/dot_init.h create mode 100644 lib/csu/m68k_elf/Makefile create mode 100644 lib/csu/m68k_elf/crt0.c create mode 100644 lib/csu/m68k_elf/dot_init.h create mode 100644 lib/csu/mips/Makefile create mode 100644 lib/csu/mips/crt0.c create mode 100644 lib/csu/mips/dot_init.h create mode 100644 lib/csu/powerpc/Makefile create mode 100644 lib/csu/powerpc/crt0.c create mode 100644 lib/csu/powerpc/dot_init.h create mode 100644 lib/csu/powerpc64/Makefile create mode 100644 lib/csu/powerpc64/crt0.c create mode 100644 lib/csu/powerpc64/dot_init.h create mode 100644 lib/csu/sh3_elf/Makefile create mode 100644 lib/csu/sh3_elf/crt0.c create mode 100644 lib/csu/sh3_elf/dot_init.h create mode 100644 lib/csu/sparc64/Makefile create mode 100644 lib/csu/sparc64/crt0.c create mode 100644 lib/csu/sparc_elf/Makefile create mode 100644 lib/csu/sparc_elf/crt0.c create mode 100644 lib/csu/sparc_elf/dot_init.h create mode 100644 lib/csu/vax_elf/Makefile create mode 100644 lib/csu/vax_elf/crt0.c create mode 100644 lib/csu/vax_elf/dot_init.h create mode 100644 libexec/ld.elf_so/Makefile create mode 100644 libexec/ld.elf_so/README create mode 100644 libexec/ld.elf_so/TODO create mode 100644 libexec/ld.elf_so/arch/alpha/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/alpha/alpha_reloc.c create mode 100644 libexec/ld.elf_so/arch/alpha/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/arm/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/arm/mdreloc.c create mode 100644 libexec/ld.elf_so/arch/arm/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/hppa/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/hppa/hppa_reloc.c create mode 100644 libexec/ld.elf_so/arch/hppa/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/i386/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/i386/mdreloc.c create mode 100644 libexec/ld.elf_so/arch/i386/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/m68k/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/m68k/mdreloc.c create mode 100644 libexec/ld.elf_so/arch/m68k/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/mips/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/mips/mips_reloc.c create mode 100644 libexec/ld.elf_so/arch/mips/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/powerpc/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/powerpc/ld.so.script create mode 100644 libexec/ld.elf_so/arch/powerpc/ppc_reloc.c create mode 100644 libexec/ld.elf_so/arch/powerpc/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/sh3/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/sh3/mdreloc.c create mode 100644 libexec/ld.elf_so/arch/sh3/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/sparc/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/sparc/mdreloc.c create mode 100644 libexec/ld.elf_so/arch/sparc/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/sparc64/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/sparc64/mdreloc.c create mode 100644 libexec/ld.elf_so/arch/sparc64/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/vax/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/vax/mdreloc.c create mode 100644 libexec/ld.elf_so/arch/vax/rtld_start.S create mode 100644 libexec/ld.elf_so/arch/x86_64/Makefile.inc create mode 100644 libexec/ld.elf_so/arch/x86_64/mdreloc.c create mode 100644 libexec/ld.elf_so/arch/x86_64/rtld_start.S rename lib/csu/i386-elf/crt1_c.c => libexec/ld.elf_so/debug.c (52%) rename lib/csu/i386-elf/crt1_s.S => libexec/ld.elf_so/debug.h (58%) create mode 100644 libexec/ld.elf_so/expand.c create mode 100644 libexec/ld.elf_so/headers.c create mode 100644 libexec/ld.elf_so/ld.elf_so.1 create mode 100644 libexec/ld.elf_so/load.c create mode 100644 libexec/ld.elf_so/map_object.c create mode 100644 libexec/ld.elf_so/paths.c create mode 100644 libexec/ld.elf_so/reloc.c create mode 100644 libexec/ld.elf_so/rtld.c create mode 100644 libexec/ld.elf_so/rtld.h create mode 100644 libexec/ld.elf_so/rtldenv.h create mode 100644 libexec/ld.elf_so/search.c create mode 100644 libexec/ld.elf_so/symbol.c create mode 100644 libexec/ld.elf_so/sysident.h create mode 100644 libexec/ld.elf_so/xmalloc.c create mode 100644 libexec/ld.elf_so/xprintf.c diff --git a/common/include/sys/exec_elf.h b/common/include/sys/exec_elf.h index e7815a74d..0b8612237 100644 --- a/common/include/sys/exec_elf.h +++ b/common/include/sys/exec_elf.h @@ -1,4 +1,4 @@ -/* $NetBSD: exec_elf.h,v 1.108 2010/12/24 12:41:43 skrll Exp $ */ +/* $NetBSD: exec_elf.h,v 1.117 2011/08/03 00:22:05 enami Exp $ */ /*- * Copyright (c) 1994 The NetBSD Foundation, Inc. @@ -169,22 +169,22 @@ typedef struct { /* e_ident[EI_OSABI] */ #define ELFOSABI_SYSV 0 /* UNIX System V ABI */ #define ELFOSABI_HPUX 1 /* HP-UX operating system */ -#define ELFOSABI_NETBSD 2 /* NetBSD */ -#define ELFOSABI_LINUX 3 /* GNU/Linux */ -#define ELFOSABI_HURD 4 /* GNU/Hurd */ -#define ELFOSABI_86OPEN 5 /* 86Open */ -#define ELFOSABI_SOLARIS 6 /* Solaris */ -#define ELFOSABI_MONTEREY 7 /* Monterey */ -#define ELFOSABI_IRIX 8 /* IRIX */ -#define ELFOSABI_FREEBSD 9 /* FreeBSD */ -#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ -#define ELFOSABI_MODESTO 11 /* Novell Modesto */ -#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_MONTEREY 7 /* Monterey */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ #define ELFOSABI_OPENVMS 13 /* OpenVMS */ #define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ #define ELFOSABI_AROS 15 /* Amiga Research OS */ /* Unofficial OSABIs follow */ -#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ #define ELFOSABI_NONE ELFOSABI_SYSV @@ -344,7 +344,12 @@ typedef struct { #define PT_NUM 8 #define PT_LOOS 0x60000000 /* OS-specific range */ -#define PT_GNU_EH_FRAME 0x6474e550 /* GNU-specific EH frame segment */ + +/* GNU-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* EH frame segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicate executable stack */ +#define PT_GNU_RELRO 0x6474e552 /* Make read-only after relocation */ + #define PT_HIOS 0x6fffffff #define PT_LOPROC 0x70000000 /* Processor-specific range */ #define PT_HIPROC 0x7fffffff @@ -414,11 +419,11 @@ typedef struct { #define SHT_LOOS 0x60000000 /* Operating system specific range */ #define SHT_SUNW_move 0x6ffffffa #define SHT_SUNW_syminfo 0x6ffffffc -#define SHT_SUNW_verdef 0x6ffffffd /* Versions defined by file */ +#define SHT_SUNW_verdef 0x6ffffffd /* Versions defined by file */ #define SHT_GNU_verdef SHT_SUNW_verdef -#define SHT_SUNW_verneed 0x6ffffffe /* Versions needed by file */ +#define SHT_SUNW_verneed 0x6ffffffe /* Versions needed by file */ #define SHT_GNU_verneed SHT_SUNW_verneed -#define SHT_SUNW_versym 0x6fffffff /* Symbol versions */ +#define SHT_SUNW_versym 0x6fffffff /* Symbol versions */ #define SHT_GNU_versym SHT_SUNW_versym #define SHT_HIOS 0x6fffffff #define SHT_LOPROC 0x70000000 /* Processor-specific range */ @@ -459,7 +464,7 @@ typedef struct { /* Symbol Table index of the undefined symbol */ #define ELF_SYM_UNDEFINED 0 -#define STN_UNDEF 0 /* undefined index */ +#define STN_UNDEF 0 /* undefined index */ /* st_info: Symbol Bindings */ #define STB_LOCAL 0 /* local symbol */ @@ -571,7 +576,7 @@ typedef struct { } Elf32_Move; #define ELF32_M_SYM(info) ((info) >> 8) -#define ELF32_M_SIZE(info) (info) & 0xff) +#define ELF32_M_SIZE(info) ((info) & 0xff) #define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size)) typedef struct { @@ -583,7 +588,7 @@ typedef struct { } Elf64_Move; #define ELF64_M_SYM(info) ((info) >> 8) -#define ELF64_M_SIZE(info) (info) & 0xff) +#define ELF64_M_SIZE(info) ((info) & 0xff) #define ELF64_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size)) /* @@ -657,12 +662,12 @@ typedef struct { #define DT_NUM 29 #define DT_LOOS 0x60000000 /* Operating system specific range */ -#define DT_VERSYM 0x6ffffff0 /* Symbol versions */ +#define DT_VERSYM 0x6ffffff0 /* Symbol versions */ #define DT_FLAGS_1 0x6ffffffb /* ELF dynamic flags */ -#define DT_VERDEF 0x6ffffffc /* Versions defined by file */ -#define DT_VERDEFNUM 0x6ffffffd /* Number of versions defined by file */ -#define DT_VERNEED 0x6ffffffe /* Versions needed by file */ -#define DT_VERNEEDNUM 0x6fffffff /* Number of versions needed by file */ +#define DT_VERDEF 0x6ffffffc /* Versions defined by file */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of versions defined by file */ +#define DT_VERNEED 0x6ffffffe /* Versions needed by file */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of versions needed by file */ #define DT_HIOS 0x6fffffff #define DT_LOPROC 0x70000000 /* Processor-specific range */ #define DT_HIPROC 0x7fffffff @@ -741,20 +746,86 @@ typedef struct { Elf64_Word n_type; } Elf64_Nhdr; -#define ELF_NOTE_TYPE_ABI_TAG 1 +#define ELF_NOTE_GNU_NAMESZ 4 +#define ELF_NOTE_GNU_NAME "GNU\0" +/* + * GNU-specific note type: ABI tag + * name: GNU\0 + * namesz: 4 + * desc: + * word[0]: OS tag + * word[1]: major version + * word[2]: minor version + * word[3]: teeny version + * descsz: 16 + */ /* GNU-specific note name and description sizes */ -#define ELF_NOTE_ABI_NAMESZ 4 +#define ELF_NOTE_TYPE_ABI_TAG 1 +#define ELF_NOTE_ABI_NAME ELF_NOTE_GNU_NAME +#define ELF_NOTE_ABI_NAMESZ ELF_NOTE_GNU_NAMESZ #define ELF_NOTE_ABI_DESCSZ 16 -/* GNU-specific note name */ -#define ELF_NOTE_ABI_NAME "GNU\0" - /* GNU-specific OS/version value stuff */ #define ELF_NOTE_ABI_OS_LINUX 0 #define ELF_NOTE_ABI_OS_HURD 1 #define ELF_NOTE_ABI_OS_SOLARIS 2 +#define ELF_NOTE_ABI_OS_KFREEBSD 3 +#define ELF_NOTE_ABI_OS_KNETBSD 4 -/* NetBSD-specific note type: Emulation name. desc is emul name string. */ +/* + * GNU-specific note type: Hardware capabilities + * name: GNU\0 + * namesz: 4 + * desc: + * word[0]: Number of entries + * word[1]: Bitmask of enabled entries + * Followed by a byte id, and a NUL terminated string per entry + * descsz: variable + */ +#define ELF_NOTE_TYPE_GNU_HWCAP 2 + +/* + * GNU-specific note type: Build ID generated by ld + * name: GNU\0 + * desc: + * word[0..4] SHA1 [default] + * or + * word[0..3] md5 or uuid + * descsz: 16 or 20 + */ +#define ELF_NOTE_TYPE_GNU_BUILD_ID 3 + +/* SuSE-specific note type: version + * name: SuSE\0\0\0\0 + * namesz: 8 + * desc: + * word[0] = VVTTMMmm + * + * V = version of following data + * T = product type: [box, sles, nld, whatever] + * M = product major version + * m = product minor version + * descsz: 8 + */ +#define ELF_NOTE_TYPE_SUSE_TAG 0x45537553 /* SuSE in LE */ +/* SuSE-specific note name and description sizes */ +#define ELF_NOTE_SUSE_NAMESZ 8 +#define ELF_NOTE_SUSE_DESCSZ 8 +/* SuSE-specific note name */ +#define ELF_NOTE_SUSE_NAME "SuSE\0\0\0\0" + +/* NetBSD-specific note type: Emulation name. + * name: NetBSD\0\0 + * namesz: 8 + * desc: + * word[0]: MMmmrrpp00 + * + * M = major version + * m = minor version + * r = release ["",A-Z,Z[A-Z] but numeric] + * p = patchlevel + * descsz: 4 + */ #define ELF_NOTE_TYPE_NETBSD_TAG 1 /* NetBSD-specific note name and description sizes */ #define ELF_NOTE_NETBSD_NAMESZ 7 @@ -762,26 +833,39 @@ typedef struct { /* NetBSD-specific note name */ #define ELF_NOTE_NETBSD_NAME "NetBSD\0\0" -/* NetBSD-specific note type: Checksum. There should be 1 NOTE per PT_LOAD - section. desc is a tuple of (16),(16),. */ +/* NetBSD-specific note type: Checksum. + * There should be 1 NOTE per PT_LOAD section. + * name: ??? + * namesz: ??? + * desc: + * a tuple of (16),(16),. + * descsz: ??? + */ #define ELF_NOTE_TYPE_CHECKSUM_TAG 2 #define ELF_NOTE_CHECKSUM_CRC32 1 #define ELF_NOTE_CHECKSUM_MD5 2 #define ELF_NOTE_CHECKSUM_SHA1 3 #define ELF_NOTE_CHECKSUM_SHA256 4 -/* NetBSD-specific note type: PaX. There should be 1 NOTE per executable. - section. desc is a 32 bit bitmask */ -#define ELF_NOTE_TYPE_PAX_TAG 3 +/* + * NetBSD-specific note type: PaX. + * There should be 1 NOTE per executable. + * name: PaX\0 + * namesz: 4 + * desc: + * word[0]: capability bitmask + * descsz: 4 + */ +#define ELF_NOTE_TYPE_PAX_TAG 3 #define ELF_NOTE_PAX_MPROTECT 0x01 /* Force enable Mprotect */ #define ELF_NOTE_PAX_NOMPROTECT 0x02 /* Force disable Mprotect */ #define ELF_NOTE_PAX_GUARD 0x04 /* Force enable Segvguard */ #define ELF_NOTE_PAX_NOGUARD 0x08 /* Force disable Servguard */ #define ELF_NOTE_PAX_ASLR 0x10 /* Force enable ASLR */ #define ELF_NOTE_PAX_NOASLR 0x20 /* Force disable ASLR */ -#define ELF_NOTE_PAX_NAMESZ 4 -#define ELF_NOTE_PAX_NAME "PaX\0" -#define ELF_NOTE_PAX_DESCSZ 4 +#define ELF_NOTE_PAX_NAMESZ 4 +#define ELF_NOTE_PAX_NAME "PaX\0" +#define ELF_NOTE_PAX_DESCSZ 4 /* * NetBSD-specific core file information. @@ -865,6 +949,11 @@ struct netbsd_elfcore_procinfo { #define Elf_Off Elf32_Off #define Elf_SOff Elf32_SOff #define Elf_Nhdr Elf32_Nhdr +#define Elf_Verdef Elf32_Verdef +#define Elf_Verdaux Elf32_Verdaux +#define Elf_Verneed Elf32_Verneed +#define Elf_Vernaux Elf32_Vernaux +#define Elf_Versym Elf32_Versym #define ELF_R_SYM ELF32_R_SYM #define ELF_R_TYPE ELF32_R_TYPE @@ -886,6 +975,11 @@ struct netbsd_elfcore_procinfo { #define Elf_Off Elf64_Off #define Elf_SOff Elf64_SOff #define Elf_Nhdr Elf64_Nhdr +#define Elf_Verdef Elf64_Verdef +#define Elf_Verdaux Elf64_Verdaux +#define Elf_Verneed Elf64_Verneed +#define Elf_Vernaux Elf64_Vernaux +#define Elf_Versym Elf64_Versym #define ELF_R_SYM ELF64_R_SYM #define ELF_R_TYPE ELF64_R_TYPE @@ -944,13 +1038,18 @@ typedef struct { /* * These constants are used for Elf32_Verdef struct's version number. */ -#define VER_DEF_NONE 0 +#define VER_DEF_NONE 0 #define VER_DEF_CURRENT 1 +/* + * These constants are used for Elf32_Verdef struct's vd_ndx. + */ +#define VER_DEF_IDX(x) VER_NDX(x) + /* * These constants are used for Elf32_Verdef struct's vd_flags. */ -#define VER_FLG_BASE 0x1 +#define VER_FLG_BASE 0x1 #define VER_FLG_WEAK 0x2 /* @@ -958,6 +1057,7 @@ typedef struct { */ #define VER_NDX_LOCAL 0 #define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 /* * These constants are used for Elf32_Verneed struct's version number. @@ -966,7 +1066,17 @@ typedef struct { #define VER_NEED_CURRENT 1 /* - * GNU Extension hidding symb + * These constants are used for Elf32_Vernaux struct's vna_other. + */ +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +/* index */ +#define VER_NDX_HIDDEN 0x8000 +#define VER_NDX(x) ((x) & ~VER_NDX_HIDDEN) + +/* + * GNU Extension hidding symbol */ #define VERSYM_HIDDEN 0x8000 #define VERSYM_VERSION 0x7fff @@ -1019,18 +1129,18 @@ typedef Elf32_Versym Elf64_Versym; #ifdef _KERNEL -#define ELF_AUX_ENTRIES 14 /* Max size of aux array passed to loader */ -#define ELF32_NO_ADDR (~(Elf32_Addr)0) /* Indicates addr. not yet filled in */ -#define ELF32_LINK_ADDR ((Elf32_Addr)-2) /* advises to use link address */ -#define ELF64_NO_ADDR (~(Elf64_Addr)0) /* Indicates addr. not yet filled in */ -#define ELF64_LINK_ADDR ((Elf64_Addr)-2) /* advises to use link address */ +#define ELF_AUX_ENTRIES 14 /* Max size of aux array passed to loader */ +#define ELF32_NO_ADDR (~(Elf32_Addr)0) /* Indicates addr. not yet filled in */ +#define ELF32_LINK_ADDR ((Elf32_Addr)-2) /* advises to use link address */ +#define ELF64_NO_ADDR (~(Elf64_Addr)0) /* Indicates addr. not yet filled in */ +#define ELF64_LINK_ADDR ((Elf64_Addr)-2) /* advises to use link address */ #if defined(ELFSIZE) && (ELFSIZE == 64) -#define ELF_NO_ADDR ELF64_NO_ADDR -#define ELF_LINK_ADDR ELF64_LINK_ADDR +#define ELF_NO_ADDR ELF64_NO_ADDR +#define ELF_LINK_ADDR ELF64_LINK_ADDR #elif defined(ELFSIZE) && (ELFSIZE == 32) -#define ELF_NO_ADDR ELF32_NO_ADDR -#define ELF_LINK_ADDR ELF32_LINK_ADDR +#define ELF_NO_ADDR ELF32_NO_ADDR +#define ELF_LINK_ADDR ELF32_LINK_ADDR #endif #ifndef ELF32_EHDR_FLAGS_OK @@ -1061,6 +1171,8 @@ struct elf_args { #include "opt_execfmt.h" #endif +struct ps_strings; + #ifdef EXEC_ELF32 int exec_elf32_makecmds(struct lwp *, struct exec_package *); int elf32_copyargs(struct lwp *, struct exec_package *, diff --git a/include/sys/Makefile b/include/sys/Makefile index 02af8846f..50c822584 100644 --- a/include/sys/Makefile +++ b/include/sys/Makefile @@ -35,7 +35,7 @@ INCS+= ansi.h atomic.h \ tree.h ttycom.h ttydefaults.h \ types.h \ ucontext.h ucred.h uio.h un.h unistd.h utsname.h uuid.h \ - wait.h + wait.h exec.h INCSYMLINKS=\ sys/fcntl.h ${NETBSDINCSDIR}/fcntl.h \ diff --git a/include/sys/cdefs_elf.h b/include/sys/cdefs_elf.h index e3e56a436..4872136b6 100644 --- a/include/sys/cdefs_elf.h +++ b/include/sys/cdefs_elf.h @@ -64,7 +64,7 @@ #define __weak_extern(sym) \ __asm(".weak " _C_LABEL_STRING(#sym)); -#if __GNUC_PREREQ__(4, 0) && !defined(__minix) +#if __GNUC_PREREQ__(4, 0) #define __weak_reference(sym) __attribute__((__weakref__)) #else #define __weak_reference(sym) ; __asm(".weak " _C_LABEL_STRING(#sym)) diff --git a/include/sys/exec.h b/include/sys/exec.h new file mode 100644 index 000000000..9d2ce870e --- /dev/null +++ b/include/sys/exec.h @@ -0,0 +1,298 @@ +/* $NetBSD: exec.h,v 1.133 2011/03/04 22:25:32 joerg Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)exec.h 8.4 (Berkeley) 2/19/95 + */ + +/*- + * Copyright (c) 1993 Theo de Raadt. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1994 Christopher G. Demetriou + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)exec.h 8.4 (Berkeley) 2/19/95 + */ + +#ifndef _SYS_EXEC_H_ +#define _SYS_EXEC_H_ + +struct pathbuf; /* from namei.h */ + + +/* + * The following structure is found at the top of the user stack of each + * user process. The ps program uses it to locate argv and environment + * strings. Programs that wish ps to display other information may modify + * it; normally ps_argvstr points to argv[0], and ps_nargvstr is the same + * as the program's argc. The fields ps_envstr and ps_nenvstr are the + * equivalent for the environment. + */ +struct ps_strings { + char **ps_argvstr; /* first of 0 or more argument strings */ + int ps_nargvstr; /* the number of argument strings */ + char **ps_envstr; /* first of 0 or more environment strings */ + int ps_nenvstr; /* the number of environment strings */ +}; + +#ifdef _KERNEL +struct ps_strings32 { + uint32_t ps_argvstr; /* first of 0 or more argument strings */ + int32_t ps_nargvstr; /* the number of argument strings */ + uint32_t ps_envstr; /* first of 0 or more environment strings */ + int32_t ps_nenvstr; /* the number of environment strings */ +}; +#endif + +/* + * the following structures allow execve() to put together processes + * in a more extensible and cleaner way. + * + * the exec_package struct defines an executable being execve()'d. + * it contains the header, the vmspace-building commands, the vnode + * information, and the arguments associated with the newly-execve'd + * process. + * + * the exec_vmcmd struct defines a command description to be used + * in creating the new process's vmspace. + */ + +#include + +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_ */ diff --git a/lib/csu/Makefile b/lib/csu/Makefile index 7764c4b81..d212be07e 100644 --- a/lib/csu/Makefile +++ b/lib/csu/Makefile @@ -1,5 +1,33 @@ +# $NetBSD: Makefile,v 1.28 2010/11/28 18:40:56 skrll Exp $ + .include -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 +. include +.endif diff --git a/lib/csu/README b/lib/csu/README new file mode 100644 index 000000000..e552c5246 --- /dev/null +++ b/lib/csu/README @@ -0,0 +1,63 @@ +Overview of the common runtime support + +The common runtime support contains two modules, crtbegin and crtend. +crtbegin is linked before all other object files of the program or +dynamic library, crtend after all other object files. They frame the +lists of constructors, destructors, Java types and exception handling frames. + +If done correctly, crtend contains no code and is therefore position +independent. crtendS.o is therefore just a link to crtend.o. + +crtbegin should be position-independent code. crtbeginT.o doesn't have +to be PIC as it is statically linked. The overhead is generally not +worth the trouble though. + + +Section types: +.ctor: writeable +.dtor: writeable +.eh_frame: read-only if platform allows mixing read-only and read-write +sections. This is supported by GNU ld. +.jcr: writeable +.init: executable +.fini: executable + + +Non-local symbols: + +Weak references: +- _Jv_RegisterClasses, +- __cxa_finalize (crtbeginS.o) +- __deregister_frame_info +- __register_frame_info + +Hidden: +- __dso_handle: pointer to self for crtbeginS.o, NULL otherwise. +- __CTOR_LIST_END__ + + +Initialisation (called from .init): + +1. Check that the init code hasn't started already, otherwise bail out. +2. If __register_frame_info is NULL, skip to 4 +3. Call __register_frame_info with start of .eh_frame as first argument + and a data object of at least 8 pointers as second argument. +4: If _Jv_RegisterClasses is NULL, skip to 6 +5: Call _Jv_RegisterClasses with the first pointer of the .jcr section + as argument. +6: Iterate from the end of the .ctor section to the start. Skip the + terminating NULL and stop when reaching the starting (void *)-1 element. + Call the pointers as void (*)(void) functions. + + +Deinitialisation (called from .fini): + +1. Check if the init code has already started, otherwise bail out. +2. If this is not crtbeginS.o or __cxa_finalize is NULL, skip to 4. +3. Call __cxa_finalize with a pointer into this Dynamic Shared Object (DSO) + as first argument. +4. Iterate from the start of the .dtor section to the send. Skip the + initial (void *)-1 and stop when reaching the terminating NULL element. + Call the pointers as void (*)(void) functions. +5. If __deregister_frame_info is NULL, return. +6. Call __deregister_frame_info with the start of .eh_frame as the argument. diff --git a/lib/csu/alpha/Makefile b/lib/csu/alpha/Makefile new file mode 100644 index 000000000..f619e3cd4 --- /dev/null +++ b/lib/csu/alpha/Makefile @@ -0,0 +1,18 @@ +# $NetBSD: Makefile,v 1.24 2008/07/21 15:34:58 lukem Exp $ + +.include + +ELFSIZE= 64 + +#Uncomment the next line to enable the new .init fallthru +CPPFLAGS+= -I${.CURDIR} + +OBJS+= crtfm.o + +.include "${.CURDIR}/../common_elf/Makefile.inc" + +crtfm.o: crtfm.c + ${_MKTARGET_COMPILE} + ${COMPILE.c} ${.ALLSRC} -o ${.TARGET}.o + ${LD} -x -r -o ${.TARGET} ${.TARGET}.o + rm -f ${.TARGET}.o diff --git a/lib/csu/alpha/crt0.c b/lib/csu/alpha/crt0.c new file mode 100644 index 000000000..58534d7b6 --- /dev/null +++ b/lib/csu/alpha/crt0.c @@ -0,0 +1,90 @@ +/* $NetBSD: crt0.c,v 1.24 2003/07/26 19:24:25 salo Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +void __start __P((char **, void (*cleanup) __P((void)), const Obj_Entry *, + struct ps_strings *)); + +void +__start(sp, cleanup, obj, ps_strings) + char **sp; + void (*cleanup) __P((void)); /* from shared loader */ + const Obj_Entry *obj; /* from shared loader */ + struct ps_strings *ps_strings; +{ + long argc; + char **argv, *namep; + + argc = *(long *)sp; + argv = sp + 1; + environ = sp + 2 + argc; /* 2: argc + NULL ending argv */ + + if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(namep, '/')) == NULL) + __progname = namep; + else + __progname++; + } + + if (ps_strings != (struct ps_strings *)0 && + ps_strings != (struct ps_strings *)0xbabefacedeadbeef) + __ps_strings = ps_strings; + +#ifdef DYNAMIC + if (&_DYNAMIC != NULL) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.24 2003/07/26 19:24:25 salo Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/alpha/crtfm.c b/lib/csu/alpha/crtfm.c new file mode 100644 index 000000000..cdfcfda98 --- /dev/null +++ b/lib/csu/alpha/crtfm.c @@ -0,0 +1,68 @@ +/* $NetBSD: crtfm.c,v 1.2 2002/01/14 01:31:00 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Support for the GCC "-ffast-math" option on the Alpha. + */ + +#include + +#include +#include + +/* + * Must provide this wrapper around sysarch(2) so that statically-linked + * programs work properly. + */ + +extern void __alpha_sysarch(int, void *); + +__asm(".ent __alpha_sysarch 0 ;\n" +"__alpha_sysarch: ;\n" +" ldiq $0, 165 ;\n" /* v0 = SYS_sysarch */ +" call_pal 0x0083 ;\n" /* PAL_OSF1_callsys */ +" ret $31,($26),1 ;\n" +".end __alpha_sysarch"); + +static void __attribute__((__constructor__)) +__alpha_set_fast_math(void) +{ + struct alpha_fp_c_args args; + + args.fp_c = IEEE_MAP_DMZ|IEEE_MAP_UMZ; + __alpha_sysarch(ALPHA_SET_FP_C, &args); +} diff --git a/lib/csu/alpha/dot_init.h b/lib/csu/alpha/dot_init.h new file mode 100644 index 000000000..1fd022a80 --- /dev/null +++ b/lib/csu/alpha/dot_init.h @@ -0,0 +1,78 @@ +/* $NetBSD: dot_init.h,v 1.8 2008/05/10 15:31:03 martin Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ +#include + +#define ASM_SETUP "sp = $30; gp = $29; pv = $27; ra = $26 \n" + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ASM_SETUP \ + ".section "#sect",\"ax\",@progbits \n"\ + ".global "#entry_pt" \n"\ + #entry_pt": \n"\ + " ldgp gp, 0(pv) \n"\ + " lda sp, -32(sp) \n"\ + " stq ra, 0(sp) \n"\ + " stq gp, 8(sp) \n"\ + " .align 5 \n"\ + " /* fall thru */ \n"\ + ".previous") + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ASM_SETUP \ + ".section "#sect",\"ax\",@progbits \n"\ + " ldq gp, 8(sp) \n"\ + " ldq ra, 0(sp) \n"\ + " lda sp, 32(sp) \n"\ + " RET \n"\ + ".previous") + +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) + +/* We assume we need to reload our GP. */ +#define MD_CALL_STATIC_FUNCTION(section, func) \ +__asm(".section " #section "\n" \ +" br $29, 1f \n" \ +"1: ldgp $29, 0($29) \n" \ +" unop \n" \ +" jsr $26, " #func "\n" \ +" .align 3; .previous"); diff --git a/lib/csu/arch/arm/Makefile.inc b/lib/csu/arch/arm/Makefile.inc new file mode 100644 index 000000000..77519435c --- /dev/null +++ b/lib/csu/arch/arm/Makefile.inc @@ -0,0 +1,5 @@ +# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:33 joerg Exp $ + +CPPFLAGS+= -DELFSIZE=32 + + diff --git a/lib/csu/arch/arm/crt0.S b/lib/csu/arch/arm/crt0.S new file mode 100644 index 000000000..4e71c1822 --- /dev/null +++ b/lib/csu/arch/arm/crt0.S @@ -0,0 +1,56 @@ +/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */ + +/* + * Copyright (C) 1997 Mark Brinicombe + * Copyright (C) 1995 Wolfgang Solfrank. + * Copyright (C) 1995 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include + +RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:33 joerg Exp $") + +STRONG_ALIAS(_start,__start) + +_ENTRY(__start) + mov r5, r2 /* cleanup */ + mov r4, r1 /* obj_main */ + mov r3, r0 /* ps_strings */ + /* Get argc, argv, and envp from stack */ + ldr r0, [sp, #0x0000] + add r1, sp, #0x0004 + add r2, r1, r0, lsl #2 + add r2, r2, #0x0004 + + /* Ensure the stack is properly aligned before calling C code. */ + bic sp, sp, #7 + sub sp, sp, #8 + str r5, [sp, #4] + str r4, [sp, #0] + + b ___start diff --git a/lib/csu/arch/arm/crti.S b/lib/csu/arch/arm/crti.S new file mode 100644 index 000000000..fe3ab872b --- /dev/null +++ b/lib/csu/arch/arm/crti.S @@ -0,0 +1,56 @@ +/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:33 joerg Exp $") + +#include "sysident.S" + + .section ".init", "ax", @progbits + .align 0 + .globl _init +_init: + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + + .section ".fini", "ax", @progbits + .align 0 + .globl _fini +_fini: + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 diff --git a/lib/csu/arch/arm/crtn.S b/lib/csu/arch/arm/crtn.S new file mode 100644 index 000000000..8d85e0923 --- /dev/null +++ b/lib/csu/arch/arm/crtn.S @@ -0,0 +1,44 @@ +/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:33 joerg Exp $") + + .section ".init", "ax", @progbits + ldmea fp, {fp, sp, pc} + + .section ".fini", "ax", @progbits + ldmea fp, {fp, sp, pc} diff --git a/lib/csu/arch/i386/Makefile.inc b/lib/csu/arch/i386/Makefile.inc new file mode 100644 index 000000000..77519435c --- /dev/null +++ b/lib/csu/arch/i386/Makefile.inc @@ -0,0 +1,5 @@ +# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:33 joerg Exp $ + +CPPFLAGS+= -DELFSIZE=32 + + diff --git a/lib/csu/arch/i386/crt0.S b/lib/csu/arch/i386/crt0.S new file mode 100644 index 000000000..bc975d93e --- /dev/null +++ b/lib/csu/arch/i386/crt0.S @@ -0,0 +1,53 @@ +/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */ + +/* + * Copyright (c) 1998 Christos Zoulas + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include + +RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:33 joerg Exp $") + +STRONG_ALIAS(_start,__start) +_ENTRY(__start) + pushl %ebx + pushl %ecx + pushl %edx + movl 12(%esp),%eax + leal 16(%esp),%edx + leal 20(%esp,%eax,4),%ecx + pushl %ecx + pushl %edx + pushl %eax + call ___start diff --git a/lib/csu/i386-elf/crtbegin.S b/lib/csu/arch/i386/crtbegin.S similarity index 100% rename from lib/csu/i386-elf/crtbegin.S rename to lib/csu/arch/i386/crtbegin.S diff --git a/lib/csu/i386-elf/crtend.S b/lib/csu/arch/i386/crtend.S similarity index 100% rename from lib/csu/i386-elf/crtend.S rename to lib/csu/arch/i386/crtend.S diff --git a/lib/csu/arch/i386/crti.S b/lib/csu/arch/i386/crti.S new file mode 100644 index 000000000..fbc5ddd72 --- /dev/null +++ b/lib/csu/arch/i386/crti.S @@ -0,0 +1,54 @@ +/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:33 joerg Exp $") + +#include "sysident.S" + + .section ".init", "ax", @progbits + .align 16 + .globl _init +_init: + pushl %ebp + movl %esp, %ebp + + .section ".fini", "ax", @progbits + .align 16 + .globl _fini +_fini: + pushl %ebp + movl %esp, %ebp diff --git a/lib/csu/arch/i386/crtn.S b/lib/csu/arch/i386/crtn.S new file mode 100644 index 000000000..644d6a63e --- /dev/null +++ b/lib/csu/arch/i386/crtn.S @@ -0,0 +1,46 @@ +/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + + .section ".init", "ax", @progbits + leave + ret + + .section ".fini", "ax", @progbits + leave + ret diff --git a/lib/csu/arch/m68k/Makefile.inc b/lib/csu/arch/m68k/Makefile.inc new file mode 100644 index 000000000..ade41715e --- /dev/null +++ b/lib/csu/arch/m68k/Makefile.inc @@ -0,0 +1,5 @@ +# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $ + +CPPFLAGS+= -DELFSIZE=32 + + diff --git a/lib/csu/arch/m68k/crt0.S b/lib/csu/arch/m68k/crt0.S new file mode 100644 index 000000000..6d4d4e432 --- /dev/null +++ b/lib/csu/arch/m68k/crt0.S @@ -0,0 +1,52 @@ +#include + +/* + * 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. + * + * <> + */ + +RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + +STRONG_ALIAS(_start,__start) + +_ENTRY(__start) + movl (%sp),%d0 + movl %a2,-(%sp) | ps_strings + movl %a0,-(%sp) | obj + movl %a1,-(%sp) | cleanup + movl %d0,%d1 + lsll #2,%d1 + pea (16+4)(%sp,%d1.l) | envp = &argv[argc + 1] + pea 20(%sp) | argv + movl %d0,-(%sp) | argc + jsr ___start diff --git a/lib/csu/arch/m68k/crti.S b/lib/csu/arch/m68k/crti.S new file mode 100644 index 000000000..df84a46ca --- /dev/null +++ b/lib/csu/arch/m68k/crti.S @@ -0,0 +1,50 @@ +/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + +#include "sysident.S" + + .section ".init", "ax", @progbits + .align 2 + .globl _init +_init: + + .section ".fini", "ax", @progbits + .align 2 + .globl _fini +_fini: diff --git a/lib/csu/arch/m68k/crtn.S b/lib/csu/arch/m68k/crtn.S new file mode 100644 index 000000000..9614561a0 --- /dev/null +++ b/lib/csu/arch/m68k/crtn.S @@ -0,0 +1,44 @@ +/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + + .section ".init", "ax", @progbits + rts + + .section ".fini", "ax", @progbits + rts diff --git a/lib/csu/arch/sh3/Makefile.inc b/lib/csu/arch/sh3/Makefile.inc new file mode 100644 index 000000000..ade41715e --- /dev/null +++ b/lib/csu/arch/sh3/Makefile.inc @@ -0,0 +1,5 @@ +# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $ + +CPPFLAGS+= -DELFSIZE=32 + + diff --git a/lib/csu/i386-elf/crtn.S b/lib/csu/arch/sh3/crt0.S similarity index 60% rename from lib/csu/i386-elf/crtn.S rename to lib/csu/arch/sh3/crt0.S index ae0754726..86ddcf52b 100644 --- a/lib/csu/i386-elf/crtn.S +++ b/lib/csu/arch/sh3/crt0.S @@ -1,7 +1,10 @@ -/*- - * Copyright 1996, 1997, 1998, 2000 John D. Polstra. +/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/* + * Copyright (c) 1998 Christos Zoulas + * Copyright (c) 1995 Christopher G. Demetriou * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -10,7 +13,14 @@ * 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. @@ -21,15 +31,17 @@ * 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. + * + * <> */ - .section .init,"ax",@progbits - add $12,%esp - ret +#include + +RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") - .section .fini,"ax",@progbits - add $12,%esp - ret +STRONG_ALIAS(_start,__start) - .section .rodata -.ascii "$MINIX$\0" +_ENTRY(__start) + mov.l r9,@-r15 + bra ___start + mov.l r8,@-r15 diff --git a/lib/csu/arch/sh3/crti.S b/lib/csu/arch/sh3/crti.S new file mode 100644 index 000000000..808c363f6 --- /dev/null +++ b/lib/csu/arch/sh3/crti.S @@ -0,0 +1,56 @@ +/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + +#include "sysident.S" + + .section ".init", "ax", @progbits + .align 4 + .globl _init +_init: + mov.l r14, @-sp + sts.l pr, @-sp + mov sp, r14 + + .section ".fini", "ax", @progbits + .align 4 + .globl _fini +_fini: + mov.l r14, @-sp + sts.l pr, @-sp + mov sp, r14 diff --git a/lib/csu/arch/sh3/crtn.S b/lib/csu/arch/sh3/crtn.S new file mode 100644 index 000000000..54edfb99c --- /dev/null +++ b/lib/csu/arch/sh3/crtn.S @@ -0,0 +1,50 @@ +/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + + .section ".init", "ax", @progbits + mov r14, sp + lds.l @sp+, pr + rts + mov.l @sp+, r14 + + .section ".fini", "ax", @progbits + mov r14, sp + lds.l @sp+, pr + rts + mov.l @sp+, r14 diff --git a/lib/csu/arch/sparc/Makefile.inc b/lib/csu/arch/sparc/Makefile.inc new file mode 100644 index 000000000..ade41715e --- /dev/null +++ b/lib/csu/arch/sparc/Makefile.inc @@ -0,0 +1,5 @@ +# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $ + +CPPFLAGS+= -DELFSIZE=32 + + diff --git a/lib/csu/arch/sparc/crt0.S b/lib/csu/arch/sparc/crt0.S new file mode 100644 index 000000000..05b20c54b --- /dev/null +++ b/lib/csu/arch/sparc/crt0.S @@ -0,0 +1,56 @@ +/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/* + * Copyright (c) 1998 Christos Zoulas + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include + +RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + +STRONG_ALIAS(_start,__start) + +_ENTRY(__start) + mov 0, %fp + ld [%sp + 64], %o0 ! get argc + add %sp, 68, %o1 ! get argv + sll %o0, 2, %o2 ! + add %o2, 4, %o2 ! envp = argv + (argc << 2) + 4 + add %o1, %o2, %o2 ! + andn %sp, 7, %sp ! align + sub %sp, 24, %sp ! expand to standard stack frame size + mov %g3, %o3 + mov %g2, %o4 + call ___start + mov %g1, %o5 diff --git a/lib/csu/arch/sparc/crti.S b/lib/csu/arch/sparc/crti.S new file mode 100644 index 000000000..8f8128a7e --- /dev/null +++ b/lib/csu/arch/sparc/crti.S @@ -0,0 +1,78 @@ +/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/* + * Copyright (c) 2001 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + +#include "sysident.S" + + .section ".init", "ax", @progbits + .align 4 + .globl _init +_init: + save %sp, -96, %sp + + .section ".fini", "ax", @progbits + .align 4 + .globl _fini +_fini: + save %sp, -96, %sp diff --git a/lib/csu/arch/sparc/crtn.S b/lib/csu/arch/sparc/crtn.S new file mode 100644 index 000000000..d86319a99 --- /dev/null +++ b/lib/csu/arch/sparc/crtn.S @@ -0,0 +1,74 @@ +/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/* + * Copyright (c) 2001 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + + .section ".init", "ax", @progbits + .align 4 + ret + restore + + .section ".fini", "ax", @progbits + .align 4 + ret + restore diff --git a/lib/csu/arch/vax/Makefile.inc b/lib/csu/arch/vax/Makefile.inc new file mode 100644 index 000000000..ade41715e --- /dev/null +++ b/lib/csu/arch/vax/Makefile.inc @@ -0,0 +1,5 @@ +# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $ + +CPPFLAGS+= -DELFSIZE=32 + + diff --git a/lib/csu/arch/vax/crt0.S b/lib/csu/arch/vax/crt0.S new file mode 100644 index 000000000..2db43a5a9 --- /dev/null +++ b/lib/csu/arch/vax/crt0.S @@ -0,0 +1,53 @@ +/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/* + * Copyright (c) 1999 Matt Thomas + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include + +RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + +STRONG_ALIAS(_start,__start) + +_ENTRY(__start) + .word 0x0101 + pushl %r9 /* ps_strings */ + pushl %r8 /* obj */ + pushl %r7 /* cleanup */ + movl (%r6),%r0 /* argc */ + pushal 8(%r6)[%r0] /* envp = &argv[argc + 1] */ + pushal 4(%r6) /* argv */ + pushl %r0 /* argc */ + calls $6,___start diff --git a/lib/csu/arch/vax/crti.S b/lib/csu/arch/vax/crti.S new file mode 100644 index 000000000..6a554539a --- /dev/null +++ b/lib/csu/arch/vax/crti.S @@ -0,0 +1,52 @@ +/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + +#include "sysident.S" + + .section ".init", "ax", @progbits + .align 1 + .globl _init +_init: + .word 0 + + .section ".fini", "ax", @progbits + .align 1 + .globl _fini +_fini: + .word 0 diff --git a/lib/csu/arch/vax/crtn.S b/lib/csu/arch/vax/crtn.S new file mode 100644 index 000000000..3cfb46693 --- /dev/null +++ b/lib/csu/arch/vax/crtn.S @@ -0,0 +1,44 @@ +/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + + .section ".init", "ax", @progbits + ret + + .section ".fini", "ax", @progbits + ret diff --git a/lib/csu/arch/x86_64/Makefile.inc b/lib/csu/arch/x86_64/Makefile.inc new file mode 100644 index 000000000..2cb588f95 --- /dev/null +++ b/lib/csu/arch/x86_64/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2010/08/07 18:01:34 joerg Exp $ + +CPPFLAGS+= -DELFSIZE=64 diff --git a/lib/csu/i386-elf/crti.S b/lib/csu/arch/x86_64/crt0.S similarity index 58% rename from lib/csu/i386-elf/crti.S rename to lib/csu/arch/x86_64/crt0.S index f06517c88..39bf6eec4 100644 --- a/lib/csu/i386-elf/crti.S +++ b/lib/csu/arch/x86_64/crt0.S @@ -1,7 +1,10 @@ -/*- - * Copyright 1996, 1997, 1998, 2000 John D. Polstra. +/* $NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ + +/* + * Copyright (c) 1998 Christos Zoulas + * Copyright (c) 1995 Christopher G. Demetriou * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -10,7 +13,14 @@ * 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. @@ -23,19 +33,20 @@ * 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 + +RCSID("$NetBSD: crt0.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") - .section .fini,"ax",@progbits - .align 4 - .globl _fini - .type _fini,@function -_fini: - sub $12,%esp /* re-align stack pointer */ +STRONG_ALIAS(_start,__start) - .section .rodata -.ascii "$MINIX$\0" +_ENTRY(__start) + movq %rbx,%r9 + movq %rcx,%r8 + movq %rdx,%rcx + movq (%rsp),%rdi + leaq 16(%rsp,%rdi,8),%rdx + leaq 8(%rsp),%rsi + subq $8,%rsp + andq $~15,%rsp + addq $8,%rsp + jmp ___start diff --git a/lib/csu/arch/x86_64/crtbegin.S b/lib/csu/arch/x86_64/crtbegin.S new file mode 100644 index 000000000..7efba6881 --- /dev/null +++ b/lib/csu/arch/x86_64/crtbegin.S @@ -0,0 +1,156 @@ +/* $NetBSD: crtbegin.S,v 1.2 2010/11/30 18:37:59 joerg Exp $ */ +/*- + * Copyright (c) 2010 Joerg Sonnenberger + * 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 + +RCSID("$NetBSD: crtbegin.S,v 1.2 2010/11/30 18:37:59 joerg Exp $") + + .section .ctors, "aw", @progbits + .align 8 +__CTOR_LIST__: + .quad -1 + + .section .dtors, "aw", @progbits + .align 8 +__DTOR_LIST__: + .quad -1 + + .section .eh_frame, "a", @progbits + .align 8 +__EH_FRAME_LIST__: + + .section .jcr, "aw", @progbits + .align 8 +__JCR_LIST__: + + .section .data.rel, "aw", @progbits + .align 8 + .type __dso_handle, @object + .size __dso_handle, 8 + .globl __dso_handle + .hidden __dso_handle +__dso_handle: +#ifdef SHARED + .quad __dso_handle +#else + .quad 0 +#endif + +__dwarf_eh_object: + .zero 64 + +__initialized: + .zero 1 +__finished: + .zero 1 + + .text + .weak __cxa_finalize + .weak __deregister_frame_info + .weak __register_frame_info + .weak _Jv_RegisterClasses + +__do_global_dtors_aux: + cmpb $0, __finished(%rip) + je 1f + ret +1: + pushq %rbx + movb $1, __finished(%rip) + + +#ifdef SHARED + cmpq $0, __cxa_finalize@GOTPCREL(%rip) + je 2f + movq __dso_handle(%rip), %rdi + call __cxa_finalize@PLT +2: +#endif + + leaq 8+__DTOR_LIST__(%rip), %rbx +3: + movq (%rbx), %rax + testq %rax, %rax + je 4f + call *%rax + addq $8, %rbx + jmp 3b +4: + + cmpq $0, __deregister_frame_info@GOTPCREL(%rip) + je 5f + leaq __EH_FRAME_LIST__(%rip), %rdi + call __deregister_frame_info@PLT +5: + popq %rbx + ret + + +__do_global_ctors_aux: + cmpb $0, __initialized(%rip) + je 1f + ret +1: + pushq %rbx + movb $1, __initialized(%rip) + + cmpq $0, __register_frame_info@GOTPCREL(%rip) + je 2f + leaq __dwarf_eh_object(%rip), %rsi + leaq __EH_FRAME_LIST__(%rip), %rdi + call __register_frame_info@PLT + +2: + cmpq $0, _Jv_RegisterClasses@GOTPCREL(%rip) + je 3f + leaq __JCR_LIST__(%rip), %rdi + cmpq $0, (%rdi) + je 3f + call _Jv_RegisterClasses@PLT +3: + + leaq -8+__CTOR_LIST_END__(%rip), %rbx +4: + movq (%rbx), %rax + cmpq $-1, %rax + je 5f + call *%rax + subq $8, %rbx + jmp 4b + +5: + popq %rbx + + ret + + .section .init, "ax", @progbits + call __do_global_ctors_aux + .section .fini, "ax", @progbits + call __do_global_dtors_aux diff --git a/lib/csu/arch/x86_64/crtend.S b/lib/csu/arch/x86_64/crtend.S new file mode 100644 index 000000000..ae7f1e405 --- /dev/null +++ b/lib/csu/arch/x86_64/crtend.S @@ -0,0 +1,52 @@ +/* $NetBSD: crtend.S,v 1.1 2010/08/07 18:01:34 joerg Exp $ */ +/*- + * Copyright (c) 2010 Joerg Sonnenberger + * 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 + +RCSID("$NetBSD: crtend.S,v 1.1 2010/08/07 18:01:34 joerg Exp $") + + .section .ctors, "aw", @progbits + .align 8 + .global __CTOR_LIST_END__ + .hidden __CTOR_LIST_END__ +__CTOR_LIST_END__: + .quad 0 + + .section .dtors, "aw", @progbits + .align 8 + .quad 0 + + .section .eh_frame, "a", @progbits + .align 8 + .quad 0 + + .section .jcr, "aw", @progbits + .align 8 + .quad 0 diff --git a/lib/csu/arch/x86_64/crti.S b/lib/csu/arch/x86_64/crti.S new file mode 100644 index 000000000..1b00f5aa9 --- /dev/null +++ b/lib/csu/arch/x86_64/crti.S @@ -0,0 +1,52 @@ +/* $NetBSD: crti.S,v 1.1 2010/08/07 18:01:35 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crti.S,v 1.1 2010/08/07 18:01:35 joerg Exp $") + +#include "sysident.S" + + .section ".init", "ax", @progbits + .align 16 + .globl _init +_init: + subq $8, %rsp + + .section ".fini", "ax", @progbits + .align 16 + .globl _fini +_fini: + subq $8, %rsp diff --git a/lib/csu/arch/x86_64/crtn.S b/lib/csu/arch/x86_64/crtn.S new file mode 100644 index 000000000..3119cbdbf --- /dev/null +++ b/lib/csu/arch/x86_64/crtn.S @@ -0,0 +1,46 @@ +/* $NetBSD: crtn.S,v 1.1 2010/08/07 18:01:35 joerg Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: crtn.S,v 1.1 2010/08/07 18:01:35 joerg Exp $") + + .section ".init", "ax", @progbits + addq $8, %rsp + ret + + .section ".fini", "ax", @progbits + addq $8, %rsp + ret diff --git a/lib/csu/arm_elf/Makefile b/lib/csu/arm_elf/Makefile new file mode 100644 index 000000000..d357eee75 --- /dev/null +++ b/lib/csu/arm_elf/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.4 2006/05/19 19:11:12 christos Exp $ +CPPFLAGS+= -I${.CURDIR} + +# Temporary hack to work around ld problems when linking Thumb applications +# where the linker does not correctly insert an interworking veneer. +CFLAGS+=-mlong-calls + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/arm_elf/crt0.c b/lib/csu/arm_elf/crt0.c new file mode 100644 index 000000000..fa2aa2b31 --- /dev/null +++ b/lib/csu/arm_elf/crt0.c @@ -0,0 +1,109 @@ +/* $NetBSD: crt0.c,v 1.7 2008/06/21 00:52:52 gmcgarry Exp $ */ + +/* + * Copyright (C) 1997 Mark Brinicombe + * Copyright (C) 1995 Wolfgang Solfrank. + * Copyright (C) 1995 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include + +#include "common.h" + +extern void _start(void); + void ___start(int, char *[], char *[], struct ps_strings *, + const Obj_Entry *, void (*)(void)); + +__asm(" .text \n" +" .align 0 \n" +" .globl _start \n" +" .globl __start \n" +"_start: \n" +"__start: \n" +" mov r5, r2 /* cleanup */ \n" +" mov r4, r1 /* obj_main */ \n" +" mov r3, r0 /* ps_strings */ \n" +" /* Get argc, argv, and envp from stack */ \n" +" ldr r0, [sp, #0x0000] \n" +" add r1, sp, #0x0004 \n" +" add r2, r1, r0, lsl #2 \n" +" add r2, r2, #0x0004 \n" +"\n" +" /* Ensure the stack is properly aligned before calling C code. */\n" +" bic sp, sp, #" ___STRING(STACKALIGNBYTES) " \n" +" sub sp, sp, #8 \n" +" str r5, [sp, #4] \n" +" str r4, [sp, #0] \n" +"\n" +" b " ___STRING(_C_LABEL(___start)) " "); + +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.7 2008/06/21 00:52:52 gmcgarry Exp $"); +#endif /* LIBC_SCCS and not lint */ + +void +___start(int argc, char **argv, char **envp, struct ps_strings *ps_strings, + const Obj_Entry *obj, void (*cleanup)(void)) +{ + char *ap; + + environ = envp; + __ps_strings = ps_strings; + + if ((ap = argv[0])) { + if ((__progname = _strrchr(ap, '/')) == NULL) + __progname = ap; + else + ++__progname; + } + +#ifdef DYNAMIC + /* ld(1) convention: if DYNAMIC = 0 then statically linked */ + if (&_DYNAMIC) + _rtld_setup(cleanup, obj); +#endif /* DYNAMIC */ + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif /* MCRT0 */ + + atexit(_fini); + _init(); + +__asm("__callmain:"); /* Defined for the benefit of debuggers */ + exit(main(argc, argv, envp)); +} + +#include "common.c" + diff --git a/lib/csu/arm_elf/dot_init.h b/lib/csu/arm_elf/dot_init.h new file mode 100644 index 000000000..275185abc --- /dev/null +++ b/lib/csu/arm_elf/dot_init.h @@ -0,0 +1,61 @@ +/* $NetBSD: dot_init.h,v 1.6 2008/05/10 15:31:03 martin Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ +#include + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",%progbits \n"\ + ".global "#entry_pt" \n"\ + " .align 0 \n"\ + #entry_pt": \n"\ + "mov ip, sp \n"\ + "stmfd sp!, {fp, ip, lr, pc} \n"\ + "sub fp, ip, #4 \n"\ + " /* fall thru */ \n"\ + ".previous") + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",%progbits \n"\ + "ldmea fp, {fp, sp, pc} \n"\ + ".previous") + +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) diff --git a/lib/csu/common/Makefile.inc b/lib/csu/common/Makefile.inc new file mode 100644 index 000000000..b7809924d --- /dev/null +++ b/lib/csu/common/Makefile.inc @@ -0,0 +1,87 @@ +# $NetBSD: Makefile.inc,v 1.2 2010/12/07 19:51:02 joerg Exp $ + +.include + +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 diff --git a/lib/csu/common/crt0-common.c b/lib/csu/common/crt0-common.c new file mode 100644 index 000000000..77e1a0984 --- /dev/null +++ b/lib/csu/common/crt0-common.c @@ -0,0 +1,137 @@ +/* $NetBSD: crt0-common.c,v 1.1 2010/08/07 18:01:33 joerg Exp $ */ + +/* + * Copyright (c) 1998 Christos Zoulas + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include +__RCSID("$NetBSD: crt0-common.c,v 1.1 2010/08/07 18:01:33 joerg Exp $"); + +#include +#ifndef __minix +#include +#endif +#include +#include +#include + +#include "rtld.h" + +extern int main(int, char **, char **); + +extern void _init(void); +extern void _fini(void); + +/* + * Arrange for _DYNAMIC to be weak and undefined (and therefore to show up + * as being at address zero, unless something else defines it). That way, + * if we happen to be compiling without -static but with without any + * shared libs present, things will still work. + */ + +#if __GNUC_PREREQ__(4,2) +static int rtld_DYNAMIC __attribute__((__weakref__, __alias__("_DYNAMIC"))); +#define DYNAMIC_SYM rtld_DYNAMIC +#else +extern int _DYNAMIC __weak_reference(_DYNAMIC); +#define DYNAMIC_SYM _DYNAMIC +#endif + +#ifdef MCRT0 +extern void monstartup(u_long, u_long); +extern void _mcleanup(void); +extern unsigned char __etext, __eprol; +#endif /* MCRT0 */ + +char **environ; +struct ps_strings *__ps_strings = 0; + +static char empty_string[] = ""; +char *__progname = empty_string; + +void ___start(int, char **, char **, void (*)(void), + const Obj_Entry *, struct ps_strings *); + +#ifndef __minix +#define write(fd, s, n) __syscall(SYS_write, (fd), (s), (n)) +#else +#define write(fd, s, n) /* NO write() from here on minix */ +#endif + +#define _FATAL(str) \ +do { \ + write(2, str, sizeof(str)-1); \ + _exit(1); \ +} while (0) + +void +___start(int argc, char **argv, char **envp, + void (*cleanup)(void), /* from shared loader */ + const Obj_Entry *obj, /* from shared loader */ + struct ps_strings *ps_strings) +{ + environ = envp; + + if (argv[0] != NULL) { + char *c; + __progname = argv[0]; + for (c = argv[0]; *c; ++c) { + if (*c == '/') + __progname = c + 1; + } + } else { + __progname = empty_string; + } + + if (ps_strings != NULL) + __ps_strings = ps_strings; + + if (&DYNAMIC_SYM != NULL) { + if ((obj == NULL) || (obj->magic != RTLD_MAGIC)) + _FATAL("Corrupt Obj_Entry pointer in GOT\n"); + if (obj->version != RTLD_VERSION) + _FATAL("Dynamic linker version mismatch\n"); + atexit(cleanup); + } + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&__eprol, (u_long)&__etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} diff --git a/lib/csu/common/sysident.S b/lib/csu/common/sysident.S new file mode 100644 index 000000000..bb83367fa --- /dev/null +++ b/lib/csu/common/sysident.S @@ -0,0 +1,82 @@ +/* $NetBSD: sysident.S,v 1.1 2010/08/07 18:01:33 joerg Exp $ */ + +/* + * Copyright (c) 1997 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +/* + * Here we define the NetBSD OS Version in an ELF .note section, structured + * like: + * + * [NOTE HEADER] + * long name size + * long description size + * long note type + * + * [NOTE DATUM] + * string OS name + * + * OSVERSION notes also have: + * long OS version (__NetBSD_Version__ constant from param.h) + * + * The DATUM fields should be padded out such that their actual (not + * declared) sizes % 4 == 0. + * + * These are used by the kernel to determine if this binary is really a + * NetBSD binary, or some other OS's. + */ + +#include "sysident_assym.h" + +#ifdef __minix + .section .rodata + .ascii "$MINIX$\0" +#else + .section ".note.netbsd.ident", "a" + .align 4 + + .long ELF_NOTE_NETBSD_NAMESZ + .long ELF_NOTE_NETBSD_DESCSZ + .long ELF_NOTE_TYPE_NETBSD_TAG + .ascii "NetBSD\0\0" /* ELF_NOTE_NETBSD_NAME */ + .long __NetBSD_Version__ + + .section ".note.netbsd.pax", "a" + .align 4 + + .long ELF_NOTE_PAX_NAMESZ + .long ELF_NOTE_PAX_DESCSZ + .long ELF_NOTE_TYPE_PAX_TAG + .ascii "PaX\0" /* ELF_NOTE_PAX_NAME */ + .long 0 +#endif diff --git a/lib/csu/common/sysident_assym.cf b/lib/csu/common/sysident_assym.cf new file mode 100644 index 000000000..6a8d83d80 --- /dev/null +++ b/lib/csu/common/sysident_assym.cf @@ -0,0 +1,12 @@ +include +include + +define ELF_NOTE_NETBSD_NAMESZ ELF_NOTE_NETBSD_NAMESZ +define ELF_NOTE_NETBSD_DESCSZ ELF_NOTE_NETBSD_DESCSZ +define ELF_NOTE_TYPE_NETBSD_TAG ELF_NOTE_TYPE_NETBSD_TAG +#define ELF_NOTE_NETBSD_NAME ELF_NOTE_NETBSD_NAME +define __NetBSD_Version__ __NetBSD_Version__ +define ELF_NOTE_PAX_NAMESZ ELF_NOTE_PAX_NAMESZ +define ELF_NOTE_PAX_DESCSZ ELF_NOTE_PAX_DESCSZ +define ELF_NOTE_TYPE_PAX_TAG ELF_NOTE_TYPE_PAX_TAG +#define ELF_NOTE_PAX_NAME ELF_NOTE_PAX_NAME diff --git a/lib/csu/common_elf/Makefile.inc b/lib/csu/common_elf/Makefile.inc new file mode 100644 index 000000000..6e4144671 --- /dev/null +++ b/lib/csu/common_elf/Makefile.inc @@ -0,0 +1,74 @@ +# $NetBSD: Makefile.inc,v 1.32 2009/12/13 08:52:38 mrg Exp $ + +.if !defined(ELFSIZE) +ELFSIZE=32 +.endif + +.include "../../Makefile.inc" + +CPPFLAGS+= -DLIBC_SCCS -DPIC -DDYNAMIC -DELFSIZE=${ELFSIZE} +CPPFLAGS+= -I${NETBSDSRCDIR}/libexec/ld.elf_so +CPPFLAGS+= -I${.CURDIR}/../common_elf +CPPFLAGS+= -I${NETBSDSRCDIR}/lib/libc/dlfcn +CPPFLAGS+= -DDWARF2_EH +CPPFLAGS+= -DJCR +CPPFLAGS+= -DDSO_HANDLE + +.if defined(HAVE_GCC) && ${HAVE_GCC} > 3 +CFLAGS+= -fno-unit-at-a-time +.endif + +.include + +.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 diff --git a/lib/csu/common_elf/common.c b/lib/csu/common_elf/common.c new file mode 100644 index 000000000..2eca5f233 --- /dev/null +++ b/lib/csu/common_elf/common.c @@ -0,0 +1,77 @@ +/* $NetBSD: common.c,v 1.17 2005/12/24 22:53:15 perry Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +/* + * NOT A STANDALONE FILE! + */ + +static char * +_strrchr(char *p, int ch) +{ + char *save; + + for (save = NULL;; ++p) { + if (*p == ch) + save = (char *)p; + if (!*p) + return(save); + } + /* NOTREACHED */ +} + +#ifdef MCRT0 +__asm (" .text"); +#ifdef EPROL_EXPORT +EPROL_EXPORT; +#endif +__asm ("_eprol:"); +#endif + +#ifdef DYNAMIC + +void +_rtld_setup(void (*cleanup)(void), const Obj_Entry *obj) +{ + + if ((obj == NULL) || (obj->magic != RTLD_MAGIC)) + _FATAL("Corrupt Obj_Entry pointer in GOT\n"); + if (obj->version != RTLD_VERSION) + _FATAL("Dynamic linker version mismatch\n"); + + atexit(cleanup); +} + +#endif /* DYNAMIC */ diff --git a/lib/csu/common_elf/common.h b/lib/csu/common_elf/common.h new file mode 100644 index 000000000..f121aaf6d --- /dev/null +++ b/lib/csu/common_elf/common.h @@ -0,0 +1,95 @@ +/* $NetBSD: common.h,v 1.13 2009/12/14 01:04:02 matt Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include +#include +#ifndef __minix +#include +#endif + +#include +#ifdef DYNAMIC +#ifdef __weak_alias +#define dlopen _dlopen +#define dlclose _dlclose +#define dlsym _dlsym +#define dlerror _dlerror +#define dladdr _dladdr +#endif +#include +#include "rtld.h" +#else +typedef void Obj_Entry; +#endif + +extern quad_t __syscall(quad_t, ...); +#define _exit(v) __syscall(SYS_exit, (v)) +#define write(fd, s, n) __syscall(SYS_write, (fd), (s), (n)) + +#define _FATAL(str) \ +do { \ + write(2, str, sizeof(str)-1); \ + _exit(1); \ +} while (0) + +static char *_strrchr(char *, int); + +char **environ; +char *__progname = ""; +struct ps_strings *__ps_strings = 0; + +extern void _init(void); +extern void _fini(void); + +#ifdef DYNAMIC +void _rtld_setup(void (*)(void), const Obj_Entry *obj); + +/* + * Arrange for _DYNAMIC to be weak and undefined (and therefore to show up + * as being at address zero, unless something else defines it). That way, + * if we happen to be compiling without -static but with without any + * shared libs present, things will still work. + */ +extern int _DYNAMIC __weak_reference(_DYNAMIC); +#endif /* DYNAMIC */ + +#ifdef MCRT0 +extern void monstartup(u_long, u_long); +extern void _mcleanup(void); +extern unsigned char _etext, _eprol; +#endif /* MCRT0 */ + +int main(int, char **, char **); diff --git a/lib/csu/common_elf/crti.c b/lib/csu/common_elf/crti.c new file mode 100644 index 000000000..e277fd1b9 --- /dev/null +++ b/lib/csu/common_elf/crti.c @@ -0,0 +1,40 @@ +/* $NetBSD: crti.c,v 1.6 2008/04/28 20:22:54 martin Exp $ */ + +/*- + * Copyright (c) 1998, 2001, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg, Ross Harvey, and Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* sysident.h requires `NetBSD' constant */ +#include +#include + +#include "sysident.h" +#include + +MD_INIT_SECTION_PROLOGUE; +MD_FINI_SECTION_PROLOGUE; diff --git a/lib/csu/common_elf/crtn.c b/lib/csu/common_elf/crtn.c new file mode 100644 index 000000000..b37319f62 --- /dev/null +++ b/lib/csu/common_elf/crtn.c @@ -0,0 +1,35 @@ +/* $NetBSD: crtn.c,v 1.3 2008/04/28 20:22:54 martin Exp $ */ + +/*- + * Copyright (c) 1998, 2001, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg, Ross Harvey, and Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +MD_INIT_SECTION_EPILOGUE; +MD_FINI_SECTION_EPILOGUE; diff --git a/lib/csu/common_elf/dot_init.h b/lib/csu/common_elf/dot_init.h new file mode 100644 index 000000000..8cf25bfbb --- /dev/null +++ b/lib/csu/common_elf/dot_init.h @@ -0,0 +1,48 @@ +/* $NetBSD: dot_init.h,v 1.3 2008/05/10 15:31:03 martin Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ + +#define INIT_FALLTHRU_DECL +#define FINI_FALLTHRU_DECL + +#define INIT_FALLTHRU() +#define FINI_FALLTHRU() + +#define MD_INIT_SECTION_PROLOGUE +#define MD_FINI_SECTION_PROLOGUE + +#define MD_INIT_SECTION_EPILOGUE +#define MD_FINI_SECTION_EPILOGUE diff --git a/lib/csu/common_elf/dwarf2_eh.h b/lib/csu/common_elf/dwarf2_eh.h new file mode 100644 index 000000000..dfa60fd58 --- /dev/null +++ b/lib/csu/common_elf/dwarf2_eh.h @@ -0,0 +1,70 @@ +/* $NetBSD: dwarf2_eh.h,v 1.3 2008/04/28 20:22:54 martin Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Definitions for DWARF2 stack frame unwinding/exception handling. + */ + +#ifdef __GNUC__ +/* + * We must pass a DWARF2 unwind object to __register_frame_info(). + * Since we don't reference any members of this object, but rather + * only provide storage for it, we just declare it in a simple, + * dumb way. We need room for 6 pointers in GCC 2.95.3 and GCC 3.0, + * but declare it with a little slop at the end. + */ +struct dwarf2_eh_object { + void *space[8]; +}; + +/* + * These routines are provided by libgcc to register/unregister + * frame info. Note these prototypes must generate weak references + * (even though the routines in libgcc have strong definitions). + * This is so that we can link with a libgcc that doesn't have these + * routines (e.g. one that uses sjlj exceptions). + */ + +/* + * A few platforms (x86_64, s390) have read-only .eh_frame by default, + * so they must have it declared 'const'. These platforms will override + * __EH_FRAME_CONST (which is empty by default) in their CPP flags. + */ + +#ifndef __EH_FRAME_CONST +#define __EH_FRAME_CONST +#endif + +extern void __register_frame_info(__EH_FRAME_CONST void *, + struct dwarf2_eh_object *) __attribute__((weak)); +extern void __deregister_frame_info(__EH_FRAME_CONST void *) + __attribute__((weak)); +#endif /* __GNUC__ */ diff --git a/lib/csu/hppa/Makefile b/lib/csu/hppa/Makefile new file mode 100644 index 000000000..533cca54d --- /dev/null +++ b/lib/csu/hppa/Makefile @@ -0,0 +1,4 @@ +# $NetBSD: Makefile,v 1.3 2006/05/19 19:11:12 christos Exp $ +CPPFLAGS+= -I${.CURDIR} + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/hppa/crt0.c b/lib/csu/hppa/crt0.c new file mode 100644 index 000000000..f46b3f035 --- /dev/null +++ b/lib/csu/hppa/crt0.c @@ -0,0 +1,158 @@ +/* $NetBSD: crt0.c,v 1.7 2004/08/26 21:07:14 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Matt Fredette + * Copyright (c) 1999 Klaus Klein + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +static void ___start(struct ps_strings *, + void (*cleanup)(void), const Obj_Entry *, int) +#ifdef __GNUC__ + __attribute__((__used__)) +#endif + ; + +__asm("\n" +" .text \n" +" .align 4 \n" +" .globl _start \n" +" .globl __start \n" +" .type _start,@function \n" +" .type __start,@function \n" +"_start: \n" +"__start: \n" +" .import _GLOBAL_OFFSET_TABLE_ \n" +"\n" +" bl L$lpc, %r27 \n" +" depi 0, 31, 2, %r27 \n" +"L$lpc: addil L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 8), %r27 \n" +" ldo R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 12)(%r1),%r27 \n" +" copy %r27, %r19 \n" +" b ___start \n" +" copy %r27, %arg3 \n"); + +static void +___start(struct ps_strings *ps_strings, + void (*cleanup)(void), /* from shared loader */ + const Obj_Entry *obj, /* from shared loader */ + int dp) +{ + int argc; + char **argv; + int fini_plabel[2]; + + argc = ps_strings->ps_nargvstr; + argv = ps_strings->ps_argvstr; + environ = ps_strings->ps_envstr; + + if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(__progname, '/')) == NULL) + __progname = argv[0]; + else + __progname++; + } + + if (ps_strings != (struct ps_strings *)0) + __ps_strings = ps_strings; + +#ifdef DYNAMIC + /* + * XXX fredette - when not compiling PIC, you currently + * can't detect an undefined weak symbol by seeing if + * its address is NULL. The compiler emits code to find + * _DYNAMIC relative to %dp, the assembler notes the + * needed relocations, but when the linker sees that the + * (weak) symbol isn't defined it drops the ball - the + * relocations are never filled, and the binary ends up + * with code that sees an address of %dp plus zero, + * which != NULL. + * + * Arguably the linker could/should distinguish between + * code that is after a weak undefined symbol's contents + * from code that is after its address. In the first case, + * it would warn and/or bail. In the second case, it + * would fix up instructions to give a symbol address + * of NULL. + * + * For now, we take the easy way out and compare &_DYNAMIC + * to %dp, as well as to NULL. + */ + if (&_DYNAMIC != NULL && (int)&_DYNAMIC != dp) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + /* + * Since crt0.o, crtbegin.o, and crtend.o are always + * compiled PIC, they must have %r19 set correctly on + * entry to any function they contain. However, when + * a program is linked statically, the linker does + * not fill a PLABEL relocation with a pointer to a + * true PLABEL, it just fills it with the offset of the + * function. This shows the linker's assumption that + * when linking statically, *all* of the code has *not* + * been compiled PIC. I guess to assume otherwise + * would be a performance hit, as you would end up + * with unnecessary PLABELs for function pointers. + * + * But here, passing the address of the PIC _fini to + * atexit, we must make sure that we pass a PLABEL. + */ + fini_plabel[0] = (int)_fini; + if (fini_plabel[0] & 2) + /* _fini is already a PLABEL. */ + atexit(_fini); + else { + fini_plabel[1] = dp; + atexit((void (*)(void))(((int)fini_plabel) | 2)); + } + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.7 2004/08/26 21:07:14 thorpej Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/hppa/dot_init.h b/lib/csu/hppa/dot_init.h new file mode 100644 index 000000000..8010f7718 --- /dev/null +++ b/lib/csu/hppa/dot_init.h @@ -0,0 +1,69 @@ +/* $NetBSD: dot_init.h,v 1.8 2008/05/10 15:31:04 martin Exp $ */ + +/*- + * Copyright (c) 2004 Nick Hudson + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n"\ + ".global "#entry_pt" \n"\ + ".proc \n"\ + ".callinfo frame=64, calls, save_rp, save_sp, entry_gr=3\n"\ + ".entry \n"\ + #entry_pt": \n"\ + " stw %rp, -20(%sp) \n"\ + " copy %r3, %r1 \n"\ + " copy %sp, %r3 \n"\ + " stw,ma %r1, 64(%sp) \n"\ + " /* fall thru */ \n"\ + ".exit \n"\ + ".procend \n"\ + ".previous") + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n"\ + " ldw -20(%r3) ,%rp \n"\ + " ldo 64(%r3), %sp \n"\ + " ldw,mb -64(%sp), %r3 \n"\ + " bv,n %r0(%rp) \n"\ + ".previous") + +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) diff --git a/lib/csu/i386-elf/Makefile b/lib/csu/i386-elf/Makefile deleted file mode 100644 index 54abd0007..000000000 --- a/lib/csu/i386-elf/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -.include - -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 diff --git a/lib/csu/ia64/Makefile b/lib/csu/ia64/Makefile new file mode 100644 index 000000000..322c9e2a5 --- /dev/null +++ b/lib/csu/ia64/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.2 2006/09/14 23:55:54 cherry Exp $ + +ELFSIZE= 64 + +#Uncomment the next line to enable the new .init fallthru +CPPFLAGS+= -I- -I${.CURDIR} + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/ia64/crt0.c b/lib/csu/ia64/crt0.c new file mode 100644 index 000000000..3983db92c --- /dev/null +++ b/lib/csu/ia64/crt0.c @@ -0,0 +1,97 @@ +/* $NetBSD: crt0.c,v 1.2 2006/09/15 05:29:44 skrll Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +void __start(char **, void (*cleanup)(void), const Obj_Entry *, + struct ps_strings *); + +void +__start(char **sp, + void (*cleanup)(void), /* from shared loader */ + const Obj_Entry *obj, /* from shared loader */ + struct ps_strings *ps_strings) +{ + long argc; + char **argv, *namep; + + __asm __volatile__ ("1: \ + { .mii \ + mov r15=@gprel(1b) \n \ + mov r16=ip ;; \n \ + sub gp=r16,r15 \n \ + ;; \ + } "); + + argc = *(long *)sp; + argv = sp + 1; + environ = sp + 2 + argc; /* 2: argc + NULL ending argv */ + + if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(namep, '/')) == NULL) + __progname = namep; + else + __progname++; + } + + if (ps_strings != (struct ps_strings *)0 && + ps_strings != (struct ps_strings *)0xbabefacedeadbeef) /* XXX: Debug: see machdep.c:setregs() */ + __ps_strings = ps_strings; + +#ifdef DYNAMIC + if (&_DYNAMIC != NULL) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); /* XXX: ia64 ABI says 4 parameters. */ +} + +/* + * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.2 2006/09/15 05:29:44 skrll Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/ia64/dot_init.h b/lib/csu/ia64/dot_init.h new file mode 100644 index 000000000..293b7dadf --- /dev/null +++ b/lib/csu/ia64/dot_init.h @@ -0,0 +1,74 @@ +/* $NetBSD: dot_init.h,v 1.6 2009/11/09 14:34:42 skrll Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ +#include + +/*- + * $FreeBSD: src/lib/csu/ia64/crti.S,v 1.3 2001/11/03 06:31:27 peter Exp $ + */ + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + ".proc "#entry_pt" \n" \ + ".global "#entry_pt" \n" \ + #entry_pt": \n" \ + ".regstk 0,2,0,0 \n" \ + ".prologue 12,loc0 \n" \ + ".save ar.pfs,loc1 \n" \ + "alloc loc1=ar.pfs,0,2,0,0 \n" \ + "mov loc0=b0 /* Save return addr */ \n" \ + ".endp "#entry_pt" \n" \ + ".previous") + +/*- + * $FreeBSD: src/lib/csu/ia64/crtn.S,v 1.2 2001/10/29 10:18:58 peter Exp $ + */ + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + ".regstk 0,2,0,0 \n" \ + "mov b0=loc0 /*Recover return addr*/ \n" \ + "mov ar.pfs=loc1 \n" \ + "br.ret.sptk.many b0 \n" \ + ".previous") + +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) diff --git a/lib/csu/m68k_elf/Makefile b/lib/csu/m68k_elf/Makefile new file mode 100644 index 000000000..257ad99f5 --- /dev/null +++ b/lib/csu/m68k_elf/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.7 2006/05/19 19:11:12 christos Exp $ + +#Uncomment the next line to enable the new .init fallthru +CPPFLAGS+= -I${.CURDIR} + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/m68k_elf/crt0.c b/lib/csu/m68k_elf/crt0.c new file mode 100644 index 000000000..fcb5e7597 --- /dev/null +++ b/lib/csu/m68k_elf/crt0.c @@ -0,0 +1,100 @@ +/* $NetBSD: crt0.c,v 1.11 2004/08/26 21:09:52 thorpej Exp $ */ + +/* + * Copyright (c) 1999 Klaus Klein + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +void __start(int, char **, char **, void (*cleanup)(void), + const Obj_Entry *, struct ps_strings *); + +__asm("\n" +" .text \n" +" .align 4 \n" +" .globl _start \n" +"_start: \n" +" movl (%sp),%d0 \n" +" movl %a2,-(%sp) | ps_strings \n" +" movl %a0,-(%sp) | obj \n" +" movl %a1,-(%sp) | cleanup \n" +" movl %d0,%d1 \n" +" lsll #2,%d1 \n" +" pea (16+4)(%sp,%d1.l) | envp = &argv[argc + 1] \n" +" pea 20(%sp) | argv \n" +" movl %d0,-(%sp) | argc \n" +" jsr __start"); + +void +__start(int argc, char **argv, char **envp, + void (*cleanup)(void), /* from shared loader */ + const Obj_Entry *obj, /* from shared loader */ + struct ps_strings *ps_strings) +{ + environ = envp; + + if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(__progname, '/')) == NULL) + __progname = argv[0]; + else + __progname++; + } + + if (ps_strings != (struct ps_strings *)0) + __ps_strings = ps_strings; + +#ifdef DYNAMIC + if (&_DYNAMIC != NULL) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.11 2004/08/26 21:09:52 thorpej Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/m68k_elf/dot_init.h b/lib/csu/m68k_elf/dot_init.h new file mode 100644 index 000000000..db1faac98 --- /dev/null +++ b/lib/csu/m68k_elf/dot_init.h @@ -0,0 +1,60 @@ +/* $NetBSD: dot_init.h,v 1.6 2008/05/10 15:31:04 martin Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ +#include + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n"\ + ".global "#entry_pt" \n"\ + #entry_pt": \n"\ + " .align 2 \n"\ + " /* fall thru */ \n"\ + ".previous") + + /* placement of the .align _after_ the label is intentional */ + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n"\ + " rts \n"\ + ".previous") + +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) diff --git a/lib/csu/mips/Makefile b/lib/csu/mips/Makefile new file mode 100644 index 000000000..a584c0a5a --- /dev/null +++ b/lib/csu/mips/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.24 2006/05/19 19:11:12 christos Exp $ + +#Uncomment the next line to enable the new .init fallthru +CPPFLAGS+= -I${.CURDIR} + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/mips/crt0.c b/lib/csu/mips/crt0.c new file mode 100644 index 000000000..32418382c --- /dev/null +++ b/lib/csu/mips/crt0.c @@ -0,0 +1,169 @@ +/* $NetBSD: crt0.c,v 1.20 2009/12/14 01:04:02 matt Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Modifications for NetBSD/mips: + * + * Jonathan Stone + * Jason R. Thorpe, Numerical Aerospace Simulation Facility, + * NASA Ames Research Center + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "common.h" + +/* + * C start-up. Assumes kernel (or ld.so) passes the + * following parameters to user-space in registers: + * + * a0 stack pointer (0 if setregs didn't fill this in) + * a1 cleanup + * a2 Obj_Entry + * a3 ps_strings + * + * XXX Does this violate the ABI? + * as well as the usual registers (pc, sp, and t9 == pc for ABI). + */ + +void __start(u_long, void (*)(void), const Obj_Entry *, + struct ps_strings *); + +__asm(".text; .align 4; .globl _start; _start:"); + +void +__start(u_long sp, + void (*cleanup)(void), /* from shared loader */ + const Obj_Entry *obj, /* from shared loader */ + struct ps_strings *ps_strings) +{ + char **ksp; + char **argv, *namep; + int argc; + + /* + * Grab the argc, argv, and envp set up by the kernel. + * Layout of stuff on the stack: + * + * [ high ] + * char kenvstr[1]; // size varies + * char kargstr[1]; // size varies + * char *argv[1]; // varies on argc + * int argc; + * [ low ] <--- kernel's SP points here + * . + * . + * . + * [ current stack pointer ] + * + * WARNING! There is an implicit sizeof(int) == sizeof(char *) here! + */ + +#ifndef DYNAMIC +#ifdef _LP64 + __asm volatile("dla $28,_gp"); +#else + __asm volatile("la $28,_gp"); +#endif +#endif + + ksp = (char**)sp; +#if defined(__mips_n32) || defined(__mips_n64) + if (ksp == 0) { + /* + * Uh, oh. We're running on a old kernel that passed + * us zero in $a0-$a3. Try adjusting the current + * $sp for our own stack-frame size and see what + * we find. + * WARNING! The constants 56 and 64 below were determined + * by examining GCC assembler output of __start to find the + * frame size. If you change the code or compiler, + * you _will_ lose! + */ + +#ifndef DYNAMIC + /* XXX 56 is compiler and stackframe dependent */ + __asm volatile(" addiu %0,$29,56" : "=r" (ksp)); +#else + /* XXX 64 is compiler and stackframe dependent */ + __asm volatile(" addiu %0,$29,64" : "=r" (ksp)); +#endif + } +#endif + + + argc = *(int *)ksp; + argv = ksp + 1; + environ = ksp + 2 + argc; /* 2: argc + NULL ending argv */ + + if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(namep, '/')) == NULL) + __progname = namep; + else + __progname++; + } + + /* + * Deal with stuff that is only provided if setregs() did + * did the right thing. + */ + if (sp != 0) { + if (ps_strings != (struct ps_strings *)0) + __ps_strings = ps_strings; +#ifdef DYNAMIC + /* + * XXX Old MIPS ld.so didn't do any of this at all. + * XXX If we were loaded by that loader, just abort + * XXX the rtld setup. + */ + if (&_DYNAMIC != NULL && cleanup != NULL && obj != NULL) + _rtld_setup(cleanup, obj); +#endif + } + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * RCSid. Place after __start for programs that assume start of text + * is the entrypoint. (Only needed for old toolchains). + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.20 2009/12/14 01:04:02 matt Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/mips/dot_init.h b/lib/csu/mips/dot_init.h new file mode 100644 index 000000000..7a7a1cfd1 --- /dev/null +++ b/lib/csu/mips/dot_init.h @@ -0,0 +1,137 @@ +/* $NetBSD: dot_init.h,v 1.10 2009/12/14 01:04:02 matt Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * Copyright (c) 2001 Simon Burge + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ + +#define t9 "$25" + +/* + * For O32/O64, allocate 8 "slots" for the stack frame. Store GP in the 4th + * (zero-based) slot (since this is where compiler generated code for fallthru + * processing expects it to be), and the RA in seventh (highest address). + * + * For N32/N64, allocate 4 8-byte "slots" for the stack frame. Store GP in the + * 2nd (zero-based) slot (since ...) and the RA in third (highest address). + */ + +#ifdef __mips_o32 +#define sPTR_ADDU "addu" +#define sREG_L "lw" +#define sREG_S "sw" +#define sRAOFF "28" +#define sFRAMESZ "32" +#define MD_GPRESTORE /* nothing */ +#else +#define sPTR_ADDU "daddu" +#define sREG_L "ld" +#define sREG_S "sd" +#if defined(__mips_n32) || defined(__mips_n64) +#define MD_GPRESTORE "ld $gp,8($sp)" "\n\t" +#define sRAOFF "24" +#define sFRAMESZ "32" +#elif defined(__mips_o64) +#define sRAOFF "56" +#define sFRAMESZ "64" +#define MD_GPRESTORE /* nothing */ +#endif +#endif + +#ifdef __ABICALLS__ +#if defined(__mips_o32) || defined(__mips_o64) +#define MD_FUNCTION_PROLOGUE(entry_pt) \ + ".set noreorder" "\n\t" \ + ".cpload "t9 "\n\t" \ + ".set reorder" "\n\t" \ + sPTR_ADDU" $sp,$sp,-"sFRAMESZ "\n\t" \ + ".cprestore 16" "\n\t" \ + sREG_S" $ra,"sRAOFF"($sp)" "\n\t" + +#elif defined(__mips_n32) || defined(__mips_n64) +#define MD_FUNCTION_PROLOGUE(entry_pt) \ + ".set noreorder" "\n\t" \ + "daddu $sp,$sp,-32" "\n\t" \ + ".cpsetup "t9", 8, "#entry_pt "\n\t" \ + "sd $ra,24($sp)" "\n\t" \ + ".set reorder" "\n\t" +#else +#error ABI not supported (__ABICALLS) +#endif +#else +#if defined(__mips_o32) || defined(__mips_o64) +#define MD_FUNCTION_PROLOGUE(entry_pt) \ + sPTR_ADDU" $sp,$sp,-"sFRAMESZ "\n\t" \ + sREG_S" $ra,"sRAOFF"($sp)" "\n\t" + +#elif defined(__mips_n32) || defined(__mips_n64) +/* + * On N32/N64, GP is callee-saved. + */ +#define MD_FUNCTION_PROLOGUE(entry_pt) \ + "daddu $sp,$sp,-32" "\n\t" \ + "sd $gp,8($sp)" "\n\t" \ + "sd $ra,24($sp)" "\n\t" +#else +#error ABI not supported (!__ABICALLS) +#endif +#endif /* __ABICALLS */ + + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits" "\n\t" \ + ".align 2" "\n\t" \ + ".globl "#entry_pt "\n\t" \ + #entry_pt":" "\n\t" \ + MD_FUNCTION_PROLOGUE(entry_pt) \ + " /* fall thru */" "\n\t" \ + ".previous") + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits" "\n\t" \ + sREG_L" $ra,"sRAOFF"($sp)" "\n\t" \ + MD_GPRESTORE \ + ".set noreorder" "\n\t" \ + "j $ra" "\n\t" \ + sPTR_ADDU" $sp,$sp,"sFRAMESZ "\n\t" \ + ".set reorder" "\n\t" \ + ".previous") + +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) diff --git a/lib/csu/powerpc/Makefile b/lib/csu/powerpc/Makefile new file mode 100644 index 000000000..7db56544b --- /dev/null +++ b/lib/csu/powerpc/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.13 2006/05/19 19:11:12 christos Exp $ + +CPPFLAGS+= -I${.CURDIR} + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/powerpc/crt0.c b/lib/csu/powerpc/crt0.c new file mode 100644 index 000000000..4f0e77793 --- /dev/null +++ b/lib/csu/powerpc/crt0.c @@ -0,0 +1,107 @@ +/* $NetBSD: crt0.c,v 1.26 2006/05/18 17:54:19 christos Exp $ */ + +/* + * Copyright (c) 1997 Jason R. Thorpe. + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +/* + * Small Data Area designators. If not defined, will show up as being + * at address zero. + */ +extern int _SDA_BASE_[] __weak_reference(_SDA_BASE_); +extern int _SDA2_BASE_[] __weak_reference(_SDA2_BASE_); + +/* + * First 5 arguments are specified by the PowerPC SVR4 ABI. The + * last argument, ps_strings, is a NetBSD extension. + */ +void _start(int, char **, char **, const Obj_Entry *, + void (*)(void), struct ps_strings *); + +void +_start(int argc, char **argv, char **envp, + const Obj_Entry *obj, /* from shared loader */ + void (*cleanup)(void), /* from shared loader */ + struct ps_strings *ps_strings) /* NetBSD extension */ +{ + char *namep; + + /* + * Initialize the Small Data Area registers. + * _SDA_BASE is defined in the SVR4 ABI for PPC. + * _SDA2_BASE is defined in the E[mbedded] ABI for PPC. + */ + __asm( "lis %r13,_SDA_BASE_@ha;" + "addi %r13,%r13,_SDA_BASE_@l;" + "lis %r2,_SDA2_BASE_@ha;" + "addi %r2,%r2,_SDA2_BASE_@l" ); + + if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(namep, '/')) == NULL) + __progname = namep; + else + __progname++; + } + + environ = envp; + + if (ps_strings != (struct ps_strings *)0) + __ps_strings = ps_strings; + +#ifdef DYNAMIC + if (&_DYNAMIC != NULL) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.26 2006/05/18 17:54:19 christos Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/powerpc/dot_init.h b/lib/csu/powerpc/dot_init.h new file mode 100644 index 000000000..6918dd7a9 --- /dev/null +++ b/lib/csu/powerpc/dot_init.h @@ -0,0 +1,62 @@ +/* $NetBSD: dot_init.h,v 1.7 2008/05/10 15:31:04 martin Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + ".global "#entry_pt" \n" \ + #entry_pt": \n" \ + " stwu %r1,-16(%r1) \n" \ + " mflr %r0 \n" \ + " stw %r0,12(%r1) \n" \ + " /* fall thru */ \n" \ + ".previous") + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " lwz %r0,12(%r1) \n" \ + " mtlr %r0 \n" \ + " la %r1,16(%r1) \n" \ + " blr \n" \ + ".previous") + +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) diff --git a/lib/csu/powerpc64/Makefile b/lib/csu/powerpc64/Makefile new file mode 100644 index 000000000..3231bfab9 --- /dev/null +++ b/lib/csu/powerpc64/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2006/06/30 22:49:50 ross Exp $ + +CPPFLAGS+= -I- -I${.CURDIR} + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/powerpc64/crt0.c b/lib/csu/powerpc64/crt0.c new file mode 100644 index 000000000..8ee36609c --- /dev/null +++ b/lib/csu/powerpc64/crt0.c @@ -0,0 +1,99 @@ +/* $NetBSD: crt0.c,v 1.2 2006/07/01 01:39:17 ross Exp $ */ + +/* + * Copyright (c) 1997 Jason R. Thorpe. + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +/* + * Small Data Area designators. If not defined, will show up as being + * at address zero. + */ +extern int _SDA_BASE_[]; +__weak_extern(_SDA_BASE_); +extern int _SDA2_BASE_[]; +__weak_extern(_SDA2_BASE_); + +/* + * First 5 arguments are specified by the PowerPC SVR4 ABI. The + * last argument, ps_strings, is a NetBSD extension. + */ +void _start(int, char **, char **, const Obj_Entry *, + void (*)(void), struct ps_strings *); + +void +_start(int argc, char **argv, char **envp, + const Obj_Entry *obj, /* from shared loader */ + void (*cleanup)(void), /* from shared loader */ + struct ps_strings *ps_strings) /* NetBSD extension */ +{ + char *namep; + + if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(namep, '/')) == NULL) + __progname = namep; + else + __progname++; + } + + environ = envp; + + if (ps_strings != (struct ps_strings *)0) + __ps_strings = ps_strings; + +#ifdef DYNAMIC + if (&_DYNAMIC != NULL) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.2 2006/07/01 01:39:17 ross Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/powerpc64/dot_init.h b/lib/csu/powerpc64/dot_init.h new file mode 100644 index 000000000..c91f36772 --- /dev/null +++ b/lib/csu/powerpc64/dot_init.h @@ -0,0 +1,69 @@ +/* $NetBSD: dot_init.h,v 1.7 2008/05/10 15:31:04 martin Exp $ */ + +/*- + * Copyright (c) 2001, 2006 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".globl " #entry_pt " \n" \ + ".globl ." #entry_pt " \n" \ + ".pushsection \".opd\",\"aw\" \n" \ + ".align 3 \n" \ + #entry_pt": .quad ." #entry_pt ",.TOC.@tocbase,0\n" \ + ".size " #entry_pt ",24 \n" \ + ".type " #entry_pt ",@function \n" \ + ".pushsection "#sect",\"ax\",@progbits \n" \ + "." #entry_pt": \n" \ + " stdu %r1,-48(%r1) \n" \ + " mflr %r0 \n" \ + " std %r0,16(%r1) \n" \ + " /* fall thru */ \n" \ + ".popsection \n" \ + ".popsection") + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".pushsection "#sect",\"ax\",@progbits \n" \ + " ld %r0,16(%r1) \n" \ + " mtlr %r0 \n" \ + " la %r1,48(%r1) \n" \ + " blr \n" \ + ".popsection") + +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) diff --git a/lib/csu/sh3_elf/Makefile b/lib/csu/sh3_elf/Makefile new file mode 100644 index 000000000..b8ff0f88f --- /dev/null +++ b/lib/csu/sh3_elf/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.3 2006/05/19 19:11:12 christos Exp $ + +CPPFLAGS+= -I${.CURDIR} + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/sh3_elf/crt0.c b/lib/csu/sh3_elf/crt0.c new file mode 100644 index 000000000..f47cea219 --- /dev/null +++ b/lib/csu/sh3_elf/crt0.c @@ -0,0 +1,94 @@ +/* $NetBSD: crt0.c,v 1.10 2004/08/26 21:16:41 thorpej Exp $ */ + +/* + * Copyright (c) 1998 Christos Zoulas + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +void ___start(int, char **, char **, void (*cleanup)(void), + const Obj_Entry *, struct ps_strings *); + +__asm( " .text \n" + " .align 2 \n" + " .globl _start \n" + " .globl __start \n" + "_start: \n" + "__start: \n" + " mov.l r9,@-r15 \n" + " bra ___start \n" + " mov.l r8,@-r15"); + +void +___start(int argc, char **argv, char **envp, + void (*cleanup)(void), /* from shared loader */ + const Obj_Entry *obj, /* from shared loader */ + struct ps_strings *ps_strings) +{ + environ = envp; + + if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(__progname, '/')) == NULL) + __progname = argv[0]; + else + __progname++; + } + + if (ps_strings != (struct ps_strings *)0) + __ps_strings = ps_strings; + +#ifdef DYNAMIC + if (&_DYNAMIC != NULL) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.10 2004/08/26 21:16:41 thorpej Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/sh3_elf/dot_init.h b/lib/csu/sh3_elf/dot_init.h new file mode 100644 index 000000000..529b6dca4 --- /dev/null +++ b/lib/csu/sh3_elf/dot_init.h @@ -0,0 +1,91 @@ +/* $NetBSD: dot_init.h,v 1.7 2008/05/10 15:31:04 martin Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ + + +/* + * Don't use C versions of _init/_fini, they have become just a + * rudimentary indirection to the entry points we would supply with + * MD_SECTION_PROLOGUE. + */ +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) + + +#define MD_ASM_IN_SECTION(section, content) \ + __asm( \ + ".section " #section ",\"ax\",@progbits\n" \ + content "\n" \ + ".previous") + +/* + * Declare the entry point global. + */ +#define MD_SECTION_PROLOGUE(section, entry_pt) \ + MD_ASM_IN_SECTION(section, \ + " .global "_C_LABEL_STRING(#entry_pt)" \n" \ + " .type "_C_LABEL_STRING(#entry_pt)",@function\n" \ + _C_LABEL_STRING(#entry_pt)": \n" \ + " mov.l r14, @-sp \n" \ + " sts.l pr, @-sp \n" \ + " mov sp, r14 \n" \ + " .p2align 2") + +/* + * NOTE 1: Supply the semicolon here because crtbegin.c doesn't. + * NOTE 2: We don't use our crtbegin.c for gcc3 and later, + * we use gcc crtstuff.c via src/gnu/lib/crtstuff* + */ +#define MD_CALL_STATIC_FUNCTION(section, func) \ + MD_ASM_IN_SECTION(section, \ + " mov.l 1f, r1 \n" \ + " mova 2f, r0 \n" \ + "0: braf r1 \n" \ + " lds r0, pr \n" \ + \ + " .p2align 2 \n" \ + "1: .long "_C_LABEL_STRING(#func)" - (0b+4) \n" \ + "2: "); + +#define MD_SECTION_EPILOGUE(section) \ + MD_ASM_IN_SECTION(section, \ + " mov r14, sp \n" \ + " lds.l @sp+, pr \n" \ + " rts \n" \ + " mov.l @sp+, r14") diff --git a/lib/csu/sparc64/Makefile b/lib/csu/sparc64/Makefile new file mode 100644 index 000000000..21a68d67a --- /dev/null +++ b/lib/csu/sparc64/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.6 2006/05/19 19:11:12 christos Exp $ + +#Uncomment the next line to enable the new .init fallthru +CPPFLAGS+= -I${.CURDIR}/../sparc_elf + +ELFSIZE=64 + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/sparc64/crt0.c b/lib/csu/sparc64/crt0.c new file mode 100644 index 000000000..73ef61ee6 --- /dev/null +++ b/lib/csu/sparc64/crt0.c @@ -0,0 +1,119 @@ +/* $NetBSD: crt0.c,v 1.24 2005/12/24 21:38:40 perry Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +/* + * __start needs to gather up argc, argv, env_p, ps_strings, the termination + * routine passed in %g1 and call ___start to finish up the startup processing. + * + * NB: We are violating the ELF spec by passing a pointer to the ps strings in + * %g1 instead of a termination routine. + */ + +__asm("\n\ + .data\n\ +__data_start: ! Start of data section\n\ + .text\n\ + .align 4\n\ + .global _start\n\ + .global __start\n\ + .register %g3,#scratch\n\ + .register %g2,#scratch\n\ +_start:\n\ +__start:\n\ + setx __data_start, %o0, %g4 ! Point %g4 to start of data section\n\ + clr %g4 ! egcs thinks this is zero. XXX\n\ + clr %fp\n\ + add %sp, 8*16 + 0x7ff, %o0 ! start of stack\n\ + mov %g1, %o1 ! Cleanup routine\n\ + mov %g3, %o1 ! XXXX our rtld uses %g3\n\ + mov %g2, %o2 ! XXXX obj from rtld.\n\ + ba,pt %icc, ___start ! XXXX jump over the retl egcs 2.96 inserts\n\ + mov %g1, %o3 ! ps_strings XXXX\n\ +"); + +void ___start(char **, void (*cleanup)(void), const Obj_Entry *, + struct ps_strings *); + +void +___start(char **sp, + void (*cleanup)(void), /* from shared loader */ + const Obj_Entry *obj, /* from shared loader */ + struct ps_strings *ps_strings) +{ + long argc; + char **argv, *namep; + + argc = *(long *)sp; + argv = sp + 1; + environ = sp + 2 + argc; /* 2: argc + NULL ending argv */ + + if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(namep, '/')) == NULL) + __progname = namep; + else + __progname++; + } + + if (ps_strings != (struct ps_strings *)0 && + ps_strings != (struct ps_strings *)0xbabefacedeadbeef) + __ps_strings = ps_strings; + +#ifdef DYNAMIC + if (&_DYNAMIC != NULL) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * NOTE: Leave the RCS ID _after_ _start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.24 2005/12/24 21:38:40 perry Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/sparc_elf/Makefile b/lib/csu/sparc_elf/Makefile new file mode 100644 index 000000000..68929c415 --- /dev/null +++ b/lib/csu/sparc_elf/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.6 2006/05/19 19:11:12 christos Exp $ + +#Uncomment the next line to enable the new .init fallthru +CPPFLAGS+= -I${.CURDIR} + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/sparc_elf/crt0.c b/lib/csu/sparc_elf/crt0.c new file mode 100644 index 000000000..cc27c9b7d --- /dev/null +++ b/lib/csu/sparc_elf/crt0.c @@ -0,0 +1,104 @@ +/* $NetBSD: crt0.c,v 1.12 2004/08/26 21:18:36 thorpej Exp $ */ + +/* + * Copyright (c) 1998 Christos Zoulas + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +void ___start(int, char **, char **, void (*cleanup)(void), + const Obj_Entry *, struct ps_strings *); + +__asm(" .text\n\ + .align 4\n\ + .global __start\n\ + .global _start\n\ +__start:\n\ +_start:\n\ + mov 0, %fp\n\ + ld [%sp + 64], %o0 ! get argc\n\ + add %sp, 68, %o1 ! get argv\n\ + sll %o0, 2, %o2 !\n\ + add %o2, 4, %o2 ! envp = argv + (argc << 2) + 4\n\ + add %o1, %o2, %o2 !\n\ + andn %sp, 7, %sp ! align\n\ + sub %sp, 24, %sp ! expand to standard stack frame size\n\ + mov %g3, %o3\n\ + mov %g2, %o4\n\ + call ___start\n\ + mov %g1, %o5\n\ +"); + +void +___start(int argc, char **argv, char **envp, + void (*cleanup)(void), /* from shared loader */ + const Obj_Entry *obj, /* from shared loader */ + struct ps_strings *ps_strings) +{ + environ = envp; + + if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(__progname, '/')) == NULL) + __progname = argv[0]; + else + __progname++; + } + + if (ps_strings != (struct ps_strings *)0) + __ps_strings = ps_strings; + +#ifdef DYNAMIC + if (&_DYNAMIC != NULL) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.12 2004/08/26 21:18:36 thorpej Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/sparc_elf/dot_init.h b/lib/csu/sparc_elf/dot_init.h new file mode 100644 index 000000000..6af62bb73 --- /dev/null +++ b/lib/csu/sparc_elf/dot_init.h @@ -0,0 +1,92 @@ +/* $NetBSD: dot_init.h,v 1.9 2008/05/29 14:51:25 mrg Exp $ */ + +/* + * Copyright (c) 2001 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ + +#ifdef __sparc64__ +#define SAVE " save %sp, -176, %sp \n" +#else +#define SAVE " save %sp, -96, %sp \n" +#endif + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n"\ + " .align 4 \n"\ + ".global "#entry_pt" \n"\ + #entry_pt": \n"\ + SAVE \ + " /* fall thru */ \n"\ + ".previous") + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n"\ + " .align 4 \n"\ + " ret \n"\ + " restore \n"\ + ".previous") + +#define MD_INIT_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.init, _init) +#define MD_FINI_SECTION_PROLOGUE MD_SECTION_PROLOGUE(.fini, _fini) + +#define MD_INIT_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.init) +#define MD_FINI_SECTION_EPILOGUE MD_SECTION_EPILOGUE(.fini) diff --git a/lib/csu/vax_elf/Makefile b/lib/csu/vax_elf/Makefile new file mode 100644 index 000000000..533cca54d --- /dev/null +++ b/lib/csu/vax_elf/Makefile @@ -0,0 +1,4 @@ +# $NetBSD: Makefile,v 1.3 2006/05/19 19:11:12 christos Exp $ +CPPFLAGS+= -I${.CURDIR} + +.include "${.CURDIR}/../common_elf/Makefile.inc" diff --git a/lib/csu/vax_elf/crt0.c b/lib/csu/vax_elf/crt0.c new file mode 100644 index 000000000..1ee996352 --- /dev/null +++ b/lib/csu/vax_elf/crt0.c @@ -0,0 +1,101 @@ +/* $NetBSD: crt0.c,v 1.10 2004/08/26 21:24:09 thorpej Exp $ */ + +/* + * Copyright (c) 1999 Matt Thomas + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +#include "common.h" + +void ___start(int, char **, char **, void (*cleanup)(void), + const Obj_Entry *, struct ps_strings *); + +__asm(" .text;" +" .align 2;" +" .globl _start;" +" .globl __start;" +"__start:;" +"_start:;" +" .word 0x0101;" +" pushl %r9;" /* ps_strings */ +" pushl %r8;" /* obj */ +" pushl %r7;" /* cleanup */ +" movl (%r6),%r0;" /* argc */ +" pushal 8(%r6)[%r0];" /* envp = &argv[argc + 1] */ +" pushal 4(%r6);" /* argv */ +" pushl %r0;" /* argc */ +" calls $6,___start;" + ); + +void +___start(int argc, char **argv, char **envp, + void (*cleanup)(void), /* from shared loader */ + const Obj_Entry *obj, /* from shared loader */ + struct ps_strings *ps_strings) +{ + environ = envp; + + if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ + if ((__progname = _strrchr(__progname, '/')) == NULL) + __progname = argv[0]; + else + __progname++; + } + + if (ps_strings != (struct ps_strings *)0) + __ps_strings = ps_strings; + +#ifdef DYNAMIC + if (&_DYNAMIC != NULL) + _rtld_setup(cleanup, obj); +#endif + +#ifdef MCRT0 + atexit(_mcleanup); + monstartup((u_long)&_eprol, (u_long)&_etext); +#endif + + atexit(_fini); + _init(); + + exit(main(argc, argv, environ)); +} + +/* + * NOTE: Leave the RCS ID _after_ __start(), in case it gets placed in .text. + */ +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: crt0.c,v 1.10 2004/08/26 21:24:09 thorpej Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "common.c" diff --git a/lib/csu/vax_elf/dot_init.h b/lib/csu/vax_elf/dot_init.h new file mode 100644 index 000000000..97c5082c4 --- /dev/null +++ b/lib/csu/vax_elf/dot_init.h @@ -0,0 +1,66 @@ +/* $NetBSD: dot_init.h,v 1.7 2008/05/10 15:31:04 martin Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* RCS ID & Copyright macro defns */ +#include + +#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) diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c index 3def5d19d..2a3536af6 100644 --- a/lib/libc/net/nsdispatch.c +++ b/lib/libc/net/nsdispatch.c @@ -168,17 +168,15 @@ static LIST_HEAD(, _ns_drec) _ns_drec = LIST_HEAD_INITIALIZER(&_ns_drec); static mutex_t _ns_drec_lock = MUTEX_INITIALIZER; #endif /* _REENTRANT */ - -/* - * Runtime determination of whether we are dynamically linked or not. - */ -#ifdef __ELF__ -extern int _DYNAMIC __weak_reference(_DYNAMIC); -#define is_dynamic() (&_DYNAMIC != NULL) -#else +#ifndef __ELF__ #define is_dynamic() (0) /* don't bother - switch to ELF! */ -#endif /* __ELF__ */ - +#elif __GNUC_PREREQ__(4,2) +static int rtld_DYNAMIC __attribute__((__weakref__, __alias__("_DYNAMIC"))); +#define is_dynamic() (&rtld_DYNAMIC != NULL) +#else +extern int _DYNAMIC __weak_reference(_DYNAMIC); +#define is_dynamic() (&_DYNAMIC != NULL) +#endif /* * size of dynamic array chunk for _nsmap and _nsmap[x].srclist (and other diff --git a/libexec/ld.elf_so/Makefile b/libexec/ld.elf_so/Makefile new file mode 100644 index 000000000..42feec03d --- /dev/null +++ b/libexec/ld.elf_so/Makefile @@ -0,0 +1,133 @@ +# $NetBSD: Makefile,v 1.102 2011/01/16 02:36:05 matt Exp $ +# +# NOTE: when changing ld.so, ensure that ldd still compiles. +# + +WARNS?=4 + +# This needs to be before bsd.init.mk +.if defined(BSD_MK_COMPAT_FILE) +.include <${BSD_MK_COMPAT_FILE}> +.endif + +# We are not building this with PIE +PIE_CFLAGS= +PIE_LDFLAGS= +.include # for MKPIC definition +.include # 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 +.else + +MAN= ld.elf_so.1 + +.include +.endif diff --git a/libexec/ld.elf_so/README b/libexec/ld.elf_so/README new file mode 100644 index 000000000..9bf3423aa --- /dev/null +++ b/libexec/ld.elf_so/README @@ -0,0 +1,6 @@ +$NetBSD: README,v 1.11 2006/11/24 22:52:16 wiz Exp $ + +TO DO: + +* Support for coexistence of 32-bit and 64-bit ELF on platforms that can + do that. diff --git a/libexec/ld.elf_so/TODO b/libexec/ld.elf_so/TODO new file mode 100644 index 000000000..55ecf74a5 --- /dev/null +++ b/libexec/ld.elf_so/TODO @@ -0,0 +1,33 @@ +rtld: +* resolve MIPS binding lossage + +binutils/gcc: +* alpha: why are there GLOB_DAT relocs in ld.elf_so? +* alpha: bogus textrels in rtti info +* mips: why are there global GOT relocs in ld.elf_so? +* mips: bogus textrels in .rel.dyn +* powerpc: make sure the .got section is always executable +* powerpc: fix ld scripts so that .rodata is still used for PIC + +machine-specific: +* #ifdefs: +headers.c:#ifndef __mips__ +headers.c:#ifdef __mips__ +reloc.c:#if defined(__hppa__) +rtld.c:#if !defined(__hppa__) +rtld.c:#if !defined(__mips__) && !defined(__hppa__) +rtld.c:#if !defined(__arm__) && !defined(__mips__) && !defined(__sh__) +rtld.c:#ifdef __mips__ +rtld.h:#ifdef __mips__ +symbol.c:#ifndef __mips__ + +issues to research: +* sh, x86_64 have different absolute and GLOB_DAT relocs; nothing else does +* sh, vax, x86_64 use addend on PLT; nothing else does + + +rela: alpha hppa m68k powerpc sh sparc sparc64 vax x86_64 +rel: arm i386 mips + +- mycroft + 2003/09/24 diff --git a/libexec/ld.elf_so/arch/alpha/Makefile.inc b/libexec/ld.elf_so/arch/alpha/Makefile.inc new file mode 100644 index 000000000..b20689f77 --- /dev/null +++ b/libexec/ld.elf_so/arch/alpha/Makefile.inc @@ -0,0 +1,11 @@ +# $NetBSD: Makefile.inc,v 1.12 2005/06/04 16:17:17 lukem Exp $ + +SRCS+= rtld_start.S alpha_reloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic -mno-fp-regs + +CPPFLAGS+= -DELFSIZE=64 +#CPPFLAGS+= -DRTLD_DEBUG_ALPHA + +LDFLAGS+= -Wl,-e,_rtld_start diff --git a/libexec/ld.elf_so/arch/alpha/alpha_reloc.c b/libexec/ld.elf_so/arch/alpha/alpha_reloc.c new file mode 100644 index 000000000..357adc78e --- /dev/null +++ b/libexec/ld.elf_so/arch/alpha/alpha_reloc.c @@ -0,0 +1,503 @@ +/* $NetBSD: alpha_reloc.c,v 1.38 2010/09/30 09:11:18 skrll Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright 1996, 1997, 1998, 1999 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: alpha_reloc.c,v 1.38 2010/09/30 09:11:18 skrll Exp $"); +#endif /* not lint */ + +#include +#include + +#include "rtld.h" +#include "debug.h" + +#ifdef RTLD_DEBUG_ALPHA +#define adbg(x) xprintf x +#else +#define adbg(x) /* nothing */ +#endif + +void _rtld_bind_start(void); +void _rtld_bind_start_old(void); +void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); +caddr_t _rtld_bind(const Obj_Entry *, Elf_Addr); +static inline int _rtld_relocate_plt_object(const Obj_Entry *, + const Elf_Rela *, Elf_Addr *); + +void +_rtld_setup_pltgot(const Obj_Entry *obj) +{ + uint32_t word0; + + /* + * The PLTGOT on the Alpha looks like this: + * + * PLT HEADER + * . + * . 32 bytes + * . + * PLT ENTRY #0 + * . + * . 12 bytes + * . + * PLT ENTRY #1 + * . + * . 12 bytes + * . + * etc. + * + * The old-format entries look like (displacements filled in + * by the linker): + * + * ldah $28, 0($31) # 0x279f0000 + * lda $28, 0($28) # 0x239c0000 + * br $31, plt0 # 0xc3e00000 + * + * The new-format entries look like: + * + * br $28, plt0 # 0xc3800000 + * # 0x00000000 + * # 0x00000000 + * + * What we do is fetch the first PLT entry and check to + * see the first word of it matches the first word of the + * old format. If so, we use a binding routine that can + * handle the old format, otherwise we use a binding routine + * that handles the new format. + * + * Note that this is done on a per-object basis, we can mix + * and match shared objects build with both the old and new + * linker. + */ + word0 = *(uint32_t *)(((char *) obj->pltgot) + 32); + if ((word0 & 0xffff0000) == 0x279f0000) { + /* Old PLT entry format. */ + adbg(("ALPHA: object %p has old PLT format\n", obj)); + obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start_old; + obj->pltgot[3] = (Elf_Addr) obj; + } else { + /* New PLT entry format. */ + adbg(("ALPHA: object %p has new PLT format\n", obj)); + obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; + obj->pltgot[3] = (Elf_Addr) obj; + } + + __asm volatile("imb"); +} + +/* + * It is possible for the compiler to emit relocations for unaligned data. + * We handle this situation with these inlines. + */ +#define RELOC_ALIGNED_P(x) \ + (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) + +static inline Elf_Addr +load_ptr(void *where) +{ + Elf_Addr res; + + memcpy(&res, where, sizeof(res)); + + return (res); +} + +static inline void +store_ptr(void *where, Elf_Addr val) +{ + + memcpy(where, &val, sizeof(val)); +} + +void +_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rela *rela = 0, *relalim; + Elf_Addr relasz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_RELA: + rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + } + } + relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); + for (; rela < relalim; rela++) { + where = (Elf_Addr *)(relocbase + rela->r_offset); + /* XXX For some reason I see a few GLOB_DAT relocs here. */ + *where += (Elf_Addr)relocbase; + } +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rela *rela; + Elf_Addr target = -1; + + for (rela = obj->rela; rela < obj->relalim; rela++) { + Elf_Addr *where; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr tmp; + unsigned long symnum; + + where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + symnum = ELF_R_SYM(rela->r_info); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(NONE): + break; + + case R_TYPE(REFQUAD): + case R_TYPE(GLOB_DAT): + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + target = (Elf_Addr)(defobj->relocbase + + def->st_value); + + tmp = target + rela->r_addend; + if (__predict_true(RELOC_ALIGNED_P(where))) { + if (*where != tmp) + *where = tmp; + } else { + if (load_ptr(where) != tmp) + store_ptr(where, tmp); + } + rdbg(("REFQUAD/GLOB_DAT %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)tmp, defobj->path)); + break; + + case R_TYPE(RELATIVE): + if (__predict_true(RELOC_ALIGNED_P(where))) + *where += (Elf_Addr)obj->relocbase; + else + store_ptr(where, + load_ptr(where) + (Elf_Addr)obj->relocbase); + rdbg(("RELATIVE in %s --> %p", obj->path, + (void *)*where)); + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + if (obj->isdynamic) { + _rtld_error( + "%s: Unexpected R_COPY relocation in shared library", + obj->path); + return -1; + } + rdbg(("COPY (avoid in main)")); + break; + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "addend = %p, contents = %p, symbol = %s", + symnum, (u_long)ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)rela->r_addend, + (void *)load_ptr(where), + obj->strtab + obj->symtab[symnum].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rela->r_info)); + return -1; + } + } + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + if (!obj->relocbase) + return 0; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + + assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); + + /* Just relocate the GOT slots pointing into the PLT */ + *where += (Elf_Addr)obj->relocbase; + rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); + } + + return 0; +} + +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, + Elf_Addr *tp) +{ + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + Elf_Addr new_value; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr stubaddr; + unsigned long info = rela->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(("bind now/fixup in %s --> old=%p new=%p", + defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); + + if ((stubaddr = *where) != new_value) { + int64_t delta, idisp; + uint32_t insn[3], *stubptr; + int insncnt; + Elf_Addr pc; + + /* Point this GOT entry at the target. */ + *where = new_value; + + /* + * Alpha shared objects may have multiple GOTs, each + * of which may point to this entry in the PLT. But, + * we only have a reference to the first GOT entry which + * points to this PLT entry. In order to avoid having to + * re-bind this call every time a non-first GOT entry is + * used, we will attempt to patch up the PLT entry to + * reference the target, rather than the binder. + * + * When the PLT stub gets control, PV contains the address + * of the PLT entry. Each PLT entry has room for 3 insns. + * If the displacement of the target from PV fits in a signed + * 32-bit integer, we can simply add it to PV. Otherwise, + * we must load the GOT entry itself into PV. + * + * Note if the shared object uses the old PLT format, then + * we cannot patch up the PLT safely, and so we skip it + * in that case[*]. + * + * [*] Actually, if we're not doing lazy-binding, then + * we *can* (and do) patch up this PLT entry; the PLTGOT + * thunk won't yet point to any binder entry point, and + * so this test will fail as it would for the new PLT + * entry format. + */ + if (obj->pltgot[2] == (Elf_Addr) &_rtld_bind_start_old) { + rdbg((" old PLT format")); + goto out; + } + + delta = new_value - stubaddr; + rdbg((" stubaddr=%p, where-stubaddr=%ld, delta=%ld", + (void *)stubaddr, (long)where - (long)stubaddr, + (long)delta)); + insncnt = 0; + if ((int32_t)delta == delta) { + /* + * We can adjust PV with an LDA, LDAH sequence. + * + * First, build an LDA insn to adjust the low 16 + * bits. + */ + insn[insncnt++] = 0x08 << 26 | 27 << 21 | 27 << 16 | + (delta & 0xffff); + rdbg((" LDA $27,%d($27)", (int16_t)delta)); + /* + * Adjust the delta to account for the effects of + * the LDA, including sign-extension. + */ + delta -= (int16_t)delta; + if (delta != 0) { + /* + * Build an LDAH instruction to adjust the + * high 16 bits. + */ + insn[insncnt++] = 0x09 << 26 | 27 << 21 | + 27 << 16 | ((delta >> 16) & 0xffff); + rdbg((" LDAH $27,%d($27)", + (int16_t)(delta >> 16))); + } + } else { + int64_t dhigh; + + /* We must load the GOT entry. */ + delta = (Elf_Addr)where - stubaddr; + + /* + * If the GOT entry is too far away from the PLT + * entry, then we can't patch up the PLT entry. + * This PLT entry will have to be bound for each + * GOT entry except for the first one. This program + * will still run, albeit very slowly. It is very + * unlikely that this case will ever happen in + * practice. + */ + if ((int32_t)delta != delta) { + rdbg((" PLT stub too far from GOT to relocate")); + goto out; + } + dhigh = delta - (int16_t)delta; + if (dhigh != 0) { + /* + * Build an LDAH instruction to adjust the + * high 16 bits. + */ + insn[insncnt++] = 0x09 << 26 | 27 << 21 | + 27 << 16 | ((dhigh >> 16) & 0xffff); + rdbg((" LDAH $27,%d($27)", + (int16_t)(dhigh >> 16))); + } + /* Build an LDQ to load the GOT entry. */ + insn[insncnt++] = 0x29 << 26 | 27 << 21 | + 27 << 16 | (delta & 0xffff); + rdbg((" LDQ $27,%d($27)", + (int16_t)delta)); + } + + /* + * Now, build a JMP or BR insn to jump to the target. If + * the displacement fits in a sign-extended 21-bit field, + * we can use the more efficient BR insn. Otherwise, we + * have to jump indirect through PV. + */ + pc = stubaddr + (4 * (insncnt + 1)); + idisp = (int64_t)(new_value - pc) >> 2; + if (-0x100000 <= idisp && idisp < 0x100000) { + insn[insncnt++] = 0x30 << 26 | 31 << 21 | + (idisp & 0x1fffff); + rdbg((" BR $31,%p", (void *)new_value)); + } else { + insn[insncnt++] = 0x1a << 26 | 31 << 21 | + 27 << 16 | (idisp & 0x3fff); + rdbg((" JMP $31,($27),%d", + (int)(idisp & 0x3fff))); + } + + /* + * Fill in the tail of the PLT entry first, for reentrancy. + * Until we have overwritten the first insn (an unconditional + * branch), the remaining insns have no effect. + */ + stubptr = (uint32_t *)stubaddr; + while (insncnt > 1) { + insncnt--; + stubptr[insncnt] = insn[insncnt]; + } + /* + * Commit the tail of the insn sequence to memory + * before overwriting the first insn. + */ + __asm volatile("wmb" ::: "memory"); + stubptr[0] = insn[0]; + /* + * I-stream will be sync'd when we either return from + * the binder (lazy bind case) or when the PLTGOT thunk + * is patched up (bind-now case). + */ + } +out: + if (tp) + *tp = new_value; + + return 0; +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Addr reloff) +{ + const Elf_Rela *rela = + (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff); + Elf_Addr result = 0; /* XXX gcc */ + int err; + + err = _rtld_relocate_plt_object(obj, rela, &result); + if (err) + _rtld_die(); + + return (caddr_t)result; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) + if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) + return -1; + + return 0; +} diff --git a/libexec/ld.elf_so/arch/alpha/rtld_start.S b/libexec/ld.elf_so/arch/alpha/rtld_start.S new file mode 100644 index 000000000..22d18ce2a --- /dev/null +++ b/libexec/ld.elf_so/arch/alpha/rtld_start.S @@ -0,0 +1,194 @@ +/* $NetBSD: rtld_start.S,v 1.16 2004/02/18 23:04:49 enami Exp $ */ + +/* + * Copyright 1996 Matt Thomas + * Portions copyright 2002 Charles M. Hannum + * 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 + +/* + * Note: we can call ourselves LEAF even though we use callee-saved + * registers because we're the root of the call graph. + */ +LEAF_NOPROFILE(_rtld_start, 0) + .set noreorder + br pv, 1f +1: LDGP(pv) + + /* + * Relocate ourself. + */ + br s2, 2f /* get our PC */ +2: ldiq s3, 2b /* get where the linker thought we were */ + + subq s2, s3, a1 /* relocbase */ + lda t5, _DYNAMIC + addq a1, t5, a0 /* &_DYNAMIC */ + + /* Squirrel away ps_strings. */ + mov a3, s0 + + bsr ra, _rtld_relocate_nonplt_self + LDGP(ra) + + /* + * Allocate space on the stack for the cleanup and obj_main + * entries that _rtld() will provide for us. + */ + lda sp, -16(sp) + + subq s2, s3, a1 /* relocbase */ + mov sp, a0 /* sp */ + CALL(_rtld) /* v0 = _rtld(sp, relocbase); */ + + ldq a1, 0(sp) /* cleanup */ + ldq a2, 8(sp) /* obj_main */ + lda sp, 16(sp) /* pop stack */ + + mov sp, a0 /* stack pointer */ + mov s0, a3 /* ps_strings */ + + mov v0, pv /* set up PV for entry point */ + + jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj, ps_strings); */ + ldgp gp, 0(ra) + + CALL(exit) + halt +END(_rtld_start) + +#define RTLD_BIND_START_PROLOGUE \ + /* at_reg already used by PLT code. */ \ + .set noat ; \ + \ + /* \ + * Allocate stack frame and preserve all registers that the \ + * caller would have normally saved themselves. \ + */ \ + lda sp, -168(sp) ; \ + stq ra, 0(sp) ; \ + stq v0, 8(sp) ; \ + stq t0, 16(sp) ; \ + stq t1, 24(sp) ; \ + stq t2, 32(sp) ; \ + stq t3, 40(sp) ; \ + stq t4, 48(sp) ; \ + stq t5, 56(sp) ; \ + stq t6, 64(sp) ; \ + stq t7, 72(sp) ; \ + stq a0, 80(sp) ; \ + stq a1, 88(sp) ; \ + stq a2, 96(sp) ; \ + stq a3, 104(sp) ; \ + stq a4, 112(sp) ; \ + stq a5, 120(sp) ; \ + stq t8, 128(sp) ; \ + stq t9, 136(sp) ; \ + stq t10, 144(sp) ; \ + stq t11, 152(sp) ; \ + stq gp, 160(sp) ; \ + \ + /* \ + * Load our global pointer. Note, can't use pv, since it is \ + * already used by the PLT code. \ + */ \ + br t0, 1f ; \ +1: LDGP(t0) + +#define RTLD_BIND_START_EPILOGUE \ + /* Move the destination address into position. */ \ + mov v0, pv ; \ + \ + /* Restore program registers. */ \ + ldq ra, 0(sp) ; \ + ldq v0, 8(sp) ; \ + ldq t0, 16(sp) ; \ + ldq t1, 24(sp) ; \ + ldq t2, 32(sp) ; \ + ldq t3, 40(sp) ; \ + ldq t4, 48(sp) ; \ + ldq t5, 56(sp) ; \ + ldq t6, 64(sp) ; \ + ldq t7, 72(sp) ; \ + ldq a0, 80(sp) ; \ + ldq a1, 88(sp) ; \ + ldq a2, 96(sp) ; \ + ldq a3, 104(sp) ; \ + ldq a4, 112(sp) ; \ + ldq a5, 120(sp) ; \ + ldq t8, 128(sp) ; \ + ldq t9, 136(sp) ; \ + ldq t10, 144(sp) ; \ + ldq t11, 152(sp) ; \ + ldq gp, 160(sp) ; \ + /* XXX LDGP? */ \ + \ + /* \ + * We've patched the PLT; sync the I-stream. \ + */ \ + imb ; \ + \ + /* Pop the stack frame and turn control to the destination. */ \ + lda sp, 168(sp) ; \ + jmp zero, (pv) + +/* + * Lazy binding entry point, called via PLT. + */ +NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0) + + RTLD_BIND_START_PROLOGUE + + /* Set up the arguments for _rtld_bind. */ + subq at_reg, pv, a1 /* calculate offset of reloc entry */ + ldq a0, 8(pv) /* object structure */ + subq a1, 20, a1 /* = (at - pv - 20) / 12 * 24 */ + addq a1, a1, a1 + + CALL(_rtld_bind) + + RTLD_BIND_START_EPILOGUE + +END(_rtld_bind_start) + +/* + * Lazy binding entry point, called via PLT. This version is for the + * old PLT entry format. + */ +NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0) + + RTLD_BIND_START_PROLOGUE + + /* Set up the arguments for _rtld_bind. */ + ldq a0, 8(pv) /* object structure */ + mov at_reg, a1 /* offset of reloc entry */ + + CALL(_rtld_bind) + + RTLD_BIND_START_EPILOGUE + +END(_rtld_bind_start_old) diff --git a/libexec/ld.elf_so/arch/arm/Makefile.inc b/libexec/ld.elf_so/arch/arm/Makefile.inc new file mode 100644 index 000000000..280a20d98 --- /dev/null +++ b/libexec/ld.elf_so/arch/arm/Makefile.inc @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.11 2005/06/04 16:17:17 lukem Exp $ + +SRCS+= rtld_start.S mdreloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic + +CPPFLAGS+= -DELFSIZE=32 + +LDFLAGS+= -Wl,-e,_rtld_start diff --git a/libexec/ld.elf_so/arch/arm/mdreloc.c b/libexec/ld.elf_so/arch/arm/mdreloc.c new file mode 100644 index 000000000..d62c6902c --- /dev/null +++ b/libexec/ld.elf_so/arch/arm/mdreloc.c @@ -0,0 +1,276 @@ +/* $NetBSD: mdreloc.c,v 1.34 2010/08/06 16:33:17 joerg Exp $ */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.34 2010/08/06 16:33:17 joerg Exp $"); +#endif /* not lint */ + +#include +#include + +#include "debug.h" +#include "rtld.h" + +void _rtld_bind_start(void); +void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); +caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); + +void +_rtld_setup_pltgot(const Obj_Entry *obj) +{ + obj->pltgot[1] = (Elf_Addr) obj; + obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; +} + +void +_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rel *rel = 0, *rellim; + Elf_Addr relsz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_REL: + rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELSZ: + relsz = dynp->d_un.d_val; + break; + } + } + rellim = (const Elf_Rel *)((const uint8_t *)rel + relsz); + for (; rel < rellim; rel++) { + where = (Elf_Addr *)(relocbase + rel->r_offset); + *where += (Elf_Addr)relocbase; + } +} + +/* + * It is possible for the compiler to emit relocations for unaligned data. + * We handle this situation with these inlines. + */ +#define RELOC_ALIGNED_P(x) \ + (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) + +static inline Elf_Addr +load_ptr(void *where) +{ + Elf_Addr res; + + memcpy(&res, where, sizeof(res)); + + return (res); +} + +static inline void +store_ptr(void *where, Elf_Addr val) +{ + + memcpy(where, &val, sizeof(val)); +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rel *rel; + + for (rel = obj->rel; rel < obj->rellim; rel++) { + Elf_Addr *where; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr tmp; + unsigned long symnum; + + where = (Elf_Addr *)(obj->relocbase + rel->r_offset); + symnum = ELF_R_SYM(rel->r_info); + + switch (ELF_R_TYPE(rel->r_info)) { + case R_TYPE(NONE): + break; + +#if 1 /* XXX should not occur */ + case R_TYPE(PC24): { /* word32 S - P + A */ + Elf32_Sword addend; + + /* + * Extract addend and sign-extend if needed. + */ + addend = *where; + if (addend & 0x00800000) + addend |= 0xff000000; + + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + tmp = (Elf_Addr)obj->relocbase + def->st_value + - (Elf_Addr)where + (addend << 2); + if ((tmp & 0xfe000000) != 0xfe000000 && + (tmp & 0xfe000000) != 0) { + _rtld_error( + "%s: R_ARM_PC24 relocation @ %p to %s failed " + "(displacement %ld (%#lx) out of range)", + obj->path, where, + obj->strtab + obj->symtab[symnum].st_name, + (long) tmp, (long) tmp); + return -1; + } + tmp >>= 2; + *where = (*where & 0xff000000) | (tmp & 0x00ffffff); + rdbg(("PC24 %s in %s --> %p @ %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, where, defobj->path)); + break; + } +#endif + + case R_TYPE(ABS32): /* word32 B + S + A */ + case R_TYPE(GLOB_DAT): /* word32 B + S */ + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + if (__predict_true(RELOC_ALIGNED_P(where))) { + tmp = *where + (Elf_Addr)defobj->relocbase + + def->st_value; + /* Set the Thumb bit, if needed. */ + if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) + tmp |= 1; + *where = tmp; + } else { + tmp = load_ptr(where) + + (Elf_Addr)defobj->relocbase + + def->st_value; + /* Set the Thumb bit, if needed. */ + if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) + tmp |= 1; + store_ptr(where, tmp); + } + rdbg(("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)tmp, where, defobj->path)); + break; + + case R_TYPE(RELATIVE): /* word32 B + A */ + if (__predict_true(RELOC_ALIGNED_P(where))) { + tmp = *where + (Elf_Addr)obj->relocbase; + *where = tmp; + } else { + tmp = load_ptr(where) + + (Elf_Addr)obj->relocbase; + store_ptr(where, tmp); + } + rdbg(("RELATIVE in %s --> %p", obj->path, + (void *)tmp)); + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + if (obj->isdynamic) { + _rtld_error( + "%s: Unexpected R_COPY relocation in shared library", + obj->path); + return -1; + } + rdbg(("COPY (avoid in main)")); + break; + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "contents = %p, symbol = %s", + symnum, (u_long)ELF_R_TYPE(rel->r_info), + (void *)rel->r_offset, (void *)load_ptr(where), + obj->strtab + obj->symtab[symnum].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rel->r_info)); + return -1; + } + } + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + const Elf_Rel *rel; + + if (!obj->relocbase) + return 0; + + for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); + + assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT)); + + /* Just relocate the GOT slots pointing into the PLT */ + *where += (Elf_Addr)obj->relocbase; + rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); + } + + return 0; +} + +static int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel, + Elf_Addr *tp) +{ + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); + Elf_Addr new_value; + const Elf_Sym *def; + const Obj_Entry *defobj; + unsigned long info = rel->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JUMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + /* Set the Thumb bit, if needed. */ + if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) + new_value |= 1; + rdbg(("bind now/fixup in %s --> old=%p new=%p", + defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); + if (*where != new_value) + *where = new_value; + if (tp) + *tp = new_value; + + return 0; +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rel *rel = (const Elf_Rel *)((const uint8_t *)obj->pltrel + reloff); + Elf_Addr new_value = 0; /* XXX gcc */ + int err; + + err = _rtld_relocate_plt_object(obj, rel, &new_value); + if (err) + _rtld_die(); + + return (caddr_t)new_value; +} +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rel *rel; + int err = 0; + + for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { + err = _rtld_relocate_plt_object(obj, rel, NULL); + if (err) + break; + } + + return err; +} diff --git a/libexec/ld.elf_so/arch/arm/rtld_start.S b/libexec/ld.elf_so/arch/arm/rtld_start.S new file mode 100644 index 000000000..41a599c19 --- /dev/null +++ b/libexec/ld.elf_so/arch/arm/rtld_start.S @@ -0,0 +1,104 @@ +/* $NetBSD: rtld_start.S,v 1.10 2009/11/11 14:15:41 skrll Exp $ */ + +/*- + * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas and by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: rtld_start.S,v 1.10 2009/11/11 14:15:41 skrll Exp $") + + .text + .align 0 + .globl _rtld_start + .type _rtld_start,%function +_rtld_start: + sub sp, sp, #8 /* make room for obj_main & exit proc */ + mov r4, r0 /* save ps_strings */ + + ldr sl, .L2 + ldr r5, .L2+4 + ldr r0, .L2+8 +.L1: + add sl, pc, sl + ldr r5, [sl, r5] + ldr r0, [sl, r0] + + sub r1, sl, r5 /* relocbase */ + add r0, r1, r0 /* &_DYNAMIC */ + bl _rtld_relocate_nonplt_self + + sub r1, sl, r5 /* relocbase */ + mov r0, sp /* sp */ + bl _rtld /* call the shared loader */ + mov r3, r0 /* save entry point */ + + ldr r2, [sp, #0] /* r2 = cleanup */ + ldr r1, [sp, #4] /* r1 = obj_main */ + add sp, sp, #8 /* restore stack */ + mov r0, r4 /* restore ps_strings */ +#ifdef _ARM_ARCH_4T + bx r3 /* jump to the entry point */ +#else + mov pc, r3 /* jump to the entry point */ +#endif +.L2: + .word _GLOBAL_OFFSET_TABLE_ - (.L1+8) + .word _GLOBAL_OFFSET_TABLE_(GOT) + .word _DYNAMIC(GOT) + + .align 0 + .globl _rtld_bind_start + .type _rtld_bind_start,%function +/* + * stack[0] = RA + * ip = &GOT[n+3] + * lr = &GOT[2] + */ +_rtld_bind_start: + stmdb sp!,{r0-r4,sl,fp} + + sub r1, ip, lr /* r1 = 4 * (n + 1) */ + sub r1, r1, #4 /* r1 = 4 * n */ + add r1, r1, r1 /* r1 = 8 * n */ + + ldr r0, [lr, #-4] /* get obj ptr from GOT[1] */ + mov r4, ip /* save GOT location */ + + bl _rtld_bind /* Call the binder */ + + str r0, [r4] /* save address in GOT */ + mov ip, r0 /* save new address */ + + ldmia sp!,{r0-r4,sl,fp,lr} /* restore the stack */ +#ifdef _ARM_ARCH_4T + bx ip /* jump to the new address */ +#else + mov pc, ip /* jump to the new address */ +#endif + diff --git a/libexec/ld.elf_so/arch/hppa/Makefile.inc b/libexec/ld.elf_so/arch/hppa/Makefile.inc new file mode 100644 index 000000000..6f6c7f86e --- /dev/null +++ b/libexec/ld.elf_so/arch/hppa/Makefile.inc @@ -0,0 +1,14 @@ +# $NetBSD: Makefile.inc,v 1.8 2009/09/12 07:22:16 skrll Exp $ + +SRCS+= rtld_start.S hppa_reloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic + +CPPFLAGS+= -DELFSIZE=32 +#CPPFLAGS+= -DDEBUG +#CPPFLAGS+= -DRTLD_DEBUG +#CPPFLAGS+= -DRTLD_DEBUG_RELOC +#CPPFLAGS+= -DRTLD_DEBUG_HPPA + +LDFLAGS+= -Wl,-e,'$$rtld_start' diff --git a/libexec/ld.elf_so/arch/hppa/hppa_reloc.c b/libexec/ld.elf_so/arch/hppa/hppa_reloc.c new file mode 100644 index 000000000..ef1cdf1fb --- /dev/null +++ b/libexec/ld.elf_so/arch/hppa/hppa_reloc.c @@ -0,0 +1,617 @@ +/* $NetBSD: hppa_reloc.c,v 1.34 2010/09/24 11:41:46 skrll Exp $ */ + +/*- + * Copyright (c) 2002, 2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Fredette and Nick Hudson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: hppa_reloc.c,v 1.34 2010/09/24 11:41:46 skrll Exp $"); +#endif /* not lint */ + +#include +#include +#include + +#include + +#include "rtld.h" +#include "debug.h" + +#ifdef RTLD_DEBUG_HPPA +#define hdbg(x) xprintf x +#else +#define hdbg(x) /* nothing */ +#endif + +caddr_t _rtld_bind(const Obj_Entry *, const Elf_Addr); +void _rtld_bind_start(void); +void __rtld_setup_hppa_pltgot(const Obj_Entry *, Elf_Addr *); + +/* + * It is possible for the compiler to emit relocations for unaligned data. + * We handle this situation with these inlines. + */ +#define RELOC_ALIGNED_P(x) \ + (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) + +static inline Elf_Addr +load_ptr(void *where) +{ + if (__predict_true(RELOC_ALIGNED_P(where))) + return *(Elf_Addr *)where; + else { + Elf_Addr res; + + (void)memcpy(&res, where, sizeof(res)); + return res; + } +} + +static inline void +store_ptr(void *where, Elf_Addr val) +{ + if (__predict_true(RELOC_ALIGNED_P(where))) + *(Elf_Addr *)where = val; + else + (void)memcpy(where, &val, sizeof(val)); +} + +/* + * In the runtime architecture (ABI), PLABEL function pointers are + * distinguished from normal function pointers by having the next-least- + * significant bit set. (This bit is referred to as the L field in HP + * documentation). The $$dyncall millicode is aware of this. + */ +#define RTLD_MAKE_PLABEL(plabel) (((Elf_Addr)(plabel)) | (1 << 1)) +#define RTLD_IS_PLABEL(addr) (((Elf_Addr)(addr)) & (1 << 1)) +#define RTLD_GET_PLABEL(addr) ((hppa_plabel *) (((Elf_Addr)addr) & ~3)) + +/* + * This is the PLABEL structure. The function PC and + * shared linkage members must come first, as they are + * the actual PLABEL. + */ +typedef struct _hppa_plabel { + Elf_Addr hppa_plabel_pc; + Elf_Addr hppa_plabel_sl; + SLIST_ENTRY(_hppa_plabel) hppa_plabel_next; +} hppa_plabel; + +/* + * For now allocated PLABEL structures are tracked on a + * singly linked list. This maybe should be revisited. + */ +static SLIST_HEAD(hppa_plabel_head, _hppa_plabel) hppa_plabel_list + = SLIST_HEAD_INITIALIZER(hppa_plabel_list); + +/* + * Because I'm hesitant to use NEW while relocating self, + * this is a small pool of preallocated PLABELs. + */ +#define HPPA_PLABEL_PRE (14) +static hppa_plabel hppa_plabel_pre[HPPA_PLABEL_PRE]; +static int hppa_plabel_pre_next = 0; + +void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); +int _rtld_relocate_plt_objects(const Obj_Entry *); +static inline int _rtld_relocate_plt_object(const Obj_Entry *, + const Elf_Rela *, Elf_Addr *); + +/* + * This bootstraps the dynamic linker by relocating its GOT. + * On the hppa, unlike on other architectures, static strings + * are found through the GOT. Static strings are essential + * for RTLD_DEBUG, and I suspect they're used early even when + * !defined(RTLD_DEBUG), making relocating the GOT essential. + * + * It gets worse. Relocating the GOT doesn't mean just walking + * it and adding the relocbase to all of the entries. You must + * find and use the GOT relocations, since those RELA relocations + * have the necessary addends - the GOT comes initialized as + * zeroes. + */ +void +_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rela *relafirst, *rela, *relalim; + Elf_Addr relasz; + void *where; + Elf_Addr *pltgot; + const Elf_Rela *plabel_relocs[HPPA_PLABEL_PRE]; + int nplabel_relocs = 0; + int i; + const Elf_Sym *symtab, *sym; + unsigned long symnum; + hppa_plabel *plabel; + + /* + * Process the DYNAMIC section, looking for the non-PLT relocations. + */ + relafirst = NULL; + relasz = 0; + symtab = NULL; + pltgot = NULL; + for (; dynp->d_tag != DT_NULL; ++dynp) { + switch (dynp->d_tag) { + + case DT_RELA: + relafirst = (const Elf_Rela *) + (relocbase + dynp->d_un.d_ptr); + break; + + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + + case DT_SYMTAB: + symtab = (const Elf_Sym *) + (relocbase + dynp->d_un.d_ptr); + break; + + case DT_PLTGOT: + pltgot = (Elf_Addr *) + (relocbase + dynp->d_un.d_ptr); + break; + } + } + relalim = (const Elf_Rela *)((const char *)relafirst + relasz); + + for (rela = relafirst; rela < relalim; rela++) { + symnum = ELF_R_SYM(rela->r_info); + where = (void *)(relocbase + rela->r_offset); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(DIR32): + if (symnum == 0) + store_ptr(where, + relocbase + rela->r_addend); + else { + sym = symtab + symnum; + store_ptr(where, + relocbase + rela->r_addend + sym->st_value); + } + break; + + case R_TYPE(PLABEL32): + /* + * PLABEL32 relocation processing is done in two phases + * + * i) local function relocations (symbol number == 0) + * can be resolved immediately. + * + * ii) external function relocations are deferred until + * we finish all other relocations so that global + * data isn't accessed until all other non-PLT + * relocations have been done. + */ + if (symnum == 0) + *((Elf_Addr *)where) = + relocbase + rela->r_addend; + else + plabel_relocs[nplabel_relocs++] = rela; + break; + + default: + break; + } + } + + assert(nplabel_relocs < HPPA_PLABEL_PRE); + for (i = 0; i < nplabel_relocs; i++) { + rela = plabel_relocs[i]; + where = (void *)(relocbase + rela->r_offset); + sym = symtab + ELF_R_SYM(rela->r_info); + + plabel = &hppa_plabel_pre[hppa_plabel_pre_next++]; + + plabel->hppa_plabel_pc = (Elf_Addr) + (relocbase + sym->st_value + rela->r_addend); + plabel->hppa_plabel_sl = (Elf_Addr)pltgot; + + SLIST_INSERT_HEAD(&hppa_plabel_list, plabel, hppa_plabel_next); + *((Elf_Addr *)where) = (Elf_Addr)(RTLD_MAKE_PLABEL(plabel)); + } + +#if defined(RTLD_DEBUG_HPPA) + for (rela = relafirst; rela < relalim; rela++) { + where = (void *)(relocbase + rela->r_offset); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(DIR32): + hdbg(("DIR32 rela @%p(%p) -> %p(%p)\n", + (void *)rela->r_offset, + (void *)where, + (void *)rela->r_addend, + (void *)*((Elf_Addr *)where) )); + break; + + case R_TYPE(PLABEL32): + symnum = ELF_R_SYM(rela->r_info); + if (symnum == 0) { + hdbg(("PLABEL rela @%p(%p) -> %p(%p)\n", + (void *)rela->r_offset, + (void *)where, + (void *)rela->r_addend, + (void *)*((Elf_Addr *)where) )); + } else { + sym = symtab + symnum; + + hdbg(("PLABEL32 rela @%p(%p), symnum=%ld(%p) -> %p(%p)\n", + (void *)rela->r_offset, + (void *)where, + symnum, + (void *)sym->st_value, + (void *)rela->r_addend, + (void *)*((Elf_Addr *)where) )); + } + break; + default: + hdbg(("rela XXX reloc\n")); + break; + } + } +#endif /* RTLD_DEBUG_HPPA */ +} + +/* + * This allocates a PLABEL. If called with a non-NULL def, the + * plabel is for the function associated with that definition + * in the defining object defobj, plus the given addend. If + * called with a NULL def, the plabel is for the function at + * the (unrelocated) address in addend in the object defobj. + */ +Elf_Addr +_rtld_function_descriptor_alloc(const Obj_Entry *defobj, const Elf_Sym *def, + Elf_Addr addend) +{ + Elf_Addr func_pc, func_sl; + hppa_plabel *plabel; + + if (def != NULL) { + + /* + * We assume that symbols of type STT_NOTYPE + * are undefined. Return NULL for these. + */ + if (ELF_ST_TYPE(def->st_info) == STT_NOTYPE) + return (Elf_Addr)NULL; + + /* Otherwise assert that this symbol must be a function. */ + assert(ELF_ST_TYPE(def->st_info) == STT_FUNC); + + func_pc = (Elf_Addr)(defobj->relocbase + def->st_value + + addend); + } else + func_pc = (Elf_Addr)(defobj->relocbase + addend); + + /* + * Search the existing PLABELs for one matching + * this function. If there is one, return it. + */ + func_sl = (Elf_Addr)(defobj->pltgot); + SLIST_FOREACH(plabel, &hppa_plabel_list, hppa_plabel_next) + if (plabel->hppa_plabel_pc == func_pc && + plabel->hppa_plabel_sl == func_sl) + return RTLD_MAKE_PLABEL(plabel); + + /* + * Once we've used up the preallocated set, we start + * using NEW to allocate plabels. + */ + if (hppa_plabel_pre_next < HPPA_PLABEL_PRE) + plabel = &hppa_plabel_pre[hppa_plabel_pre_next++]; + else { + plabel = NEW(hppa_plabel); + if (plabel == NULL) + return (Elf_Addr)-1; + } + + /* Fill the new entry and insert it on the list. */ + plabel->hppa_plabel_pc = func_pc; + plabel->hppa_plabel_sl = func_sl; + SLIST_INSERT_HEAD(&hppa_plabel_list, plabel, hppa_plabel_next); + + return RTLD_MAKE_PLABEL(plabel); +} + +/* + * If a pointer is a PLABEL, this unwraps it. + */ +const void * +_rtld_function_descriptor_function(const void *addr) +{ + return (RTLD_IS_PLABEL(addr) ? + (const void *) RTLD_GET_PLABEL(addr)->hppa_plabel_pc : + addr); +} + +/* This sets up an object's GOT. */ +void +_rtld_setup_pltgot(const Obj_Entry *obj) +{ + __rtld_setup_hppa_pltgot(obj, obj->pltgot); +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->rela; rela < obj->relalim; rela++) { + Elf_Addr *where; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr tmp; + unsigned long symnum; + + where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + symnum = ELF_R_SYM(rela->r_info); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(NONE): + break; + + case R_TYPE(DIR32): + if (symnum) { + /* + * This is either a DIR32 against a symbol + * (def->st_name != 0), or against a local + * section (def->st_name == 0). + */ + def = obj->symtab + symnum; + defobj = obj; + if (def->st_name != 0) + def = _rtld_find_symdef(symnum, obj, + &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + + def->st_value + rela->r_addend); + + if (load_ptr(where) != tmp) + store_ptr(where, tmp); + rdbg(("DIR32 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)load_ptr(where), + defobj->path)); + } else { + tmp = (Elf_Addr)(obj->relocbase + + rela->r_addend); + + if (load_ptr(where) != tmp) + store_ptr(where, tmp); + rdbg(("DIR32 in %s --> %p", obj->path, + (void *)load_ptr(where))); + } + break; + + case R_TYPE(PLABEL32): + if (symnum) { + def = _rtld_find_symdef(symnum, obj, &defobj, + false); + if (def == NULL) + return -1; + + tmp = _rtld_function_descriptor_alloc(defobj, + def, rela->r_addend); + if (tmp == (Elf_Addr)-1) + return -1; + + if (*where != tmp) + *where = tmp; + rdbg(("PLABEL32 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + } else { + /* + * This is a PLABEL for a static function, and + * the dynamic linker has both allocated a PLT + * entry for this function and told us where it + * is. We can safely use the PLT entry as the + * PLABEL because there should be no other + * PLABEL reloc referencing this function. + * This object should also have an IPLT + * relocation to initialize the PLT entry. + * + * The dynamic linker should also have ensured + * that the addend has the + * next-least-significant bit set; the + * $$dyncall millicode uses this to distinguish + * a PLABEL pointer from a plain function + * pointer. + */ + tmp = (Elf_Addr) + (obj->relocbase + rela->r_addend); + + if (*where != tmp) + *where = tmp; + rdbg(("PLABEL32 in %s --> %p", obj->path, + (void *)*where)); + } + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + if (obj->isdynamic) { + _rtld_error( + "%s: Unexpected R_COPY relocation in shared library", + obj->path); + return -1; + } + rdbg(("COPY (avoid in main)")); + break; + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "addend = %p, contents = %p, symbol = %s", + symnum, (u_long)ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)rela->r_addend, + (void *)load_ptr(where), + obj->strtab + obj->symtab[symnum].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rela->r_info)); + return -1; + } + } + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + Elf_Addr func_pc, func_sl; + + assert(ELF_R_TYPE(rela->r_info) == R_TYPE(IPLT)); + + /* + * If this is an IPLT reloc for a static function, + * fully resolve the PLT entry now. + */ + if (ELF_R_SYM(rela->r_info) == 0) { + func_pc = (Elf_Addr)(obj->relocbase + rela->r_addend); + func_sl = (Elf_Addr)(obj->pltgot); + } + + /* + * Otherwise set up for lazy binding. + */ + else { + /* + * This function pointer points to the PLT + * stub added by the linker, and instead of + * a shared linkage value, we stash this + * relocation's offset. The PLT stub has + * already been set up to transfer to + * _rtld_bind_start. + */ + func_pc = ((Elf_Addr)(obj->pltgot)) - 16; + func_sl = (Elf_Addr) + ((const char *)rela - (const char *)(obj->pltrela)); + } + rdbg(("lazy bind %s(%p) --> old=(%p,%p) new=(%p,%p)", + obj->path, + (void *)where, + (void *)where[0], (void *)where[1], + (void *)func_pc, (void *)func_sl)); + + /* + * Fill this PLT entry and return. + */ + where[0] = func_pc; + where[1] = func_sl; + } + return 0; +} + +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, + Elf_Addr *tp) +{ + Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset); + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr func_pc, func_sl; + unsigned long info = rela->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(IPLT)); + + if (ELF_R_SYM(info) == 0) { + func_pc = (Elf_Addr)(obj->relocbase + rela->r_addend); + func_sl = (Elf_Addr)(obj->pltgot); + } else { + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, + tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + func_pc = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + func_sl = (Elf_Addr)(defobj->pltgot); + + rdbg(("bind now/fixup in %s --> old=(%p,%p) new=(%p,%p)", + defobj->strtab + def->st_name, + (void *)where[0], (void *)where[1], + (void *)func_pc, (void *)func_sl)); + } + /* + * Fill this PLT entry and return. + */ + if (where[0] != func_pc) + where[0] = func_pc; + if (where[1] != func_sl) + where[1] = func_sl; + + if (tp) + *tp = (Elf_Addr)where; + + return 0; +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rela *rela; + Elf_Addr new_value = 0; /* XXX gcc */ + int err; + + rela = (const Elf_Rela *)((const char *)obj->pltrela + reloff); + + assert(ELF_R_SYM(rela->r_info) != 0); + + err = _rtld_relocate_plt_object(obj, rela, &new_value); + if (err) + _rtld_die(); + + return (caddr_t)new_value; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rela *rela = obj->pltrela; + + for (; rela < obj->pltrelalim; rela++) { + if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) + return -1; + } + return 0; +} diff --git a/libexec/ld.elf_so/arch/hppa/rtld_start.S b/libexec/ld.elf_so/arch/hppa/rtld_start.S new file mode 100644 index 000000000..ce2f229e3 --- /dev/null +++ b/libexec/ld.elf_so/arch/hppa/rtld_start.S @@ -0,0 +1,231 @@ +/* $NetBSD: rtld_start.S,v 1.9 2010/09/30 19:32:40 skrll Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Fredette. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + + .import _GLOBAL_OFFSET_TABLE_ + +ENTRY($rtld_start,HPPA_FRAME_SIZE) + + /* Start stack calling convention. */ + copy %r3, %r1 + copy %sp, %r3 + stw,ma %r1, HPPA_FRAME_SIZE(%sp) + + /* + * Save our single argument, the ps_strings pointer. We'll need this + * twice later: once to call _rtld, and again to transfer to the + * program's entry point. + */ + stw %arg0, HPPA_FRAME_ARG(0)(%r3) + + /* + * We can't move to C until we relocate at least the + * Global Offset Table. Even finding the GOT is tricky + * without inadvertently causing the linker to make + * relocations for this part of the text segment. + */ + + bl L$lpc1, %r19 + depi 0, 31, 2, %r19 +L$lpc1: addil L'_DYNAMIC - ($PIC_pcrel$0 - 8), %r19 + ldo R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%r1),%arg0 + + /* + * Load the absolute address of the beginning of the GOT into %r19, the + * shared library linkage table register, leaving it ready-to-use by + * the dynamic linker C code. + */ + addil L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16), %r19 + ldo R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%r1),%r19 + + /* + * The linker sets the first entry in the GOT to the unrelocated + * address of _DYNAMIC. Subtract this from the absolute address of + * _DYNAMIC to get our relocbase. + */ + ldw 0(%r19), %arg1 + sub %arg0, %arg1, %arg1 ; %arg1 = relocbase + bl _rtld_relocate_nonplt_self, %rp + copy %arg1, %r4 ; save for later + + /* + * Recover the ps_strings pointer, and take out the + * ps_argvstr member. + */ + ldw HPPA_FRAME_ARG(0)(%r3), %arg0 ; ps_strings + ldw 0(%arg0), %arg0 ; ps_argvstr member first in struct + + /* + * ps_argvstr - 4 would get us a pointer to argc, comparable to the + * initial stack pointer on architectures where the stack grows down. + * Subtracting an additional eight creates the storage for obj and + * cleanup that _rtld needs. + */ + ldo -12(%arg0), %arg0 + stw %arg0, HPPA_FRAME_ARG(1)(%r3) + + /* Call _rtld, copying relocbase into arg1. */ + bl _rtld, %rp + copy %r4, %arg1 ; %arg1 = relocbase + + /* Prepare the arguments for the entry point. */ + ldw HPPA_FRAME_ARG(1)(%r3), %r1 + ldw HPPA_FRAME_ARG(0)(%r3), %arg0 ; ps_strings + ldw 0(%r1), %arg1 ; cleanup + ldw 4(%r1), %arg2 ; obj + + /* End stack calling convention. */ + ldo HPPA_FRAME_SIZE(%r3), %sp + ldw,mb -HPPA_FRAME_SIZE(%sp), %r3 + + /* Go for it. */ + bv %r0(%ret0) + copy %r0, %rp +EXIT($rtld_start) + +/* + * This does our setup for an object's GOT. %arg0 is the Obj_Entry * for the + * object, and %arg1 is its GOT pointer. + */ +LEAF_ENTRY(__rtld_setup_hppa_pltgot) + + /* + * The second entry of the GOT is reserved for the dynamic linker. We + * put the Obj_Entry * for the object in there. + */ + stw %arg0, 4(%arg1) + + /* + * Fill the fixup_func and fixup_ltp members of the PLT stub. This + * stub is inserted by the linker immediately before the GOT. We use + * this stub to enter our binder. + */ + + bl L$lpc2, %arg0 + depi 0, 31, 2, %arg0 +L$lpc2: addil L'_rtld_bind_start - ($PIC_pcrel$0 - 8), %arg0 + ldo R'_rtld_bind_start - ($PIC_pcrel$0 - 12)(%r1),%arg0 + + stw %arg0, -8(%arg1) + bv %r0(%rp) + stw %r19, -4(%arg1) +EXIT(__rtld_hppa_setup_pltgot) + +/* + * In order to support lazy binding, this implementation of _rtld_bind_start is + * very closely tied to the shared-library call stub and the PLT stub, both + * inserted by the linker. + */ + +/* + * This is a magic branch instruction that is used by GCC's + * __canonicalize_funcptr_for_compare() function to fixup relocations + * in order to do function pointer comparisons. + */ + + bl _rtld_bind, %rp + +ENTRY(_rtld_bind_start,HPPA_FRAME_SIZE) + + /* Start stack calling convention. */ + copy %r3, %r1 + copy %sp, %r3 + + stw,ma %r1, HPPA_FRAME_SIZE(%sp) + + /* + * We have to save all calling convention registers that are set by the + * caller, because we have to restore them before transferring to the + * bound function. Note that this includes %ret0, %ret1, and %t1. + * + * %ret0 and %ret1 because they can have meaning on entry to a + * function. + * + * %t1 because it's used by libc to pass on errno values to cerror. + */ + stw %rp, HPPA_FRAME_CRP(%r3) + stw %arg0, HPPA_FRAME_ARG(0)(%r3) + stw %arg1, HPPA_FRAME_ARG(1)(%r3) + stw %arg2, HPPA_FRAME_ARG(2)(%r3) + stw %arg3, HPPA_FRAME_ARG(3)(%r3) + /* 0(%r3) is filled with the saved %r3 above */ + stw %ret0, 4(%r3) + stw %ret1, 8(%r3) + + /* + * The linker PLT stub loads %r20 with (GOT - 8) for the object that + * needs binding done. The second entry of the GOT is reserved for the + * dynamic linker's use, and we previously stashed the object's + * Obj_Entry * there. + */ + ldw 12(%r20), %arg0 + + /* + * The linker shared-library call stub loads %r19 from the shared + * linkage member of the PLT entry. We previously stashed the reloff + * of the relocation there. + */ + copy %r19, %arg1 + + /* + * The linker PLT stub loads %r21 with the fixup_ltp word in itself. + * We previously stashed our %r19 value there. + */ + bl _rtld_bind, %rp + copy %r21, %r19 + + /* + * Our hppa version of _rtld_bind returns to us the address of the PLT + * entry that it fixed up. Load the function address and shared + * linkage for the newly bound function. + */ + ldw 0(%ret0), %r21 + ldw 4(%ret0), %r19 + + /* Restore registers saved above. */ + ldw HPPA_FRAME_CRP(%r3), %rp + ldw HPPA_FRAME_ARG(0)(%r3), %arg0 + ldw HPPA_FRAME_ARG(1)(%r3), %arg1 + ldw HPPA_FRAME_ARG(2)(%r3), %arg2 + ldw HPPA_FRAME_ARG(3)(%r3), %arg3 + ldw 4(%r3), %ret0 + ldw 8(%r3), %ret1 + + /* End stack calling convention. */ + ldo HPPA_FRAME_SIZE(%r3), %sp + ldw,mb -HPPA_FRAME_SIZE(%sp), %r3 + + /* Transfer to the function. */ + bv %r0(%r21) + nop +EXIT(_rtld_bind_start) diff --git a/libexec/ld.elf_so/arch/i386/Makefile.inc b/libexec/ld.elf_so/arch/i386/Makefile.inc new file mode 100644 index 000000000..14cbaedf5 --- /dev/null +++ b/libexec/ld.elf_so/arch/i386/Makefile.inc @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.14 2009/12/13 09:31:47 mrg Exp $ + +SRCS+= rtld_start.S mdreloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic + +CPPFLAGS+= -DELFSIZE=32 + +LDFLAGS+= -Wl,-e,.rtld_start diff --git a/libexec/ld.elf_so/arch/i386/mdreloc.c b/libexec/ld.elf_so/arch/i386/mdreloc.c new file mode 100644 index 000000000..b1657c682 --- /dev/null +++ b/libexec/ld.elf_so/arch/i386/mdreloc.c @@ -0,0 +1,216 @@ +/* $NetBSD: mdreloc.c,v 1.32 2010/08/06 16:33:18 joerg Exp $ */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.32 2010/08/06 16:33:18 joerg Exp $"); +#endif /* not lint */ + +#include + +#include "debug.h" +#include "rtld.h" + +void _rtld_bind_start(void); +void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); +caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); + +void +_rtld_setup_pltgot(const Obj_Entry *obj) +{ + obj->pltgot[1] = (Elf_Addr) obj; + obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; +} + +void +_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rel *rel = 0, *rellim; + Elf_Addr relsz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_REL: + rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELSZ: + relsz = dynp->d_un.d_val; + break; + } + } + if (rel == 0 || relsz == 0) + return; + rellim = (const Elf_Rel *)((const uint8_t *)rel + relsz); + for (; rel < rellim; rel++) { + where = (Elf_Addr *)(relocbase + rel->r_offset); + *where += (Elf_Addr)relocbase; + } +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rel *rel; + Elf_Addr target = 0; + + for (rel = obj->rel; rel < obj->rellim; rel++) { + Elf_Addr *where; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr tmp; + unsigned long symnum; + + where = (Elf_Addr *)(obj->relocbase + rel->r_offset); + symnum = ELF_R_SYM(rel->r_info); + + switch (ELF_R_TYPE(rel->r_info)) { + case R_TYPE(NONE): + break; + +#if 1 /* XXX should not occur */ + case R_TYPE(PC32): + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + target = (Elf_Addr)(defobj->relocbase + def->st_value); + + *where += target - (Elf_Addr)where; + rdbg(("PC32 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; + + case R_TYPE(GOT32): +#endif + case R_TYPE(32): + case R_TYPE(GLOB_DAT): + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + target = (Elf_Addr)(defobj->relocbase + def->st_value); + + tmp = target + *where; + if (*where != tmp) + *where = tmp; + rdbg(("32/GLOB_DAT %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; + + case R_TYPE(RELATIVE): + *where += (Elf_Addr)obj->relocbase; + rdbg(("RELATIVE in %s --> %p", obj->path, + (void *)*where)); + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + if (obj->isdynamic) { + _rtld_error( + "%s: Unexpected R_COPY relocation in shared library", + obj->path); + return -1; + } + rdbg(("COPY (avoid in main)")); + break; + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "contents = %p, symbol = %s", + symnum, (u_long)ELF_R_TYPE(rel->r_info), + (void *)rel->r_offset, (void *)*where, + obj->strtab + obj->symtab[symnum].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rel->r_info)); + return -1; + } + } + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + const Elf_Rel *rel; + + if (!obj->relocbase) + return 0; + + for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); + + assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JMP_SLOT)); + + /* Just relocate the GOT slots pointing into the PLT */ + *where += (Elf_Addr)obj->relocbase; + rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); + } + + return 0; +} + +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel, + Elf_Addr *tp) +{ + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); + Elf_Addr target; + const Elf_Sym *def; + const Obj_Entry *defobj; + unsigned long info = rel->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + target = (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(("bind now/fixup in %s --> old=%p new=%p", + defobj->strtab + def->st_name, (void *)*where, + (void *)target)); + if (*where != target) + *where = target; + if (tp) + *tp = target; + return 0; +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rel *rel = (const Elf_Rel *)((const uint8_t *)obj->pltrel + + reloff); + Elf_Addr new_value; + int err; + + new_value = 0; /* XXX gcc */ + + err = _rtld_relocate_plt_object(obj, rel, &new_value); + if (err) + _rtld_die(); + + return (caddr_t)new_value; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rel *rel; + int err = 0; + + for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { + err = _rtld_relocate_plt_object(obj, rel, NULL); + if (err) + break; + } + return err; +} diff --git a/libexec/ld.elf_so/arch/i386/rtld_start.S b/libexec/ld.elf_so/arch/i386/rtld_start.S new file mode 100644 index 000000000..211649ff2 --- /dev/null +++ b/libexec/ld.elf_so/arch/i386/rtld_start.S @@ -0,0 +1,88 @@ +/* $NetBSD: rtld_start.S,v 1.11 2010/12/05 00:56:07 joerg Exp $ */ + +/*- + * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas and by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + .text + .align 4 + .globl .rtld_start + .hidden .rtld_start + .type .rtld_start,@function +.rtld_start: + subl $8,%esp # make room of obj_main and exit proc + pushl %ebx # save ps_strings + + call 1f +1: + popl %edx + leal _DYNAMIC-1b(%edx),%ecx # &_DYNAMIC + movl %ecx,%ebx + subl _GLOBAL_OFFSET_TABLE_-1b(%edx),%ebx + + pushl %ebx # relocbase + pushl %ecx # &_DYNAMIC + call _rtld_relocate_nonplt_self + + leal 12(%esp),%eax # &cleanup + pushl %ebx # relocbase + pushl %eax # sp + call _rtld # _rtld(sp, relocbase) + + addl $16,%esp # pop args + + popl %ebx # %ebx = ps_strings + popl %edx # %edx = cleanup + popl %ecx # %ecx = obj_main + jmp *%eax + + .align 4 + .globl _rtld_bind_start + .hidden _rtld_bind_start + .type _rtld_bind_start,@function +_rtld_bind_start: # (obj, reloff) + pushf # save registers + pushl %eax + pushl %ecx + pushl %edx + + pushl 20(%esp) # Copy of reloff + pushl 20(%esp) # Copy of obj + call _rtld_bind # Call the binder + addl $8,%esp # pop binder args + movl %eax,20(%esp) # Store function to be called in obj + + popl %edx + popl %ecx + popl %eax + popf + + leal 4(%esp),%esp # Discard reloff, do not change eflags + ret diff --git a/libexec/ld.elf_so/arch/m68k/Makefile.inc b/libexec/ld.elf_so/arch/m68k/Makefile.inc new file mode 100644 index 000000000..42257cefb --- /dev/null +++ b/libexec/ld.elf_so/arch/m68k/Makefile.inc @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.10 2005/06/04 16:17:17 lukem Exp $ + +SRCS+= rtld_start.S mdreloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic + +CPPFLAGS+= -DELFSIZE=32 + +LDFLAGS+= -Wl,-e,.rtld_start diff --git a/libexec/ld.elf_so/arch/m68k/mdreloc.c b/libexec/ld.elf_so/arch/m68k/mdreloc.c new file mode 100644 index 000000000..ea18f0330 --- /dev/null +++ b/libexec/ld.elf_so/arch/m68k/mdreloc.c @@ -0,0 +1,224 @@ +/* $NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:18 joerg Exp $ */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:18 joerg Exp $"); +#endif /* not lint */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:18 joerg Exp $"); +#endif /* not lint */ + +#include + +#include "debug.h" +#include "rtld.h" + +void _rtld_bind_start(void); +void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); +caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); +static inline int _rtld_relocate_plt_object(const Obj_Entry *, + const Elf_Rela *, Elf_Addr *); + + +void +_rtld_setup_pltgot(const Obj_Entry *obj) +{ + obj->pltgot[1] = (Elf_Addr) obj; + obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; +} + +void +_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rela *rela = 0, *relalim; + Elf_Addr relasz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_RELA: + rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + } + } + relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); + for (; rela < relalim; rela++) { + where = (Elf_Addr *)(relocbase + rela->r_offset); + *where += (Elf_Addr)relocbase; + } +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->rela; rela < obj->relalim; rela++) { + Elf_Addr *where; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr tmp; + unsigned long symnum; + + where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + symnum = ELF_R_SYM(rela->r_info); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(NONE): + break; + +#if 1 /* XXX should not occur */ + case R_TYPE(PC32): + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend) - (Elf_Addr)where; + if (*where != tmp) + *where = tmp; + rdbg(("PC32 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; + + case R_TYPE(GOT32): +#endif + case R_TYPE(32): + case R_TYPE(GLOB_DAT): + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + if (*where != tmp) + *where = tmp; + rdbg(("32/GLOB_DAT %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; + + case R_TYPE(RELATIVE): + *where += (Elf_Addr)obj->relocbase; + rdbg(("RELATIVE in %s --> %p", obj->path, + (void *)*where)); + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + if (obj->isdynamic) { + _rtld_error( + "%s: Unexpected R_COPY relocation in shared library", + obj->path); + return -1; + } + rdbg(("COPY (avoid in main)")); + break; + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "addend = %p, contents = %p, symbol = %s", + symnum, (u_long)ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)rela->r_addend, + (void *)*where, + obj->strtab + obj->symtab[symnum].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rela->r_info)); + return -1; + } + } + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + if (!obj->relocbase) + return 0; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + + assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); + + /* Just relocate the GOT slots pointing into the PLT */ + *where += (Elf_Addr)obj->relocbase; + rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); + } + + return 0; +} + +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, + Elf_Addr *tp) +{ + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + Elf_Addr new_value; + const Elf_Sym *def; + const Obj_Entry *defobj; + unsigned long info = rela->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + assert(rela->r_addend == 0); + new_value = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + rdbg(("bind now/fixup in %s --> old=%p new=%p", + defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); + if (*where != new_value) + *where = new_value; + + if (tp) + *tp = new_value - rela->r_addend; + + return 0; +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff); + Elf_Addr result; + int err; + + result = 0; /* XXX gcc */ + + err = _rtld_relocate_plt_object(obj, rela, &result); + if (err) + _rtld_die(); + + return (caddr_t)result; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) + if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) + return -1; + + return 0; +} diff --git a/libexec/ld.elf_so/arch/m68k/rtld_start.S b/libexec/ld.elf_so/arch/m68k/rtld_start.S new file mode 100644 index 000000000..d6e6549cf --- /dev/null +++ b/libexec/ld.elf_so/arch/m68k/rtld_start.S @@ -0,0 +1,79 @@ +/* $NetBSD: rtld_start.S,v 1.9 2008/04/28 20:23:03 martin Exp $ */ + +/*- + * Copyright (c) 1999, 2002, 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein and by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + .text + .align 4 + .globl .rtld_start + .type .rtld_start,@function +.rtld_start: + subql #8,%sp | storage for obj and cleanup + + lea (%pc,_GLOBAL_OFFSET_TABLE_@GOTPC),%a0 + lea (%pc,_DYNAMIC),%a1 + movel %a1,%a5 + subl (%a0),%a5 + + movel %a5,-(%sp) | relocbase + movel %a1,-(%sp) | &_DYNAMIC + jbsr _rtld_relocate_nonplt_self@PLTPC + addql #8,%sp | pop arguments + + movel %a5,-(%sp) | relocbase + pea 4(%sp) | sp + jbsr _rtld@PLTPC | entry = _rtld(sp, relocbase) + addql #8,%sp | pop arguments + + moveal (%sp)+,%a1 | cleanup + moveal (%sp)+,%a0 | obj + moveal %d0,%a3 + jmp (%a3) | Go for it! + .size .rtld_start,.-.rtld_start + + .align 4 + .globl _rtld_bind_start + .type _rtld_bind_start,@function +_rtld_bind_start: + moveml %d0-%d1/%a0-%a1,-(%sp) | preserve caller-saved registers + movel 20(%sp),-(%sp) | push reloff + movel (16+4)(%sp),-(%sp) | push obj + jbsr _rtld_bind@PLTPC | %a0 = _rtld_bind(obj, reloff) + addql #8,%sp | pop args +#ifdef __SVR4_ABI__ + movel %a0,(16+4)(%sp) | write fake `return' address over obj +#else + movel %d0,(16+4)(%sp) | write fake `return' address over obj +#endif + moveml (%sp)+,%d0-%d1/%a0-%a1 | restore caller-saved registers + addql #4,%sp | skip reloff + rts | `return' right into function + .size _rtld_bind_start,.-_rtld_bind_start diff --git a/libexec/ld.elf_so/arch/mips/Makefile.inc b/libexec/ld.elf_so/arch/mips/Makefile.inc new file mode 100644 index 000000000..d5169f924 --- /dev/null +++ b/libexec/ld.elf_so/arch/mips/Makefile.inc @@ -0,0 +1,17 @@ +# $NetBSD: Makefile.inc,v 1.19 2010/07/11 07:43:12 mrg Exp $ + +SRCS+= rtld_start.S mips_reloc.c + +COPTS+= -G0 + +ABI64?= ${CFLAGS:M-mabi=64} ${CPPFLAGS:M-mabi=64} ${COPTS:M-mabi=64} +ABIO64?= ${CFLAGS:M-mabi=o64} ${CPPFLAGS:M-mabi=o64} ${COPTS:M-mabi=o64} +.if !empty(ABI64) || !empty(ABIO64) +CPPFLAGS+= -DELFSIZE=64 +.else +CPPFLAGS+= -DELFSIZE=32 +.endif +CPPFLAGS+= -DRTLD_INHIBIT_COPY_RELOCS +AFLAGS+= -Wa,--fatal-warnings + +LDFLAGS+= -Wl,-e,rtld_start diff --git a/libexec/ld.elf_so/arch/mips/mips_reloc.c b/libexec/ld.elf_so/arch/mips/mips_reloc.c new file mode 100644 index 000000000..a77e5a923 --- /dev/null +++ b/libexec/ld.elf_so/arch/mips/mips_reloc.c @@ -0,0 +1,454 @@ +/* $NetBSD: mips_reloc.c,v 1.60 2010/09/24 15:20:52 matt Exp $ */ + +/* + * Copyright 1997 Michael L. Hitch + * Portions copyright 2002 Charles M. Hannum + * 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 +#ifndef lint +__RCSID("$NetBSD: mips_reloc.c,v 1.60 2010/09/24 15:20:52 matt Exp $"); +#endif /* not lint */ + +#include +#include + +#include +#include + +#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 ", + where, (void *)old, (void *)val)); + store_ptr(where, val, rlen); + break; + } + + case R_TYPE(GPREL32): + case R_TYPE(NONE): + break; + + + default: + abort(); + } + } +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rel *rel; + Elf_Addr *got = obj->pltgot; + const Elf_Sym *sym, *def; + const Obj_Entry *defobj; + Elf_Word i; +#ifdef SUPPORT_OLD_BROKEN_LD + int broken; +#endif + +#ifdef SUPPORT_OLD_BROKEN_LD + broken = 0; + sym = obj->symtab; + for (i = 1; i < 12; i++) + if (sym[i].st_info == ELF_ST_INFO(STB_LOCAL, STT_NOTYPE)) + broken = 1; + dbg(("%s: broken=%d", obj->path, broken)); +#endif + + i = (got[1] & 0x80000000) ? 2 : 1; + /* Relocate the local GOT entries */ + got += i; + for (; i < obj->local_gotno; i++) + *got++ += (Elf_Addr)obj->relocbase; + sym = obj->symtab + obj->gotsym; + /* Now do the global GOT entries */ + for (i = obj->gotsym; i < obj->symtabno; i++) { + rdbg((" doing got %d sym %p (%s, %lx)", i - obj->gotsym, sym, + sym->st_name + obj->strtab, (u_long) *got)); + +#ifdef SUPPORT_OLD_BROKEN_LD + if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && + broken && sym->st_shndx == SHN_UNDEF) { + /* + * XXX DANGER WILL ROBINSON! + * You might think this is stupid, as it intentionally + * defeats lazy binding -- and you'd be right. + * Unfortunately, for lazy binding to work right, we + * need to a way to force the GOT slots used for + * function pointers to be resolved immediately. This + * is supposed to be done automatically by the linker, + * by not outputting a PLT slot and setting st_value + * to 0 if there are non-PLT references, but older + * versions of GNU ld do not do this. + */ + def = _rtld_find_symdef(i, obj, &defobj, false); + if (def == NULL) + return -1; + *got = def->st_value + (Elf_Addr)defobj->relocbase; + } else +#endif + if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && + sym->st_value != 0 && sym->st_shndx == SHN_UNDEF) { + /* + * If there are non-PLT references to the function, + * st_value should be 0, forcing us to resolve the + * address immediately. + * + * XXX DANGER WILL ROBINSON! + * The linker is not outputting PLT slots for calls to + * functions that are defined in the same shared + * library. This is a bug, because it can screw up + * link ordering rules if the symbol is defined in + * more than one module. For now, if there is a + * definition, we fail the test above and force a full + * symbol lookup. This means that all intra-module + * calls are bound immediately. - mycroft, 2003/09/24 + */ + *got = sym->st_value + (Elf_Addr)obj->relocbase; + } else if (sym->st_info == ELF_ST_INFO(STB_GLOBAL, STT_SECTION)) { + /* Symbols with index SHN_ABS are not relocated. */ + if (sym->st_shndx != SHN_ABS) + *got = sym->st_value + + (Elf_Addr)obj->relocbase; + } else { + def = _rtld_find_symdef(i, obj, &defobj, false); + if (def == NULL) + return -1; + *got = def->st_value + (Elf_Addr)defobj->relocbase; + } + + rdbg((" --> now %lx", (u_long) *got)); + ++sym; + ++got; + } + + got = obj->pltgot; + for (rel = obj->rel; rel < obj->rellim; rel++) { + Elf_Word r_symndx, r_type; + void *where; + + where = obj->relocbase + rel->r_offset; + r_symndx = ELF_R_SYM(rel->r_info); + r_type = ELF_R_TYPE(rel->r_info); + + switch (r_type & 0xff) { + case R_TYPE(NONE): + break; + + case R_TYPE(REL32): { + /* 32-bit PC-relative reference */ + const size_t rlen = + ELF_R_NXTTYPE_64_P(r_type) + ? sizeof(Elf_Sxword) + : sizeof(Elf_Sword); + Elf_Sxword old = load_ptr(where, rlen); + Elf_Sxword val = old; + + def = obj->symtab + r_symndx; + + if (r_symndx >= obj->gotsym) { + val += got[obj->local_gotno + r_symndx - obj->gotsym]; + rdbg(("REL32/G(%p) %p --> %p (%s) in %s", + where, (void *)old, (void *)val, + obj->strtab + def->st_name, + obj->path)); + } else { + /* + * XXX: ABI DIFFERENCE! + * + * Old NetBSD binutils would generate shared + * libs with section-relative relocations being + * already adjusted for the start address of + * the section. + * + * New binutils, OTOH, generate shared libs + * with the same relocations being based at + * zero, so we need to add in the start address + * of the section. + * + * --rkb, Oct 6, 2001 + */ + + if (def->st_info == + ELF_ST_INFO(STB_LOCAL, STT_SECTION) +#ifdef SUPPORT_OLD_BROKEN_LD + && !broken +#endif + ) + val += (Elf_Addr)def->st_value; + + val += (Elf_Addr)obj->relocbase; + + rdbg(("REL32/L(%p) %p -> %p (%s) in %s", + where, (void *)old, (void *)val, + obj->strtab + def->st_name, obj->path)); + } + store_ptr(where, val, rlen); + break; + } + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "contents = %p, symbol = %s", + (u_long)r_symndx, (u_long)ELF_R_TYPE(rel->r_info), + (void *)rel->r_offset, + (void *)load_ptr(where, sizeof(Elf_Sword)), + obj->strtab + obj->symtab[r_symndx].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rel->r_info)); + return -1; + } + } + + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + /* PLT fixups were done above in the GOT relocation. */ + return 0; +} + +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, Elf_Word sym, Elf_Addr *tp) +{ + Elf_Addr *got = obj->pltgot; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr new_value; + + def = _rtld_find_plt_symdef(sym, obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(("bind now/fixup in %s --> new=%p", + defobj->strtab + def->st_name, (void *)new_value)); + got[obj->local_gotno + sym - obj->gotsym] = new_value; + + if (tp) + *tp = new_value; + return 0; +} + +caddr_t +_rtld_bind(Elf_Word a0, Elf_Addr a1, Elf_Addr a2, Elf_Addr a3) +{ + Elf_Addr *got = (Elf_Addr *)(a2 - 0x7ff0); + const Obj_Entry *obj = (Obj_Entry *)(got[1] & GOT1_MASK); + Elf_Addr new_value = 0; /* XXX gcc */ + int err; + + err = _rtld_relocate_plt_object(obj, a0, &new_value); + if (err) + _rtld_die(); + + return (caddr_t)new_value; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Sym *sym = obj->symtab + obj->gotsym; + Elf_Word i; + + for (i = obj->gotsym; i < obj->symtabno; i++, sym++) { + if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) + if (_rtld_relocate_plt_object(obj, i, NULL) < 0) + return -1; + } + + return 0; +} diff --git a/libexec/ld.elf_so/arch/mips/rtld_start.S b/libexec/ld.elf_so/arch/mips/rtld_start.S new file mode 100644 index 000000000..e7de1961a --- /dev/null +++ b/libexec/ld.elf_so/arch/mips/rtld_start.S @@ -0,0 +1,140 @@ +/* $NetBSD: rtld_start.S,v 1.10 2009/12/14 00:41:19 matt Exp $ */ + +/* + * Copyright 1997 Michael L. Hitch + * Portions copyright 2002 Charles M. Hannum + * 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 + +.globl _C_LABEL(_rtld_relocate_nonplt_self) +.globl _C_LABEL(_rtld) + +#define PTR_SIZE (1< 1*PTR_SIZE(sp) for atexit + # -> 2*PTR_SIZE(sp) for obj_main + move s0, a0 # save stack pointer from a0 + move s3, a3 # save ps_strings pointer + + PTR_LA a1, 1f + bal 1f + PTR_LA t0, _C_LABEL(_rtld_relocate_nonplt_self) +1: PTR_SUBU a1, ra, a1 # relocbase + move s2, a1 # save for _rtld + PTR_LA a0, _DYNAMIC + PTR_ADDU t9, a1, t0 + jalr t9 # _rtld_relocate_nonplt_self(dynp, relocabase) + PTR_ADDU a0, a1, a0 # &_DYNAMIC + + move a1, s2 # relocbase + PTR_ADDU a0, sp, 2*PTR_SIZE # sp + jal _C_LABEL(_rtld) # v0 = _rtld(sp, relocbase) + nop + + PTR_L a1, 2*PTR_SIZE(sp) # our atexit function + PTR_L a2, 3*PTR_SIZE(sp) # obj_main entry + PTR_ADDU sp, 4*PTR_SIZE # readjust stack + move a0, s0 # stack pointer + move t9, v0 + jr t9 # _start(sp, cleanup, obj); + move a3, s3 # restore ps_strings + +END(rtld_start) + +#define XCALLFRAME_SIZ (12*SZREG) +#define XCALLFRAME_RA (10*SZREG) +#define XCALLFRAME_GP (9*SZREG) +#define XCALLFRAME_S0 (8*SZREG) +#define XCALLFRAME_A3 (7*SZREG) +#define XCALLFRAME_A2 (6*SZREG) +#define XCALLFRAME_A1 (5*SZREG) +#define XCALLFRAME_A0 (4*SZREG) +#if defined(__mips_n32) || defined(__mips_n64) +#define XCALLFRAME_A7 (3*SZREG) +#define XCALLFRAME_A6 (2*SZREG) +#define XCALLFRAME_A5 (1*SZREG) +#define XCALLFRAME_A4 (0*SZREG) +#endif + + .globl _rtld_bind_start + .ent _rtld_bind_start +_rtld_bind_start: + .frame sp, XCALLFRAME_SIZ, $15 + move v1, gp # save old GP +#if defined(__mips_o32) || defined(__mips_o64) + PTR_ADDU t9, 8 # modify T9 to point at .cpload +#endif + SETUP_GP + PTR_SUBU sp, XCALLFRAME_SIZ # save arguments and sp value in stack + SETUP_GP64(XCALLFRAME_GP, _rtld_bind_start) + SAVE_GP(XCALLFRAME_GP) +#if defined(__mips_n32) || defined(__mips_n64) + REG_S a4, XCALLFRAME_A4(sp) + REG_S a5, XCALLFRAME_A5(sp) + REG_S a6, XCALLFRAME_A6(sp) + REG_S a7, XCALLFRAME_A7(sp) +#endif + REG_S a0, XCALLFRAME_A0(sp) + REG_S a1, XCALLFRAME_A1(sp) + REG_S a2, XCALLFRAME_A2(sp) + REG_S a3, XCALLFRAME_A3(sp) + REG_S $15, XCALLFRAME_RA(sp) # ra is in t7/t3 + REG_S s0, XCALLFRAME_S0(sp) + move s0, sp + move a0, t8 # symbol index + move a1, $15 # old RA + move a2, v1 # old GP + move a3, ra # current RA + jal _C_LABEL(_rtld_bind) + nop + move sp, s0 + REG_L ra, XCALLFRAME_RA(sp) + REG_L s0, XCALLFRAME_S0(sp) + REG_L a0, XCALLFRAME_A0(sp) + REG_L a1, XCALLFRAME_A1(sp) + REG_L a2, XCALLFRAME_A2(sp) + REG_L a3, XCALLFRAME_A3(sp) +#if defined(__mips_n32) || defined(__mips_n64) + REG_L a4, XCALLFRAME_A4(sp) + REG_L a5, XCALLFRAME_A5(sp) + REG_L a6, XCALLFRAME_A6(sp) + REG_L a7, XCALLFRAME_A7(sp) +#endif + RESTORE_GP64 + PTR_ADDU sp, XCALLFRAME_SIZ + move t9, v0 + jr t9 + nop +END(_rtld_bind_start) diff --git a/libexec/ld.elf_so/arch/powerpc/Makefile.inc b/libexec/ld.elf_so/arch/powerpc/Makefile.inc new file mode 100644 index 000000000..49264ea75 --- /dev/null +++ b/libexec/ld.elf_so/arch/powerpc/Makefile.inc @@ -0,0 +1,11 @@ +# $NetBSD: Makefile.inc,v 1.11 2009/10/22 21:56:13 skrll Exp $ + +SRCS+= rtld_start.S ppc_reloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic -msoft-float + +CPPFLAGS+= -DELFSIZE=32 + +LDFLAGS+= -Wl,-e,_rtld_start +LDFLAGS+= -Wl,--script,${.CURDIR}/arch/powerpc/ld.so.script diff --git a/libexec/ld.elf_so/arch/powerpc/ld.so.script b/libexec/ld.elf_so/arch/powerpc/ld.so.script new file mode 100644 index 000000000..0ca2300f7 --- /dev/null +++ b/libexec/ld.elf_so/arch/powerpc/ld.so.script @@ -0,0 +1,271 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc) +ENTRY(_start) +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +PROVIDE (__stack = 0); PROVIDE (___stack = 0); +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0 + SIZEOF_HEADERS; + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : + { + *(.rel.text) + *(.rel.text.*) + *(.rel.gnu.linkonce.t.*) + } + .rela.text : + { + *(.rela.text) + *(.rela.text.*) + *(.rela.gnu.linkonce.t.*) + } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : + { + *(.rel.rodata) + *(.rel.rodata.*) + *(.rel.gnu.linkonce.r.*) + } + .rela.rodata : + { + *(.rela.rodata) + *(.rela.rodata.*) + *(.rela.gnu.linkonce.r.*) + } + .rel.data : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.gnu.linkonce.d.*) + } + .rela.data : + { + *(.rela.data) + *(.rela.data.*) + *(.rela.gnu.linkonce.d.*) + } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.sdata : + { + *(.rel.sdata) + *(.rel.sdata.*) + *(.rel.gnu.linkonce.s.*) + } + .rela.sdata : + { + *(.rela.sdata) + *(.rela.sdata.*) + *(.rela.gnu.linkonce.s.*) + } + .rel.sbss : + { + *(.rel.sbss) + *(.rel.sbss.*) + *(.rel.gnu.linkonce.sb.*) + } + .rela.sbss : + { + *(.rela.sbss) + *(.rela.sbss.*) + *(.rel.gnu.linkonce.sb.*) + } + .rel.sdata2 : + { + *(.rel.sdata2) + *(.rel.sdata2.*) + *(.rel.gnu.linkonce.s2.*) + } + .rela.sdata2 : + { + *(.rela.sdata2) + *(.rela.sdata2.*) + *(.rela.gnu.linkonce.s2.*) + } + .rel.sbss2 : + { + *(.rel.sbss2) + *(.rel.sbss2.*) + *(.rel.gnu.linkonce.sb2.*) + } + .rela.sbss2 : + { + *(.rela.sbss2) + *(.rela.sbss2.*) + *(.rela.gnu.linkonce.sb2.*) + } + .rel.bss : + { + *(.rel.bss) + *(.rel.bss.*) + *(.rel.gnu.linkonce.b.*) + } + .rela.bss : + { + *(.rela.bss) + *(.rela.bss.*) + *(.rela.gnu.linkonce.b.*) + } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0 + .text : + { + *(.text) + *(.text.*) + *(.stub) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t.*) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(8); + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table) } + .fixup : { *(.fixup) } + .got1 : { *(.got1) } + .got2 : { *(.got2) } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .got : { *(.got.plt) *(.got) } + PROVIDE (_GOT_END_ = .); + .sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) } + .sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .sbss : + { + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + } + .plt : { *(.plt) } + .bss : + { + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(8); + } + . = ALIGN(8); + _end = .; + __end = .; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c new file mode 100644 index 000000000..88b93a76e --- /dev/null +++ b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c @@ -0,0 +1,370 @@ +/* $NetBSD: ppc_reloc.c,v 1.46 2011/01/16 01:22:29 matt Exp $ */ + +/*- + * Copyright (C) 1998 Tsubai Masanari + * Portions copyright 2002 Charles M. Hannum + * 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 +#ifndef lint +__RCSID("$NetBSD: ppc_reloc.c,v 1.46 2011/01/16 01:22:29 matt Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "rtld.h" + +void _rtld_powerpc_pltcall(Elf_Word); +void _rtld_powerpc_pltresolve(Elf_Word, Elf_Word); + +#define ha(x) ((((u_int32_t)(x) & 0x8000) ? \ + ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16) +#define l(x) ((u_int32_t)(x) & 0xffff) + +void _rtld_bind_bssplt_start(void); +void _rtld_bind_secureplt_start(void); +void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); +caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); +static int _rtld_relocate_plt_object(const Obj_Entry *, + const Elf_Rela *, int, Elf_Addr *); + +/* + * The PPC PLT format consists of three sections: + * (1) The "pltcall" and "pltresolve" glue code. This is always 18 words. + * (2) The code part of the PLT entries. There are 2 words per entry for + * up to 8192 entries, then 4 words per entry for any additional entries. + * (3) The data part of the PLT entries, comprising a jump table. + * This section is half the size of the second section (ie. 1 or 2 words + * per entry). + */ + +/* + * Setup the plt glue routines (for bss-plt). + */ +#define PLTCALL_SIZE 20 +#define PLTRESOLVE_SIZE 24 + +void +_rtld_setup_pltgot(const Obj_Entry *obj) +{ + /* + * Secure-PLT is much more sane. + */ + if (obj->gotptr != NULL) { + obj->gotptr[1] = (Elf_Addr) _rtld_bind_secureplt_start; + obj->gotptr[2] = (Elf_Addr) obj; + } else { + Elf_Word *pltcall, *pltresolve; + Elf_Word *jmptab; + int N = obj->pltrelalim - obj->pltrela; + + /* Entries beyond 8192 take twice as much space. */ + if (N > 8192) + N += N-8192; + + pltcall = obj->pltgot; + jmptab = pltcall + 18 + N * 2; + + memcpy(pltcall, _rtld_powerpc_pltcall, PLTCALL_SIZE); + pltcall[1] |= ha(jmptab); + pltcall[2] |= l(jmptab); + + pltresolve = obj->pltgot + 8; + + memcpy(pltresolve, _rtld_powerpc_pltresolve, PLTRESOLVE_SIZE); + pltresolve[0] |= ha(_rtld_bind_bssplt_start); + pltresolve[1] |= l(_rtld_bind_bssplt_start); + pltresolve[3] |= ha(obj); + pltresolve[4] |= l(obj); + + /* + * Invalidate the icache for only the code part of the PLT + * (and not the jump table at the end). + */ + __syncicache(pltcall, (char *)jmptab - (char *)pltcall); + } +} + +void +_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rela *rela = 0, *relalim; + Elf_Addr relasz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_RELA: + rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + } + } + relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); + for (; rela < relalim; rela++) { + where = (Elf_Addr *)(relocbase + rela->r_offset); + *where = (Elf_Addr)(relocbase + rela->r_addend); + } +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->rela; rela < obj->relalim; rela++) { + Elf_Addr *where; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr tmp; + unsigned long symnum; + + where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + symnum = ELF_R_SYM(rela->r_info); + + switch (ELF_R_TYPE(rela->r_info)) { +#if 1 /* XXX Should not be necessary. */ + case R_TYPE(JMP_SLOT): +#endif + case R_TYPE(NONE): + break; + + case R_TYPE(32): /* word32 S + A */ + case R_TYPE(GLOB_DAT): /* word32 S + A */ + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + if (*where != tmp) + *where = tmp; + rdbg(("32/GLOB_DAT %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; + + case R_TYPE(RELATIVE): /* word32 B + A */ + *where = (Elf_Addr)(obj->relocbase + rela->r_addend); + rdbg(("RELATIVE in %s --> %p", obj->path, + (void *)*where)); + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + if (obj->isdynamic) { + _rtld_error( + "%s: Unexpected R_COPY relocation in shared library", + obj->path); + return -1; + } + rdbg(("COPY (avoid in main)")); + break; + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "addend = %p, contents = %p, symbol = %s", + symnum, (u_long)ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)rela->r_addend, + (void *)*where, + obj->strtab + obj->symtab[symnum].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rela->r_info)); + return -1; + } + } + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + Elf_Addr * const pltresolve = obj->pltgot + 8; + const Elf_Rela *rela; + int reloff; + + for (rela = obj->pltrela, reloff = 0; + rela < obj->pltrelalim; + rela++, reloff++) { + Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset); + + assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); + + if (obj->gotptr != NULL) { + /* + * For now, simply treat then as relative. + */ + *where += (Elf_Addr)obj->relocbase; + } else { + int distance; + + if (reloff < 32768) { + /* li r11,reloff */ + *where++ = 0x39600000 | reloff; + } else { + /* lis r11,ha(reloff) */ + /* addi r11,l(reloff) */ + *where++ = 0x3d600000 | ha(reloff); + *where++ = 0x396b0000 | l(reloff); + } + /* b pltresolve */ + distance = (Elf_Addr)pltresolve - (Elf_Addr)where; + *where++ = 0x48000000 | (distance & 0x03fffffc); + + /* + * Icache invalidation is not done for each entry here + * because we sync the entire code part of the PLT once + * in _rtld_setup_pltgot() after all the entries have been + * initialized. + */ + /* __syncicache(where - 3, 12); */ + } + } + + return 0; +} + +static int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff, Elf_Addr *tp) +{ + Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset); + Elf_Addr value; + const Elf_Sym *def; + const Obj_Entry *defobj; + int distance; + unsigned long info = rela->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + value = (Elf_Addr)(defobj->relocbase + def->st_value); + distance = value - (Elf_Addr)where; + rdbg(("bind now/fixup in %s --> new=%p", + defobj->strtab + def->st_name, (void *)value)); + + if (obj->gotptr != NULL) { + /* + * For Secure-PLT we simply replace the entry in GOT with the address + * of the routine. + */ + assert(where >= (Elf_Word *)obj->pltgot); + assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela)); + *where = value; + } else if (abs(distance) < 32*1024*1024) { /* inside 32MB? */ + /* b value # branch directly */ + *where = 0x48000000 | (distance & 0x03fffffc); + __syncicache(where, 4); + } else { + Elf_Addr *pltcall, *jmptab; + int N = obj->pltrelalim - obj->pltrela; + + /* Entries beyond 8192 take twice as much space. */ + if (N > 8192) + N += N-8192; + + pltcall = obj->pltgot; + jmptab = pltcall + 18 + N * 2; + + jmptab[reloff] = value; + + if (reloff < 32768) { + /* li r11,reloff */ + *where++ = 0x39600000 | reloff; + } else { +#ifdef notyet + /* lis r11,ha(value) */ + /* addi r11,l(value) */ + /* mtctr r11 */ + /* bctr */ + *where++ = 0x3d600000 | ha(value); + *where++ = 0x396b0000 | l(value); + *where++ = 0x7d6903a6; + *where++ = 0x4e800420; +#else + /* lis r11,ha(reloff) */ + /* addi r11,l(reloff) */ + *where++ = 0x3d600000 | ha(reloff); + *where++ = 0x396b0000 | l(reloff); +#endif + } + /* b pltcall */ + distance = (Elf_Addr)pltcall - (Elf_Addr)where; + *where++ = 0x48000000 | (distance & 0x03fffffc); + __syncicache(where - 3, 12); + } + + if (tp) + *tp = value; + return 0; +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rela *rela = (const void *)((const char *)obj->pltrela + reloff); + Elf_Addr new_value; + int err; + + new_value = 0; /* XXX gcc */ + + err = _rtld_relocate_plt_object(obj, rela, reloff, &new_value); + if (err) + _rtld_die(); + + return (caddr_t)new_value; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + int reloff; + + for (rela = obj->pltrela, reloff = 0; rela < obj->pltrelalim; rela++, reloff++) { + if (_rtld_relocate_plt_object(obj, rela, reloff, NULL) < 0) + return -1; + } + return 0; +} diff --git a/libexec/ld.elf_so/arch/powerpc/rtld_start.S b/libexec/ld.elf_so/arch/powerpc/rtld_start.S new file mode 100644 index 000000000..aa57681ac --- /dev/null +++ b/libexec/ld.elf_so/arch/powerpc/rtld_start.S @@ -0,0 +1,133 @@ +/* $NetBSD: rtld_start.S,v 1.14 2011/01/16 01:22:29 matt Exp $ */ + +/*- + * Copyright (C) 1998 Tsubai Masanari + * Portions copyright 2002 Charles M. Hannum + * 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 + + .globl _rtld_start + .globl _rtld + + .text + +_rtld_start: + stwu %r1,-48(%r1) + stw %r3,12(%r1) # argc + stw %r4,16(%r1) # argv + stw %r5,20(%r1) # envp +/* stw %r6,24(%r1) # obj (always 0) */ +/* stw %r7,28(%r1) # cleanup (always 0) */ + stw %r8,32(%r1) # ps_strings + + bcl 20,31,1f +1: mflr %r30 + mr %r3,%r30 # save for _DYNAMIC + addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha + addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l + addis %r3,%r3,_DYNAMIC-1b@ha # get _DYNAMIC actual address + addi %r3,%r3,_DYNAMIC-1b@l + lwz %r28,0(%r30) # get base-relative &_DYNAMIC + sub %r28,%r3,%r28 # r28 = relocbase + mr %r4,%r28 # r4 = relocbase + bl _rtld_relocate_nonplt_self + + lwz %r3,16(%r1) + addi %r3,%r3,-12 # sp = &argv[-3] /* XXX */ + mr %r4,%r28 # r4 = relocbase + bl _rtld # _start = _rtld(sp, relocbase) + mtlr %r3 + + lwz %r3,12(%r1) # argc + lwz %r4,16(%r1) # argv + lwz %r5,20(%r1) # envp + lwz %r6,-8(%r4) # obj = sp[1] (== argv[-2]) + lwz %r7,-12(%r4) # cleanup = sp[0] (== argv[-3]) + lwz %r8,32(%r1) # ps_strings + + addi %r1,%r1,48 + blrl # _start(argc, argv, envp, obj, cleanup, ps_strings) + + li %r0,1 # _exit() + sc + +END(_rtld_start) + + .globl _rtld_bind + +/* + * secure-plt expects %r11 to be the offset to the rela entry. + * bss-plt expects %r11 to be index of the rela entry. + * So for bss-plt, we multiply the index by 12 to get the offset. + */ +ENTRY_NOPROFILE(_rtld_bind_bssplt_start) + slwi %r11,%r11,2 + add %r0,%r11,%r11 + add %r11,%r11,%r0 +ENTRY_NOPROFILE(_rtld_bind_secureplt_start) + stwu %r1,-160(%r1) + + stw %r0,20(%r1) + mflr %r0 + stw %r0,16(%r1) # save lr + mfcr %r0 + stw %r0,12(%r1) # save cr + stmw %r3,24(%r1) # save r3-r31 + + mr %r3,%r12 # obj + mr %r4,%r11 # reloff + bl _rtld_bind # _rtld_bind(obj, reloff) + mtctr %r3 + + lmw %r3,24(%r1) # load r3-r31 + lwz %r0,12(%r1) # restore cr + mtcr %r0 + lwz %r0,16(%r1) # restore lr + mtlr %r0 + lwz %r0,20(%r1) + + addi %r1,%r1,160 + bctr +END(_rtld_bind_start) + + .globl _rtld_powerpc_pltcall + .globl _rtld_powerpc_pltresolve + +_rtld_powerpc_pltcall: + slwi %r11,%r11,2 + addis %r11,%r11,0 # addis 11,11,jmptab@ha + lwz %r11,0(%r11) # lwz 11,jmptab@l(11) + mtctr %r11 + bctr + +_rtld_powerpc_pltresolve: + lis %r12,0 # lis 12,_rtld_bind_bssplt_start@ha + addi %r12,%r12,0 # addi 12,12,_rtld_bind_bssplt_start@l + mtctr %r12 + lis %r12,0 # lis 12,obj@ha + addi %r12,%r12,0 # addi 12,12,obj@l + bctr diff --git a/libexec/ld.elf_so/arch/sh3/Makefile.inc b/libexec/ld.elf_so/arch/sh3/Makefile.inc new file mode 100644 index 000000000..2bb9e96b1 --- /dev/null +++ b/libexec/ld.elf_so/arch/sh3/Makefile.inc @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.7 2005/06/04 16:17:17 lukem Exp $ + +SRCS+= rtld_start.S mdreloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic + +CPPFLAGS+= -DELFSIZE=32 + +LDFLAGS+= -Wl,-e,.rtld_start diff --git a/libexec/ld.elf_so/arch/sh3/mdreloc.c b/libexec/ld.elf_so/arch/sh3/mdreloc.c new file mode 100644 index 000000000..6ceb4ca0a --- /dev/null +++ b/libexec/ld.elf_so/arch/sh3/mdreloc.c @@ -0,0 +1,249 @@ +/* $NetBSD: mdreloc.c,v 1.28 2010/08/06 16:33:18 joerg Exp $ */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.28 2010/08/06 16:33:18 joerg Exp $"); +#endif /* not lint */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.28 2010/08/06 16:33:18 joerg Exp $"); +#endif /* not lint */ + +#include + +#include "debug.h" +#include "rtld.h" + +void _rtld_bind_start(void); +void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); +caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); +static inline int _rtld_relocate_plt_object(const Obj_Entry *, + const Elf_Rela *, Elf_Addr *); + +void +_rtld_setup_pltgot(const Obj_Entry *obj) +{ + obj->pltgot[1] = (Elf_Addr) obj; + obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; +} + +void +_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rela *rela = 0, *relalim; + Elf_Addr relasz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_RELA: + rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + } + } + relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); + for (; rela < relalim; rela++) { + where = (Elf_Addr *)(relocbase + rela->r_offset); + *where = (Elf_Addr)(relocbase + rela->r_addend); + } +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->rela; rela < obj->relalim; rela++) { + Elf_Addr *where; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr tmp; + unsigned long symnum; + + where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + symnum = ELF_R_SYM(rela->r_info); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(NONE): + break; + +#if 1 /* XXX should not occur */ + case R_TYPE(GOT32): + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + if (*where != tmp) + *where = tmp; + rdbg(("GOT32 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; + + case R_TYPE(REL32): + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend) - (Elf_Addr)where; + if (*where != tmp) + *where = tmp; + rdbg(("PC32 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; +#endif + + case R_TYPE(DIR32): + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + if (*where != tmp) + *where = tmp; + rdbg(("32 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; + + case R_TYPE(GLOB_DAT): + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value) + + rela->r_addend; + if (*where != tmp) + *where = tmp; + rdbg(("GLOB_DAT %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; + + case R_TYPE(RELATIVE): + if (rela->r_addend) + *where = (Elf_Addr)obj->relocbase + rela->r_addend; + else + *where += (Elf_Addr)obj->relocbase; + rdbg(("RELATIVE in %s --> %p", obj->path, + (void *)*where)); + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + if (obj->isdynamic) { + _rtld_error( + "%s: Unexpected R_COPY relocation in shared library", + obj->path); + return -1; + } + rdbg(("COPY (avoid in main)")); + break; + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "addend = %p, contents = %p, symbol = %s", + symnum, (u_long)ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)rela->r_addend, + (void *)*where, + obj->strtab + obj->symtab[symnum].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rela->r_info)); + return -1; + } + } + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + if (!obj->relocbase) + return 0; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + + assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); + + /* Just relocate the GOT slots pointing into the PLT */ + *where += (Elf_Addr)obj->relocbase; + rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); + } + + return 0; +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff); + Elf_Addr new_value; + int err; + + new_value = 0; /* XXX gcc */ + + err = _rtld_relocate_plt_object(obj, rela, &new_value); + if (err) + _rtld_die(); + + return (caddr_t)new_value; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rela *rela = obj->pltrela; + + for (; rela < obj->pltrelalim; rela++) + if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) + return -1; + + return 0; +} + +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) +{ + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + Elf_Addr new_value; + const Elf_Sym *def; + const Obj_Entry *defobj; + unsigned long info = rela->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(("bind now/fixup in %s --> old=%p new=%p", + defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); + if (*where != new_value) + *where = new_value; + + if (tp) + *tp = new_value; + + return 0; +} diff --git a/libexec/ld.elf_so/arch/sh3/rtld_start.S b/libexec/ld.elf_so/arch/sh3/rtld_start.S new file mode 100644 index 000000000..9ac5b1347 --- /dev/null +++ b/libexec/ld.elf_so/arch/sh3/rtld_start.S @@ -0,0 +1,117 @@ +/* $NetBSD: rtld_start.S,v 1.7 2008/04/28 20:23:03 martin Exp $ */ + +/*- + * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Marcus Comstedt. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + .text + .align 2 + .globl .rtld_start + .type .rtld_start,@function + +.rtld_start: + mova 2f,r0 + mov.l @r0,r2 + add r0,r2 /* GOT */ + mov.l @(4,r0),r4 /* _DYNAMIC@GOTOFF */ + add r2,r4 /* _DYNAMIC */ + mov.l @(12,r0),r1 /* _rtld_relocate_nonplt_self offset */ + mov.l @(8,r0),r0 /* _DYNAMIC@GOT */ + mov r4,r5 + mov.l @(r0,r2),r0 /* where linker thinks _DYNAMIC is */ + sub r0,r5 /* compute relocation base */ + bsrf r1 /* _rtld_relocate_nonplt_self(dynp, relocbase) */ + mov.l r5,@-r15 /* save relocbase */ + +4: + mov.l @r15+,r5 /* restore relocbase */ + add #-8,r15 /* room for values returned by _rtld */ + mov r15,r4 + mov.l 1f,r0 + bsrf r0 /* _rtld(sp, relocbase) */ + mov.l r9,@-r15 /* save ps_strings */ +3: + mov.l @r15+,r9 /* restore ps_strings */ + + mov.l @r15+,r7 /* from _rtld: exit procedure */ + mov.l @r15+,r8 /* from _rtld: main object */ + + mov.l @r15,r4 /* restore argc */ + + mov r15,r5 /* restore argv */ + add #4,r5 + + mov r4,r6 /* restore envp */ + shll2 r6 + add r15,r6 + jmp @r0 /* entry point returned by _rtld */ + add #8,r6 + .align 2 +1: .long _rtld-3b +2: .long _GLOBAL_OFFSET_TABLE_ + .long _DYNAMIC@GOTOFF + .long _DYNAMIC@GOT + .long _rtld_relocate_nonplt_self-4b + .size .rtld_start,.-.rtld_start + + .align 2 + .globl _rtld_bind_start + .type _rtld_bind_start,@function +_rtld_bind_start: /* r0 = obj, r1 = reloff */ + mov.l r2,@-r15 /* save registers */ + mov.l r3,@-r15 + mov.l r4,@-r15 + mov.l r5,@-r15 + mov.l r6,@-r15 + mov.l r7,@-r15 + sts.l mach,@-r15 + sts.l macl,@-r15 + sts.l pr,@-r15 + + mov r0,r4 /* copy of obj */ + mov.l 2f,r0 + bsrf r0 /* call the binder */ + mov r1,r5 /* copy of reloff */ +4: + lds.l @r15+,pr /* restore registers */ + lds.l @r15+,macl + lds.l @r15+,mach + mov.l @r15+,r7 + mov.l @r15+,r6 + mov.l @r15+,r5 + mov.l @r15+,r4 + mov.l @r15+,r3 + jmp @r0 + mov.l @r15+,r2 + .align 2 +2: .long _rtld_bind-4b + .size _rtld_bind_start,.-_rtld_bind_start + + .end diff --git a/libexec/ld.elf_so/arch/sparc/Makefile.inc b/libexec/ld.elf_so/arch/sparc/Makefile.inc new file mode 100644 index 000000000..e13e6e0c6 --- /dev/null +++ b/libexec/ld.elf_so/arch/sparc/Makefile.inc @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.14 2009/12/13 09:31:47 mrg Exp $ + +SRCS+= rtld_start.S mdreloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic + +CPPFLAGS+= -DELFSIZE=32 + +LDFLAGS+= -Wl,-e,_rtld_start diff --git a/libexec/ld.elf_so/arch/sparc/mdreloc.c b/libexec/ld.elf_so/arch/sparc/mdreloc.c new file mode 100644 index 000000000..6b10b5861 --- /dev/null +++ b/libexec/ld.elf_so/arch/sparc/mdreloc.c @@ -0,0 +1,394 @@ +/* $NetBSD: mdreloc.c,v 1.44 2010/08/06 16:33:18 joerg Exp $ */ + +/*- + * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg and by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.44 2010/08/06 16:33:18 joerg Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#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> (8*i)) & 0xff); +#ifdef RTLD_DEBUG_RELOC + value = (Elf_Word)tmp; +#endif + + } else { + *where &= ~mask; + *where |= value; +#ifdef RTLD_DEBUG_RELOC + value = (Elf_Word)*where; +#endif + } +#ifdef RTLD_DEBUG_RELOC + if (RELOC_RESOLVE_SYMBOL(type)) { + rdbg(("%s %s in %s --> %p in %s", reloc_names[type], + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)value, defobj->path)); + } else { + rdbg(("%s in %s --> %p", reloc_names[type], + obj->path, (void *)value)); + } +#endif + } + return (0); +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + return (0); +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff); + Elf_Addr value; + int err; + + value = 0; /* XXX gcc */ + + err = _rtld_relocate_plt_object(obj, rela, &value); + if (err) + _rtld_die(); + + return (caddr_t)value; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rela *rela = obj->pltrela; + + for (; rela < obj->pltrelalim; rela++) + if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) + return -1; + + return 0; +} + +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) +{ + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Word *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + Elf_Addr value; + unsigned long info = rela->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + value = (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(("bind now/fixup in %s --> new=%p", + defobj->strtab + def->st_name, (void *)value)); + + /* + * At the PLT entry pointed at by `where', we now construct + * a direct transfer to the now fully resolved function + * address. The resulting code in the jump slot is: + * + * sethi %hi(roffset), %g1 + * sethi %hi(addr), %g1 + * jmp %g1+%lo(addr) + * + * We write the third instruction first, since that leaves the + * previous `b,a' at the second word in place. Hence the whole + * PLT slot can be atomically change to the new sequence by + * writing the `sethi' instruction at word 2. + */ +#define SETHI 0x03000000 +#define JMP 0x81c06000 +#define NOP 0x01000000 + where[2] = JMP | (value & 0x000003ff); + where[1] = SETHI | ((value >> 10) & 0x003fffff); + __asm volatile("iflush %0+8" : : "r" (where)); + __asm volatile("iflush %0+4" : : "r" (where)); + + if (tp) + *tp = value; + + return 0; +} diff --git a/libexec/ld.elf_so/arch/sparc/rtld_start.S b/libexec/ld.elf_so/arch/sparc/rtld_start.S new file mode 100644 index 000000000..67761cd8b --- /dev/null +++ b/libexec/ld.elf_so/arch/sparc/rtld_start.S @@ -0,0 +1,81 @@ +/* $NetBSD: rtld_start.S,v 1.16 2008/04/28 20:23:03 martin Exp $ */ + +/*- + * Copyright (c) 1999, 2002, 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas, Paul Kranenburg, and by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + .section ".text" + .align 4 + .global _rtld_start + .type _rtld_start,@function +_rtld_start: + mov 0, %fp /* Erect a fence post for ourselves */ + mov %g1, %l1 /* save ps_strings */ + sub %sp, 32+8, %sp /* room for return args and save area */ + + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7 + call 0f + add %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7 + call _DYNAMIC+8 +0: add %l7, %o7, %l7 /* real &_GLOBAL_OFFSET_TABLE_ */ + ld [%o7+8], %o0 /* load stub call instruction */ + ld [%l7], %l0 /* base-relative &_DYNAMIC */ + sll %o0, 2, %o0 /* extract PC offset */ + + add %o0, %o7, %o0 /* real &_DYNAMIC */ + sub %o0, %l0, %l0 /* relocbase */ + call _rtld_relocate_nonplt_self + mov %l0, %o1 /* relocbase */ + + mov %l0, %o1 /* relocbase */ + call _rtld + add %sp, 96, %o0 /* &argc - 8 */ + + ld [%sp + 96], %g3 /* arg: cleanup */ + ld [%sp + 96 + 4], %g2 /* arg: obj */ + add %sp, 32+8, %sp /* restore stack pointer */ + + jmp %o0 + mov %l1, %g1 /* restore ps_strings */ + + + .section ".text" + .align 4 + .global _rtld_bind_start + .type _rtld_bind_start,@function +_rtld_bind_start: # (obj, reloff) + ld [%o7 + 8], %o0 /* obj id is in second PLT slot */ + srl %g1, 10, %o1 /* offset is in high 22 bits */ + call _rtld_bind /* Call _rtld_bind(obj, offset) */ + sub %o1, 12*4, %o1 /* first 4 `pltrel' entries missing! */ + + jmp %o0 /* return value == function address */ + restore + diff --git a/libexec/ld.elf_so/arch/sparc64/Makefile.inc b/libexec/ld.elf_so/arch/sparc64/Makefile.inc new file mode 100644 index 000000000..a7527c02c --- /dev/null +++ b/libexec/ld.elf_so/arch/sparc64/Makefile.inc @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.8 2005/06/04 16:17:17 lukem Exp $ + +SRCS+= rtld_start.S mdreloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic + +CPPFLAGS+= -DELFSIZE=64 + +LDFLAGS+= -Wl,-e,_rtld_start diff --git a/libexec/ld.elf_so/arch/sparc64/mdreloc.c b/libexec/ld.elf_so/arch/sparc64/mdreloc.c new file mode 100644 index 000000000..0dc7e821d --- /dev/null +++ b/libexec/ld.elf_so/arch/sparc64/mdreloc.c @@ -0,0 +1,732 @@ +/* $NetBSD: mdreloc.c,v 1.50 2010/09/24 12:00:10 skrll Exp $ */ + +/*- + * Copyright (c) 2000 Eduardo Horvath. + * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg and by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.50 2010/09/24 12:00:10 skrll Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#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> (8*i)) & 0xff); +#ifdef RTLD_DEBUG_RELOC + value = (Elf_Addr)tmp; +#endif + + } else if (RELOC_TARGET_SIZE(type) > 32) { + *where &= ~mask; + *where |= value; +#ifdef RTLD_DEBUG_RELOC + value = (Elf_Addr)*where; +#endif + } else { + Elf32_Addr *where32 = (Elf32_Addr *)where; + + *where32 &= ~mask; + *where32 |= value; +#ifdef RTLD_DEBUG_RELOC + value = (Elf_Addr)*where32; +#endif + } + +#ifdef RTLD_DEBUG_RELOC + if (RELOC_RESOLVE_SYMBOL(type)) { + rdbg(("%s %s in %s --> %p in %s", reloc_names[type], + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)value, defobj->path)); + } else { + rdbg(("%s in %s --> %p", reloc_names[type], + obj->path, (void *)value)); + } +#endif + } + return (0); +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + return (0); +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rela *rela = obj->pltrela + reloff; + Elf_Addr result; + int err; + + result = 0; /* XXX gcc */ + + if (ELF_R_TYPE(obj->pltrela->r_info) == R_TYPE(JMP_SLOT)) { + /* + * XXXX + * + * The first four PLT entries are reserved. There is some + * disagreement whether they should have associated relocation + * entries. Both the SPARC 32-bit and 64-bit ELF + * specifications say that they should have relocation entries, + * but the 32-bit SPARC binutils do not generate them, and now + * the 64-bit SPARC binutils have stopped generating them too. + * + * So, to provide binary compatibility, we will check the first + * entry, if it is reserved it should not be of the type + * JMP_SLOT. If it is JMP_SLOT, then the 4 reserved entries + * were not generated and our index is 4 entries too far. + */ + rela -= 4; + } + + err = _rtld_relocate_plt_object(obj, rela, &result); + if (err) + _rtld_die(); + + return (caddr_t)result; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + rela = obj->pltrela; + + /* + * Check for first four reserved entries - and skip them. + * See above for details. + */ + if (ELF_R_TYPE(obj->pltrela->r_info) != R_TYPE(JMP_SLOT)) + rela += 4; + + for (; rela < obj->pltrelalim; rela++) + if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) + return -1; + + return 0; +} + +/* + * New inline function that is called by _rtld_relocate_plt_object and + * _rtld_bind + */ +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, + Elf_Addr *tp) +{ + Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset); + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr value, offset; + unsigned long info = rela->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + value = (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(("bind now/fixup in %s --> new=%p", + defobj->strtab + def->st_name, (void *)value)); + + /* + * At the PLT entry pointed at by `where', we now construct a direct + * transfer to the now fully resolved function address. + * + * A PLT entry is supposed to start by looking like this: + * + * sethi %hi(. - .PLT0), %g1 + * ba,a %xcc, .PLT1 + * nop + * nop + * nop + * nop + * nop + * nop + * + * When we replace these entries we start from the last instruction + * and do it in reverse order so the last thing we do is replace the + * branch. That allows us to change this atomically. + * + * We now need to find out how far we need to jump. We have a choice + * of several different relocation techniques which are increasingly + * expensive. + */ + + offset = ((Elf_Addr)where) - value; + if (rela->r_addend) { + Elf_Addr *ptr = (Elf_Addr *)where; + /* + * This entry is >= 32768. The relocations points to a + * PC-relative pointer to the bind_0 stub at the top of the + * PLT section. Update it to point to the target function. + */ + ptr[0] += value - (Elf_Addr)obj->pltgot; + + } else if (offset <= (1L<<20) && (Elf_SOff)offset >= -(1L<<20)) { + /* + * We're within 1MB -- we can use a direct branch insn. + * + * We can generate this pattern: + * + * sethi %hi(. - .PLT0), %g1 + * ba,a %xcc, addr + * nop + * nop + * nop + * nop + * nop + * nop + * + */ + where[1] = BAA | ((offset >> 2) & 0x3fffff); + __asm volatile("iflush %0+4" : : "r" (where)); + } else if (value < (1L<<32)) { + /* + * We're within 32-bits of address zero. + * + * The resulting code in the jump slot is: + * + * sethi %hi(. - .PLT0), %g1 + * sethi %hi(addr), %g1 + * jmp %g1+%lo(addr) + * nop + * nop + * nop + * nop + * nop + * + */ + where[2] = JMP | LOVAL(value, 0); + where[1] = SETHI | HIVAL(value, 10); + __asm volatile("iflush %0+8" : : "r" (where)); + __asm volatile("iflush %0+4" : : "r" (where)); + + } else if ((Elf_SOff)value <= 0 && (Elf_SOff)value > -(1L<<32)) { + /* + * We're within 32-bits of address -1. + * + * The resulting code in the jump slot is: + * + * sethi %hi(. - .PLT0), %g1 + * sethi %hix(addr), %g1 + * xor %g1, %lox(addr), %g1 + * jmp %g1 + * nop + * nop + * nop + * nop + * + */ + where[3] = JMP; + where[2] = XOR | ((~value) & 0x00001fff); + where[1] = SETHI | HIVAL(~value, 10); + __asm volatile("iflush %0+12" : : "r" (where)); + __asm volatile("iflush %0+8" : : "r" (where)); + __asm volatile("iflush %0+4" : : "r" (where)); + + } else if (offset <= (1L<<32) && (Elf_SOff)offset >= -((1L<<32) - 4)) { + /* + * We're within 32-bits -- we can use a direct call insn + * + * The resulting code in the jump slot is: + * + * sethi %hi(. - .PLT0), %g1 + * mov %o7, %g1 + * call (.+offset) + * mov %g1, %o7 + * nop + * nop + * nop + * nop + * + */ + where[3] = MOV17; + where[2] = CALL | ((offset >> 4) & 0x3fffffff); + where[1] = MOV71; + __asm volatile("iflush %0+12" : : "r" (where)); + __asm volatile("iflush %0+8" : : "r" (where)); + __asm volatile("iflush %0+4" : : "r" (where)); + + } else if (offset < (1L<<44)) { + /* + * We're within 44 bits. We can generate this pattern: + * + * The resulting code in the jump slot is: + * + * sethi %hi(. - .PLT0), %g1 + * sethi %h44(addr), %g1 + * or %g1, %m44(addr), %g1 + * sllx %g1, 12, %g1 + * jmp %g1+%l44(addr) + * nop + * nop + * nop + * + */ + where[4] = JMP | LOVAL(offset, 0); + where[3] = SLLX | 12; + where[2] = OR | (((offset) >> 12) & 0x00001fff); + where[1] = SETHI | HIVAL(offset, 22); + __asm volatile("iflush %0+16" : : "r" (where)); + __asm volatile("iflush %0+12" : : "r" (where)); + __asm volatile("iflush %0+8" : : "r" (where)); + __asm volatile("iflush %0+4" : : "r" (where)); + + } else if ((Elf_SOff)offset < 0 && (Elf_SOff)offset > -(1L<<44)) { + /* + * We're within 44 bits. We can generate this pattern: + * + * The resulting code in the jump slot is: + * + * sethi %hi(. - .PLT0), %g1 + * sethi %h44(-addr), %g1 + * xor %g1, %m44(-addr), %g1 + * sllx %g1, 12, %g1 + * jmp %g1+%l44(addr) + * nop + * nop + * nop + * + */ + where[4] = JMP | LOVAL(offset, 0); + where[3] = SLLX | 12; + where[2] = XOR | (((~offset) >> 12) & 0x00001fff); + where[1] = SETHI | HIVAL(~offset, 22); + __asm volatile("iflush %0+16" : : "r" (where)); + __asm volatile("iflush %0+12" : : "r" (where)); + __asm volatile("iflush %0+8" : : "r" (where)); + __asm volatile("iflush %0+4" : : "r" (where)); + + } else { + /* + * We need to load all 64-bits + * + * The resulting code in the jump slot is: + * + * sethi %hi(. - .PLT0), %g1 + * sethi %hh(addr), %g1 + * sethi %lm(addr), %g5 + * or %g1, %hm(addr), %g1 + * sllx %g1, 32, %g1 + * or %g1, %g5, %g1 + * jmp %g1+%lo(addr) + * nop + * + */ + where[6] = JMP | LOVAL(value, 0); + where[5] = ORG5; + where[4] = SLLX | 32; + where[3] = OR | LOVAL(value, 32); + where[2] = SETHIG5 | HIVAL(value, 10); + where[1] = SETHI | HIVAL(value, 42); + __asm volatile("iflush %0+24" : : "r" (where)); + __asm volatile("iflush %0+20" : : "r" (where)); + __asm volatile("iflush %0+16" : : "r" (where)); + __asm volatile("iflush %0+12" : : "r" (where)); + __asm volatile("iflush %0+8" : : "r" (where)); + __asm volatile("iflush %0+4" : : "r" (where)); + + } + + if (tp) + *tp = value; + + return 0; +} diff --git a/libexec/ld.elf_so/arch/sparc64/rtld_start.S b/libexec/ld.elf_so/arch/sparc64/rtld_start.S new file mode 100644 index 000000000..79171cc54 --- /dev/null +++ b/libexec/ld.elf_so/arch/sparc64/rtld_start.S @@ -0,0 +1,172 @@ +/* $NetBSD: rtld_start.S,v 1.17 2008/04/28 20:23:04 martin Exp $ */ + +/*- + * Copyright (c) 2000 Eduardo Horvath. + * Copyright (c) 1999, 2002, 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas, Paul Kranenburg and by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#define _LOCORE +#include + +/* + * ELF: + * On startup the stack should contain 16 extended word register save area, + * followed by the arg count, etc. + * + * _rtld() expects the stack pointer to point to two longwords for argument + * return followed by argc, etc. We need to create a pointer to + * &argc + 16 and pass that in. The return args will be in those locations. + * + * NB: We are violating the ELF spec by passing a pointer to the ps strings in + * %g1 instead of a termination routine. + */ + + .register %g2,#scratch + .register %g3,#scratch + +/* Offset of ARGC from bottom of stack */ +#define ARGC 176 + + .section ".text" + .align 4 + .global _rtld_start + .type _rtld_start,@function +_rtld_start: + mov 0, %fp /* Erect a fence post for ourselves */ + mov %g1, %l1 /* save ps_strings */ + sub %sp, 48+16, %sp /* Make room for return args */ + + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7 + call 0f + add %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7 + call _DYNAMIC+8 +0: add %l7, %o7, %l7 /* real &_GLOBAL_OFFSET_TABLE_ */ + ld [%o7+8], %o0 /* load stub call instruction */ + ldx [%l7], %l0 /* base-relative &_DYNAMIC */ + sll %o0, 2, %o0 /* extract PC offset */ + sra %o0, 0, %o0 /* sign-extend */ + + add %o0, %o7, %o0 /* real &_DYNAMIC */ + sub %o0, %l0, %l0 /* relocbase */ + call _rtld_relocate_nonplt_self + mov %l0, %o1 /* relocbase */ + + mov %l0, %o1 /* relocbase */ + call _rtld + add %sp, BIAS + ARGC, %o0 /* &argc - 16 */ + + ldx [%sp + BIAS + ARGC], %g3 /* arg: cleanup */ + ldx [%sp + BIAS + ARGC + 8], %g2 /* arg: obj */ + add %sp, 48+16, %sp /* restore stack pointer */ + + jmp %o0 + mov %l1, %g1 /* restore ps_strings */ + + + /* + * We have two separate entry points to the runtime linker. + * I'm implementing this following the SPARC v9 ABI spec. + * + * _rtld_bind_start_0(y, x) is called from .PLT0, and is used for + * PLT entries above 32768. + * + * _rtld_bind_start_1(y, x) is called from .PLT1, and is used for + * PLT entries below 32768. + * + * The first two entries of PLT2 contain the xword object pointer. + * + * These routines are called with two longword arguments, + * x and y. To calculate the address of the entry, + * _rtld_bind_start_1(y, x) does: + * + * n = x >> 15; + * + * and _rtld_bind_start_0(y, x) does: + * + * i = x - y + 8 - 32768*32; + * n = 32768 + (i/5120)*160 + (i%5120)/24; + * + * Neither routine needs to issue a save since it's already been + * done in the PLT entry. + */ + + .section ".text" + .align 4 + .global _rtld_bind_start_0 + .type _rtld_bind_start_0,@function +_rtld_bind_start_0: # (y, x) + /* %o0 = obj->pltgot[6] */ + /* %o1 = plt[4] */ + /* %o1 - %o0 + 8 == offset of plt[] from obj->pltgot[] */ + /* -32768*32 to get offset from beginning of upper PLT section */ + + sethi %hi(32768*32-8), %l1 + sub %o1, %o0, %l0 /* i = x - y */ + or %l1, %lo(32768*32-8), %l1 + sub %l0, %l1, %l0 /* i = x - y + 8 - 32768*32 */ + + ldx [%o0 + (10*4)], %o0 /* Load object pointer from PLT2 */ + + sethi %hi(5120), %l1 + sdivx %l0, %l1, %l1 /* Calculate i/5120 */ + sllx %l1, 2, %l2 + add %l2, %l1, %l2 + sllx %l2, 10, %l2 + sub %l0, %l2, %l2 /* And i%5120 */ + + /* Let the division churn for a bit. */ + sdivx %l2, 24, %l4 /* (i%5120)/24 */ + + /* 160 is (32 * 5) or (32 * (4 + 1)) */ + sllx %l1, 2, %l3 /* 4 * (i/5120) */ + add %l1, %l3, %l3 /* 5 * (i/5120) */ + sllx %l3, 5, %l3 /* 32 * 5 * (i/5120) */ + + sethi %hi(32768), %l6 + add %l3, %l4, %l5 /* %l5 = (i/5120)*160 + (i%5120)/24; */ + + call _rtld_bind /* Call _rtld_bind(obj, offset) */ + add %l5, %l6, %o1 /* %o1 = 32768 + ... */ + + jmp %o0 /* return value == function address */ + restore /* Dump our stack frame */ + + .section ".text" + .align 4 + .global _rtld_bind_start_1 + .type _rtld_bind_start_1,@function +_rtld_bind_start_1: # (y, x) + ldx [%o0 + (2*4)], %o0 /* Load object pointer from PLT2 */ + + call _rtld_bind /* Call _rtld_bind(obj, offset) */ + srax %o1, 15, %o1 /* %o1 is the index to our PLT slot */ + + jmp %o0 /* return value == function address */ + restore /* Dump our stack frame */ + diff --git a/libexec/ld.elf_so/arch/vax/Makefile.inc b/libexec/ld.elf_so/arch/vax/Makefile.inc new file mode 100644 index 000000000..bf52eb771 --- /dev/null +++ b/libexec/ld.elf_so/arch/vax/Makefile.inc @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.11 2009/09/19 14:54:17 skrll Exp $ + +SRCS+= rtld_start.S mdreloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fpic + +CPPFLAGS+= -DELFSIZE=32 + +LDFLAGS+= -Wl,-Bsymbolic -Wl,-e,_rtld_start diff --git a/libexec/ld.elf_so/arch/vax/mdreloc.c b/libexec/ld.elf_so/arch/vax/mdreloc.c new file mode 100644 index 000000000..a7b99e6cd --- /dev/null +++ b/libexec/ld.elf_so/arch/vax/mdreloc.c @@ -0,0 +1,207 @@ +/* $NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:19 joerg Exp $ */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:19 joerg Exp $"); +#endif /* not lint */ + +#include +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.27 2010/08/06 16:33:19 joerg Exp $"); +#endif /* not lint */ + +#include + +#include "debug.h" +#include "rtld.h" + +void _rtld_bind_start(void); +void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); +caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); +static inline int _rtld_relocate_plt_object(const Obj_Entry *, + const Elf_Rela *, Elf_Addr *); + +void +_rtld_setup_pltgot(const Obj_Entry *obj) +{ + obj->pltgot[1] = (Elf_Addr) obj; + obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; +} + +void +_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rela *rela = 0, *relalim; + Elf_Addr relasz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_RELA: + rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + } + } + relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); + for (; rela < relalim; rela++) { + where = (Elf_Addr *)(relocbase + rela->r_offset); + *where = (Elf_Addr)(relocbase + rela->r_addend); + } +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->rela; rela < obj->relalim; rela++) { + Elf_Addr *where; + const Elf_Sym *def; + const Obj_Entry *defobj; + Elf_Addr tmp; + unsigned long symnum; + + where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + symnum = ELF_R_SYM(rela->r_info); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(NONE): + break; + + case R_TYPE(32): /* word32 S + A */ + case R_TYPE(GLOB_DAT): /* word32 S + A */ + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + + if (*where != tmp) + *where = tmp; + rdbg(("32/GLOB_DAT %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where, defobj->path)); + break; + + case R_TYPE(RELATIVE): /* word32 B + A */ + tmp = (Elf_Addr)(obj->relocbase + rela->r_addend); + if (*where != tmp) + *where = tmp; + rdbg(("RELATIVE in %s --> %p", obj->path, + (void *)*where)); + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + if (obj->isdynamic) { + _rtld_error( + "%s: Unexpected R_COPY relocation in shared library", + obj->path); + return -1; + } + rdbg(("COPY (avoid in main)")); + break; + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "addend = %p, contents = %p, symbol = %s", + symnum, (u_long)ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)rela->r_addend, + (void *)*where, + obj->strtab + obj->symtab[symnum].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rela->r_info)); + return -1; + } + } + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + if (!obj->relocbase) + return 0; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + + assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); + + /* Just relocate the GOT slots pointing into the PLT */ + *where += (Elf_Addr)obj->relocbase; + rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); + } + + return 0; +} + +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) +{ + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + Elf_Addr new_value; + const Elf_Sym *def; + const Obj_Entry *defobj; + unsigned long info = rela->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + new_value = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + rdbg(("bind now/fixup in %s --> old=%p new=%p", + defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); + if (*where != new_value) + *where = new_value; + + if (tp) + *tp = new_value - rela->r_addend; + + return 0; +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff); + Elf_Addr result; + int err; + + result = 0; /* XXX gcc */ + + err = _rtld_relocate_plt_object(obj, rela, &result); + if (err) + _rtld_die(); + + return (caddr_t)result; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) + if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) + return -1; + + return 0; +} diff --git a/libexec/ld.elf_so/arch/vax/rtld_start.S b/libexec/ld.elf_so/arch/vax/rtld_start.S new file mode 100644 index 000000000..6f5fc70bc --- /dev/null +++ b/libexec/ld.elf_so/arch/vax/rtld_start.S @@ -0,0 +1,78 @@ +/* $NetBSD: rtld_start.S,v 1.16 2003/03/02 22:03:40 mycroft Exp $ */ + +/* + * Copyright 1996 Matt Thomas + * Portions copyright 2002, 2003 Charles M. Hannum + * 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 + +/* R9 contains the address of PS_STRINGS and since its caller saved, + * we can just use it. R6 has a backup copy of the stack pointer which + * we can use as well. + */ +ENTRY(_rtld_start, 0) + /* Allocate space on the stack for the cleanup and obj_main + * entries that _rtld() will provide for us. + */ + clrl %fp + subl2 $8,%sp + + movab _DYNAMIC,%r0 + subl3 _GLOBAL_OFFSET_TABLE_,%r0,%r10 + pushl %r10 /* relocbase */ + pushl %r0 /* &_DYNAMIC */ + calls $2,_rtld_relocate_nonplt_self + + pushl %r10 /* relocbase */ + pushal 4(%sp) /* sp */ + calls $2,_rtld /* entry = _rtld(sp, relocbase) */ + + movq (%sp)+,%r7 /* grab cleanup and obj_main into %r7/%r8 */ + jmp 2(%r0) /* jump to entry point + 2 */ + +/* + * Lazy binding entry point, called via PLT. + * + * Note: Some functions rely on there not being an additional call frame; + * hence the `optimization' to avoid the callg opportunistically. + */ +ALTENTRY(_rtld_bind_start) + pushr $0x3f /* save R0-R5 */ + movq 24(%sp),%r0 /* get addresses of plt.got & reloc index */ + pushl (%r1) /* push relocation index */ + pushl %r0 /* push address of obj entry */ + calls $2,_rtld_bind + movl %r0,28(%sp) /* save return address onto stack */ + bicw3 6(%fp),(%r0),%r0/* does the entry mask save any additional regs */ + popr $0x3f /* restore R0-R5 (cond flags not modified) */ + bneq 4f /* yes? do it the hard way */ + addl2 $4,%sp /* no? skip past plt.got on stack */ + addl2 $2,(%sp) /* skip past the mask */ + rsb /* and jump to it */ +4: addl2 $4,%sp + callg (%ap),*(%sp)+ /* return value from _rtld_bind() == actual */ + ret diff --git a/libexec/ld.elf_so/arch/x86_64/Makefile.inc b/libexec/ld.elf_so/arch/x86_64/Makefile.inc new file mode 100644 index 000000000..96d3660bb --- /dev/null +++ b/libexec/ld.elf_so/arch/x86_64/Makefile.inc @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.7 2005/06/04 16:17:17 lukem Exp $ + +SRCS+= rtld_start.S mdreloc.c + +# XXX Should not be in CPPFLAGS! +CPPFLAGS+= -fPIC + +CPPFLAGS+= -DELFSIZE=64 + +LDFLAGS+= -Wl,-e,.rtld_start diff --git a/libexec/ld.elf_so/arch/x86_64/mdreloc.c b/libexec/ld.elf_so/arch/x86_64/mdreloc.c new file mode 100644 index 000000000..b0ea28588 --- /dev/null +++ b/libexec/ld.elf_so/arch/x86_64/mdreloc.c @@ -0,0 +1,311 @@ +/* $NetBSD: mdreloc.c,v 1.38 2010/08/06 16:33:19 joerg Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas + * 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 +#ifndef lint +__RCSID("$NetBSD: mdreloc.c,v 1.38 2010/08/06 16:33:19 joerg Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "rtld.h" + +void _rtld_bind_start(void); +void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); +caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); +static inline int _rtld_relocate_plt_object(const Obj_Entry *, + const Elf_Rela *, Elf_Addr *); + +void +_rtld_setup_pltgot(const Obj_Entry *obj) +{ + obj->pltgot[1] = (Elf_Addr) obj; + obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; +} + +void +_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rela *rela = 0, *relalim; + Elf_Addr relasz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_RELA: + rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + } + } + /* + * Assume only 64-bit relocations here, which should always + * be true for the dynamic linker. + */ + relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); + for (; rela < relalim; rela++) { + where = (Elf_Addr *)(relocbase + rela->r_offset); + *where = (Elf_Addr)(relocbase + rela->r_addend); + } +} + +int +_rtld_relocate_nonplt_objects(Obj_Entry *obj) +{ + const Elf_Rela *rela; + const Elf_Sym *def = NULL; + const Obj_Entry *defobj =NULL; + + for (rela = obj->rela; rela < obj->relalim; rela++) { + Elf64_Addr *where64; + Elf32_Addr *where32; + Elf64_Addr tmp64; + Elf32_Addr tmp32; + unsigned long symnum; + + where64 = (Elf64_Addr *)(obj->relocbase + rela->r_offset); + where32 = (Elf32_Addr *)where64; + symnum = ELF_R_SYM(rela->r_info); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(NONE): + break; + + case R_TYPE(32): /* word32 S + A, truncate */ + case R_TYPE(32S): /* word32 S + A, signed truncate */ + case R_TYPE(GOT32): /* word32 G + A (XXX can we see these?) */ + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase + + def->st_value + rela->r_addend); + + if (*where32 != tmp32) + *where32 = tmp32; + rdbg(("32/32S %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)(unsigned long)*where32, + defobj->path)); + break; + case R_TYPE(64): /* word64 S + A */ + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + + if (*where64 != tmp64) + *where64 = tmp64; + rdbg(("64 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where64, defobj->path)); + break; + case R_TYPE(PC32): /* word32 S + A - P */ + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase + + def->st_value + rela->r_addend - + (Elf64_Addr)where64); + if (*where32 != tmp32) + *where32 = tmp32; + rdbg(("PC32 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)(unsigned long)*where32, + defobj->path)); + break; + case R_TYPE(GLOB_DAT): /* word64 S */ + def = _rtld_find_symdef(symnum, obj, &defobj, false); + if (def == NULL) + return -1; + tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value); + + if (*where64 != tmp64) + *where64 = tmp64; + rdbg(("64 %s in %s --> %p in %s", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)*where64, defobj->path)); + break; + case R_TYPE(RELATIVE): /* word64 B + A */ + tmp64 = (Elf64_Addr)(obj->relocbase + rela->r_addend); + if (*where64 != tmp64) + *where64 = tmp64; + rdbg(("RELATIVE in %s --> %p", obj->path, + (void *)*where64)); + break; + + case R_TYPE(COPY): + rdbg(("COPY")); + break; + + default: + rdbg(("sym = %lu, type = %lu, offset = %p, " + "addend = %p, contents = %p, symbol = %s", + symnum, (u_long)ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)rela->r_addend, + (void *)*where64, + obj->strtab + obj->symtab[symnum].st_name)); + _rtld_error("%s: Unsupported relocation type %ld " + "in non-PLT relocations", + obj->path, (u_long) ELF_R_TYPE(rela->r_info)); + return -1; + } + } + return 0; +} + +int +_rtld_relocate_plt_lazy(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + if (!obj->relocbase) + return 0; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + + assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT)); + + /* Just relocate the GOT slots pointing into the PLT */ + *where += (Elf_Addr)obj->relocbase; + rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); + } + + return 0; +} + +static inline int +_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) +{ + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + Elf_Addr new_value; + const Elf_Sym *def; + const Obj_Entry *defobj; + unsigned long info = rela->r_info; + + assert(ELF_R_TYPE(info) == R_TYPE(JUMP_SLOT)); + + def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL); + if (__predict_false(def == NULL)) + return -1; + if (__predict_false(def == &_rtld_sym_zero)) + return 0; + + new_value = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + rdbg(("bind now/fixup in %s --> old=%p new=%p", + defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); + if (*where != new_value) + *where = new_value; + + if (tp) + *tp = new_value - rela->r_addend; + + return 0; +} + +caddr_t +_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) +{ + const Elf_Rela *rela = obj->pltrela + reloff; + Elf_Addr new_value; + int error; + + new_value = 0; /* XXX GCC4 */ + + error = _rtld_relocate_plt_object(obj, rela, &new_value); + if (error) + _rtld_die(); + + return (caddr_t)new_value; +} + +int +_rtld_relocate_plt_objects(const Obj_Entry *obj) +{ + const Elf_Rela *rela; + + for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) + if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) + return -1; + + return 0; +} diff --git a/libexec/ld.elf_so/arch/x86_64/rtld_start.S b/libexec/ld.elf_so/arch/x86_64/rtld_start.S new file mode 100644 index 000000000..d154e9475 --- /dev/null +++ b/libexec/ld.elf_so/arch/x86_64/rtld_start.S @@ -0,0 +1,105 @@ +/* $NetBSD: rtld_start.S,v 1.8 2010/12/05 00:56:07 joerg Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + .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 diff --git a/lib/csu/i386-elf/crt1_c.c b/libexec/ld.elf_so/debug.c similarity index 52% rename from lib/csu/i386-elf/crt1_c.c rename to libexec/ld.elf_so/debug.c index f60e8b64f..e8af26ec5 100644 --- a/lib/csu/i386-elf/crt1_c.c +++ b/libexec/ld.elf_so/debug.c @@ -1,6 +1,8 @@ -/* LINTLIBRARY */ -/*- - * Copyright 1996-1998 John D. Polstra. +/* $NetBSD: debug.c,v 1.6 2004/10/22 05:39:56 skrll Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,6 +13,11 @@ * 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 @@ -22,77 +29,36 @@ * 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 - -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 +#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 -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 diff --git a/lib/csu/i386-elf/crt1_s.S b/libexec/ld.elf_so/debug.h similarity index 58% rename from lib/csu/i386-elf/crt1_s.S rename to libexec/ld.elf_so/debug.h index e101330e2..f4abc12a4 100644 --- a/lib/csu/i386-elf/crt1_s.S +++ b/libexec/ld.elf_so/debug.h @@ -1,5 +1,8 @@ -/*- - * Copyright 2009 Konstantin Belousov. +/* $NetBSD: debug.h,v 1.5 2002/09/12 22:56:28 mycroft Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,6 +13,11 @@ * 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 @@ -21,31 +29,30 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ +/* + * Support for printing debugging messages. + */ + +#ifndef DEBUG_H +#define DEBUG_H + + +#ifdef DEBUG + +extern void debug_printf __P((const char *, ...)) + __attribute__((__format__(__printf__, 1, 2))); +extern int debug; + +# define dbg(a) debug_printf a +#else +# define dbg(a) ((void) 0) +#endif +#ifdef RTLD_DEBUG_RELOC +# define rdbg(a) debug_printf a +#else +# define rdbg(a) ((void) 0) +#endif - .text - .align 4 - .globl _start - .type _start, @function -_start: - .cfi_startproc - xorl %ebp,%ebp - pushl %ebp - .cfi_def_cfa_offset 4 - movl %esp,%ebp - .cfi_offset %ebp,-8 - .cfi_def_cfa_register %ebp - andl $0xfffffff0,%esp # align stack - leal 8(%ebp),%eax - pushl %eax # argv - pushl 4(%ebp) # argc - pushl %edx # rtld cleanup - call _start1 - int3 - .cfi_endproc - .size _start, . - _start - - .ident "$MINIX$" +#endif diff --git a/libexec/ld.elf_so/expand.c b/libexec/ld.elf_so/expand.c new file mode 100644 index 000000000..3be194d37 --- /dev/null +++ b/libexec/ld.elf_so/expand.c @@ -0,0 +1,172 @@ +/* $NetBSD: expand.c,v 1.5 2008/04/28 20:23:03 martin Exp $ */ + +/*- + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#ifndef lint +__RCSID("$NetBSD: expand.c,v 1.5 2008/04/28 20:23:03 martin Exp $"); +#endif /* not lint */ + +#include +#include +#include + +#ifdef DEBUG_EXPAND +#include +#include +#define xwarn warn +#define xerr err +size_t _rtld_expand_path(char *, size_t, const char *, const char *, + const char *); +#else +#include +#include "rtld.h" +#endif + +static const struct { + const char *name; + size_t namelen; +} bltn[] = { +#define ADD(a) { #a, sizeof(#a) - 1 }, + ADD(HWCAP) /* SSE, MMX, etc */ + ADD(ISALIST) /* XXX */ + ADD(ORIGIN) /* dirname argv[0] */ + ADD(OSNAME) /* uname -s */ + ADD(OSREL) /* uname -r */ + ADD(PLATFORM) /* uname -p */ +}; + +static int mib[3][2] = { + { CTL_KERN, KERN_OSTYPE }, + { CTL_KERN, KERN_OSRELEASE }, + { CTL_HW, HW_MACHINE_ARCH }, +}; + +static size_t +expand(char *buf, const char *execname, int what, size_t bl) +{ + const char *p, *ep; + char *bp = buf; + size_t len; + char name[32]; + + switch (what) { + case 0: /* HWCAP XXX: Not yet */ + case 1: /* ISALIST XXX: Not yet */ + return 0; + + case 2: /* ORIGIN */ + if (execname == NULL) + xerr(1, "execname not specified in AUX vector"); + if ((ep = strrchr(p = execname, '/')) == NULL) + xerr(1, "bad execname `%s' in AUX vector", execname); + break; + + case 3: /* OSNAME */ + case 4: /* OSREL */ + case 5: /* PLATFORM */ + len = sizeof(name); + if (sysctl(mib[what - 3], 2, name, &len, NULL, 0) == -1) { + xwarn("sysctl"); + return 0; + } + ep = (p = name) + len - 1; + break; + default: + return 0; + } + + while (p != ep && bl) + *bp++ = *p++, bl--; + + return bp - buf; +} + + +size_t +_rtld_expand_path(char *buf, size_t bufsize, const char *execname, + const char *bp, const char *ep) +{ + size_t i, ds = bufsize; + char *dp = buf; + const char *p; + int br; + + for (p = bp; p < ep;) { + if (*p == '$') { + br = *++p == '{'; + + if (br) + p++; + + for (i = 0; i < sizeof(bltn) / sizeof(bltn[0]); i++) { + size_t s = bltn[i].namelen; + const char *es = p + s; + + if ((br && *es != '}') || + (!br && (es != ep && + isalpha((unsigned char)*es)))) + continue; + + if (strncmp(bltn[i].name, p, s) == 0) { + size_t ls = expand(dp, execname, i, ds); + if (ls >= ds) + return bufsize; + ds -= ls; + dp += ls; + p = es + br; + goto done; + } + } + p -= br + 1; + + } + *dp++ = *p++; + ds--; +done:; + } + *dp = '\0'; + return dp - buf; +} + +#ifdef DEBUG_EXPAND +int +main(int argc, char *argv[]) +{ + char buf[1024]; + size_t i; + + for (i = 1; i < argc; i++) { + char *p = argv[i], *ep = argv[i] + strlen(p); + size_t n = _rtld_expand_path(buf, sizeof(buf), argv[0], p, ep); + printf("%s\n", buf); + } + return 0; +} +#endif diff --git a/libexec/ld.elf_so/headers.c b/libexec/ld.elf_so/headers.c new file mode 100644 index 000000000..0725530c0 --- /dev/null +++ b/libexec/ld.elf_so/headers.c @@ -0,0 +1,369 @@ +/* $NetBSD: headers.c,v 1.39 2011/01/16 01:22:29 matt Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas + * Copyright 2002 Charles M. Hannum + * 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 . + */ + +#include +#ifndef lint +__RCSID("$NetBSD: headers.c,v 1.39 2011/01/16 01:22:29 matt Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "rtld.h" + +/* + * Process a shared object's DYNAMIC section, and save the important + * information in its Obj_Entry structure. + */ +void +_rtld_digest_dynamic(const char *execname, Obj_Entry *obj) +{ + Elf_Dyn *dynp; + Needed_Entry **needed_tail = &obj->needed; + const Elf_Dyn *dyn_rpath = NULL; + bool use_pltrel = false; + bool use_pltrela = false; + Elf_Addr relsz = 0, relasz = 0; + Elf_Addr pltrel = 0, pltrelsz = 0; + Elf_Addr init = 0, fini = 0; + + for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) { + switch (dynp->d_tag) { + + case DT_REL: + obj->rel = (const Elf_Rel *) + (obj->relocbase + dynp->d_un.d_ptr); + break; + + case DT_RELSZ: + relsz = dynp->d_un.d_val; + break; + + case DT_RELENT: + assert(dynp->d_un.d_val == sizeof(Elf_Rel)); + break; + + case DT_JMPREL: + pltrel = dynp->d_un.d_ptr; + break; + + case DT_PLTRELSZ: + pltrelsz = dynp->d_un.d_val; + break; + + case DT_RELA: + obj->rela = (const Elf_Rela *) + (obj->relocbase + dynp->d_un.d_ptr); + break; + + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + + case DT_RELAENT: + assert(dynp->d_un.d_val == sizeof(Elf_Rela)); + break; + + case DT_PLTREL: + use_pltrel = dynp->d_un.d_val == DT_REL; + use_pltrela = dynp->d_un.d_val == DT_RELA; + assert(use_pltrel || use_pltrela); + break; + + case DT_SYMTAB: + obj->symtab = (const Elf_Sym *) + (obj->relocbase + dynp->d_un.d_ptr); + break; + + case DT_SYMENT: + assert(dynp->d_un.d_val == sizeof(Elf_Sym)); + break; + + case DT_STRTAB: + obj->strtab = (const char *) + (obj->relocbase + dynp->d_un.d_ptr); + break; + + case DT_STRSZ: + obj->strsize = dynp->d_un.d_val; + break; + + case DT_HASH: + { + const Elf_Symindx *hashtab = (const Elf_Symindx *) + (obj->relocbase + dynp->d_un.d_ptr); + + if (hashtab[0] > UINT32_MAX) + obj->nbuckets = UINT32_MAX; + else + obj->nbuckets = hashtab[0]; + obj->nchains = hashtab[1]; + obj->buckets = hashtab + 2; + obj->chains = obj->buckets + obj->nbuckets; + /* + * Should really be in _rtld_relocate_objects, + * but _rtld_symlook_obj might be used before. + */ + if (obj->nbuckets) { + fast_divide32_prepare(obj->nbuckets, + &obj->nbuckets_m, + &obj->nbuckets_s1, + &obj->nbuckets_s2); + } + } + break; + + case DT_NEEDED: + { + Needed_Entry *nep = NEW(Needed_Entry); + + nep->name = dynp->d_un.d_val; + nep->obj = NULL; + nep->next = NULL; + + *needed_tail = nep; + needed_tail = &nep->next; + } + break; + + case DT_PLTGOT: + obj->pltgot = (Elf_Addr *) + (obj->relocbase + dynp->d_un.d_ptr); + break; + + case DT_TEXTREL: + obj->textrel = true; + break; + + case DT_SYMBOLIC: + obj->symbolic = true; + break; + + case DT_RPATH: + /* + * We have to wait until later to process this, because + * we might not have gotten the address of the string + * table yet. + */ + dyn_rpath = dynp; + break; + + case DT_SONAME: + /* Not used by the dynamic linker. */ + break; + + case DT_INIT: + init = dynp->d_un.d_ptr; + break; + + case DT_FINI: + fini = dynp->d_un.d_ptr; + break; + + /* + * Don't process DT_DEBUG on MIPS as the dynamic section + * is mapped read-only. DT_MIPS_RLD_MAP is used instead. + * XXX: n32/n64 may use DT_DEBUG, not sure yet. + */ +#ifndef __mips__ + case DT_DEBUG: +#ifdef RTLD_LOADER + dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug; +#endif + break; +#endif + +#ifdef __mips__ + case DT_MIPS_LOCAL_GOTNO: + obj->local_gotno = dynp->d_un.d_val; + break; + + case DT_MIPS_SYMTABNO: + obj->symtabno = dynp->d_un.d_val; + break; + + case DT_MIPS_GOTSYM: + obj->gotsym = dynp->d_un.d_val; + break; + + case DT_MIPS_RLD_MAP: +#ifdef RTLD_LOADER + *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr) + &_rtld_debug; +#endif + break; +#endif +#ifdef __powerpc__ + case DT_PPC_GOT: + obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); + break; +#endif + case DT_FLAGS_1: + obj->z_now = + ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0); + obj->z_nodelete = + ((dynp->d_un.d_val & DF_1_NODELETE) != 0); + obj->z_initfirst = + ((dynp->d_un.d_val & DF_1_INITFIRST) != 0); + obj->z_noopen = + ((dynp->d_un.d_val & DF_1_NOOPEN) != 0); + break; + } + } + + obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz); + obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz); + if (use_pltrel) { + obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel); + obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz); + obj->pltrelalim = 0; + /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL. + Trim rel(a)lim to save time later. */ + if (obj->rellim && obj->pltrel && + obj->rellim > obj->pltrel && + obj->rellim <= obj->pltrellim) + obj->rellim = obj->pltrel; + } else if (use_pltrela) { + obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel); + obj->pltrellim = 0; + obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz); + /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL. + Trim rel(a)lim to save time later. */ + if (obj->relalim && obj->pltrela && + obj->relalim > obj->pltrela && + obj->relalim <= obj->pltrelalim) + obj->relalim = obj->pltrela; + } + +#if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS) + if (init != 0) + obj->init = (void (*)(void)) + _rtld_function_descriptor_alloc(obj, NULL, init); + if (fini != 0) + obj->fini = (void (*)(void)) + _rtld_function_descriptor_alloc(obj, NULL, fini); +#else + if (init != 0) + obj->init = (void (*)(void)) + (obj->relocbase + init); + if (fini != 0) + obj->fini = (void (*)(void)) + (obj->relocbase + fini); +#endif + + if (dyn_rpath != NULL) { + _rtld_add_paths(execname, &obj->rpaths, obj->strtab + + dyn_rpath->d_un.d_val); + } +} + +/* + * Process a shared object's program header. This is used only for the + * main program, when the kernel has already loaded the main program + * into memory before calling the dynamic linker. It creates and + * returns an Obj_Entry structure. + */ +Obj_Entry * +_rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry) +{ + Obj_Entry *obj; + const Elf_Phdr *phlimit = phdr + phnum; + const Elf_Phdr *ph; + int nsegs = 0; + Elf_Addr vaddr; + + obj = _rtld_obj_new(); + + for (ph = phdr; ph < phlimit; ++ph) { + if (ph->p_type != PT_PHDR) + continue; + + obj->phdr = (void *)(uintptr_t)phdr->p_vaddr; + obj->phsize = phdr->p_memsz; + obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr); + dbg(("headers: phdr %p phsize %zu relocbase %lx", obj->phdr, + obj->phsize, (long)obj->relocbase)); + break; + } + assert(obj->phdr == phdr); + + for (ph = phdr; ph < phlimit; ++ph) { + vaddr = (Elf_Addr)(uintptr_t)(obj->relocbase + ph->p_vaddr); + switch (ph->p_type) { + + case PT_INTERP: + obj->interp = (const char *)(uintptr_t)vaddr; + break; + + case PT_LOAD: + assert(nsegs < 2); + if (nsegs == 0) { /* First load segment */ + obj->vaddrbase = round_down(vaddr); + obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase; + obj->textsize = round_up(vaddr + ph->p_memsz) - + obj->vaddrbase; + } else { /* Last load segment */ + obj->mapsize = round_up(vaddr + ph->p_memsz) - + obj->vaddrbase; + } + ++nsegs; + break; + + case PT_DYNAMIC: + obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr; + break; + } + } + assert(nsegs == 2); + + obj->entry = entry; + return obj; +} diff --git a/libexec/ld.elf_so/ld.elf_so.1 b/libexec/ld.elf_so/ld.elf_so.1 new file mode 100644 index 000000000..e8bb619b6 --- /dev/null +++ b/libexec/ld.elf_so/ld.elf_so.1 @@ -0,0 +1,224 @@ +.\" $NetBSD: ld.elf_so.1,v 1.15 2010/12/17 08:50:26 wiz Exp $ +.\" +.\" Copyright (c) 2001 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Nick Hudson. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd December 17, 2010 +.Dt LD.ELF_SO 1 +.Os +.Sh NAME +.Nm ld.elf_so +.Nd run-time link-editor (linker) +.Sh DESCRIPTION +.Nm +is a self-contained, position independent program +image providing run-time support for loading and +link-editing shared objects into a process' address space. +It uses information stored in data structures within the binary (see +.Xr elf 5 ) +and environment variables to determine which shared objects are needed. +These shared objects are loaded at a convenient virtual address using the +.Xr mmap 2 +system call. +After all shared objects have been successfully loaded, +.Nm +proceeds to resolve external references from both +the main program and all objects loaded. +Once all required references are resolved control is +passed to the program via its entry point. +.Ss Startup +On the execution of a dynamically linked binary the kernel will load +the program and its run-time linker as specified in the PT_INTERP +section in the program header. +At this point, instead of passing control directly to the program, +the kernel passes control to the specified linker. +An auxiliary vector of information is passed that includes +the address of the program header, the size of each entry in the header, +and the number of entries. +The entry point of the program and the base address of where +.Nm +is loaded is also supplied. +.Ss Finding objects +Each +.Xr elf 5 +object file may contain information in its dynamic (PT_DYNAMIC) section +about which shared objects it requires (often referred to as dependencies). +These dependencies are specified in the optional DT_NEEDED entry within +the dynamic section. +Each DT_NEEDED entry refers to a filename string of +the shared object that is to be searched for. +.Pp +The linker will search for libraries in three lists of paths: +.Bl -enum +.It +A user defined list of paths as specified in LD_LIBRARY_PATH and +.Xr ld.so.conf 5 . +.Pp +The use of ld.so.conf should be avoided as the setting of a global search +path can present a security risk. +.It +A list of paths specified within a shared object using a DT_RPATH entry in +the dynamic section. +This is defined at shared object link time. +.It +The list of default paths which is set to +.Pa /usr/lib . +.El +.Pp +.Nm +will expand the following variables if present in the paths: +.Bl -tag -width $PLATFORM +.It $HWCAP +Processor hardware capabilities, for example FPU, MMX, SSE. +Currently unimplemented. +.It $ISALIST +List of instructions sets this processor can execute. +Currently unimplemented. +.It $ORIGIN +The directory of the main object. +Implemented in +.Nm +but the kernel support is currently disabled. +.It $OSNAME +The value of the +.Dv kern.ostype +.Xr sysctl 3 . +.It $OSREL +The value of the +.Dv kern.osrelease +.Xr sysctl 3 . +.It $PLATFORM +The value of the +.Dv hw.machine_arch +.Xr sysctl 3 . +.El +.Pp +Both +.Dv ${VARIABLE} +and +.Dv $VARIABLE +are recognized. +.Pp +The filename string can be considered free form, however, it will almost +always take the form lib\*[Lt]name\*[Gt].so.\*[Lt]number\*[Gt], +where name specifies the +.Sq library +name and number is conceptually the library's major version number. +.Pp +This name and another of the form lib\*[Lt]name\*[Gt].so are normally +symbolic links to the real shared object which has a filename of the form +lib\*[Lt]name\*[Gt].so.\*[Lt]major\*[Gt].\*[Lt]minor\*[Gt][.\*[Lt]teeny\*[Gt]]. +This naming convention allows a versioning scheme similar to +.Xr a.out 5 . +.Ss Relocation +.Nm +will perform all necessary relocations immediately except for relocations +relating to the Procedure Linkage Table (PLT). +The PLT is used as a indirection method for procedure +calls to globally defined functions. +It allows, through the use of intermediate code, the delayed binding of +a call to a globally defined function to be performed at procedure call time. +This +.Sq lazy +method is the default (see LD_BIND_NOW). +.Ss Initialization +A mechanism is provided for initialization and termination routines +to be called, on a per-object basis before execution of the program proper +begins or after the program has completed. +This gives a shared object an opportunity to perform +any extra set-up or completion work. +.Pp +The DT_INIT and DT_FINI entries in the dynamic section specify the addresses +of the initialization and termination functions, respectively, for +the shared object. +.Nm +arranges for each initialization function to be called before control is passed +to the program and for the termination functions to be called by using +.Xr atexit 3 . +.Pp +This mechanism is exploited by the system-supplied constructor +initialization and destructor code located in +.Pa /usr/lib/crtbeginS.o +and +.Pa /usr/lib/crtendS.o . +These files are automatically included by +.Xr cc 1 +and +.Xr c++ 1 +in the list of object-code files passed to +.Xr ld 1 +when building a shared C or C++ object. +.Sh ENVIRONMENT +If the following environment variables exist they will be used by +.Nm . +.Bl -tag -width "LD_LIBRARY_PATH" +.It Ev LD_LIBRARY_PATH +A colon separated list of directories, overriding the default search path +for shared libraries. +.It Ev LD_PRELOAD +A colon or space separated list of shared object filenames to be loaded +.Em after +the main program but +.Em before +its shared object dependencies. +Space is allowed as a separator for backwards compatibility only. +Support may be removed in a future release and should not be relied upon. +.It Ev LD_BIND_NOW +If defined immediate binding of Procedure Link Table (PLT) entries is +performed instead of the default lazy method. +.It Ev LD_DEBUG +If defined a variety of debug information will be written to the standard +error of an dynamically linked executed when it is run. +This variable is only recognized if +.Nm +was compiled with debugging support +.Sy ( -DDEBUG ) . +.El +.Sh FILES +.Bl -tag -width /etc/ld.so.conf -compact +.It Pa /etc/ld.so.conf +library location hints supplied by the system administrator. +.El +.Sh SEE ALSO +.Xr ld 1 , +.Xr ld.aout_so 1 , +.Xr dlfcn 3 , +.Xr elf 5 +.Sh HISTORY +The ELF shared library model employed first appeared in Sys V R4. +.Pp +The path expansion variables first appeared in Solaris 10, and +in +.Nx 5.0 . +.Sh SECURITY CONSIDERATIONS +The environment variables +.Ev LD_LIBRARY_PATH +and +.Ev LD_PRELOAD +are not honored when executing in a set-user-ID or set-group-ID environment. +This action is taken to prevent malicious substitution of shared object +dependencies or interposition of symbols. diff --git a/libexec/ld.elf_so/load.c b/libexec/ld.elf_so/load.c new file mode 100644 index 000000000..cefda1edb --- /dev/null +++ b/libexec/ld.elf_so/load.c @@ -0,0 +1,350 @@ +/* $NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas + * Copyright 2002 Charles M. Hannum + * 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 . + */ + +#include +#ifndef lint +__RCSID("$NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "rtld.h" + +static bool _rtld_load_by_name(const char *, Obj_Entry *, Needed_Entry **, + int); + +#ifdef RTLD_LOADER +Objlist _rtld_list_main = /* Objects loaded at program startup */ + SIMPLEQ_HEAD_INITIALIZER(_rtld_list_main); +Objlist _rtld_list_global = /* Objects dlopened with RTLD_GLOBAL */ + SIMPLEQ_HEAD_INITIALIZER(_rtld_list_global); + +void +_rtld_objlist_push_head(Objlist *list, Obj_Entry *obj) +{ + Objlist_Entry *elm; + + elm = NEW(Objlist_Entry); + elm->obj = obj; + SIMPLEQ_INSERT_HEAD(list, elm, link); +} + +void +_rtld_objlist_push_tail(Objlist *list, Obj_Entry *obj) +{ + Objlist_Entry *elm; + + elm = NEW(Objlist_Entry); + elm->obj = obj; + SIMPLEQ_INSERT_TAIL(list, elm, link); +} + +Objlist_Entry * +_rtld_objlist_find(Objlist *list, const Obj_Entry *obj) +{ + Objlist_Entry *elm; + + SIMPLEQ_FOREACH(elm, list, link) { + if (elm->obj == obj) + return elm; + } + return NULL; +} +#endif + +/* + * Load a shared object into memory, if it is not already loaded. + * + * Returns a pointer to the Obj_Entry for the object. Returns NULL + * on failure. + */ +Obj_Entry * +_rtld_load_object(const char *filepath, int flags) +{ + Obj_Entry *obj; + int fd = -1; + struct stat sb; + size_t pathlen = strlen(filepath); + + for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next) + if (pathlen == obj->pathlen && !strcmp(obj->path, filepath)) + break; + + /* + * If we didn't find a match by pathname, open the file and check + * again by device and inode. This avoids false mismatches caused + * by multiple links or ".." in pathnames. + * + * To avoid a race, we open the file and use fstat() rather than + * using stat(). + */ + if (obj == NULL) { + if ((fd = open(filepath, O_RDONLY)) == -1) { + _rtld_error("Cannot open \"%s\"", filepath); + return NULL; + } + if (fstat(fd, &sb) == -1) { + _rtld_error("Cannot fstat \"%s\"", filepath); + close(fd); + return NULL; + } + for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next) { + if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) { + close(fd); + break; + } + } + } + + if (obj == NULL) { /* First use of this object, so we must map it in */ + obj = _rtld_map_object(filepath, fd, &sb); + (void)close(fd); + if (obj == NULL) + return NULL; + _rtld_digest_dynamic(filepath, obj); + + if (flags & _RTLD_DLOPEN) { + if (obj->z_noopen || (flags & _RTLD_NOLOAD)) { + dbg(("refusing to load non-loadable \"%s\"", + obj->path)); + _rtld_error("Cannot dlopen non-loadable %s", + obj->path); + munmap(obj->mapbase, obj->mapsize); + _rtld_obj_free(obj); + return OBJ_ERR; + } + } + + *_rtld_objtail = obj; + _rtld_objtail = &obj->next; + _rtld_objcount++; + _rtld_objloads++; +#ifdef RTLD_LOADER + _rtld_linkmap_add(obj); /* for GDB */ +#endif + dbg((" %p .. %p: %s", obj->mapbase, + obj->mapbase + obj->mapsize - 1, obj->path)); + if (obj->textrel) + dbg((" WARNING: %s has impure text", obj->path)); + } + + ++obj->refcount; +#ifdef RTLD_LOADER + if (flags & _RTLD_MAIN && !obj->mainref) { + obj->mainref = 1; + dbg(("adding %p (%s) to _rtld_list_main", obj, obj->path)); + _rtld_objlist_push_tail(&_rtld_list_main, obj); + } + if (flags & _RTLD_GLOBAL && !obj->globalref) { + obj->globalref = 1; + dbg(("adding %p (%s) to _rtld_list_global", obj, obj->path)); + _rtld_objlist_push_tail(&_rtld_list_global, obj); + } +#endif + return obj; +} + +static bool +_rtld_load_by_name(const char *name, Obj_Entry *obj, Needed_Entry **needed, + int flags) +{ + Library_Xform *x = _rtld_xforms; + Obj_Entry *o = NULL; + size_t j; + ssize_t i; + bool got = false; + union { + int i; + u_quad_t q; + char s[16]; + } val; + + dbg(("load by name %s %p", name, x)); + for (; x; x = x->next) { + if (strcmp(x->name, name) != 0) + continue; + + j = sizeof(val); + if ((i = _rtld_sysctl(x->ctlname, &val, &j)) == -1) { + xwarnx(_PATH_LD_HINTS ": invalid/unknown sysctl for %s (%d)", + name, errno); + break; + } + + switch (i) { + case CTLTYPE_QUAD: + xsnprintf(val.s, sizeof(val.s), "%" PRIu64, val.q); + break; + case CTLTYPE_INT: + xsnprintf(val.s, sizeof(val.s), "%d", val.i); + break; + case CTLTYPE_STRING: + break; + default: + xwarnx("unsupported sysctl type %d", (int)i); + break; + } + + dbg(("sysctl returns %s", val.s)); + + for (i = 0; i < RTLD_MAX_ENTRY && x->entry[i].value != NULL; + i++) { + dbg(("entry %ld", (unsigned long)i)); + if (strcmp(x->entry[i].value, val.s) == 0) + break; + } + + if (i == RTLD_MAX_ENTRY) { + xwarnx("sysctl value %s not found for lib%s", + val.s, name); + break; + } + + for (j = 0; j < RTLD_MAX_LIBRARY && + x->entry[i].library[j] != NULL; j++) { + o = _rtld_load_library(x->entry[i].library[j], obj, + flags); + if (o == NULL) { + xwarnx("could not load %s for %s", + x->entry[i].library[j], name); + continue; + } + got = true; + if (j == 0) + (*needed)->obj = o; + else { + /* make a new one and put it in the chain */ + Needed_Entry *ne = xmalloc(sizeof(*ne)); + ne->name = (*needed)->name; + ne->obj = o; + ne->next = (*needed)->next; + (*needed)->next = ne; + *needed = ne; + } + + } + + } + + if (got) + return true; + + return ((*needed)->obj = _rtld_load_library(name, obj, flags)) != NULL; +} + + +/* + * Given a shared object, traverse its list of needed objects, and load + * each of them. Returns 0 on success. Generates an error message and + * returns -1 on failure. + */ +int +_rtld_load_needed_objects(Obj_Entry *first, int flags) +{ + Obj_Entry *obj; + int status = 0; + + for (obj = first; obj != NULL; obj = obj->next) { + Needed_Entry *needed; + + for (needed = obj->needed; needed != NULL; + needed = needed->next) { + const char *name = obj->strtab + needed->name; +#ifdef RTLD_LOADER + Obj_Entry *nobj; +#endif + if (!_rtld_load_by_name(name, obj, &needed, + flags & ~_RTLD_NOLOAD)) + status = -1; /* FIXME - cleanup */ +#ifdef RTLD_LOADER + if (status == -1) + return status; + + if (flags & _RTLD_MAIN) + continue; + + nobj = needed->obj; + if (nobj->z_nodelete && !obj->ref_nodel) { + dbg(("obj %s nodelete", nobj->path)); + _rtld_ref_dag(nobj); + nobj->ref_nodel = true; + } +#endif + } + } + + return status; +} + +#ifdef RTLD_LOADER +int +_rtld_preload(const char *preload_path) +{ + const char *path; + char *cp, *buf; + int status = 0; + + if (preload_path != NULL && *preload_path != '\0') { + cp = buf = xstrdup(preload_path); + while ((path = strsep(&cp, " :")) != NULL && status == 0) { + if (!_rtld_load_object(path, _RTLD_MAIN)) + status = -1; + else + dbg((" preloaded \"%s\"", path)); + } + xfree(buf); + } + + return status; +} +#endif diff --git a/libexec/ld.elf_so/map_object.c b/libexec/ld.elf_so/map_object.c new file mode 100644 index 000000000..71cc85335 --- /dev/null +++ b/libexec/ld.elf_so/map_object.c @@ -0,0 +1,422 @@ +/* $NetBSD: map_object.c,v 1.41 2010/10/16 10:27:07 skrll Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas + * Copyright 2002 Charles M. Hannum + * 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 +#ifndef lint +__RCSID("$NetBSD: map_object.c,v 1.41 2010/10/16 10:27:07 skrll Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "rtld.h" + +static int protflags(int); /* Elf flags -> mmap protection */ + +#define EA_UNDEF (~(Elf_Addr)0) + +/* + * Map a shared object into memory. The argument is a file descriptor, + * which must be open on the object and positioned at its beginning. + * + * The return value is a pointer to a newly-allocated Obj_Entry structure + * for the shared object. Returns NULL on failure. + */ +Obj_Entry * +_rtld_map_object(const char *path, int fd, const struct stat *sb) +{ + Obj_Entry *obj; + Elf_Ehdr *ehdr; + Elf_Phdr *phdr; + size_t phsize; + Elf_Phdr *phlimit; + Elf_Phdr *segs[2]; + int nsegs; + caddr_t mapbase = MAP_FAILED; + size_t mapsize = 0; + int mapflags; + Elf_Off base_offset; +#ifdef MAP_ALIGNED + Elf_Addr base_alignment; +#endif + Elf_Addr base_vaddr; + Elf_Addr base_vlimit; + Elf_Addr text_vlimit; + int text_flags; + caddr_t base_addr; + Elf_Off data_offset; + Elf_Addr data_vaddr; + Elf_Addr data_vlimit; + int data_flags; + caddr_t data_addr; + Elf_Addr phdr_vaddr; + size_t phdr_memsz; + caddr_t gap_addr; + size_t gap_size; + int i; +#ifdef RTLD_LOADER + Elf_Addr clear_vaddr; + caddr_t clear_addr; + size_t nclear; +#endif + + if (sb != NULL && sb->st_size < (off_t)sizeof (Elf_Ehdr)) { + _rtld_error("%s: unrecognized file format1", path); + return NULL; + } + + obj = _rtld_obj_new(); + obj->path = xstrdup(path); + obj->pathlen = strlen(path); + if (sb != NULL) { + obj->dev = sb->st_dev; + obj->ino = sb->st_ino; + } + + ehdr = mmap(NULL, _rtld_pagesz, PROT_READ, MAP_FILE | MAP_SHARED, fd, + (off_t)0); + obj->ehdr = ehdr; + if (ehdr == MAP_FAILED) { + _rtld_error("%s: read error: %s", path, xstrerror(errno)); + goto bad; + } + /* Make sure the file is valid */ + if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 || + ehdr->e_ident[EI_CLASS] != ELFCLASS) { + _rtld_error("%s: unrecognized file format2 [%x != %x]", path, + ehdr->e_ident[EI_CLASS], ELFCLASS); + goto bad; + } + /* Elf_e_ident includes class */ + if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_version != EV_CURRENT || + ehdr->e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) { + _rtld_error("%s: unsupported file version", path); + goto bad; + } + if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) { + _rtld_error("%s: unsupported file type", path); + goto bad; + } + switch (ehdr->e_machine) { + ELFDEFNNAME(MACHDEP_ID_CASES) + default: + _rtld_error("%s: unsupported machine", path); + goto bad; + } + + /* + * We rely on the program header being in the first page. This is + * not strictly required by the ABI specification, but it seems to + * always true in practice. And, it simplifies things considerably. + */ + assert(ehdr->e_phentsize == sizeof(Elf_Phdr)); + assert(ehdr->e_phoff + ehdr->e_phnum * sizeof(Elf_Phdr) <= + _rtld_pagesz); + + /* + * Scan the program header entries, and save key information. + * + * We rely on there being exactly two load segments, text and data, + * in that order. + */ + phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff); + phsize = ehdr->e_phnum * sizeof(phdr[0]); + obj->phdr = NULL; + phdr_vaddr = EA_UNDEF; + phdr_memsz = 0; + phlimit = phdr + ehdr->e_phnum; + nsegs = 0; + while (phdr < phlimit) { + switch (phdr->p_type) { + case PT_INTERP: + obj->interp = (void *)(uintptr_t)phdr->p_vaddr; + dbg(("%s: PT_INTERP %p", obj->path, obj->interp)); + break; + + case PT_LOAD: + if (nsegs < 2) + segs[nsegs] = phdr; + ++nsegs; + dbg(("%s: PT_LOAD %p", obj->path, phdr)); + break; + + case PT_PHDR: + phdr_vaddr = phdr->p_vaddr; + phdr_memsz = phdr->p_memsz; + dbg(("%s: PT_PHDR %p phsize %zu", obj->path, + (void *)(uintptr_t)phdr_vaddr, phdr_memsz)); + break; + + case PT_DYNAMIC: + obj->dynamic = (void *)(uintptr_t)phdr->p_vaddr; + dbg(("%s: PT_DYNAMIC %p", obj->path, obj->dynamic)); + break; + } + + ++phdr; + } + phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff); + obj->entry = (void *)(uintptr_t)ehdr->e_entry; + if (!obj->dynamic) { + _rtld_error("%s: not dynamically linked", path); + goto bad; + } + if (nsegs != 2) { + _rtld_error("%s: wrong number of segments (%d != 2)", path, + nsegs); + goto bad; + } + + /* + * Map the entire address space of the object as a file + * region to stake out our contiguous region and establish a + * base for relocation. We use a file mapping so that + * the kernel will give us whatever alignment is appropriate + * for the platform we're running on. + * + * We map it using the text protection, map the data segment + * into the right place, then map an anon segment for the bss + * and unmap the gaps left by padding to alignment. + */ + +#ifdef MAP_ALIGNED + base_alignment = segs[0]->p_align; +#endif + base_offset = round_down(segs[0]->p_offset); + base_vaddr = round_down(segs[0]->p_vaddr); + base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz); + text_vlimit = round_up(segs[0]->p_vaddr + segs[0]->p_memsz); + text_flags = protflags(segs[0]->p_flags); + data_offset = round_down(segs[1]->p_offset); + data_vaddr = round_down(segs[1]->p_vaddr); + data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz); + data_flags = protflags(segs[1]->p_flags); +#ifdef RTLD_LOADER + clear_vaddr = segs[1]->p_vaddr + segs[1]->p_filesz; +#endif + + obj->textsize = text_vlimit - base_vaddr; + obj->vaddrbase = base_vaddr; + obj->isdynamic = ehdr->e_type == ET_DYN; + + obj->phdr_loaded = false; + for (i = 0; i < nsegs; i++) { + if (phdr_vaddr != EA_UNDEF && + segs[i]->p_vaddr <= phdr_vaddr && + segs[i]->p_memsz >= phdr_memsz) { + obj->phdr_loaded = true; + break; + } + if (segs[i]->p_offset <= ehdr->e_phoff && + segs[i]->p_memsz >= phsize) { + phdr_vaddr = segs[i]->p_vaddr + ehdr->e_phoff; + phdr_memsz = phsize; + obj->phdr_loaded = true; + break; + } + } + if (obj->phdr_loaded) { + obj->phdr = (void *)(uintptr_t)phdr_vaddr; + obj->phsize = phdr_memsz; + } else { + Elf_Phdr *buf; + buf = xmalloc(phsize); + if (buf == NULL) { + _rtld_error("%s: cannot allocate program header", path); + goto bad; + } + memcpy(buf, phdr, phsize); + obj->phdr = buf; + obj->phsize = phsize; + } + dbg(("%s: phdr %p phsize %zu (%s)", obj->path, obj->phdr, obj->phsize, + obj->phdr_loaded ? "loaded" : "allocated")); + + /* Unmap header if it overlaps the first load section. */ + if (base_offset < _rtld_pagesz) { + munmap(ehdr, _rtld_pagesz); + obj->ehdr = MAP_FAILED; + } + + /* + * Calculate log2 of the base section alignment. + */ + mapflags = 0; +#ifdef MAP_ALIGNED + if (base_alignment > _rtld_pagesz) { + unsigned int log2 = 0; + for (; base_alignment > 1; base_alignment >>= 1) + log2++; + mapflags = MAP_ALIGNED(log2); + } +#endif + +#ifdef RTLD_LOADER + base_addr = obj->isdynamic ? NULL : (caddr_t)base_vaddr; +#else + base_addr = NULL; +#endif + mapsize = base_vlimit - base_vaddr; + mapbase = mmap(base_addr, mapsize, text_flags, + mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset); + if (mapbase == MAP_FAILED) { + _rtld_error("mmap of entire address space failed: %s", + xstrerror(errno)); + goto bad; + } + + /* Overlay the data segment onto the proper region. */ + data_addr = mapbase + (data_vaddr - base_vaddr); + if (mmap(data_addr, data_vlimit - data_vaddr, data_flags, + MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, data_offset) == + MAP_FAILED) { + _rtld_error("mmap of data failed: %s", xstrerror(errno)); + goto bad; + } + + /* Overlay the bss segment onto the proper region. */ + if (mmap(mapbase + data_vlimit - base_vaddr, base_vlimit - data_vlimit, + data_flags, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) == + MAP_FAILED) { + _rtld_error("mmap of bss failed: %s", xstrerror(errno)); + goto bad; + } + + /* Unmap the gap between the text and data. */ + gap_addr = mapbase + round_up(text_vlimit - base_vaddr); + gap_size = data_addr - gap_addr; + if (gap_size != 0 && mprotect(gap_addr, gap_size, PROT_NONE) == -1) { + _rtld_error("mprotect of text -> data gap failed: %s", + xstrerror(errno)); + goto bad; + } + +#ifdef RTLD_LOADER + /* Clear any BSS in the last page of the data segment. */ + clear_addr = mapbase + (clear_vaddr - base_vaddr); + if ((nclear = data_vlimit - clear_vaddr) > 0) + memset(clear_addr, 0, nclear); + + /* Non-file portion of BSS mapped above. */ +#endif + + obj->mapbase = mapbase; + obj->mapsize = mapsize; + obj->relocbase = mapbase - base_vaddr; + + if (obj->dynamic) + obj->dynamic = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->dynamic); + if (obj->entry) + obj->entry = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->entry); + if (obj->interp) + obj->interp = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->interp); + if (obj->phdr_loaded) + obj->phdr = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->phdr); + + return obj; + +bad: + if (obj->ehdr != MAP_FAILED) + munmap(obj->ehdr, _rtld_pagesz); + if (mapbase != MAP_FAILED) + munmap(mapbase, mapsize); + _rtld_obj_free(obj); + return NULL; +} + +void +_rtld_obj_free(Obj_Entry *obj) +{ + Objlist_Entry *elm; + + xfree(obj->path); + while (obj->needed != NULL) { + Needed_Entry *needed = obj->needed; + obj->needed = needed->next; + xfree(needed); + } + while ((elm = SIMPLEQ_FIRST(&obj->dldags)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&obj->dldags, link); + xfree(elm); + } + while ((elm = SIMPLEQ_FIRST(&obj->dagmembers)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&obj->dagmembers, link); + xfree(elm); + } + if (!obj->phdr_loaded) + xfree((void *)(uintptr_t)obj->phdr); + xfree(obj); +#ifdef COMBRELOC + _rtld_combreloc_reset(obj); +#endif +} + +Obj_Entry * +_rtld_obj_new(void) +{ + Obj_Entry *obj; + + obj = CNEW(Obj_Entry); + SIMPLEQ_INIT(&obj->dldags); + SIMPLEQ_INIT(&obj->dagmembers); + return obj; +} + +/* + * Given a set of ELF protection flags, return the corresponding protection + * flags for MMAP. + */ +static int +protflags(int elfflags) +{ + int prot = 0; + + if (elfflags & PF_R) + prot |= PROT_READ; +#ifdef RTLD_LOADER + if (elfflags & PF_W) + prot |= PROT_WRITE; +#endif + if (elfflags & PF_X) + prot |= PROT_EXEC; + return prot; +} diff --git a/libexec/ld.elf_so/paths.c b/libexec/ld.elf_so/paths.c new file mode 100644 index 000000000..6ccffbc53 --- /dev/null +++ b/libexec/ld.elf_so/paths.c @@ -0,0 +1,478 @@ +/* $NetBSD: paths.c,v 1.40 2009/05/19 20:44:52 christos Exp $ */ + +/* + * Copyright 1996 Matt Thomas + * Copyright 2002 Charles M. Hannum + * 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 +#ifndef lint +__RCSID("$NetBSD: paths.c,v 1.40 2009/05/19 20:44:52 christos Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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: + * ... + */ +static void +_rtld_process_mapping(Library_Xform **lib_p, const char *bp, const char *ep) +{ + Library_Xform *hwptr = NULL; + const char *ptr, *key, *ekey, *lib, *elib, *l; + int i, j; + + dbg((" processing mapping \"%.*s\"", (int)(ep - bp), bp)); + + if ((ptr = getword(&bp, ep, WS)) == NULL || ptr == bp) + return; + + dbg((" library \"%.*s\"", (int)(bp - ptr), ptr)); + + hwptr = xmalloc(sizeof(*hwptr)); + memset(hwptr, 0, sizeof(*hwptr)); + hwptr->name = exstrdup(ptr, bp); + + bp++; + + if ((ptr = getword(&bp, ep, WS)) == NULL || ptr == bp) { + xwarnx("missing sysctl variable name"); + goto cleanup; + } + + dbg((" sysctl \"%.*s\"", (int)(bp - ptr), ptr)); + + hwptr->ctlname = exstrdup(ptr, bp); + + for (i = 0; bp++, (ptr = getword(&bp, ep, WS)) != NULL;) { + dbg((" ptr = %.*s", (int)(bp - ptr), ptr)); + if (ptr == bp) + continue; + + if (i == RTLD_MAX_ENTRY) { +no_more: + xwarnx("maximum library entries exceeded `%s'", + hwptr->name); + goto cleanup; + } + if ((key = getstr(&ptr, bp, ":")) == NULL) { + xwarnx("missing sysctl variable value for `%s'", + hwptr->name); + goto cleanup; + } + ekey = ptr++; + if ((lib = getstr(&ptr, bp, ":")) == NULL) { + xwarnx("missing sysctl library list for `%s'", + hwptr->name); + goto cleanup; + } + elib = ptr; /* No need to advance */ + for (j = 0; (l = getstr(&lib, elib, ",")) != NULL; + j++, lib++) { + if (j == RTLD_MAX_LIBRARY) { + xwarnx("maximum library entries exceeded `%s'", + hwptr->name); + goto cleanup; + } + dbg((" library \"%.*s\"", (int)(lib - l), l)); + hwptr->entry[i].library[j] = exstrdup(l, lib); + } + if (j == 0) { + xwarnx("No library map entries for `%s/%.*s'", + hwptr->name, (int)(bp - ptr), ptr); + goto cleanup; + } + j = i; + for (; (l = getstr(&key, ekey, ",")) != NULL; i++, key++) { + /* + * Allow empty key (it is valid as string + * value). Thus, we loop at least once and + * `i' is incremented. + */ + + dbg((" key \"%.*s\"", (int)(key - l), l)); + if (i == RTLD_MAX_ENTRY) + goto no_more; + if (i != j) + (void)memcpy(hwptr->entry[i].library, + hwptr->entry[j].library, + sizeof(hwptr->entry[j].library)); + hwptr->entry[i].value = exstrdup(l, key); + } + } + + if (i == 0) { + xwarnx("No library entries for `%s'", hwptr->name); + goto cleanup; + } + + hwptr->next = *lib_p; + *lib_p = hwptr; + + return; + +cleanup: + if (hwptr->name) + xfree(hwptr->name); + xfree(hwptr); +} + +void +_rtld_process_hints(const char *execname, Search_Path **path_p, + Library_Xform **lib_p, const char *fname) +{ + int fd; + char *buf, small[128]; + const char *b, *ep, *ptr; + struct stat st; + ssize_t sz; + Search_Path **head_p = path_p; + + if ((fd = open(fname, O_RDONLY)) == -1) { + /* Don't complain */ + return; + } + + /* Try to avoid mmap/stat on the file. */ + buf = small; + buf[0] = '\0'; + sz = read(fd, buf, sizeof(small)); + if (sz == -1) { + xwarn("read: %s", fname); + (void)close(fd); + return; + } + if (sz >= (ssize_t)sizeof(small)) { + if (fstat(fd, &st) == -1) { + /* Complain */ + xwarn("fstat: %s", fname); + (void)close(fd); + return; + } + + sz = (ssize_t) st.st_size; + + buf = mmap(0, sz, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); + if (buf == MAP_FAILED) { + xwarn("mmap: %s", fname); + (void)close(fd); + return; + } + } + (void)close(fd); + + while ((*path_p) != NULL) + path_p = &(*path_p)->sp_next; + + for (b = buf, ep = buf + sz; b < ep; b++) { + (void)getcstr(&b, ep, WS); + if (b == ep) + break; + + ptr = getstr(&b, ep, "\n#"); + if (*ptr == '/') { + /* + * Since '/' != '\n' and != '#', we know ptr < + * b. And we will stop when b[-1] == '/'. + */ + while (b[-1] == ' ' || b[-1] == '\t') + b--; + path_p = _rtld_append_path(head_p, path_p, execname, + ptr, b); + } else + _rtld_process_mapping(lib_p, ptr, b); + + /* + * b points one of ' ', \t, \n, # or equal to ep. So, + * make sure we are at newline or end of string. + */ + (void)getstr(&b, ep, "\n"); + } + + if (buf != small) + (void)munmap(buf, sz); +} + +/* Basic name -> sysctl MIB translation */ +int +_rtld_sysctl(const char *name, void *oldp, size_t *oldlen) +{ + const char *node, *ep; + struct sysctlnode query, *result, *newresult; + int mib[CTL_MAXNAME], r; + size_t res_size, n, i; + u_int miblen = 0; + + /* Start with 16 entries, will grow it up as needed. */ + res_size = 16 * sizeof(struct sysctlnode); + result = xmalloc(res_size); + if (result == NULL) + return (-1); + + ep = name + strlen(name); + do { + i = ~0ul; + while (*name == '/' || *name == '.') + name++; + if (name >= ep) + break; + + mib[miblen] = CTL_QUERY; + memset(&query, 0, sizeof(query)); + query.sysctl_flags = SYSCTL_VERSION; + + n = res_size; + if (sysctl(mib, miblen + 1, result, &n, &query, + sizeof(query)) == -1) { + if (errno != ENOMEM) + goto bad; + /* Grow up result */ + res_size = n; + newresult = xrealloc(result, res_size); + if (newresult == NULL) + goto bad; + result = newresult; + if (sysctl(mib, miblen + 1, result, &n, &query, + sizeof(query)) == -1) + goto bad; + } + n /= sizeof(struct sysctlnode); + + node = getstr(&name, ep, "./"); + + for (i = 0; i < n; i++) + if (matchstr(result[i].sysctl_name, node, name)) { + mib[miblen] = result[i].sysctl_num; + miblen++; + break; + } + } while (name < ep && miblen <= CTL_MAXNAME); + + if (name < ep || i == ~0ul) + goto bad; + r = SYSCTL_TYPE(result[i].sysctl_flags); + + xfree(result); + if (sysctl(mib, miblen, oldp, oldlen, NULL, 0) == -1) + return (-1); + return r; + +bad: + xfree(result); + return (-1); +} diff --git a/libexec/ld.elf_so/reloc.c b/libexec/ld.elf_so/reloc.c new file mode 100644 index 000000000..c0666b211 --- /dev/null +++ b/libexec/ld.elf_so/reloc.c @@ -0,0 +1,224 @@ +/* $NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas + * 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 . + */ + +#include +#ifndef lint +__RCSID("$NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "rtld.h" + +#ifndef RTLD_INHIBIT_COPY_RELOCS +static int _rtld_do_copy_relocation(const Obj_Entry *, const Elf_Rela *); + +static int +_rtld_do_copy_relocation(const Obj_Entry *dstobj, const Elf_Rela *rela) +{ + void *dstaddr = (void *)(dstobj->relocbase + rela->r_offset); + const Elf_Sym *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); + const char *name = dstobj->strtab + dstsym->st_name; + unsigned long hash = _rtld_elf_hash(name); + size_t size = dstsym->st_size; + const void *srcaddr; + const Elf_Sym *srcsym = NULL; + Obj_Entry *srcobj; + + for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) + if ((srcsym = _rtld_symlook_obj(name, hash, srcobj, false)) != NULL) + break; + + if (srcobj == NULL) { + _rtld_error("Undefined symbol \"%s\" referenced from COPY" + " relocation in %s", name, dstobj->path); + return (-1); + } + srcaddr = (const void *)(srcobj->relocbase + srcsym->st_value); + (void)memcpy(dstaddr, srcaddr, size); + rdbg(("COPY %s %s %s --> src=%p dst=%p size %ld", + dstobj->path, srcobj->path, name, srcaddr, + (void *)dstaddr, (long)size)); + return (0); +} +#endif /* RTLD_INHIBIT_COPY_RELOCS */ + + +/* + * Process the special R_xxx_COPY relocations in the main program. These + * copy data from a shared object into a region in the main program's BSS + * segment. + * + * Returns 0 on success, -1 on failure. + */ +int +_rtld_do_copy_relocations(const Obj_Entry *dstobj) +{ +#ifndef RTLD_INHIBIT_COPY_RELOCS + + /* COPY relocations are invalid elsewhere */ + assert(!dstobj->isdynamic); + + if (dstobj->rel != NULL) { + const Elf_Rel *rel; + for (rel = dstobj->rel; rel < dstobj->rellim; ++rel) { + if (ELF_R_TYPE(rel->r_info) == R_TYPE(COPY)) { + Elf_Rela ourrela; + ourrela.r_info = rel->r_info; + ourrela.r_offset = rel->r_offset; + ourrela.r_addend = 0; + if (_rtld_do_copy_relocation(dstobj, + &ourrela) < 0) + return (-1); + } + } + } + if (dstobj->rela != NULL) { + const Elf_Rela *rela; + for (rela = dstobj->rela; rela < dstobj->relalim; ++rela) { + if (ELF_R_TYPE(rela->r_info) == R_TYPE(COPY)) { + if (_rtld_do_copy_relocation(dstobj, rela) < 0) + return (-1); + } + } + } +#endif /* RTLD_INHIBIT_COPY_RELOCS */ + + return (0); +} + +/* + * Relocate newly-loaded shared objects. The argument is a pointer to + * the Obj_Entry for the first such object. All objects from the first + * to the end of the list of objects are relocated. Returns 0 on success, + * or -1 on failure. + */ +int +_rtld_relocate_objects(Obj_Entry *first, bool bind_now) +{ + Obj_Entry *obj; + int ok = 1; + + for (obj = first; obj != NULL; obj = obj->next) { + if (obj->nbuckets == 0 || obj->nchains == 0 || + obj->buckets == NULL || obj->symtab == NULL || + obj->strtab == NULL) { + _rtld_error("%s: Shared object has no run-time" + " symbol table", obj->path); + return -1; + } + if (obj->nbuckets == UINT32_MAX) { + _rtld_error("%s: Symbol table too large", obj->path); + return -1; + } + rdbg((" relocating %s (%ld/%ld rel/rela, %ld/%ld plt rel/rela)", + obj->path, + (long)(obj->rellim - obj->rel), + (long)(obj->relalim - obj->rela), + (long)(obj->pltrellim - obj->pltrel), + (long)(obj->pltrelalim - obj->pltrela))); + + if (obj->textrel) { + /* + * There are relocations to the write-protected text + * segment. + */ + if (mprotect(obj->mapbase, obj->textsize, + PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { + _rtld_error("%s: Cannot write-enable text " + "segment: %s", obj->path, xstrerror(errno)); + return -1; + } + } + dbg(("doing non-PLT relocations")); + if (_rtld_relocate_nonplt_objects(obj) < 0) + ok = 0; + if (obj->textrel) { /* Re-protected the text segment. */ + if (mprotect(obj->mapbase, obj->textsize, + PROT_READ | PROT_EXEC) == -1) { + _rtld_error("%s: Cannot write-protect text " + "segment: %s", obj->path, xstrerror(errno)); + return -1; + } + } + dbg(("doing lazy PLT binding")); + if (_rtld_relocate_plt_lazy(obj) < 0) + ok = 0; +#if defined(__hppa__) + bind_now = 1; +#endif + if (obj->z_now || bind_now) { + dbg(("doing immediate PLT binding")); + if (_rtld_relocate_plt_objects(obj) < 0) + ok = 0; + } + if (!ok) + return -1; + + /* Set some sanity-checking numbers in the Obj_Entry. */ + obj->magic = RTLD_MAGIC; + obj->version = RTLD_VERSION; + + /* Fill in the dynamic linker entry points. */ + obj->dlopen = dlopen; + obj->dlsym = dlsym; + obj->dlerror = dlerror; + obj->dlclose = dlclose; + obj->dladdr = dladdr; + + dbg(("fixing up PLTGOT")); + /* Set the special PLTGOT entries. */ + if (obj->pltgot != NULL) + _rtld_setup_pltgot(obj); + } + + return 0; +} diff --git a/libexec/ld.elf_so/rtld.c b/libexec/ld.elf_so/rtld.c new file mode 100644 index 000000000..24528c387 --- /dev/null +++ b/libexec/ld.elf_so/rtld.c @@ -0,0 +1,1265 @@ +/* $NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas + * Copyright 2002 Charles M. Hannum + * 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 . + */ + +#include +#ifndef lint +__RCSID("$NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "debug.h" +#include "rtld.h" + +#if !defined(lint) +#include "sysident.h" +#endif + +/* + * Function declarations. + */ +static void _rtld_init(caddr_t, caddr_t, const char *); +static void _rtld_exit(void); + +Elf_Addr _rtld(Elf_Addr *, Elf_Addr); + + +/* + * Data declarations. + */ +static char *error_message; /* Message for dlopen(), or NULL */ + +struct r_debug _rtld_debug; /* for GDB; */ +bool _rtld_trust; /* False for setuid and setgid programs */ +Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */ +Obj_Entry **_rtld_objtail; /* Link field of last object in list */ +Obj_Entry *_rtld_objmain; /* The main program shared object */ +Obj_Entry _rtld_objself; /* The dynamic linker shared object */ +u_int _rtld_objcount; /* Number of objects in _rtld_objlist */ +u_int _rtld_objloads; /* Number of objects loaded in _rtld_objlist */ +const char _rtld_path[] = _PATH_RTLD; + +/* Initialize a fake symbol for resolving undefined weak references. */ +Elf_Sym _rtld_sym_zero = { + .st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), + .st_shndx = SHN_ABS, +}; +size_t _rtld_pagesz; /* Page size, as provided by kernel */ + +Search_Path *_rtld_default_paths; +Search_Path *_rtld_paths; + +Library_Xform *_rtld_xforms; + +/* + * Global declarations normally provided by crt0. + */ +char *__progname; +char **environ; + +#if defined(RTLD_DEBUG) +#ifndef __sh__ +extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; +#else /* 32-bit SuperH */ +register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12"); +#endif +#endif /* RTLD_DEBUG */ +extern Elf_Dyn _DYNAMIC; + +static void _rtld_call_fini_functions(int); +static void _rtld_call_init_functions(void); +static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int); +static void _rtld_initlist_tsort(Objlist *, int); +static Obj_Entry *_rtld_dlcheck(void *); +static void _rtld_init_dag(Obj_Entry *); +static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *); +static void _rtld_objlist_remove(Objlist *, Obj_Entry *); +static void _rtld_objlist_clear(Objlist *); +static void _rtld_unload_object(Obj_Entry *, bool); +static void _rtld_unref_dag(Obj_Entry *); +static Obj_Entry *_rtld_obj_from_addr(const void *); + +static void +_rtld_call_fini_functions(int force) +{ + Objlist_Entry *elm; + Objlist finilist; + Obj_Entry *obj; + + dbg(("_rtld_call_fini_functions(%d)", force)); + + SIMPLEQ_INIT(&finilist); + _rtld_initlist_tsort(&finilist, 1); + + /* First pass: objects _not_ marked with DF_1_INITFIRST. */ + SIMPLEQ_FOREACH(elm, &finilist, link) { + obj = elm->obj; + if (obj->refcount > 0 && !force) { + continue; + } + if (obj->fini == NULL || obj->fini_called || obj->z_initfirst) { + continue; + } + dbg (("calling fini function %s at %p", obj->path, + (void *)obj->fini)); + obj->fini_called = 1; + (*obj->fini)(); + } + + /* Second pass: objects marked with DF_1_INITFIRST. */ + SIMPLEQ_FOREACH(elm, &finilist, link) { + obj = elm->obj; + if (obj->refcount > 0 && !force) { + continue; + } + if (obj->fini == NULL || obj->fini_called) { + continue; + } + dbg (("calling fini function %s at %p (DF_1_INITFIRST)", + obj->path, (void *)obj->fini)); + obj->fini_called = 1; + (*obj->fini)(); + } + + _rtld_objlist_clear(&finilist); +} + +static void +_rtld_call_init_functions() +{ + Objlist_Entry *elm; + Objlist initlist; + Obj_Entry *obj; + + dbg(("_rtld_call_init_functions()")); + SIMPLEQ_INIT(&initlist); + _rtld_initlist_tsort(&initlist, 0); + + /* First pass: objects marked with DF_1_INITFIRST. */ + SIMPLEQ_FOREACH(elm, &initlist, link) { + obj = elm->obj; + if (obj->init == NULL || obj->init_called || !obj->z_initfirst) { + continue; + } + dbg (("calling init function %s at %p (DF_1_INITFIRST)", + obj->path, (void *)obj->init)); + obj->init_called = 1; + (*obj->init)(); + } + + /* Second pass: all other objects. */ + SIMPLEQ_FOREACH(elm, &initlist, link) { + obj = elm->obj; + if (obj->init == NULL || obj->init_called) { + continue; + } + dbg (("calling init function %s at %p", obj->path, + (void *)obj->init)); + obj->init_called = 1; + (*obj->init)(); + } + + _rtld_objlist_clear(&initlist); +} + +/* + * Initialize the dynamic linker. The argument is the address at which + * the dynamic linker has been mapped into memory. The primary task of + * this function is to create an Obj_Entry for the dynamic linker and + * to resolve the PLT relocation for platforms that need it (those that + * define __HAVE_FUNCTION_DESCRIPTORS + */ +static void +_rtld_init(caddr_t mapbase, caddr_t relocbase, const char *execname) +{ + + /* Conjure up an Obj_Entry structure for the dynamic linker. */ + _rtld_objself.path = __UNCONST(_rtld_path); + _rtld_objself.pathlen = sizeof(_rtld_path)-1; + _rtld_objself.rtld = true; + _rtld_objself.mapbase = mapbase; + _rtld_objself.relocbase = relocbase; + _rtld_objself.dynamic = (Elf_Dyn *) &_DYNAMIC; + _rtld_objself.strtab = "_rtld_sym_zero"; + + /* + * Set value to -relocbase so that + * + * _rtld_objself.relocbase + _rtld_sym_zero.st_value == 0 + * + * This allows unresolved references to weak symbols to be computed + * to a value of 0. + */ + _rtld_sym_zero.st_value = -(uintptr_t)relocbase; + + _rtld_digest_dynamic(_rtld_path, &_rtld_objself); + assert(!_rtld_objself.needed); +#if !defined(__hppa__) + assert(!_rtld_objself.pltrel && !_rtld_objself.pltrela); +#else + _rtld_relocate_plt_objects(&_rtld_objself); +#endif +#if !defined(__mips__) && !defined(__hppa__) + assert(!_rtld_objself.pltgot); +#endif +#if !defined(__arm__) && !defined(__mips__) && !defined(__sh__) + /* ARM, MIPS and SH{3,5} have a bogus DT_TEXTREL. */ + assert(!_rtld_objself.textrel); +#endif + + _rtld_add_paths(execname, &_rtld_default_paths, + RTLD_DEFAULT_LIBRARY_PATH); + +#ifdef RTLD_ARCH_SUBDIR + _rtld_add_paths(execname, &_rtld_default_paths, + RTLD_DEFAULT_LIBRARY_PATH "/" RTLD_ARCH_SUBDIR); +#endif + + /* + * Set up the _rtld_objlist pointer, so that rtld symbols can be found. + */ + _rtld_objlist = &_rtld_objself; + + /* Make the object list empty again. */ + _rtld_objlist = NULL; + _rtld_objtail = &_rtld_objlist; + _rtld_objcount = 0; + + _rtld_debug.r_brk = _rtld_debug_state; + _rtld_debug.r_state = RT_CONSISTENT; +} + +/* + * Cleanup procedure. It will be called (by the atexit() mechanism) just + * before the process exits. + */ +static void +_rtld_exit(void) +{ + dbg(("rtld_exit()")); + + _rtld_call_fini_functions(1); +} + +/* + * Main entry point for dynamic linking. The argument is the stack + * pointer. The stack is expected to be laid out as described in the + * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically, + * the stack pointer points to a word containing ARGC. Following that + * in the stack is a null-terminated sequence of pointers to argument + * strings. Then comes a null-terminated sequence of pointers to + * environment strings. Finally, there is a sequence of "auxiliary + * vector" entries. + * + * This function returns the entry point for the main program, the dynamic + * linker's exit procedure in sp[0], and a pointer to the main object in + * sp[1]. + */ +Elf_Addr +_rtld(Elf_Addr *sp, Elf_Addr relocbase) +{ + const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr, + *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid, + *pAUX_ruid, *pAUX_rgid; + const AuxInfo *pAUX_pagesz; + char **env, **oenvp; + const AuxInfo *aux; + const AuxInfo *auxp; + Elf_Addr *const osp = sp; + bool bind_now = 0; + const char *ld_bind_now, *ld_preload, *ld_library_path; + const char **argv; + const char *execname; + long argc; + const char **real___progname; + const Obj_Entry **real___mainprog_obj; + char ***real_environ; +#ifdef DEBUG + int i = 0; + const char *ld_debug; +#endif + + /* + * On entry, the dynamic linker itself has not been relocated yet. + * Be very careful not to reference any global data until after + * _rtld_init has returned. It is OK to reference file-scope statics + * and string constants, and to call static and global functions. + */ + /* Find the auxiliary vector on the stack. */ + /* first Elf_Word reserved to address of exit routine */ +#if defined(RTLD_DEBUG) + debug = 1; + dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp, + (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase)); + dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_, + &_DYNAMIC)); + dbg(("_ctype_ is %p", _ctype_)); +#endif + + sp += 2; /* skip over return argument space */ + argv = (const char **) &sp[1]; + argc = *(long *)sp; + sp += 2 + argc; /* Skip over argc, arguments, and NULL + * terminator */ + env = (char **) sp; + while (*sp++ != 0) { /* Skip over environment, and NULL terminator */ +#if defined(RTLD_DEBUG) + dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1])); +#endif + } + aux = (const AuxInfo *) sp; + + pAUX_base = pAUX_entry = pAUX_execfd = NULL; + pAUX_phdr = pAUX_phent = pAUX_phnum = NULL; + pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL; + pAUX_pagesz = NULL; + + execname = NULL; + + /* Digest the auxiliary vector. */ + for (auxp = aux; auxp->a_type != AT_NULL; ++auxp) { + switch (auxp->a_type) { + case AT_BASE: + pAUX_base = auxp; + break; + case AT_ENTRY: + pAUX_entry = auxp; + break; + case AT_EXECFD: + pAUX_execfd = auxp; + break; + case AT_PHDR: + pAUX_phdr = auxp; + break; + case AT_PHENT: + pAUX_phent = auxp; + break; + case AT_PHNUM: + pAUX_phnum = auxp; + break; +#ifdef AT_EUID + case AT_EUID: + pAUX_euid = auxp; + break; + case AT_RUID: + pAUX_ruid = auxp; + break; + case AT_EGID: + pAUX_egid = auxp; + break; + case AT_RGID: + pAUX_rgid = auxp; + break; +#endif +#ifdef AT_SUN_EXECNAME + case AT_SUN_EXECNAME: + execname = (const char *)(const void *)auxp->a_v; + break; +#endif + case AT_PAGESZ: + pAUX_pagesz = auxp; + break; + } + } + + /* Initialize and relocate ourselves. */ + if (pAUX_base == NULL) { + _rtld_error("Bad pAUX_base"); + _rtld_die(); + } + assert(pAUX_pagesz != NULL); + _rtld_pagesz = (int)pAUX_pagesz->a_v; + _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname); + + __progname = _rtld_objself.path; + environ = env; + + _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) == + (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) && + ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) == + (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid())); + +#ifdef DEBUG + ld_debug = NULL; +#endif + ld_bind_now = NULL; + ld_library_path = NULL; + ld_preload = NULL; + /* + * Inline avoid using normal getenv/unsetenv here as the libc + * code is quite a bit more complicated. + */ + for (oenvp = env; *env != NULL; ++env) { + static const char bind_var[] = "LD_BIND_NOW="; + static const char debug_var[] = "LD_DEBUG="; + static const char path_var[] = "LD_LIBRARY_PATH="; + static const char preload_var[] = "LD_PRELOAD="; +#define LEN(x) (sizeof(x) - 1) + + if ((*env)[0] != 'L' || (*env)[1] != 'D') { + /* + * Special case to skip most entries without + * the more expensive calls to strncmp. + */ + *oenvp++ = *env; + } else if (strncmp(*env, debug_var, LEN(debug_var)) == 0) { + if (_rtld_trust) { +#ifdef DEBUG + ld_debug = *env + LEN(debug_var); +#endif + *oenvp++ = *env; + } + } else if (strncmp(*env, bind_var, LEN(bind_var)) == 0) { + ld_bind_now = *env + LEN(bind_var); + } else if (strncmp(*env, path_var, LEN(path_var)) == 0) { + if (_rtld_trust) { + ld_library_path = *env + LEN(path_var); + *oenvp++ = *env; + } + } else if (strncmp(*env, preload_var, LEN(preload_var)) == 0) { + if (_rtld_trust) { + ld_preload = *env + LEN(preload_var); + *oenvp++ = *env; + } + } else { + *oenvp++ = *env; + } +#undef LEN + } + *oenvp++ = NULL; + + if (ld_bind_now != NULL && *ld_bind_now != '\0') + bind_now = true; + if (_rtld_trust) { +#ifdef DEBUG +#ifdef RTLD_DEBUG + debug = 0; +#endif + if (ld_debug != NULL && *ld_debug != '\0') + debug = 1; +#endif + _rtld_add_paths(execname, &_rtld_paths, ld_library_path); + } else { + execname = NULL; + } + _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms, + _PATH_LD_HINTS); + dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p", + _rtld_objself.mapbase, _rtld_objself.relocbase)); + + /* + * Load the main program, or process its program header if it is + * already loaded. + */ + if (pAUX_execfd != NULL) { /* Load the main program. */ + int fd = pAUX_execfd->a_v; + const char *obj_name = argv[0] ? argv[0] : "main program"; + dbg(("loading main program")); + _rtld_objmain = _rtld_map_object(obj_name, fd, NULL); + close(fd); + if (_rtld_objmain == NULL) + _rtld_die(); + } else { /* Main program already loaded. */ + const Elf_Phdr *phdr; + int phnum; + caddr_t entry; + + dbg(("processing main program's program header")); + assert(pAUX_phdr != NULL); + phdr = (const Elf_Phdr *) pAUX_phdr->a_v; + assert(pAUX_phnum != NULL); + phnum = pAUX_phnum->a_v; + assert(pAUX_phent != NULL); + assert(pAUX_phent->a_v == sizeof(Elf_Phdr)); + assert(pAUX_entry != NULL); + entry = (caddr_t) pAUX_entry->a_v; + _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry); + _rtld_objmain->path = xstrdup(argv[0] ? argv[0] : + "main program"); + _rtld_objmain->pathlen = strlen(_rtld_objmain->path); + } + + _rtld_objmain->mainprog = true; + + /* + * Get the actual dynamic linker pathname from the executable if + * possible. (It should always be possible.) That ensures that + * gdb will find the right dynamic linker even if a non-standard + * one is being used. + */ + if (_rtld_objmain->interp != NULL && + strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0) + _rtld_objself.path = xstrdup(_rtld_objmain->interp); + dbg(("actual dynamic linker is %s", _rtld_objself.path)); + + _rtld_digest_dynamic(execname, _rtld_objmain); + + /* Link the main program into the list of objects. */ + *_rtld_objtail = _rtld_objmain; + _rtld_objtail = &_rtld_objmain->next; + _rtld_objcount++; + _rtld_objloads++; + + _rtld_linkmap_add(_rtld_objmain); + _rtld_linkmap_add(&_rtld_objself); + + ++_rtld_objmain->refcount; + _rtld_objmain->mainref = 1; + _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain); + + if (ld_preload) { + /* + * Pre-load user-specified objects after the main program + * but before any shared object dependencies. + */ + dbg(("preloading objects")); + if (_rtld_preload(ld_preload) == -1) + _rtld_die(); + } + + dbg(("loading needed objects")); + if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1) + _rtld_die(); + + dbg(("relocating objects")); + if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1) + _rtld_die(); + + dbg(("doing copy relocations")); + if (_rtld_do_copy_relocations(_rtld_objmain) == -1) + _rtld_die(); + + /* + * Set the __progname, environ and, __mainprog_obj before + * calling anything that might use them. + */ + real___progname = _rtld_objmain_sym("__progname"); + if (real___progname) { + if (argv[0] != NULL) { + if ((*real___progname = strrchr(argv[0], '/')) == NULL) + (*real___progname) = argv[0]; + else + (*real___progname)++; + } else { + (*real___progname) = NULL; + } + } + real_environ = _rtld_objmain_sym("environ"); + if (real_environ) + *real_environ = environ; + /* + * Set __mainprog_obj for old binaries. + */ + real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj"); + if (real___mainprog_obj) + *real___mainprog_obj = _rtld_objmain; + + dbg(("calling _init functions")); + _rtld_call_init_functions(); + + dbg(("control at program entry point = %p, obj = %p, exit = %p", + _rtld_objmain->entry, _rtld_objmain, _rtld_exit)); + + /* + * Return with the entry point and the exit procedure in at the top + * of stack. + */ + + _rtld_debug_state(); /* say hello to gdb! */ + + ((void **) osp)[0] = _rtld_exit; + ((void **) osp)[1] = _rtld_objmain; + return (Elf_Addr) _rtld_objmain->entry; +} + +void +_rtld_die(void) +{ + const char *msg = dlerror(); + + if (msg == NULL) + msg = "Fatal error"; + xerrx(1, "%s", msg); +} + +static Obj_Entry * +_rtld_dlcheck(void *handle) +{ + Obj_Entry *obj; + + for (obj = _rtld_objlist; obj != NULL; obj = obj->next) + if (obj == (Obj_Entry *) handle) + break; + + if (obj == NULL || obj->dl_refcount == 0) { + xwarnx("Invalid shared object handle %p", handle); + return NULL; + } + return obj; +} + +static void +_rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev) +{ + Needed_Entry* elm; + + /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */ + + if (obj->init_done) + return; + obj->init_done = 1; + + for (elm = obj->needed; elm != NULL; elm = elm->next) { + if (elm->obj != NULL) { + _rtld_initlist_visit(list, elm->obj, rev); + } + } + + if (rev) { + _rtld_objlist_push_head(list, obj); + } else { + _rtld_objlist_push_tail(list, obj); + } +} + +static void +_rtld_initlist_tsort(Objlist* list, int rev) +{ + dbg(("_rtld_initlist_tsort")); + + Obj_Entry* obj; + + for (obj = _rtld_objlist->next; obj; obj = obj->next) { + obj->init_done = 0; + } + + for (obj = _rtld_objlist->next; obj; obj = obj->next) { + _rtld_initlist_visit(list, obj, rev); + } +} + +static void +_rtld_init_dag(Obj_Entry *root) +{ + + _rtld_init_dag1(root, root); +} + +static void +_rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj) +{ + const Needed_Entry *needed; + + if (!obj->mainref) { + if (_rtld_objlist_find(&obj->dldags, root)) + return; + dbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root, + root->path)); + _rtld_objlist_push_tail(&obj->dldags, root); + _rtld_objlist_push_tail(&root->dagmembers, obj); + } + for (needed = obj->needed; needed != NULL; needed = needed->next) + if (needed->obj != NULL) + _rtld_init_dag1(root, needed->obj); +} + +/* + * Note, this is called only for objects loaded by dlopen(). + */ +static void +_rtld_unload_object(Obj_Entry *root, bool do_fini_funcs) +{ + + _rtld_unref_dag(root); + if (root->refcount == 0) { /* We are finished with some objects. */ + Obj_Entry *obj; + Obj_Entry **linkp; + Objlist_Entry *elm; + + /* Finalize objects that are about to be unmapped. */ + if (do_fini_funcs) + _rtld_call_fini_functions(0); + + /* Remove the DAG from all objects' DAG lists. */ + SIMPLEQ_FOREACH(elm, &root->dagmembers, link) + _rtld_objlist_remove(&elm->obj->dldags, root); + + /* Remove the DAG from the RTLD_GLOBAL list. */ + if (root->globalref) { + root->globalref = 0; + _rtld_objlist_remove(&_rtld_list_global, root); + } + + /* Unmap all objects that are no longer referenced. */ + linkp = &_rtld_objlist->next; + while ((obj = *linkp) != NULL) { + if (obj->refcount == 0) { + dbg(("unloading \"%s\"", obj->path)); + if (obj->ehdr != MAP_FAILED) + munmap(obj->ehdr, _rtld_pagesz); + munmap(obj->mapbase, obj->mapsize); + _rtld_objlist_remove(&_rtld_list_global, obj); + _rtld_linkmap_delete(obj); + *linkp = obj->next; + _rtld_objcount--; + _rtld_obj_free(obj); + } else + linkp = &obj->next; + } + _rtld_objtail = linkp; + } +} + +void +_rtld_ref_dag(Obj_Entry *root) +{ + const Needed_Entry *needed; + + assert(root); + + ++root->refcount; + + dbg(("incremented reference on \"%s\" (%d)", root->path, + root->refcount)); + for (needed = root->needed; needed != NULL; + needed = needed->next) { + if (needed->obj != NULL) + _rtld_ref_dag(needed->obj); + } +} + +static void +_rtld_unref_dag(Obj_Entry *root) +{ + + assert(root); + assert(root->refcount != 0); + + --root->refcount; + dbg(("decremented reference on \"%s\" (%d)", root->path, + root->refcount)); + + if (root->refcount == 0) { + const Needed_Entry *needed; + + for (needed = root->needed; needed != NULL; + needed = needed->next) { + if (needed->obj != NULL) + _rtld_unref_dag(needed->obj); + } + } +} + +__strong_alias(__dlclose,dlclose) +int +dlclose(void *handle) +{ + Obj_Entry *root = _rtld_dlcheck(handle); + + if (root == NULL) + return -1; + + _rtld_debug.r_state = RT_DELETE; + _rtld_debug_state(); + + --root->dl_refcount; + _rtld_unload_object(root, true); + + _rtld_debug.r_state = RT_CONSISTENT; + _rtld_debug_state(); + + return 0; +} + +__strong_alias(__dlerror,dlerror) +char * +dlerror(void) +{ + char *msg = error_message; + + error_message = NULL; + return msg; +} + +__strong_alias(__dlopen,dlopen) +void * +dlopen(const char *name, int mode) +{ + Obj_Entry **old_obj_tail = _rtld_objtail; + Obj_Entry *obj = NULL; + int flags = _RTLD_DLOPEN; + bool nodelete; + bool now; + + flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0; + flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0; + + nodelete = (mode & RTLD_NODELETE) ? true : false; + now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false; + + _rtld_debug.r_state = RT_ADD; + _rtld_debug_state(); + + if (name == NULL) { + obj = _rtld_objmain; + obj->refcount++; + } else + obj = _rtld_load_library(name, _rtld_objmain, flags); + + + if (obj != NULL) { + ++obj->dl_refcount; + if (*old_obj_tail != NULL) { /* We loaded something new. */ + assert(*old_obj_tail == obj); + + if (_rtld_load_needed_objects(obj, flags) == -1 || + (_rtld_init_dag(obj), + _rtld_relocate_objects(obj, + (now || obj->z_now))) == -1) { + _rtld_unload_object(obj, false); + obj->dl_refcount--; + obj = NULL; + } else { + _rtld_call_init_functions(); + } + } + if (obj != NULL) { + if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) { + dbg(("dlopen obj %s nodelete", obj->path)); + _rtld_ref_dag(obj); + obj->z_nodelete = obj->ref_nodel = true; + } + } + } + _rtld_debug.r_state = RT_CONSISTENT; + _rtld_debug_state(); + + return obj; +} + +/* + * Find a symbol in the main program. + */ +void * +_rtld_objmain_sym(const char *name) +{ + unsigned long hash; + const Elf_Sym *def; + const Obj_Entry *obj; + DoneList donelist; + + hash = _rtld_elf_hash(name); + obj = _rtld_objmain; + _rtld_donelist_init(&donelist); + + def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, false, + &donelist); + + if (def != NULL) + return obj->relocbase + def->st_value; + return NULL; +} + +#ifdef __powerpc__ +static void * +hackish_return_address(void) +{ + return __builtin_return_address(1); +} +#endif + +__strong_alias(__dlsym,dlsym) +void * +dlsym(void *handle, const char *name) +{ + const Obj_Entry *obj; + unsigned long hash; + const Elf_Sym *def; + const Obj_Entry *defobj; + void *retaddr; + DoneList donelist; + + hash = _rtld_elf_hash(name); + def = NULL; + defobj = NULL; + + switch ((intptr_t)handle) { + case (intptr_t)NULL: + case (intptr_t)RTLD_NEXT: + case (intptr_t)RTLD_DEFAULT: + case (intptr_t)RTLD_SELF: +#ifdef __powerpc__ + retaddr = hackish_return_address(); +#else + retaddr = __builtin_return_address(0); +#endif + if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) { + _rtld_error("Cannot determine caller's shared object"); + return NULL; + } + + switch ((intptr_t)handle) { + case (intptr_t)NULL: /* Just the caller's shared object. */ + def = _rtld_symlook_obj(name, hash, obj, false); + defobj = obj; + break; + + case (intptr_t)RTLD_NEXT: /* Objects after callers */ + obj = obj->next; + /*FALLTHROUGH*/ + + case (intptr_t)RTLD_SELF: /* Caller included */ + for (; obj; obj = obj->next) { + if ((def = _rtld_symlook_obj(name, hash, obj, + false)) != NULL) { + defobj = obj; + break; + } + } + break; + + case (intptr_t)RTLD_DEFAULT: + def = _rtld_symlook_default(name, hash, obj, &defobj, + false); + break; + + default: + abort(); + } + break; + + default: + if ((obj = _rtld_dlcheck(handle)) == NULL) + return NULL; + + _rtld_donelist_init(&donelist); + + if (obj->mainprog) { + /* Search main program and all libraries loaded by it */ + def = _rtld_symlook_list(name, hash, &_rtld_list_main, + &defobj, false, &donelist); + } else { + Needed_Entry fake; + DoneList depth; + + /* Search the object and all the libraries loaded by it. */ + fake.next = NULL; + fake.obj = __UNCONST(obj); + fake.name = 0; + + _rtld_donelist_init(&depth); + def = _rtld_symlook_needed(name, hash, &fake, &defobj, + false, &donelist, &depth); + } + + break; + } + + if (def != NULL) { +#ifdef __HAVE_FUNCTION_DESCRIPTORS + if (ELF_ST_TYPE(def->st_info) == STT_FUNC) + return (void *)_rtld_function_descriptor_alloc(defobj, + def, 0); +#endif /* __HAVE_FUNCTION_DESCRIPTORS */ + return defobj->relocbase + def->st_value; + } + + _rtld_error("Undefined symbol \"%s\"", name); + return NULL; +} + +__strong_alias(__dladdr,dladdr) +int +dladdr(const void *addr, Dl_info *info) +{ + const Obj_Entry *obj; + const Elf_Sym *def, *best_def; + void *symbol_addr; + unsigned long symoffset; + +#ifdef __HAVE_FUNCTION_DESCRIPTORS + addr = _rtld_function_descriptor_function(addr); +#endif /* __HAVE_FUNCTION_DESCRIPTORS */ + + obj = _rtld_obj_from_addr(addr); + if (obj == NULL) { + _rtld_error("No shared object contains address"); + return 0; + } + info->dli_fname = obj->path; + info->dli_fbase = obj->mapbase; + info->dli_saddr = (void *)0; + info->dli_sname = NULL; + + /* + * Walk the symbol list looking for the symbol whose address is + * closest to the address sent in. + */ + best_def = NULL; + for (symoffset = 0; symoffset < obj->nchains; symoffset++) { + def = obj->symtab + symoffset; + + /* + * For skip the symbol if st_shndx is either SHN_UNDEF or + * SHN_COMMON. + */ + if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) + continue; + + /* + * If the symbol is greater than the specified address, or if it + * is further away from addr than the current nearest symbol, + * then reject it. + */ + symbol_addr = obj->relocbase + def->st_value; + if (symbol_addr > addr || symbol_addr < info->dli_saddr) + continue; + + /* Update our idea of the nearest symbol. */ + info->dli_sname = obj->strtab + def->st_name; + info->dli_saddr = symbol_addr; + best_def = def; + + /* Exact match? */ + if (info->dli_saddr == addr) + break; + } + +#ifdef __HAVE_FUNCTION_DESCRIPTORS + if (best_def != NULL && ELF_ST_TYPE(best_def->st_info) == STT_FUNC) + info->dli_saddr = (void *)_rtld_function_descriptor_alloc(obj, + best_def, 0); +#endif /* __HAVE_FUNCTION_DESCRIPTORS */ + + return 1; +} + +__strong_alias(__dlinfo,dlinfo) +int +dlinfo(void *handle, int req, void *v) +{ + const Obj_Entry *obj; + void *retaddr; + + if (handle == RTLD_SELF) { +#ifdef __powerpc__ + retaddr = hackish_return_address(); +#else + retaddr = __builtin_return_address(0); +#endif + if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) { + _rtld_error("Cannot determine caller's shared object"); + return -1; + } + } else { + if ((obj = _rtld_dlcheck(handle)) == NULL) { + _rtld_error("Invalid handle"); + return -1; + } + } + + switch (req) { + case RTLD_DI_LINKMAP: + { + const struct link_map **map = v; + + *map = &obj->linkmap; + break; + } + + default: + _rtld_error("Invalid request"); + return -1; + } + + return 0; +} + +__strong_alias(__dl_iterate_phdr,dl_iterate_phdr); +int +dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *param) +{ + struct dl_phdr_info phdr_info; + const Obj_Entry *obj; + int error = 0; + + for (obj = _rtld_objlist; obj != NULL; obj = obj->next) { + phdr_info.dlpi_addr = (Elf_Addr)obj->relocbase; + phdr_info.dlpi_name = STAILQ_FIRST(&obj->names) ? + STAILQ_FIRST(&obj->names)->name : obj->path; + phdr_info.dlpi_phdr = obj->phdr; + phdr_info.dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]); +#if 1 + phdr_info.dlpi_tls_modid = 0; + phdr_info.dlpi_tls_data = 0; +#else + phdr_info.dlpi_tls_modid = obj->tlsindex; + phdr_info.dlpi_tls_data = obj->tlsinit; +#endif + phdr_info.dlpi_adds = _rtld_objloads; + phdr_info.dlpi_subs = _rtld_objloads - _rtld_objcount; + + error = callback(&phdr_info, sizeof(phdr_info), param); + if (error) + break; + } + + return error; +} + +/* + * Error reporting function. Use it like printf. If formats the message + * into a buffer, and sets things up so that the next call to dlerror() + * will return the message. + */ +void +_rtld_error(const char *fmt,...) +{ + static char buf[512]; + va_list ap; + + va_start(ap, fmt); + xvsnprintf(buf, sizeof buf, fmt, ap); + error_message = buf; + va_end(ap); +} + +void +_rtld_debug_state(void) +{ + + /* do nothing */ +} + +void +_rtld_linkmap_add(Obj_Entry *obj) +{ + struct link_map *l = &obj->linkmap; + struct link_map *prev; + + obj->linkmap.l_name = obj->path; + obj->linkmap.l_addr = obj->relocbase; + obj->linkmap.l_ld = obj->dynamic; +#ifdef __mips__ + /* XXX This field is not standard and will be removed eventually. */ + obj->linkmap.l_offs = obj->relocbase; +#endif + + if (_rtld_debug.r_map == NULL) { + _rtld_debug.r_map = l; + return; + } + + /* + * Scan to the end of the list, but not past the entry for the + * dynamic linker, which we want to keep at the very end. + */ + for (prev = _rtld_debug.r_map; + prev->l_next != NULL && prev->l_next != &_rtld_objself.linkmap; + prev = prev->l_next); + + l->l_prev = prev; + l->l_next = prev->l_next; + if (l->l_next != NULL) + l->l_next->l_prev = l; + prev->l_next = l; +} + +void +_rtld_linkmap_delete(Obj_Entry *obj) +{ + struct link_map *l = &obj->linkmap; + + if (l->l_prev == NULL) { + if ((_rtld_debug.r_map = l->l_next) != NULL) + l->l_next->l_prev = NULL; + return; + } + if ((l->l_prev->l_next = l->l_next) != NULL) + l->l_next->l_prev = l->l_prev; +} + +static Obj_Entry * +_rtld_obj_from_addr(const void *addr) +{ + Obj_Entry *obj; + + for (obj = _rtld_objlist; obj != NULL; obj = obj->next) { + if (addr < (void *) obj->mapbase) + continue; + if (addr < (void *) (obj->mapbase + obj->mapsize)) + return obj; + } + return NULL; +} + +static void +_rtld_objlist_clear(Objlist *list) +{ + while (!SIMPLEQ_EMPTY(list)) { + Objlist_Entry* elm = SIMPLEQ_FIRST(list); + SIMPLEQ_REMOVE_HEAD(list, link); + xfree(elm); + } +} + +static void +_rtld_objlist_remove(Objlist *list, Obj_Entry *obj) +{ + Objlist_Entry *elm; + + if ((elm = _rtld_objlist_find(list, obj)) != NULL) { + SIMPLEQ_REMOVE(list, elm, Struct_Objlist_Entry, link); + xfree(elm); + } +} diff --git a/libexec/ld.elf_so/rtld.h b/libexec/ld.elf_so/rtld.h new file mode 100644 index 000000000..11f0a8257 --- /dev/null +++ b/libexec/ld.elf_so/rtld.h @@ -0,0 +1,362 @@ +/* $NetBSD: rtld.h,v 1.99 2011/01/16 15:56:37 matt Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas + * 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 +#include +#include +#include +#include +#include +#include +#include "rtldenv.h" +#include "link.h" + +#if defined(_RTLD_SOURCE) + +#ifndef RTLD_DEFAULT_LIBRARY_PATH +#define RTLD_DEFAULT_LIBRARY_PATH "/usr/lib" +#endif +#define _PATH_LD_HINTS "/etc/ld.so.conf" + +extern size_t _rtld_pagesz; + +#define round_down(x) ((x) & ~(_rtld_pagesz - 1)) +#define round_up(x) round_down((x) + _rtld_pagesz - 1) + +#define NEW(type) ((type *) xmalloc(sizeof(type))) +#define CNEW(type) ((type *) xcalloc(sizeof(type))) + +/* + * Fill in a DoneList with an allocation large enough to hold all of + * the currently-loaded objects. Keep this in a macro since it calls + * alloca and we want that to occur within the scope of the caller. + */ +#define _rtld_donelist_init(dlp) \ + ((dlp)->num_alloc = _rtld_objcount, \ + (dlp)->objs = alloca((dlp)->num_alloc * sizeof((dlp)->objs[0])), \ + assert((dlp)->objs != NULL), \ + (dlp)->num_used = 0) + +#endif /* _RTLD_SOURCE */ + +/* + * C++ has mandated the use of the following keywords for its new boolean + * type. We might as well follow their lead. + */ +struct Struct_Obj_Entry; + +typedef struct Struct_Objlist_Entry { + SIMPLEQ_ENTRY(Struct_Objlist_Entry) link; + struct Struct_Obj_Entry *obj; +} Objlist_Entry; + +typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; + +typedef struct Struct_Name_Entry { + STAILQ_ENTRY(Struct_Name_Entry) link; + char name[1]; +} Name_Entry; + +typedef struct Struct_Needed_Entry { + struct Struct_Needed_Entry *next; + struct Struct_Obj_Entry *obj; + unsigned long name; /* Offset of name in string table */ +} Needed_Entry; + +typedef struct _rtld_search_path_t { + struct _rtld_search_path_t *sp_next; + const char *sp_path; + size_t sp_pathlen; +} Search_Path; + + +#define RTLD_MAX_ENTRY 10 +#define RTLD_MAX_LIBRARY 4 +#define RTLD_MAX_CTL 2 +typedef struct _rtld_library_xform_t { + struct _rtld_library_xform_t *next; + char *name; + const char *ctlname; + struct { + char *value; + char *library[RTLD_MAX_LIBRARY]; + } entry[RTLD_MAX_ENTRY]; +} Library_Xform; + +/* + * Shared object descriptor. + * + * Items marked with "(%)" are dynamically allocated, and must be freed + * when the structure is destroyed. + * + * The layout of this structure needs to be preserved because pre-2.0 binaries + * hard-coded the location of dlopen() and friends. + */ + +#define RTLD_MAGIC 0xd550b87a +#define RTLD_VERSION 1 + +typedef struct Struct_Obj_Entry { + Elf32_Word magic; /* Magic number (sanity check) */ + Elf32_Word version; /* Version number of struct format */ + + struct Struct_Obj_Entry *next; + char *path; /* Pathname of underlying file (%) */ + int refcount; + int dl_refcount; /* Number of times loaded by dlopen */ + + /* These items are computed by map_object() or by digest_phdr(). */ + caddr_t mapbase; /* Base address of mapped region */ + size_t mapsize; /* Size of mapped region in bytes */ + size_t textsize; /* Size of text segment in bytes */ + Elf_Addr vaddrbase; /* Base address in shared object file */ + caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */ + Elf_Dyn *dynamic; /* Dynamic section */ + caddr_t entry; /* Entry point */ + const Elf_Phdr *phdr; /* Program header (may be xmalloc'ed) */ + size_t phsize; /* Size of program header in bytes */ + + /* Items from the dynamic section. */ + Elf_Addr *pltgot; /* PLTGOT table */ + const Elf_Rel *rel; /* Relocation entries */ + const Elf_Rel *rellim; /* Limit of Relocation entries */ + const Elf_Rela *rela; /* Relocation entries */ + const Elf_Rela *relalim; /* Limit of Relocation entries */ + const Elf_Rel *pltrel; /* PLT relocation entries */ + const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */ + const Elf_Rela *pltrela; /* PLT relocation entries */ + const Elf_Rela *pltrelalim; /* Limit of PLT relocation entries */ + const Elf_Sym *symtab; /* Symbol table */ + const char *strtab; /* String table */ + unsigned long strsize; /* Size in bytes of string table */ +#ifdef __mips__ + Elf_Word local_gotno; /* Number of local GOT entries */ + Elf_Word symtabno; /* Number of dynamic symbols */ + Elf_Word gotsym; /* First dynamic symbol in GOT */ +#endif + + const Elf_Symindx *buckets; /* Hash table buckets array */ + unsigned long unused1; /* Used to be nbuckets */ + const Elf_Symindx *chains; /* Hash table chain array */ + unsigned long nchains; /* Number of chains */ + + Search_Path *rpaths; /* Search path specified in object */ + Needed_Entry *needed; /* Shared objects needed by this (%) */ + + void (*init)(void); /* Initialization function to call */ + void (*fini)(void); /* Termination function to call */ + + /* Entry points for dlopen() and friends. */ + void *(*dlopen)(const char *, int); + void *(*dlsym)(void *, const char *); + char *(*dlerror)(void); + int (*dlclose)(void *); + int (*dladdr)(const void *, Dl_info *); + + u_int32_t mainprog:1, /* True if this is the main program */ + rtld:1, /* True if this is the dynamic linker */ + textrel:1, /* True if there are relocations to + * text seg */ + symbolic:1, /* True if generated with + * "-Bsymbolic" */ + printed:1, /* True if ldd has printed it */ + isdynamic:1, /* True if this is a pure PIC object */ + mainref:1, /* True if on _rtld_list_main */ + globalref:1, /* True if on _rtld_list_global */ + init_done:1, /* True if .init has been added */ + init_called:1, /* True if .init function has been + * called */ + fini_called:1, /* True if .fini function has been + * called */ + z_now:1, /* True if object's symbols should be + bound immediately */ + z_nodelete:1, /* True if object should never be + unloaded */ + z_initfirst:1, /* True if object's .init/.fini take + * priority over others */ + z_noopen:1, /* True if object should never be + dlopen'ed */ + phdr_loaded:1, /* Phdr is loaded and doesn't need to + * be freed. */ + ref_nodel:1; /* Refcount increased to prevent dlclose */ + + struct link_map linkmap; /* for GDB */ + + /* These items are computed by map_object() or by digest_phdr(). */ + const char *interp; /* Pathname of the interpreter, if any */ + Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ + Objlist dagmembers; /* DAG has these members (%) */ + dev_t dev; /* Object's filesystem's device */ + ino_t ino; /* Object's inode number */ + + void *ehdr; + + uint32_t nbuckets; /* Number of buckets */ + uint32_t nbuckets_m; /* Precomputed for fast remainder */ + uint8_t nbuckets_s1; + uint8_t nbuckets_s2; + size_t pathlen; /* Pathname length */ + STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we + know about. */ +#ifdef __powerpc__ + Elf_Addr *gotptr; /* GOT table (secure-plt only) */ +#endif +} Obj_Entry; + +typedef struct Struct_DoneList { + const Obj_Entry **objs; /* Array of object pointers */ + unsigned int num_alloc; /* Allocated size of the array */ + unsigned int num_used; /* Number of array slots used */ +} DoneList; + + +#if defined(_RTLD_SOURCE) + +extern struct r_debug _rtld_debug; +extern Search_Path *_rtld_default_paths; +extern Obj_Entry *_rtld_objlist; +extern Obj_Entry **_rtld_objtail; +extern u_int _rtld_objcount; +extern u_int _rtld_objloads; +extern Obj_Entry *_rtld_objmain; +extern Obj_Entry _rtld_objself; +extern Search_Path *_rtld_paths; +extern Library_Xform *_rtld_xforms; +extern bool _rtld_trust; +extern Objlist _rtld_list_global; +extern Objlist _rtld_list_main; +extern Elf_Sym _rtld_sym_zero; + +#define RTLD_MODEMASK 0x3 + +/* Flags for _rtld_load_object() and friends. */ +#define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */ +#define _RTLD_MAIN 0x02 +#define _RTLD_NOLOAD 0x04 /* dlopen() specified RTLD_NOLOAD. */ +#define _RTLD_DLOPEN 0x08 /* Load_object() called from dlopen(). */ + +/* rtld.c */ + +/* We export these symbols using _rtld_symbol_lookup and is_exported. */ +__dso_public char *dlerror(void); +__dso_public void *dlopen(const char *, int); +__dso_public void *dlsym(void *, const char *); +__dso_public int dlclose(void *); +__dso_public int dladdr(const void *, Dl_info *); +__dso_public int dlinfo(void *, int, void *); +__dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), + void *); + +/* These aren't exported */ +void _rtld_error(const char *, ...) + __attribute__((__format__(__printf__,1,2))); +void _rtld_die(void) __attribute__((__noreturn__)); +void *_rtld_objmain_sym(const char *); +void _rtld_debug_state(void); +void _rtld_linkmap_add(Obj_Entry *); +void _rtld_linkmap_delete(Obj_Entry *); +void _rtld_objlist_push_head(Objlist *, Obj_Entry *); +void _rtld_objlist_push_tail(Objlist *, Obj_Entry *); +Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *); +void _rtld_ref_dag(Obj_Entry *); + +/* expand.c */ +size_t _rtld_expand_path(char *, size_t, const char *, const char *,\ + const char *); + +/* headers.c */ +void _rtld_digest_dynamic(const char *, Obj_Entry *); +Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t); + +/* load.c */ +Obj_Entry *_rtld_load_object(const char *, int); +int _rtld_load_needed_objects(Obj_Entry *, int); +int _rtld_preload(const char *); + +#define OBJ_ERR (Obj_Entry *)(-1) +/* path.c */ +void _rtld_add_paths(const char *, Search_Path **, const char *); +void _rtld_process_hints(const char *, Search_Path **, Library_Xform **, + const char *); +int _rtld_sysctl(const char *, void *, size_t *); + +/* reloc.c */ +int _rtld_do_copy_relocations(const Obj_Entry *); +int _rtld_relocate_objects(Obj_Entry *, bool); +int _rtld_relocate_nonplt_objects(Obj_Entry *); +int _rtld_relocate_plt_lazy(const Obj_Entry *); +int _rtld_relocate_plt_objects(const Obj_Entry *); +void _rtld_setup_pltgot(const Obj_Entry *); + +/* search.c */ +Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); + +/* symbol.c */ +unsigned long _rtld_elf_hash(const char *); +const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, + const Obj_Entry *, bool); +const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, + const Obj_Entry **, bool); +const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *, + const Obj_Entry **, bool); + +const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, + const Objlist *, const Obj_Entry **, bool, DoneList *); +const Elf_Sym *_rtld_symlook_default(const char *, unsigned long, + const Obj_Entry *, const Obj_Entry **, bool); +const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long, + const Needed_Entry *, const Obj_Entry **, bool, + DoneList *, DoneList *); +#ifdef COMBRELOC +void _rtld_combreloc_reset(const Obj_Entry *); +#endif + +/* map_object.c */ +struct stat; +Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); +void _rtld_obj_free(Obj_Entry *); +Obj_Entry *_rtld_obj_new(void); + +/* function descriptors */ +#ifdef __HAVE_FUNCTION_DESCRIPTORS +Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, + const Elf_Sym *, Elf_Addr); +const void *_rtld_function_descriptor_function(const void *); +#endif /* __HAVE_FUNCTION_DESCRIPTORS */ + +#endif /* _RTLD_SOURCE */ + +#endif /* RTLD_H */ diff --git a/libexec/ld.elf_so/rtldenv.h b/libexec/ld.elf_so/rtldenv.h new file mode 100644 index 000000000..a1b3ba939 --- /dev/null +++ b/libexec/ld.elf_so/rtldenv.h @@ -0,0 +1,86 @@ +/* $NetBSD: rtldenv.h,v 1.10 2010/10/29 15:08:17 christos Exp $ */ + +/* + * Copyright 1996 Matt Thomas + * 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 +#include + +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 +# include +# include + +# define xprintf printf +# define xvprintf vprintf +# define xsnprintf snprintf +# define xvsnprintf vsnprintf +# define xwarn warn +# define xwarnx warnx +# define xerr err +# define xerrx errx +# define xassert assert +# define xstrerror strerror +#endif + +#endif /* _RTLDENV_H */ diff --git a/libexec/ld.elf_so/search.c b/libexec/ld.elf_so/search.c new file mode 100644 index 000000000..513f0adb9 --- /dev/null +++ b/libexec/ld.elf_so/search.c @@ -0,0 +1,192 @@ +/* $NetBSD: search.c,v 1.23 2010/12/24 12:41:43 skrll Exp $ */ + +/* + * Copyright 1996 Matt Thomas + * 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 . + */ + +#include +#ifndef lint +__RCSID("$NetBSD: search.c,v 1.23 2010/12/24 12:41:43 skrll Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "rtld.h" + +/* + * Data declarations. + */ +Search_Path *_rtld_invalid_paths; + +static Obj_Entry *_rtld_search_library_path(const char *, size_t, + const char *, size_t, int); + +static Obj_Entry * +_rtld_search_library_path(const char *name, size_t namelen, + const char *dir, size_t dirlen, int flags) +{ + char pathname[MAXPATHLEN]; + size_t pathnamelen; + Obj_Entry *obj; + Search_Path *sp; + + pathnamelen = dirlen + 1 + namelen; + if (pathnamelen >= sizeof(pathname)) + return NULL; + + for (sp = _rtld_invalid_paths; sp != NULL; sp = sp->sp_next) { + if (sp->sp_pathlen == pathnamelen && + sp->sp_path[dirlen] == '/' && + !memcmp(name, sp->sp_path + dirlen + 1, namelen) && + !memcmp(dir, sp->sp_path, dirlen)) { + return NULL; + } + } + + memcpy(pathname, dir, dirlen); + pathname[dirlen] = '/'; + memcpy(pathname + dirlen + 1, name, namelen); + pathname[pathnamelen] = '\0'; + + dbg((" Trying \"%s\"", pathname)); + obj = _rtld_load_object(pathname, flags); + if (obj == NULL) { + Search_Path *path; + + path = NEW(Search_Path); + path->sp_pathlen = pathnamelen; + path->sp_path = xstrdup(pathname); + path->sp_next = _rtld_invalid_paths; + _rtld_invalid_paths = path; + } + return obj; +} + +/* + * Find the library with the given name, and return its full pathname. + * The returned string is dynamically allocated. Generates an error + * message and returns NULL if the library cannot be found. + * + * If the second argument is non-NULL, then it refers to an already- + * loaded shared object, whose library search path will be searched. + */ +Obj_Entry * +_rtld_load_library(const char *name, const Obj_Entry *refobj, int flags) +{ + char tmperror[512], *tmperrorp; + Search_Path *sp; + const char *pathname; + int namelen; + Obj_Entry *obj; + + if (strchr(name, '/') != NULL) { /* Hard coded pathname */ + if (name[0] != '/' && !_rtld_trust) { + _rtld_error( + "absolute pathname required for shared object \"%s\"", + name); + return NULL; + } + pathname = name; + goto found; + } + dbg((" Searching for \"%s\" (%p)", name, refobj)); + + tmperrorp = dlerror(); + if (tmperrorp != NULL) { + strncpy(tmperror, tmperrorp, sizeof tmperror); + tmperrorp = tmperror; + } + + namelen = strlen(name); + + for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next) + if ((obj = _rtld_search_library_path(name, namelen, + sp->sp_path, sp->sp_pathlen, flags)) != NULL) + goto pathfound; + + if (refobj != NULL) + for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next) + if ((obj = _rtld_search_library_path(name, + namelen, sp->sp_path, sp->sp_pathlen, flags)) != NULL) + goto pathfound; + + for (sp = _rtld_default_paths; sp != NULL; sp = sp->sp_next) + if ((obj = _rtld_search_library_path(name, namelen, + sp->sp_path, sp->sp_pathlen, flags)) != NULL) + goto pathfound; + + _rtld_error("Shared object \"%s\" not found", name); + return NULL; + +pathfound: + /* + * The library has been found, but it couldn't be loaded for some + * reason. + */ + if (obj == OBJ_ERR) + return NULL; + /* + * Successfully found a library; restore the dlerror state as it was + * before _rtld_load_library() was called (any failed call to + * _rtld_search_library_path() will set the dlerror state, but if the + * library was eventually found, then the error state should not + * change. + */ + if (tmperrorp) + _rtld_error("%s", tmperror); + else + (void)dlerror(); + return obj; + +found: + obj = _rtld_load_object(pathname, flags); + if (obj == OBJ_ERR) + return NULL; + + return obj; +} + diff --git a/libexec/ld.elf_so/symbol.c b/libexec/ld.elf_so/symbol.c new file mode 100644 index 000000000..f4979bbd3 --- /dev/null +++ b/libexec/ld.elf_so/symbol.c @@ -0,0 +1,488 @@ +/* $NetBSD: symbol.c,v 1.54 2010/10/16 10:27:07 skrll Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas + * Copyright 2002 Charles M. Hannum + * 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 . + */ + +#include +#ifndef lint +__RCSID("$NetBSD: symbol.c,v 1.54 2010/10/16 10:27:07 skrll Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "rtld.h" + +typedef void (*fptr_t)(void); + +/* + * If the given object is already in the donelist, return true. Otherwise + * add the object to the list and return false. + */ +static bool +_rtld_donelist_check(DoneList *dlp, const Obj_Entry *obj) +{ + unsigned int i; + + for (i = 0; i < dlp->num_used; i++) + if (dlp->objs[i] == obj) + return true; + /* + * Our donelist allocation may not always be sufficient as we're not + * thread safe. We'll handle it properly anyway. + */ + if (dlp->num_used < dlp->num_alloc) + dlp->objs[dlp->num_used++] = obj; + return false; +} + +static bool +_rtld_is_exported(const Elf_Sym *def) +{ + static const fptr_t _rtld_exports[] = { + (fptr_t)dlopen, + (fptr_t)dlclose, + (fptr_t)dlsym, + (fptr_t)dlerror, + (fptr_t)dladdr, + (fptr_t)dlinfo, + (fptr_t)dl_iterate_phdr, + NULL + }; + int i; + fptr_t value; + + value = (fptr_t)(_rtld_objself.relocbase + def->st_value); + for (i = 0; _rtld_exports[i] != NULL; i++) { + if (value == _rtld_exports[i]) + return true; + } + return false; +} + +/* + * Hash function for symbol table lookup. Don't even think about changing + * this. It is specified by the System V ABI. + */ +unsigned long +_rtld_elf_hash(const char *name) +{ + const unsigned char *p = (const unsigned char *) name; + unsigned long h = 0; + unsigned long g; + unsigned long c; + + for (; __predict_true((c = *p) != '\0'); p++) { + h <<= 4; + h += c; + if ((g = h & 0xf0000000) != 0) { + h ^= g; + h ^= g >> 24; + } + } + return (h); +} + +const Elf_Sym * +_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist, + const Obj_Entry **defobj_out, bool in_plt, DoneList *dlp) +{ + const Elf_Sym *symp; + const Elf_Sym *def; + const Obj_Entry *defobj; + const Objlist_Entry *elm; + + def = NULL; + defobj = NULL; + SIMPLEQ_FOREACH(elm, objlist, link) { + if (_rtld_donelist_check(dlp, elm->obj)) + continue; + rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path, + name)); + if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt)) + != NULL) { + if ((def == NULL) || + (ELF_ST_BIND(symp->st_info) != STB_WEAK)) { + def = symp; + defobj = elm->obj; + if (ELF_ST_BIND(def->st_info) != STB_WEAK) + break; + } + } + } + if (def != NULL) + *defobj_out = defobj; + return def; +} + +/* + * Search the symbol table of a shared object and all objects needed by it for + * a symbol of the given name. Search order is breadth-first. Returns a pointer + * to the symbol, or NULL if no definition was found. + */ +const Elf_Sym * +_rtld_symlook_needed(const char *name, unsigned long hash, + const Needed_Entry *needed, const Obj_Entry **defobj_out, bool inplt, + DoneList *breadth, DoneList *depth) +{ + const Elf_Sym *def, *def_w; + const Needed_Entry *n; + const Obj_Entry *obj, *defobj, *defobj1; + + def = def_w = NULL; + defobj = NULL; + for (n = needed; n != NULL; n = n->next) { + if ((obj = n->obj) == NULL) + continue; + if (_rtld_donelist_check(breadth, obj)) + continue; + if ((def = _rtld_symlook_obj(name, hash, obj, inplt)) == NULL) + continue; + defobj = obj; + if (ELF_ST_BIND(def->st_info) != STB_WEAK) { + *defobj_out = defobj; + + return (def); + } + } + /* + * Either the symbol definition has not been found in directly needed + * objects, or the found symbol is weak. + */ + for (n = needed; n != NULL; n = n->next) { + if ((obj = n->obj) == NULL) + continue; + if (_rtld_donelist_check(depth, obj)) + continue; + def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1, + inplt, breadth, depth); + if (def_w == NULL) + continue; + if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { + def = def_w; + defobj = defobj1; + if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) + break; + } + } + if (def != NULL) + *defobj_out = defobj; + + return def; +} + +/* + * Search the symbol table of a single shared object for a symbol of + * the given name. Returns a pointer to the symbol, or NULL if no + * definition was found. + * + * The symbol's hash value is passed in for efficiency reasons; that + * eliminates many recomputations of the hash value. + */ +const Elf_Sym * +_rtld_symlook_obj(const char *name, unsigned long hash, + const Obj_Entry *obj, bool in_plt) +{ + unsigned long symnum; + + for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets, + obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)]; + symnum != ELF_SYM_UNDEFINED; + symnum = obj->chains[symnum]) { + const Elf_Sym *symp; + const char *strp; + + assert(symnum < obj->nchains); + symp = obj->symtab + symnum; + strp = obj->strtab + symp->st_name; + rdbg(("check \"%s\" vs \"%s\" in %p", name, strp, obj)); + if (name[1] == strp[1] && !strcmp(name, strp)) { + if (symp->st_shndx != SHN_UNDEF) + return symp; +#ifndef __mips__ + /* + * XXX DANGER WILL ROBINSON! + * If we have a function pointer in the executable's + * data section, it points to the executable's PLT + * slot, and there is NO relocation emitted. To make + * the function pointer comparable to function pointers + * in shared libraries, we must resolve data references + * in the libraries to point to PLT slots in the + * executable, if they exist. + */ + else if (!in_plt && symp->st_value != 0 && + ELF_ST_TYPE(symp->st_info) == STT_FUNC) + return symp; +#endif + else + return NULL; + } + } + + return NULL; +} + +#ifdef COMBRELOC +static const Obj_Entry *_rtld_last_refobj; + +/* + * Called when an object is freed. Reset the cached symbol look up if + * our last referencing or definition object just got unloaded. + */ +void +_rtld_combreloc_reset(const Obj_Entry *obj) +{ + if (_rtld_last_refobj == obj) + _rtld_last_refobj = NULL; +} +#endif + +/* + * Given a symbol number in a referencing object, find the corresponding + * definition of the symbol. Returns a pointer to the symbol, or NULL if + * no definition was found. Returns a pointer to the Obj_Entry of the + * defining object via the reference parameter DEFOBJ_OUT. + */ +const Elf_Sym * +_rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj, + const Obj_Entry **defobj_out, bool in_plt) +{ + const Elf_Sym *ref; + const Elf_Sym *def; + const Obj_Entry *defobj; + const char *name; + unsigned long hash; + +#ifdef COMBRELOC + /* + * COMBRELOC combines multiple reloc sections and sorts them to make + * dynamic symbol lookup caching possible. + * + * So if the lookup we are doing is the same as the previous lookup + * return the cached results. + */ + static unsigned long last_symnum; + static const Obj_Entry *last_defobj; + static const Elf_Sym *last_def; + + if (symnum == last_symnum && refobj == _rtld_last_refobj + && in_plt == false) { + *defobj_out = last_defobj; + return last_def; + } +#endif + + ref = refobj->symtab + symnum; + name = refobj->strtab + ref->st_name; + + /* + * We don't have to do a full scale lookup if the symbol is local. + * We know it will bind to the instance in this load module; to + * which we already have a pointer (ie ref). + */ + if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { + if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { + _rtld_error("%s: Bogus symbol table entry %lu", + refobj->path, symnum); + } + + hash = _rtld_elf_hash(name); + defobj = NULL; + def = _rtld_symlook_default(name, hash, refobj, &defobj, in_plt); + } else { + rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path)); + def = ref; + defobj = refobj; + } + + /* + * If we found no definition and the reference is weak, treat the + * symbol as having the value zero. + */ + if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { + rdbg((" returning _rtld_sym_zero@_rtld_objself")); + def = &_rtld_sym_zero; + defobj = &_rtld_objself; + } + + if (def != NULL) { + *defobj_out = defobj; +#ifdef COMBRELOC + if (in_plt == false) { + /* + * Cache the lookup arguments and results if this was + * non-PLT lookup. + */ + last_symnum = symnum; + _rtld_last_refobj = refobj; + last_def = def; + last_defobj = defobj; + } +#endif + } else { + rdbg(("lookup failed")); + _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)", + refobj->path, in_plt ? "PLT " : "", name, symnum); + } + return def; +} + +const Elf_Sym * +_rtld_find_plt_symdef(unsigned long symnum, const Obj_Entry *obj, + const Obj_Entry **defobj, bool imm) +{ + const Elf_Sym *def = _rtld_find_symdef(symnum, obj, defobj, true); + if (__predict_false(def == NULL)) + return NULL; + + if (__predict_false(def == &_rtld_sym_zero)) { + /* tp is set during lazy binding. */ + if (imm) { + const Elf_Sym *ref = obj->symtab + symnum; + const char *name = obj->strtab + ref->st_name; + + _rtld_error( + "%s: Trying to call undefined weak symbol `%s'", + obj->path, name); + return NULL; + } + } + return def; +} + +/* + * Given a symbol name in a referencing object, find the corresponding + * definition of the symbol. Returns a pointer to the symbol, or NULL if + * no definition was found. Returns a pointer to the Obj_Entry of the + * defining object via the reference parameter DEFOBJ_OUT. + */ +const Elf_Sym * +_rtld_symlook_default(const char *name, unsigned long hash, + const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt) +{ + const Elf_Sym *def; + const Elf_Sym *symp; + const Obj_Entry *obj; + const Obj_Entry *defobj; + const Objlist_Entry *elm; + def = NULL; + defobj = NULL; + DoneList donelist; + + _rtld_donelist_init(&donelist); + + /* Look first in the referencing object if linked symbolically. */ + if (refobj->symbolic && !_rtld_donelist_check(&donelist, refobj)) { + rdbg(("search referencing object for %s", name)); + symp = _rtld_symlook_obj(name, hash, refobj, in_plt); + if (symp != NULL) { + def = symp; + defobj = refobj; + } + } + + /* Search all objects loaded at program start up. */ + if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { + rdbg(("search _rtld_list_main for %s", name)); + symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, + in_plt, &donelist); + if (symp != NULL && + (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { + def = symp; + defobj = obj; + } + } + + /* Search all RTLD_GLOBAL objects. */ + if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { + rdbg(("search _rtld_list_global for %s", name)); + symp = _rtld_symlook_list(name, hash, &_rtld_list_global, + &obj, in_plt, &donelist); + if (symp != NULL && + (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { + def = symp; + defobj = obj; + } + } + + /* Search all dlopened DAGs containing the referencing object. */ + SIMPLEQ_FOREACH(elm, &refobj->dldags, link) { + if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) + break; + rdbg(("search DAG with root %p (%s) for %s", elm->obj, + elm->obj->path, name)); + symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, + &obj, in_plt, &donelist); + if (symp != NULL && + (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { + def = symp; + defobj = obj; + } + } + + /* + * Search the dynamic linker itself, and possibly resolve the + * symbol from there. This is how the application links to + * dynamic linker services such as dlopen. Only the values listed + * in the "_rtld_exports" array can be resolved from the dynamic + * linker. + */ + if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { + rdbg(("Search the dynamic linker itself.")); + symp = _rtld_symlook_obj(name, hash, &_rtld_objself, in_plt); + if (symp != NULL && _rtld_is_exported(symp)) { + def = symp; + defobj = &_rtld_objself; + } + } + + if (def != NULL) + *defobj_out = defobj; + return def; +} diff --git a/libexec/ld.elf_so/sysident.h b/libexec/ld.elf_so/sysident.h new file mode 100644 index 000000000..a710d8c99 --- /dev/null +++ b/libexec/ld.elf_so/sysident.h @@ -0,0 +1,91 @@ +/* $NetBSD: sysident.h,v 1.14 2007/06/24 20:35:36 christos Exp $ */ + +/* + * Copyright (c) 1997 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.NetBSD.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <> + */ + +/* + * Here we define the NetBSD OS Version in an ELF .note section, structured + * like: + * + * [NOTE HEADER] + * long name size + * long description size + * long note type + * + * [NOTE DATUM] + * string OS name + * + * OSVERSION notes also have: + * long OS version (__NetBSD_Version__ constant from param.h) + * + * The DATUM fields should be padded out such that their actual (not + * declared) sizes % 4 == 0. + * + * These are used by the kernel to determine if this binary is really a + * NetBSD binary, or some other OS's. + */ + +/* XXX: NetBSD 1.5 compatibility only! */ +#if __NetBSD_Version__ < 105010000 +#define ELF_NOTE_TYPE_NETBSD_TAG 1 +#endif + +#define __S(x) __STRING(x) +__asm( + ".section\t\".note.netbsd.ident\", \"a\"\n" + "\t.p2align\t2\n\n" + + "\t.long\t" __S(ELF_NOTE_NETBSD_NAMESZ) "\n" + "\t.long\t" __S(ELF_NOTE_NETBSD_DESCSZ) "\n" + "\t.long\t" __S(ELF_NOTE_TYPE_NETBSD_TAG) "\n" + "\t.ascii\t" __S(ELF_NOTE_NETBSD_NAME) "\n" + "\t.long\t" __S(__NetBSD_Version__) "\n\n" + + "\t.previous\n" + "\t.p2align\t2\n" +); + +__asm( + ".section\t\".note.netbsd.pax\", \"a\"\n" + "\t.p2align\t2\n\n" + + "\t.long\t" __S(ELF_NOTE_PAX_NAMESZ) "\n" + "\t.long\t" __S(ELF_NOTE_PAX_DESCSZ) "\n" + "\t.long\t" __S(ELF_NOTE_TYPE_PAX_TAG) "\n" + "\t.ascii\t" __S(ELF_NOTE_PAX_NAME) "\n" + "\t.long\t" __S(0) "\n\n" + + "\t.previous\n" + "\t.p2align\t2\n" +); diff --git a/libexec/ld.elf_so/xmalloc.c b/libexec/ld.elf_so/xmalloc.c new file mode 100644 index 000000000..e80c03a77 --- /dev/null +++ b/libexec/ld.elf_so/xmalloc.c @@ -0,0 +1,486 @@ +/* $NetBSD: xmalloc.c,v 1.10 2010/12/03 23:07:49 joerg Exp $ */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas + * 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 +#ifndef lint +__RCSID("$NetBSD: xmalloc.c,v 1.10 2010/12/03 23:07:49 joerg Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "rtld.h" + +/* + * Pre-allocate mmap'ed pages + */ +#define NPOOLPAGES (32*1024/pagesz) +static char *pagepool_start, *pagepool_end; +static int morepages(int); +#define PAGEPOOL_SIZE (size_t)(pagepool_end - pagepool_start) + +/* + * The overhead on a block is at least 4 bytes. When free, this space + * contains a pointer to the next free block, and the bottom two bits must + * be zero. When in use, the first byte is set to MAGIC, and the second + * byte is the size index. The remaining bytes are for alignment. + * If range checking is enabled then a second word holds the size of the + * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC). + * The order of elements is critical: ov_magic must overlay the low order + * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern. + */ +union overhead { + union overhead *ov_next; /* when free */ + struct { + u_char ovu_magic; /* magic number */ + u_char ovu_index; /* bucket # */ +#ifdef RCHECK + u_short ovu_rmagic; /* range magic number */ + u_int ovu_size; /* actual block size */ +#endif + } ovu; +#define ov_magic ovu.ovu_magic +#define ov_index ovu.ovu_index +#define ov_rmagic ovu.ovu_rmagic +#define ov_size ovu.ovu_size +}; + +static void morecore(size_t); +static void *imalloc(size_t); + +#define MAGIC 0xef /* magic # on accounting info */ +#define RMAGIC 0x5555 /* magic # on range info */ + +#ifdef RCHECK +#define RSLOP (sizeof (u_short)) +#else +#define RSLOP 0 +#endif + +/* + * nextf[i] is the pointer to the next free block of size 2^(i+3). The + * smallest allocatable block is 8 bytes. The overhead information + * precedes the data area returned to the user. + */ +#define NBUCKETS 30 +static union overhead *nextf[NBUCKETS]; + +static size_t pagesz; /* page size */ +static size_t pagebucket; /* page size bucket */ + +#ifdef MSTATS +/* + * nmalloc[i] is the difference between the number of mallocs and frees + * for a given block size. + */ +static u_int nmalloc[NBUCKETS]; +#endif + +#if defined(MALLOC_DEBUG) || defined(RCHECK) +#define ASSERT(p) if (!(p)) botch("p") +static void +botch(const char *s) +{ + xwarnx("\r\nassertion botched: %s\r\n", s); + abort(); +} +#else +#define ASSERT(p) +#endif + +#define TRACE() xprintf("TRACE %s:%d\n", __FILE__, __LINE__) + +static void * +imalloc(size_t nbytes) +{ + union overhead *op; + size_t bucket; + size_t n, m; + unsigned amt; + + /* + * First time malloc is called, setup page size and + * align break pointer so all data will be page aligned. + */ + if (pagesz == 0) { + pagesz = n = _rtld_pagesz; + if (morepages(NPOOLPAGES) == 0) + return NULL; + op = (union overhead *)(pagepool_start); + m = sizeof (*op) - (((char *)op - (char *)NULL) & (n - 1)); + if (n < m) + n += pagesz - m; + else + n -= m; + if (n) { + pagepool_start += n; + } + bucket = 0; + amt = sizeof(union overhead); + while (pagesz > amt) { + amt <<= 1; + bucket++; + } + pagebucket = bucket; + } + /* + * Convert amount of memory requested into closest block size + * stored in hash buckets which satisfies request. + * Account for space used per block for accounting. + */ + if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) { + if (sizeof(union overhead) & (sizeof(union overhead) - 1)) { + amt = sizeof(union overhead) * 2; + bucket = 1; + } else { + amt = sizeof(union overhead); /* size of first bucket */ + bucket = 0; + } + n = -(sizeof (*op) + RSLOP); + } else { + amt = pagesz; + bucket = pagebucket; + } + while (nbytes > amt + n) { + amt <<= 1; + if (amt == 0) + return (NULL); + bucket++; + } + /* + * If nothing in hash bucket right now, + * request more memory from the system. + */ + if ((op = nextf[bucket]) == NULL) { + morecore(bucket); + if ((op = nextf[bucket]) == NULL) + return (NULL); + } + /* remove from linked list */ + nextf[bucket] = op->ov_next; + op->ov_magic = MAGIC; + op->ov_index = bucket; +#ifdef MSTATS + nmalloc[bucket]++; +#endif +#ifdef RCHECK + /* + * Record allocated size of block and + * bound space with magic numbers. + */ + op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); + op->ov_rmagic = RMAGIC; + *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; +#endif + return ((char *)(op + 1)); +} + +/* + * Allocate more memory to the indicated bucket. + */ +static void +morecore(size_t bucket) +{ + union overhead *op; + size_t sz; /* size of desired block */ + size_t amt; /* amount to allocate */ + size_t nblks; /* how many blocks we get */ + + /* + * sbrk_size <= 0 only for big, FLUFFY, requests (about + * 2^30 bytes on a VAX, I think) or for a negative arg. + */ + sz = 1 << (bucket + 3); +#ifdef MALLOC_DEBUG + ASSERT(sz > 0); +#endif + if (sz < pagesz) { + amt = pagesz; + nblks = amt / sz; + } else { + amt = sz + pagesz; + nblks = 1; + } + if (amt > PAGEPOOL_SIZE) + if (morepages(amt/pagesz + NPOOLPAGES) == 0) + return; + op = (union overhead *)pagepool_start; + pagepool_start += amt; + + /* + * Add new memory allocated to that on + * free list for this hash bucket. + */ + nextf[bucket] = op; + while (--nblks > 0) { + op->ov_next = (union overhead *)((caddr_t)op + sz); + op = (union overhead *)((caddr_t)op + sz); + } +} + +void +xfree(void *cp) +{ + int size; + union overhead *op; + + if (cp == NULL) + return; + op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); +#ifdef MALLOC_DEBUG + ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ +#else + if (op->ov_magic != MAGIC) + return; /* sanity */ +#endif +#ifdef RCHECK + ASSERT(op->ov_rmagic == RMAGIC); + ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); +#endif + size = op->ov_index; + ASSERT(size < NBUCKETS); + op->ov_next = nextf[size]; /* also clobbers ov_magic */ + nextf[size] = op; +#ifdef MSTATS + nmalloc[size]--; +#endif +} + +static void * +irealloc(void *cp, size_t nbytes) +{ + size_t onb; + size_t i; + union overhead *op; + char *res; + + if (cp == NULL) + return (imalloc(nbytes)); + op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); + if (op->ov_magic != MAGIC) { + static const char *err_str = + "memory corruption or double free in realloc\n"; + extern char *__progname; + write(STDERR_FILENO, __progname, strlen(__progname)); + write(STDERR_FILENO, err_str, strlen(err_str)); + abort(); + } + + i = op->ov_index; + onb = 1 << (i + 3); + if (onb < pagesz) + onb -= sizeof (*op) + RSLOP; + else + onb += pagesz - sizeof (*op) - RSLOP; + /* avoid the copy if same size block */ + if (i) { + i = 1 << (i + 2); + if (i < pagesz) + i -= sizeof (*op) + RSLOP; + else + i += pagesz - sizeof (*op) - RSLOP; + } + if (nbytes <= onb && nbytes > i) { +#ifdef RCHECK + op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); + *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; +#endif + return(cp); + } else + xfree(cp); + if ((res = imalloc(nbytes)) == NULL) + return (NULL); + if (cp != res) /* common optimization if "compacting" */ + memcpy(res, cp, (nbytes < onb) ? nbytes : onb); + return (res); +} + +#ifdef MSTATS +/* + * mstats - print out statistics about malloc + * + * Prints two lines of numbers, one showing the length of the free list + * for each size category, the second showing the number of mallocs - + * frees for each size category. + */ +void +mstats(char *s) +{ + int i, j; + union overhead *p; + int totfree = 0, + totused = 0; + + xprintf("Memory allocation statistics %s\nfree:\t", s); + for (i = 0; i < NBUCKETS; i++) { + for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) + ; + xprintf(" %d", j); + totfree += j * (1 << (i + 3)); + } + xprintf("\nused:\t"); + for (i = 0; i < NBUCKETS; i++) { + xprintf(" %d", nmalloc[i]); + totused += nmalloc[i] * (1 << (i + 3)); + } + xprintf("\n\tTotal in use: %d, total free: %d\n", + totused, totfree); +} +#endif + + +static int +morepages(int n) +{ + int fd = -1; + int offset; + +#ifdef NEED_DEV_ZERO + fd = open("/dev/zero", O_RDWR, 0); + if (fd == -1) + xerr(1, "/dev/zero"); +#endif + + if (PAGEPOOL_SIZE > pagesz) { + caddr_t addr = (caddr_t) + (((long)pagepool_start + pagesz - 1) & ~(pagesz - 1)); + if (munmap(addr, pagepool_end - addr) != 0) + xwarn("morepages: munmap %p", addr); + } + + offset = (long)pagepool_start - ((long)pagepool_start & ~(pagesz - 1)); + + if ((pagepool_start = mmap(0, n * pagesz, + PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, fd, 0)) == (caddr_t)-1) { + xprintf("Cannot map anonymous memory"); + return 0; + } + pagepool_end = pagepool_start + n * pagesz; + pagepool_start += offset; + +#ifdef NEED_DEV_ZERO + close(fd); +#endif + return n; +} + +void * +xcalloc(size_t size) +{ + + return memset(xmalloc(size), 0, size); +} + +void * +xmalloc(size_t size) +{ + void *p = imalloc(size); + + if (p == NULL) + xerr(1, "%s", xstrerror(errno)); + return p; +} + +void * +xrealloc(void *p, size_t size) +{ + p = irealloc(p, size); + + if (p == NULL) + xerr(1, "%s", xstrerror(errno)); + return p; +} + +char * +xstrdup(const char *str) +{ + size_t len; + char *copy; + + len = strlen(str) + 1; + copy = xmalloc(len); + memcpy(copy, str, len); + return (copy); +} diff --git a/libexec/ld.elf_so/xprintf.c b/libexec/ld.elf_so/xprintf.c new file mode 100644 index 000000000..77c9bbf8d --- /dev/null +++ b/libexec/ld.elf_so/xprintf.c @@ -0,0 +1,323 @@ +/* $NetBSD: xprintf.c,v 1.21 2010/12/16 22:52:32 joerg Exp $ */ + +/* + * Copyright 1996 Matt Thomas + * 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 +#ifndef lint +__RCSID("$NetBSD: xprintf.c,v 1.21 2010/12/16 22:52:32 joerg Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#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 diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk index 7c04a89b5..2add88fad 100644 --- a/share/mk/bsd.own.mk +++ b/share/mk/bsd.own.mk @@ -58,6 +58,14 @@ TOOLCHAIN_MISSING?= no HAVE_GCC= 4 .endif +.if \ + ${MACHINE_ARCH} == "i386" || \ + ${MACHINE_ARCH} == "powerpc" || \ + ${MACHINE_ARCH} == "x86_64" +USE_COMPILERCRTSTUFF?= no +.endif +USE_COMPILERCRTSTUFF?= yes + # default to GDB6 HAVE_GDB?= 6 diff --git a/tools/nbsd_ports b/tools/nbsd_ports index bfc950cfb..dfbd4412b 100644 --- a/tools/nbsd_ports +++ b/tools/nbsd_ports @@ -3,6 +3,8 @@ # minixpath: path in Minix source tree (starting from /usr/src/) # netbsdpath: path in BSD source tree (starting from src/) 2011/01/17 18:11:10,external/bsd/file +2011/01/17 18:11:10,lib/csu +2011/01/17 18:11:10,libexec/ld.elf_so 2011/01/17 18:11:10,usr.bin/genassym 2012/02/10 16:16:12,usr.bin/su 2011/12/25 06:09:09,sys/arch/i386/stand -- 2.44.0