From 0266ae5f884d72da58f33a072e865ba131234a5e Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 10 Feb 2014 17:46:57 -0800 Subject: [PATCH] Switch over to linux uapi under the covers. Remove the linker's reliance on BSD cruft and use the glibc-style ElfW macro. (Other code too, but the linker contains the majority of the code that needs to work for Elf32 and Elf64.) All platforms need dl_iterate_phdr_static, so it doesn't make sense to have that part of the per-architecture configuration. Bug: 12476126 Change-Id: I1d7f918f1303a392794a6cd8b3512ff56bd6e487 --- libc/Android.mk | 2 +- libc/arch-arm/arm.mk | 3 - libc/arch-arm64/arm64.mk | 5 - libc/arch-mips/mips.mk | 5 - libc/arch-mips64/mips64.mk | 5 - libc/arch-x86/x86.mk | 5 - libc/arch-x86_64/x86_64.mk | 5 - libc/bionic/dl_iterate_phdr_static.c | 82 -- libc/bionic/dl_iterate_phdr_static.cpp | 82 ++ libc/bionic/getauxval.cpp | 4 +- libc/bionic/libc_init_static.cpp | 8 +- libc/include/elf.h | 53 +- libc/include/sys/exec_elf.h | 1267 ------------------------ libc/private/KernelArgumentBlock.h | 7 +- libc/private/bionic_auxv.h | 3 +- linker/dlfcn.cpp | 32 +- linker/linker.cpp | 415 ++++---- linker/linker.h | 31 +- linker/linker_phdr.cpp | 314 +++--- linker/linker_phdr.h | 38 +- 20 files changed, 533 insertions(+), 1833 deletions(-) delete mode 100644 libc/bionic/dl_iterate_phdr_static.c create mode 100644 libc/bionic/dl_iterate_phdr_static.cpp delete mode 100644 libc/include/sys/exec_elf.h diff --git a/libc/Android.mk b/libc/Android.mk index 91f6cd193..c6fffb138 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -579,7 +579,7 @@ include $(LOCAL_PATH)/arch-$(TARGET_ARCH)/$(TARGET_ARCH).mk libc_bionic_src_files += $(_LIBC_ARCH_COMMON_SRC_FILES) libc_bionic_src_files += $(_LIBC_ARCH_CPU_VARIANT_SRC_FILES) -libc_arch_static_src_files := $(_LIBC_ARCH_STATIC_SRC_FILES) +libc_arch_static_src_files := $(_LIBC_ARCH_STATIC_SRC_FILES) bionic/dl_iterate_phdr_static.cpp libc_arch_dynamic_src_files := $(_LIBC_ARCH_DYNAMIC_SRC_FILES) libc_common_additional_dependencies += $(_LIBC_ARCH_ADDITIONAL_DEPENDENCIES) diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk index 95c3b610d..56b0d27bb 100644 --- a/libc/arch-arm/arm.mk +++ b/libc/arch-arm/arm.mk @@ -14,11 +14,8 @@ _LIBC_ARCH_COMMON_SRC_FILES := \ arch-arm/bionic/sigsetjmp.S \ arch-arm/bionic/syscall.S \ -# These are used by the static and dynamic versions of the libc -# respectively. _LIBC_ARCH_STATIC_SRC_FILES := \ arch-arm/bionic/exidx_static.c \ - bionic/dl_iterate_phdr_static.c \ _LIBC_ARCH_DYNAMIC_SRC_FILES := \ arch-arm/bionic/exidx_dynamic.c \ diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk index 86bf91a0a..d881ad418 100644 --- a/libc/arch-arm64/arm64.mk +++ b/libc/arch-arm64/arm64.mk @@ -12,8 +12,3 @@ _LIBC_ARCH_COMMON_SRC_FILES := \ arch-arm64/bionic/sigsetjmp.S \ arch-arm64/bionic/syscall.S \ arch-arm64/bionic/vfork.S \ - -_LIBC_ARCH_STATIC_SRC_FILES := \ - bionic/dl_iterate_phdr_static.c \ - -_LIBC_ARCH_DYNAMIC_SRC_FILES := diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk index 6f5792c5b..aa8e1ff89 100644 --- a/libc/arch-mips/mips.mk +++ b/libc/arch-mips/mips.mk @@ -15,8 +15,3 @@ _LIBC_ARCH_COMMON_SRC_FILES := \ arch-mips/string/memcpy.S \ arch-mips/string/memset.S \ arch-mips/string/mips_strlen.c \ - -_LIBC_ARCH_STATIC_SRC_FILES := \ - bionic/dl_iterate_phdr_static.c \ - -_LIBC_ARCH_DYNAMIC_SRC_FILES := diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk index fa09caa5f..d81f02a0a 100644 --- a/libc/arch-mips64/mips64.mk +++ b/libc/arch-mips64/mips64.mk @@ -21,8 +21,3 @@ _LIBC_ARCH_COMMON_SRC_FILES := \ _LIBC_ARCH_COMMON_SRC_FILES += bionic/memcpy.c _LIBC_ARCH_COMMON_SRC_FILES += bionic/memset.c _LIBC_ARCH_COMMON_SRC_FILES += string/strlen.c - -_LIBC_ARCH_STATIC_SRC_FILES := \ - bionic/dl_iterate_phdr_static.c \ - -_LIBC_ARCH_DYNAMIC_SRC_FILES := diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk index 9c7408496..912ce5adb 100644 --- a/libc/arch-x86/x86.mk +++ b/libc/arch-x86/x86.mk @@ -62,8 +62,3 @@ _LIBC_ARCH_COMMON_SRC_FILES += \ arch-x86/string/sse2-wcsrchr-atom.S \ arch-x86/string/sse2-wcslen-atom.S \ arch-x86/string/sse2-wcscmp-atom.S \ - -_LIBC_ARCH_STATIC_SRC_FILES := \ - bionic/dl_iterate_phdr_static.c \ - -_LIBC_ARCH_DYNAMIC_SRC_FILES := diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk index 261453784..f4d3ef17f 100644 --- a/libc/arch-x86_64/x86_64.mk +++ b/libc/arch-x86_64/x86_64.mk @@ -11,8 +11,3 @@ _LIBC_ARCH_COMMON_SRC_FILES := \ arch-x86_64/bionic/syscall.S \ arch-x86_64/bionic/vfork.S \ string/memcmp16.c \ - -_LIBC_ARCH_STATIC_SRC_FILES := \ - bionic/dl_iterate_phdr_static.c \ - -_LIBC_ARCH_DYNAMIC_SRC_FILES := diff --git a/libc/bionic/dl_iterate_phdr_static.c b/libc/bionic/dl_iterate_phdr_static.c deleted file mode 100644 index d03d3d2a9..000000000 --- a/libc/bionic/dl_iterate_phdr_static.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must 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 OWNER 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 -#include -#include - -/* ld provides this to us in the default link script */ -extern void* __executable_start; - -int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) { - Elf_Ehdr* ehdr = (Elf_Ehdr*) &__executable_start; - - // TODO: again, copied from linker.c. Find a better home for this later. - if (ehdr->e_ident[EI_MAG0] != ELFMAG0) return -1; - if (ehdr->e_ident[EI_MAG1] != ELFMAG1) return -1; - if (ehdr->e_ident[EI_MAG2] != ELFMAG2) return -1; - if (ehdr->e_ident[EI_MAG3] != ELFMAG3) return -1; - - // Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but - // static binaries get this. We don't have a list of shared objects to - // iterate over, since there's really only a single monolithic blob of - // code/data, plus optionally a VDSO. - - struct dl_phdr_info exe_info; - exe_info.dlpi_addr = 0; - exe_info.dlpi_name = NULL; - exe_info.dlpi_phdr = (Elf_Phdr*) ((unsigned long) ehdr + ehdr->e_phoff); - exe_info.dlpi_phnum = ehdr->e_phnum; - -#ifdef AT_SYSINFO_EHDR - // Try the executable first. - int rc = cb(&exe_info, sizeof(exe_info), data); - if (rc != 0) { - return rc; - } - - // Try the VDSO if that didn't work. - Elf_Ehdr* ehdr_vdso = (Elf_Ehdr*) getauxval(AT_SYSINFO_EHDR); - struct dl_phdr_info vdso_info; - vdso_info.dlpi_addr = 0; - vdso_info.dlpi_name = NULL; - vdso_info.dlpi_phdr = (Elf_Phdr*) ((char*) ehdr_vdso + ehdr_vdso->e_phoff); - vdso_info.dlpi_phnum = ehdr_vdso->e_phnum; - for (size_t i = 0; i < vdso_info.dlpi_phnum; ++i) { - if (vdso_info.dlpi_phdr[i].p_type == PT_LOAD) { - vdso_info.dlpi_addr = (Elf_Addr) ehdr_vdso - vdso_info.dlpi_phdr[i].p_vaddr; - break; - } - } - return cb(&vdso_info, sizeof(vdso_info), data); -#else - // There's only the executable to try. - return cb(&exe_info, sizeof(exe_info), data); -#endif -} diff --git a/libc/bionic/dl_iterate_phdr_static.cpp b/libc/bionic/dl_iterate_phdr_static.cpp new file mode 100644 index 000000000..7e9eeddb2 --- /dev/null +++ b/libc/bionic/dl_iterate_phdr_static.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must 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 OWNER 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 +#include +#include + +/* ld provides this to us in the default link script */ +extern "C" void* __executable_start; + +int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) { + ElfW(Ehdr)* ehdr = reinterpret_cast(&__executable_start); + + // TODO: again, copied from linker.c. Find a better home for this later. + if (ehdr->e_ident[EI_MAG0] != ELFMAG0) return -1; + if (ehdr->e_ident[EI_MAG1] != ELFMAG1) return -1; + if (ehdr->e_ident[EI_MAG2] != ELFMAG2) return -1; + if (ehdr->e_ident[EI_MAG3] != ELFMAG3) return -1; + + // Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but + // static binaries get this. We don't have a list of shared objects to + // iterate over, since there's really only a single monolithic blob of + // code/data, plus optionally a VDSO. + + struct dl_phdr_info exe_info; + exe_info.dlpi_addr = 0; + exe_info.dlpi_name = NULL; + exe_info.dlpi_phdr = reinterpret_cast(reinterpret_cast(ehdr) + ehdr->e_phoff); + exe_info.dlpi_phnum = ehdr->e_phnum; + +#ifdef AT_SYSINFO_EHDR + // Try the executable first. + int rc = cb(&exe_info, sizeof(exe_info), data); + if (rc != 0) { + return rc; + } + + // Try the VDSO if that didn't work. + ElfW(Ehdr)* ehdr_vdso = reinterpret_cast(getauxval(AT_SYSINFO_EHDR)); + struct dl_phdr_info vdso_info; + vdso_info.dlpi_addr = 0; + vdso_info.dlpi_name = NULL; + vdso_info.dlpi_phdr = reinterpret_cast(reinterpret_cast(ehdr_vdso) + ehdr_vdso->e_phoff); + vdso_info.dlpi_phnum = ehdr_vdso->e_phnum; + for (size_t i = 0; i < vdso_info.dlpi_phnum; ++i) { + if (vdso_info.dlpi_phdr[i].p_type == PT_LOAD) { + vdso_info.dlpi_addr = (ElfW(Addr)) ehdr_vdso - vdso_info.dlpi_phdr[i].p_vaddr; + break; + } + } + return cb(&vdso_info, sizeof(vdso_info), data); +#else + // There's only the executable to try. + return cb(&exe_info, sizeof(exe_info), data); +#endif +} diff --git a/libc/bionic/getauxval.cpp b/libc/bionic/getauxval.cpp index 3ee31d600..bc4182496 100644 --- a/libc/bionic/getauxval.cpp +++ b/libc/bionic/getauxval.cpp @@ -32,10 +32,10 @@ #include #include -__LIBC_HIDDEN__ Elf_auxv_t* __libc_auxv = NULL; +__LIBC_HIDDEN__ ElfW(auxv_t)* __libc_auxv = NULL; extern "C" unsigned long int getauxval(unsigned long int type) { - for (Elf_auxv_t* v = __libc_auxv; v->a_type != AT_NULL; ++v) { + for (ElfW(auxv_t)* v = __libc_auxv; v->a_type != AT_NULL; ++v) { if (v->a_type == type) { return v->a_un.a_val; } diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index 1825167bd..e45422ed9 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -68,16 +68,16 @@ static void call_array(void(**list)()) { } static void apply_gnu_relro() { - Elf_Phdr* phdr_start = reinterpret_cast(getauxval(AT_PHDR)); + ElfW(Phdr)* phdr_start = reinterpret_cast(getauxval(AT_PHDR)); unsigned long int phdr_ct = getauxval(AT_PHNUM); - for (Elf_Phdr* phdr = phdr_start; phdr < (phdr_start + phdr_ct); phdr++) { + for (ElfW(Phdr)* phdr = phdr_start; phdr < (phdr_start + phdr_ct); phdr++) { if (phdr->p_type != PT_GNU_RELRO) { continue; } - Elf_Addr seg_page_start = PAGE_START(phdr->p_vaddr); - Elf_Addr seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz); + ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr); + ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz); // Check return value here? What do we do if we fail? mprotect(reinterpret_cast(seg_page_start), seg_page_end - seg_page_start, PROT_READ); diff --git a/libc/include/elf.h b/libc/include/elf.h index 3f2e4f25a..7a217b07f 100644 --- a/libc/include/elf.h +++ b/libc/include/elf.h @@ -28,33 +28,58 @@ #ifndef _ELF_H #define _ELF_H -#include #include +#include +#include -/* TODO: can we switch to instead? http://b/12476126. */ -#include +#include typedef struct { - uint32_t a_type; + __u32 a_type; union { - uint32_t a_val; + __u32 a_val; } a_un; } Elf32_auxv_t; typedef struct { - uint64_t a_type; + __u64 a_type; union { - uint64_t a_val; + __u64 a_val; } a_un; } Elf64_auxv_t; -#ifdef __LP64__ -# define Elf_auxv_t Elf64_auxv_t -#else -# define Elf_auxv_t Elf32_auxv_t -#endif +#define DF_ORIGIN 0x00000001 +#define DF_SYMBOLIC 0x00000002 +#define DF_TEXTREL 0x00000004 +#define DF_BIND_NOW 0x00000008 +#define DF_STATIC_TLS 0x00000010 -/* doesn't contain any NT_ constants. aarch64 strace needs this one. */ -#define NT_PRSTATUS 1 +#define DT_BIND_NOW 24 +#define DT_INIT_ARRAY 25 +#define DT_FINI_ARRAY 26 +#define DT_INIT_ARRAYSZ 27 +#define DT_FINI_ARRAYSZ 28 +#define DT_RUNPATH 29 +#define DT_FLAGS 30 +/* glibc and BSD disagree for DT_ENCODING; glibc looks wrong. */ +#define DT_PREINIT_ARRAY 32 +#define DT_PREINIT_ARRAYSZ 33 + +#define ELFOSABI_SYSV 0 /* Synonym for ELFOSABI_NONE used by valgrind. */ + +#define EM_ARM 40 +#define EM_AARCH64 183 + +#define PT_GNU_RELRO 0x6474e552 + +#define STB_LOOS 10 +#define STB_HIOS 12 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +#define STT_LOOS 10 +#define STT_HIOS 12 +#define STT_LOPROC 13 +#define STT_HIPROC 15 #endif /* _ELF_H */ diff --git a/libc/include/sys/exec_elf.h b/libc/include/sys/exec_elf.h deleted file mode 100644 index 3c1467c56..000000000 --- a/libc/include/sys/exec_elf.h +++ /dev/null @@ -1,1267 +0,0 @@ -/* $NetBSD: exec_elf.h,v 1.131 2013/10/29 00:22:59 christos Exp $ */ - -/*- - * Copyright (c) 1994 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. - */ - -#ifndef _SYS_EXEC_ELF_H_ -#define _SYS_EXEC_ELF_H_ - -/* - * The current ELF ABI specification is available at: - * http://www.sco.com/developers/gabi/ - * - * Current header definitions are in: - * http://www.sco.com/developers/gabi/latest/ch4.eheader.html - */ - -#if defined(_KERNEL) || defined(_STANDALONE) -#include -#else -#include -#endif /* _KERNEL || _STANDALONE */ - -#if HAVE_NBTOOL_CONFIG_H -#include -#else -#include -#endif - -typedef uint8_t Elf_Byte; - -typedef uint32_t Elf32_Addr; -#define ELF32_FSZ_ADDR 4 -typedef uint32_t Elf32_Off; -typedef int32_t Elf32_SOff; -#define ELF32_FSZ_OFF 4 -typedef int32_t Elf32_Sword; -#define ELF32_FSZ_SWORD 4 -typedef uint32_t Elf32_Word; -#define ELF32_FSZ_WORD 4 -typedef uint16_t Elf32_Half; -#define ELF32_FSZ_HALF 2 -typedef uint64_t Elf32_Lword; -#define ELF32_FSZ_LWORD 8 - -typedef uint64_t Elf64_Addr; -#define ELF64_FSZ_ADDR 8 -typedef uint64_t Elf64_Off; -typedef int64_t Elf64_SOff; -#define ELF64_FSZ_OFF 8 -typedef int32_t Elf64_Shalf; -#define ELF64_FSZ_SHALF 4 - -typedef int32_t Elf64_Sword; -#define ELF64_FSZ_SWORD 4 -typedef uint32_t Elf64_Word; -#define ELF64_FSZ_WORD 4 - -typedef int64_t Elf64_Sxword; -#define ELF64_FSZ_SXWORD 8 -typedef uint64_t Elf64_Xword; -#define ELF64_FSZ_XWORD 8 -typedef uint64_t Elf64_Lword; -#define ELF64_FSZ_LWORD 8 -typedef uint16_t Elf64_Half; -#define ELF64_FSZ_HALF 2 - -/* - * ELF Header - */ -#define ELF_NIDENT 16 - -typedef struct { - unsigned char e_ident[ELF_NIDENT]; /* Id bytes */ - Elf32_Half e_type; /* file type */ - Elf32_Half e_machine; /* machine type */ - Elf32_Word e_version; /* version number */ - Elf32_Addr e_entry; /* entry point */ - Elf32_Off e_phoff; /* Program hdr offset */ - Elf32_Off e_shoff; /* Section hdr offset */ - Elf32_Word e_flags; /* Processor flags */ - Elf32_Half e_ehsize; /* sizeof ehdr */ - Elf32_Half e_phentsize; /* Program header entry size */ - Elf32_Half e_phnum; /* Number of program headers */ - Elf32_Half e_shentsize; /* Section header entry size */ - Elf32_Half e_shnum; /* Number of section headers */ - Elf32_Half e_shstrndx; /* String table index */ -} Elf32_Ehdr; - -typedef struct { - unsigned char e_ident[ELF_NIDENT]; /* Id bytes */ - Elf64_Half e_type; /* file type */ - Elf64_Half e_machine; /* machine type */ - Elf64_Word e_version; /* version number */ - Elf64_Addr e_entry; /* entry point */ - Elf64_Off e_phoff; /* Program hdr offset */ - Elf64_Off e_shoff; /* Section hdr offset */ - Elf64_Word e_flags; /* Processor flags */ - Elf64_Half e_ehsize; /* sizeof ehdr */ - Elf64_Half e_phentsize; /* Program header entry size */ - Elf64_Half e_phnum; /* Number of program headers */ - Elf64_Half e_shentsize; /* Section header entry size */ - Elf64_Half e_shnum; /* Number of section headers */ - Elf64_Half e_shstrndx; /* String table index */ -} Elf64_Ehdr; - -/* e_ident offsets */ -#define EI_MAG0 0 /* '\177' */ -#define EI_MAG1 1 /* 'E' */ -#define EI_MAG2 2 /* 'L' */ -#define EI_MAG3 3 /* 'F' */ -#define EI_CLASS 4 /* File class */ -#define EI_DATA 5 /* Data encoding */ -#define EI_VERSION 6 /* File version */ -#define EI_OSABI 7 /* Operating system/ABI identification */ -#define EI_ABIVERSION 8 /* ABI version */ -#define EI_PAD 9 /* Start of padding bytes up to EI_NIDENT*/ -#define EI_NIDENT 16 /* First non-ident header byte */ - -/* e_ident[EI_MAG0,EI_MAG3] */ -#define ELFMAG0 0x7f -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -/* e_ident[EI_CLASS] */ -#define ELFCLASSNONE 0 /* Invalid class */ -#define ELFCLASS32 1 /* 32-bit objects */ -#define ELFCLASS64 2 /* 64-bit objects */ -#define ELFCLASSNUM 3 - -/* e_ident[EI_DATA] */ -#define ELFDATANONE 0 /* Invalid data encoding */ -#define ELFDATA2LSB 1 /* 2's complement values, LSB first */ -#define ELFDATA2MSB 2 /* 2's complement values, MSB first */ - -/* e_ident[EI_VERSION] */ -#define EV_NONE 0 /* Invalid version */ -#define EV_CURRENT 1 /* Current version */ -#define EV_NUM 2 - -/* 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_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_STANDALONE 255 /* Standalone (embedded) application */ - -#define ELFOSABI_NONE ELFOSABI_SYSV -#define ELFOSABI_AIX ELFOSABI_MONTEREY - -/* e_type */ -#define ET_NONE 0 /* No file type */ -#define ET_REL 1 /* Relocatable file */ -#define ET_EXEC 2 /* Executable file */ -#define ET_DYN 3 /* Shared object file */ -#define ET_CORE 4 /* Core file */ -#define ET_NUM 5 - -#define ET_LOOS 0xfe00 /* Operating system specific range */ -#define ET_HIOS 0xfeff -#define ET_LOPROC 0xff00 /* Processor-specific range */ -#define ET_HIPROC 0xffff - -/* e_machine */ -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola 68000 */ -#define EM_88K 5 /* Motorola 88000 */ -#define EM_486 6 /* Intel 80486 */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS I Architecture */ -#define EM_S370 9 /* Amdahl UTS on System/370 */ -#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-endian */ - /* 11-14 - Reserved */ -#define EM_RS6000 11 /* IBM RS/6000 XXX reserved */ -#define EM_PARISC 15 /* Hewlett-Packard PA-RISC */ -#define EM_NCUBE 16 /* NCube XXX reserved */ -#define EM_VPP500 17 /* Fujitsu VPP500 */ -#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ -#define EM_960 19 /* Intel 80960 */ -#define EM_PPC 20 /* PowerPC */ -#define EM_PPC64 21 /* 64-bit PowerPC */ - /* 22-35 - Reserved */ -#define EM_S390 22 /* System/390 XXX reserved */ -#define EM_V800 36 /* NEC V800 */ -#define EM_FR20 37 /* Fujitsu FR20 */ -#define EM_RH32 38 /* TRW RH-32 */ -#define EM_RCE 39 /* Motorola RCE */ -#define EM_ARM 40 /* Advanced RISC Machines ARM */ -#define EM_ALPHA 41 /* DIGITAL Alpha */ -#define EM_SH 42 /* Hitachi Super-H */ -#define EM_SPARCV9 43 /* SPARC Version 9 */ -#define EM_TRICORE 44 /* Siemens Tricore */ -#define EM_ARC 45 /* Argonaut RISC Core */ -#define EM_H8_300 46 /* Hitachi H8/300 */ -#define EM_H8_300H 47 /* Hitachi H8/300H */ -#define EM_H8S 48 /* Hitachi H8S */ -#define EM_H8_500 49 /* Hitachi H8/500 */ -#define EM_IA_64 50 /* Intel Merced Processor */ -#define EM_MIPS_X 51 /* Stanford MIPS-X */ -#define EM_COLDFIRE 52 /* Motorola Coldfire */ -#define EM_68HC12 53 /* Motorola MC68HC12 */ -#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */ -#define EM_PCP 55 /* Siemens PCP */ -#define EM_NCPU 56 /* Sony nCPU embedded RISC processor */ -#define EM_NDR1 57 /* Denso NDR1 microprocessor */ -#define EM_STARCORE 58 /* Motorola Star*Core processor */ -#define EM_ME16 59 /* Toyota ME16 processor */ -#define EM_ST100 60 /* STMicroelectronics ST100 processor */ -#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ embedded family processor */ -#define EM_X86_64 62 /* AMD x86-64 architecture */ -#define EM_PDSP 63 /* Sony DSP Processor */ -#define EM_PDP10 64 /* Digital Equipment Corp. PDP-10 */ -#define EM_PDP11 65 /* Digital Equipment Corp. PDP-11 */ -#define EM_FX66 66 /* Siemens FX66 microcontroller */ -#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */ -#define EM_ST7 68 /* STMicroelectronics ST7 8-bit microcontroller */ -#define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */ -#define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */ -#define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */ -#define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */ -#define EM_SVX 73 /* Silicon Graphics SVx */ -#define EM_ST19 74 /* STMicroelectronics ST19 8-bit CPU */ -#define EM_VAX 75 /* Digital VAX */ -#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ -#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded CPU */ -#define EM_FIREPATH 78 /* Element 14 64-bit DSP processor */ -#define EM_ZSP 79 /* LSI Logic's 16-bit DSP processor */ -#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ -#define EM_HUANY 81 /* Harvard's machine-independent format */ -#define EM_PRISM 82 /* SiTera Prism */ -#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ -#define EM_FR30 84 /* Fujitsu FR30 */ -#define EM_D10V 85 /* Mitsubishi D10V */ -#define EM_D30V 86 /* Mitsubishi D30V */ -#define EM_V850 87 /* NEC v850 */ -#define EM_M32R 88 /* Mitsubishi M32R */ -#define EM_MN10300 89 /* Matsushita MN10300 */ -#define EM_MN10200 90 /* Matsushita MN10200 */ -#define EM_PJ 91 /* picoJava */ -#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ -#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ -#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ -#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor */ -#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Processor */ -#define EM_NS32K 97 /* National Semiconductor 32000 series */ -#define EM_TPC 98 /* Tenor Network TPC processor */ -#define EM_SNP1K 99 /* Trebia SNP 1000 processor */ -#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller */ -#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family */ -#define EM_MAX 102 /* MAX processor */ -#define EM_CR 103 /* National Semiconductor CompactRISC micorprocessor */ -#define EM_F2MC16 104 /* Fujitsu F2MC16 */ -#define EM_MSP430 105 /* Texas Instruments MSP430 */ -#define EM_BLACKFIN 106 /* Analog Devices Blackfin DSP */ -#define EM_SE_C33 107 /* Seiko Epson S1C33 family */ -#define EM_SEP 108 /* Sharp embedded microprocessor */ -#define EM_ARCA 109 /* Arca RISC microprocessor */ -#define EM_UNICORE 110 /* UNICORE from PKU-Unity Ltd. and MPRC Peking University */ -#define EM_AARCH64 183 /* AArch64 64-bit ARM microprocessor */ - -/* Unofficial machine types follow */ -#define EM_AVR32 6317 /* used by NetBSD/avr32 */ -#define EM_ALPHA_EXP 36902 /* used by NetBSD/alpha; obsolete */ -#define EM_NUM 36903 - -/* - * Program Header - */ -typedef struct { - Elf32_Word p_type; /* entry type */ - Elf32_Off p_offset; /* offset */ - Elf32_Addr p_vaddr; /* virtual address */ - Elf32_Addr p_paddr; /* physical address */ - Elf32_Word p_filesz; /* file size */ - Elf32_Word p_memsz; /* memory size */ - Elf32_Word p_flags; /* flags */ - Elf32_Word p_align; /* memory & file alignment */ -} Elf32_Phdr; - -typedef struct { - Elf64_Word p_type; /* entry type */ - Elf64_Word p_flags; /* flags */ - Elf64_Off p_offset; /* offset */ - Elf64_Addr p_vaddr; /* virtual address */ - Elf64_Addr p_paddr; /* physical address */ - Elf64_Xword p_filesz; /* file size */ - Elf64_Xword p_memsz; /* memory size */ - Elf64_Xword p_align; /* memory & file alignment */ -} Elf64_Phdr; - -/* p_type */ -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 /* Reserved, unspecified semantics */ -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_TLS 7 /* TLS initialisation image */ -#define PT_NUM 8 - -#define PT_LOOS 0x60000000 /* OS-specific range */ - -/* GNU-specific */ -#define PT_GNU_EH_FRAME 0x6474e550 /* EH frame segment */ -#define PT_GNU_STACK 0x6474e551 /* Indicate executable stack */ -#define PT_GNU_RELRO 0x6474e552 /* Make read-only after relocation */ - -#define PT_HIOS 0x6fffffff -#define PT_LOPROC 0x70000000 /* Processor-specific range */ -#define PT_HIPROC 0x7fffffff - -#define PT_MIPS_REGINFO 0x70000000 - -/* p_flags */ -#define PF_R 0x4 /* Segment is readable */ -#define PF_W 0x2 /* Segment is writable */ -#define PF_X 0x1 /* Segment is executable */ - -#define PF_MASKOS 0x0ff00000 /* Operating system specific values */ -#define PF_MASKPROC 0xf0000000 /* Processor-specific values */ - -/* Extended program header index. */ -#define PN_XNUM 0xffff - -/* - * Section Headers - */ -typedef struct { - Elf32_Word sh_name; /* section name (.shstrtab index) */ - Elf32_Word sh_type; /* section type */ - Elf32_Word sh_flags; /* section flags */ - Elf32_Addr sh_addr; /* virtual address */ - Elf32_Off sh_offset; /* file offset */ - Elf32_Word sh_size; /* section size */ - Elf32_Word sh_link; /* link to another */ - Elf32_Word sh_info; /* misc info */ - Elf32_Word sh_addralign; /* memory alignment */ - Elf32_Word sh_entsize; /* table entry size */ -} Elf32_Shdr; - -typedef struct { - Elf64_Word sh_name; /* section name (.shstrtab index) */ - Elf64_Word sh_type; /* section type */ - Elf64_Xword sh_flags; /* section flags */ - Elf64_Addr sh_addr; /* virtual address */ - Elf64_Off sh_offset; /* file offset */ - Elf64_Xword sh_size; /* section size */ - Elf64_Word sh_link; /* link to another */ - Elf64_Word sh_info; /* misc info */ - Elf64_Xword sh_addralign; /* memory alignment */ - Elf64_Xword sh_entsize; /* table entry size */ -} Elf64_Shdr; - -/* sh_type */ -#define SHT_NULL 0 /* Section header table entry unused */ -#define SHT_PROGBITS 1 /* Program information */ -#define SHT_SYMTAB 2 /* Symbol table */ -#define SHT_STRTAB 3 /* String table */ -#define SHT_RELA 4 /* Relocation information w/ addend */ -#define SHT_HASH 5 /* Symbol hash table */ -#define SHT_DYNAMIC 6 /* Dynamic linking information */ -#define SHT_NOTE 7 /* Auxiliary information */ -#define SHT_NOBITS 8 /* No space allocated in file image */ -#define SHT_REL 9 /* Relocation information w/o addend */ -#define SHT_SHLIB 10 /* Reserved, unspecified semantics */ -#define SHT_DYNSYM 11 /* Symbol table for dynamic linker */ -#define SHT_INIT_ARRAY 14 /* Initialization function pointers */ -#define SHT_FINI_ARRAY 15 /* Termination function pointers */ -#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs */ -#define SHT_GROUP 17 /* Section group */ -#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX) */ -#define SHT_NUM 19 - -#define SHT_LOOS 0x60000000 /* Operating system specific range */ -#define SHT_GNU_HASH 0x6ffffff6 /* GNU style symbol hash table */ -#define SHT_SUNW_move 0x6ffffffa -#define SHT_SUNW_syminfo 0x6ffffffc -#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_GNU_verneed SHT_SUNW_verneed -#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 */ -#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ -#define SHT_ARM_EXIDX 0x70000001 /* exception index table */ -#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking - * pre-emption map */ -#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility - * attributes */ -#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details */ -#define SHT_ARM_OVERLAYSECTION 0x70000005 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 /* Application-specific range */ -#define SHT_HIUSER 0xffffffff - -/* sh_flags */ -#define SHF_WRITE 0x00000001 /* Contains writable data */ -#define SHF_ALLOC 0x00000002 /* Occupies memory */ -#define SHF_EXECINSTR 0x00000004 /* Contains executable insns */ -#define SHF_MERGE 0x00000010 /* Might be merged */ -#define SHF_STRINGS 0x00000020 /* Contains nul terminated strings */ -#define SHF_INFO_LINK 0x00000040 /* "sh_info" contains SHT index */ -#define SHF_LINK_ORDER 0x00000080 /* Preserve order after combining */ -#define SHF_OS_NONCONFORMING 0x00000100 /* OS specific handling required */ -#define SHF_GROUP 0x00000200 /* Is member of a group */ -#define SHF_TLS 0x00000400 /* Holds thread-local data */ -#define SHF_MASKOS 0x0ff00000 /* Operating system specific values */ -#define SHF_MASKPROC 0xf0000000 /* Processor-specific values */ -#define SHF_ORDERED 0x40000000 /* Ordering requirement (Solaris) */ -#define SHF_EXCLUDE 0x80000000 /* Excluded unless unles ref/alloc - (Solaris).*/ -/* - * Symbol Table - */ -typedef struct { - Elf32_Word st_name; /* Symbol name (.strtab index) */ - Elf32_Word st_value; /* value of symbol */ - Elf32_Word st_size; /* size of symbol */ - Elf_Byte st_info; /* type / binding attrs */ - Elf_Byte st_other; /* unused */ - Elf32_Half st_shndx; /* section index of symbol */ -} Elf32_Sym; - -typedef struct { - Elf64_Word st_name; /* Symbol name (.strtab index) */ - Elf_Byte st_info; /* type / binding attrs */ - Elf_Byte st_other; /* unused */ - Elf64_Half st_shndx; /* section index of symbol */ - Elf64_Addr st_value; /* value of symbol */ - Elf64_Xword st_size; /* size of symbol */ -} Elf64_Sym; - -/* Symbol Table index of the undefined symbol */ -#define ELF_SYM_UNDEFINED 0 - -#define STN_UNDEF 0 /* undefined index */ - -/* st_info: Symbol Bindings */ -#define STB_LOCAL 0 /* local symbol */ -#define STB_GLOBAL 1 /* global symbol */ -#define STB_WEAK 2 /* weakly defined global symbol */ -#define STB_NUM 3 - -#define STB_LOOS 10 /* Operating system specific range */ -#define STB_HIOS 12 -#define STB_LOPROC 13 /* Processor-specific range */ -#define STB_HIPROC 15 - -/* st_info: Symbol Types */ -#define STT_NOTYPE 0 /* Type not specified */ -#define STT_OBJECT 1 /* Associated with a data object */ -#define STT_FUNC 2 /* Associated with a function */ -#define STT_SECTION 3 /* Associated with a section */ -#define STT_FILE 4 /* Associated with a file name */ -#define STT_COMMON 5 /* Uninitialised common block */ -#define STT_TLS 6 /* Thread local data object */ -#define STT_NUM 7 - -#define STT_LOOS 10 /* Operating system specific range */ -#define STT_HIOS 12 -#define STT_LOPROC 13 /* Processor-specific range */ -#define STT_HIPROC 15 - -/* st_other: Visibility Types */ -#define STV_DEFAULT 0 /* use binding type */ -#define STV_INTERNAL 1 /* not referenced from outside */ -#define STV_HIDDEN 2 /* not visible, may be used via ptr */ -#define STV_PROTECTED 3 /* visible, not preemptible */ -#define STV_EXPORTED 4 -#define STV_SINGLETON 5 -#define STV_ELIMINATE 6 - -/* st_info/st_other utility macros */ -#define ELF_ST_BIND(info) ((uint32_t)(info) >> 4) -#define ELF_ST_TYPE(info) ((uint32_t)(info) & 0xf) -#define ELF_ST_INFO(bind,type) ((Elf_Byte)(((bind) << 4) | \ - ((type) & 0xf))) -#define ELF_ST_VISIBILITY(other) ((uint32_t)(other) & 3) - -/* - * Special section indexes - */ -#define SHN_UNDEF 0 /* Undefined section */ - -#define SHN_LORESERVE 0xff00 /* Reserved range */ -#define SHN_ABS 0xfff1 /* Absolute symbols */ -#define SHN_COMMON 0xfff2 /* Common symbols */ -#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere */ -#define SHN_HIRESERVE 0xffff - -#define SHN_LOPROC 0xff00 /* Processor-specific range */ -#define SHN_HIPROC 0xff1f -#define SHN_LOOS 0xff20 /* Operating system specific range */ -#define SHN_HIOS 0xff3f - -#define SHN_MIPS_ACOMMON 0xff00 -#define SHN_MIPS_TEXT 0xff01 -#define SHN_MIPS_DATA 0xff02 -#define SHN_MIPS_SCOMMON 0xff03 - -/* - * Relocation Entries - */ -typedef struct { - Elf32_Word r_offset; /* where to do it */ - Elf32_Word r_info; /* index & type of relocation */ -} Elf32_Rel; - -typedef struct { - Elf32_Word r_offset; /* where to do it */ - Elf32_Word r_info; /* index & type of relocation */ - Elf32_Sword r_addend; /* adjustment value */ -} Elf32_Rela; - -/* r_info utility macros */ -#define ELF32_R_SYM(info) ((info) >> 8) -#define ELF32_R_TYPE(info) ((info) & 0xff) -#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) - -typedef struct { - Elf64_Addr r_offset; /* where to do it */ - Elf64_Xword r_info; /* index & type of relocation */ -} Elf64_Rel; - -typedef struct { - Elf64_Addr r_offset; /* where to do it */ - Elf64_Xword r_info; /* index & type of relocation */ - Elf64_Sxword r_addend; /* adjustment value */ -} Elf64_Rela; - -/* r_info utility macros */ -#define ELF64_R_SYM(info) ((info) >> 32) -#define ELF64_R_TYPE(info) ((info) & 0xffffffff) -#define ELF64_R_INFO(sym,type) (((sym) << 32) + (type)) - -/* - * Move entries - */ -typedef struct { - Elf32_Lword m_value; /* symbol value */ - Elf32_Word m_info; /* size + index */ - Elf32_Word m_poffset; /* symbol offset */ - Elf32_Half m_repeat; /* repeat count */ - Elf32_Half m_stride; /* stride info */ -} Elf32_Move; - -#define ELF32_M_SYM(info) ((info) >> 8) -#define ELF32_M_SIZE(info) ((info) & 0xff) -#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size)) - -typedef struct { - Elf64_Lword m_value; /* symbol value */ - Elf64_Xword m_info; /* size + index */ - Elf64_Xword m_poffset; /* symbol offset */ - Elf64_Word m_repeat; /* repeat count */ - Elf64_Word m_stride; /* stride info */ -} Elf64_Move; - -#define ELF64_M_SYM(info) ((info) >> 8) -#define ELF64_M_SIZE(info) ((info) & 0xff) -#define ELF64_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size)) - -/* - * Hardware/software capabilities entry - */ -typedef struct { - Elf32_Word c_tag; /* entry tag value */ - union { - Elf32_Addr c_ptr; - Elf32_Word c_val; - } c_un; -} Elf32_Cap; - -typedef struct { - Elf64_Xword c_tag; /* entry tag value */ - union { - Elf64_Addr c_ptr; - Elf64_Xword c_val; - } c_un; -} Elf64_Cap; - -/* - * Dynamic Section structure array - */ -typedef struct { - Elf32_Word d_tag; /* entry tag value */ - union { - Elf32_Addr d_ptr; - Elf32_Word d_val; - } d_un; -} Elf32_Dyn; - -typedef struct { - Elf64_Xword d_tag; /* entry tag value */ - union { - Elf64_Addr d_ptr; - Elf64_Xword d_val; - } d_un; -} Elf64_Dyn; - -/* d_tag */ -#define DT_NULL 0 /* Marks end of dynamic array */ -#define DT_NEEDED 1 /* Name of needed library (DT_STRTAB offset) */ -#define DT_PLTRELSZ 2 /* Size, in bytes, of relocations in PLT */ -#define DT_PLTGOT 3 /* Address of PLT and/or GOT */ -#define DT_HASH 4 /* Address of symbol hash table */ -#define DT_STRTAB 5 /* Address of string table */ -#define DT_SYMTAB 6 /* Address of symbol table */ -#define DT_RELA 7 /* Address of Rela relocation table */ -#define DT_RELASZ 8 /* Size, in bytes, of DT_RELA table */ -#define DT_RELAENT 9 /* Size, in bytes, of one DT_RELA entry */ -#define DT_STRSZ 10 /* Size, in bytes, of DT_STRTAB table */ -#define DT_SYMENT 11 /* Size, in bytes, of one DT_SYMTAB entry */ -#define DT_INIT 12 /* Address of initialization function */ -#define DT_FINI 13 /* Address of termination function */ -#define DT_SONAME 14 /* Shared object name (DT_STRTAB offset) */ -#define DT_RPATH 15 /* Library search path (DT_STRTAB offset) */ -#define DT_SYMBOLIC 16 /* Start symbol search within local object */ -#define DT_REL 17 /* Address of Rel relocation table */ -#define DT_RELSZ 18 /* Size, in bytes, of DT_REL table */ -#define DT_RELENT 19 /* Size, in bytes, of one DT_REL entry */ -#define DT_PLTREL 20 /* Type of PLT relocation entries */ -#define DT_DEBUG 21 /* Used for debugging; unspecified */ -#define DT_TEXTREL 22 /* Relocations might modify non-writable seg */ -#define DT_JMPREL 23 /* Address of relocations associated with PLT */ -#define DT_BIND_NOW 24 /* Process all relocations at load-time */ -#define DT_INIT_ARRAY 25 /* Address of initialization function array */ -#define DT_FINI_ARRAY 26 /* Size, in bytes, of DT_INIT_ARRAY array */ -#define DT_INIT_ARRAYSZ 27 /* Address of termination function array */ -#define DT_FINI_ARRAYSZ 28 /* Size, in bytes, of DT_FINI_ARRAY array*/ -#define DT_RUNPATH 29 /* overrides DT_RPATH */ -#define DT_FLAGS 30 /* Encodes ORIGIN, SYMBOLIC, TEXTREL, BIND_NOW, STATIC_TLS */ -#define DT_ENCODING 31 /* ??? */ -#define DT_PREINIT_ARRAY 32 /* Address of pre-init function array */ -#define DT_PREINIT_ARRAYSZ 33 /* Size, in bytes, of DT_PREINIT_ARRAY array */ -#define DT_NUM 34 - -#define DT_LOOS 0x60000000 /* Operating system specific range */ -#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_HIOS 0x6fffffff -#define DT_LOPROC 0x70000000 /* Processor-specific range */ -#define DT_HIPROC 0x7fffffff - -/* Flag values for DT_FLAGS */ -#define DF_ORIGIN 0x00000001 /* uses $ORIGIN */ -#define DF_SYMBOLIC 0x00000002 /* */ -#define DF_TEXTREL 0x00000004 /* */ -#define DF_BIND_NOW 0x00000008 /* */ -#define DF_STATICT_LS 0x00000010 /* */ - -/* Flag values for DT_FLAGS_1 (incomplete) */ -#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ -#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ -#define DF_1_INITFIRST 0x00000020 /* Object's init/fini take priority */ -#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ - -/* - * Auxiliary Vectors - */ -typedef struct { - Elf32_Word a_type; /* 32-bit id */ - Elf32_Word a_v; /* 32-bit id */ -} Aux32Info; - -typedef struct { - Elf64_Word a_type; /* 32-bit id */ - Elf64_Xword a_v; /* 64-bit id */ -} Aux64Info; - -/* BEGIN android-changed: these constants should come from . */ -#if 0 -/* a_type */ -#define AT_NULL 0 /* Marks end of array */ -#define AT_IGNORE 1 /* No meaning, a_un is undefined */ -#define AT_EXECFD 2 /* Open file descriptor of object file */ -#define AT_PHDR 3 /* &phdr[0] */ -#define AT_PHENT 4 /* sizeof(phdr[0]) */ -#define AT_PHNUM 5 /* # phdr entries */ -#define AT_PAGESZ 6 /* PAGESIZE */ -#define AT_BASE 7 /* Interpreter base addr */ -#define AT_FLAGS 8 /* Processor flags */ -#define AT_ENTRY 9 /* Entry address of executable */ -#define AT_DCACHEBSIZE 10 /* Data cache block size */ -#define AT_ICACHEBSIZE 11 /* Instruction cache block size */ -#define AT_UCACHEBSIZE 12 /* Unified cache block size */ -#define AT_STACKBASE 13 /* Base address of the main thread */ - - /* Vendor specific */ -#define AT_MIPS_NOTELF 10 /* XXX a_val != 0 -> MIPS XCOFF executable */ - -#define AT_EUID 2000 /* euid (solaris compatible numbers) */ -#define AT_RUID 2001 /* ruid (solaris compatible numbers) */ -#define AT_EGID 2002 /* egid (solaris compatible numbers) */ -#define AT_RGID 2003 /* rgid (solaris compatible numbers) */ - - /* Solaris kernel specific */ -#define AT_SUN_LDELF 2004 /* dynamic linker's ELF header */ -#define AT_SUN_LDSHDR 2005 /* dynamic linker's section header */ -#define AT_SUN_LDNAME 2006 /* dynamic linker's name */ -#define AT_SUN_LPGSIZE 2007 /* large pagesize */ - - /* Other information */ -#define AT_SUN_PLATFORM 2008 /* sysinfo(SI_PLATFORM) */ -#define AT_SUN_HWCAP 2009 /* process hardware capabilities */ -#define AT_SUN_IFLUSH 2010 /* do we need to flush the instruction cache? */ -#define AT_SUN_CPU 2011 /* CPU name */ - /* ibcs2 emulation band aid */ -#define AT_SUN_EMUL_ENTRY 2012 /* coff entry point */ -#define AT_SUN_EMUL_EXECFD 2013 /* coff file descriptor */ - /* Executable's fully resolved name */ -#define AT_SUN_EXECNAME 2014 -#endif -/* END android-changed */ - -/* - * Note Headers - */ -typedef struct { - Elf32_Word n_namesz; - Elf32_Word n_descsz; - Elf32_Word n_type; -} Elf32_Nhdr; - -typedef struct { - Elf64_Word n_namesz; - Elf64_Word n_descsz; - Elf64_Word n_type; -} Elf64_Nhdr; - -#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_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 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 - -/* - * 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: ABI - * name: SuSE\0 - * namesz: 5 - * desc: - * half[0] = MMmm - * - * M = product major version - * m = product minor version - * descsz: 2 - */ -#define ELF_NOTE_TYPE_SUSE_TAG 1 -/* SuSE-specific note name and description sizes */ -#define ELF_NOTE_SUSE_NAMESZ 5 -#define ELF_NOTE_SUSE_DESCSZ 2 -/* SuSE-specific note name */ -#define ELF_NOTE_SUSE_NAME "SuSE\0" - -/* 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_VERSION_TAG 0x45537553 /* SuSE in LE */ -/* SuSE-specific note name and description sizes */ -#define ELF_NOTE_SUSE_VERSION_NAMESZ 8 -#define ELF_NOTE_SUSE_VERSION_DESCSZ 8 -/* SuSE-specific note name */ -#define ELF_NOTE_SUSE_VERSION_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 -#define ELF_NOTE_NETBSD_DESCSZ 4 -/* 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. - * 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. - * 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 - -/* - * NetBSD-specific core file information. - * - * NetBSD ELF core files use notes to provide information about - * the process's state. The note name is "NetBSD-CORE" for - * information that is global to the process, and "NetBSD-CORE@nn", - * where "nn" is the lwpid of the LWP that the information belongs - * to (such as register state). - * - * We use the following note identifiers: - * - * ELF_NOTE_NETBSD_CORE_PROCINFO - * Note is a "netbsd_elfcore_procinfo" structure. - * - * We also use ptrace(2) request numbers (the ones that exist in - * machine-dependent space) to identify register info notes. The - * info in such notes is in the same format that ptrace(2) would - * export that information. - * - * Please try to keep the members of this structure nicely aligned, - * and if you add elements, add them to the end and bump the version. - */ - -#define ELF_NOTE_NETBSD_CORE_NAME "NetBSD-CORE" - -#define ELF_NOTE_NETBSD_CORE_PROCINFO 1 - -#define NETBSD_ELFCORE_PROCINFO_VERSION 1 - -struct netbsd_elfcore_procinfo { - /* Version 1 fields start here. */ - uint32_t cpi_version; /* our version */ - uint32_t cpi_cpisize; /* sizeof(this struct) */ - uint32_t cpi_signo; /* killing signal */ - uint32_t cpi_sigcode; /* signal code */ - uint32_t cpi_sigpend[4]; /* pending signals */ - uint32_t cpi_sigmask[4]; /* blocked signals */ - uint32_t cpi_sigignore[4]; /* ignored signals */ - uint32_t cpi_sigcatch[4]; /* caught signals */ - int32_t cpi_pid; /* process ID */ - int32_t cpi_ppid; /* parent process ID */ - int32_t cpi_pgrp; /* process group ID */ - int32_t cpi_sid; /* session ID */ - uint32_t cpi_ruid; /* real user ID */ - uint32_t cpi_euid; /* effective user ID */ - uint32_t cpi_svuid; /* saved user ID */ - uint32_t cpi_rgid; /* real group ID */ - uint32_t cpi_egid; /* effective group ID */ - uint32_t cpi_svgid; /* saved group ID */ - uint32_t cpi_nlwps; /* number of LWPs */ - int8_t cpi_name[32]; /* copy of p->p_comm */ - /* Add version 2 fields below here. */ - int32_t cpi_siglwp; /* LWP target of killing signal */ -}; - -/* - * NetBSD-specific note type: MACHINE_ARCH. - * There should be 1 NOTE per executable. - * name: NetBSD\0 - * namesz: 7 - * desc: string - * descsz: variable - */ -#define ELF_NOTE_TYPE_MARCH_TAG 5 -/* NetBSD-specific note name and description sizes */ -#define ELF_NOTE_MARCH_NAMESZ ELF_NOTE_NETBSD_NAMESZ -/* NetBSD-specific note name */ -#define ELF_NOTE_MARCH_NAME ELF_NOTE_NETBSD_NAME - -#if !defined(ELFSIZE) && defined(ARCH_ELFSIZE) -#define ELFSIZE ARCH_ELFSIZE -#endif - -#if defined(ELFSIZE) -#define CONCAT(x,y) __CONCAT(x,y) -#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) -#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y)))) -#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE)) -#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) -#endif - -#if defined(ELFSIZE) && (ELFSIZE == 32) -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Phdr Elf32_Phdr -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Rel Elf32_Rel -#define Elf_Rela Elf32_Rela -#define Elf_Dyn Elf32_Dyn -#define Elf_Word Elf32_Word -#define Elf_Sword Elf32_Sword -#define Elf_Half Elf32_Half -#define Elf_Addr Elf32_Addr -#define Elf_Off Elf32_Off -#define Elf_SOff Elf32_SOff -#define Elf_Nhdr Elf32_Nhdr -#define Elf_Verdef Elf32_Verdef -#define Elf_Verdaux Elf32_Verdaux -#define Elf_Verneed Elf32_Verneed -#define Elf_Vernaux Elf32_Vernaux -#define Elf_Versym Elf32_Versym - -#define ELF_R_SYM ELF32_R_SYM -#define ELF_R_TYPE ELF32_R_TYPE -#define ELFCLASS ELFCLASS32 - -#define AuxInfo Aux32Info -#elif defined(ELFSIZE) && (ELFSIZE == 64) -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Phdr Elf64_Phdr -#define Elf_Shdr Elf64_Shdr -#define Elf_Sym Elf64_Sym -#define Elf_Rel Elf64_Rel -#define Elf_Rela Elf64_Rela -#define Elf_Dyn Elf64_Dyn -#define Elf_Word Elf64_Word -#define Elf_Sword Elf64_Sword -#define Elf_Half Elf64_Half -#define Elf_Addr Elf64_Addr -#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 -#define ELFCLASS ELFCLASS64 - -#define AuxInfo Aux64Info -#endif - -#ifndef Elf_Symindx -#define Elf_Symindx uint32_t -#endif - -#define ELF32_ST_BIND(info) ELF_ST_BIND(info) -#define ELF32_ST_TYPE(info) ELF_ST_TYPE(info) -#define ELF32_ST_INFO(bind,type) ELF_ST_INFO(bind,type) -#define ELF32_ST_VISIBILITY(other) ELF_ST_VISIBILITY(other) - -#define ELF64_ST_BIND(info) ELF_ST_BIND(info) -#define ELF64_ST_TYPE(info) ELF_ST_TYPE(info) -#define ELF64_ST_INFO(bind,type) ELF_ST_INFO(bind,type) -#define ELF64_ST_VISIBILITY(other) ELF_ST_VISIBILITY(other) - -typedef struct { - Elf32_Half si_boundto; /* direct bindings - symbol bound to */ - Elf32_Half si_flags; /* per symbol flags */ -} Elf32_Syminfo; - -typedef struct { - Elf64_Word si_boundto; /* direct bindings - symbol bound to */ - Elf64_Word si_flags; /* per symbol flags */ -} Elf64_Syminfo; - -#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association - to object containing definition */ -#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ -#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ -#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be - lazily-loaded */ -#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to - object containing definition */ -#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference - directly bind to this symbol */ -#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ -#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ - -#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ -#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ -#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ -#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ -#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ - -#define SYMINFO_NONE 0 /* Syminfo version */ -#define SYMINFO_CURRENT 1 -#define SYMINFO_NUM 2 - -/* - * These constants are used for Elf32_Verdef struct's version number. - */ -#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_WEAK 0x2 - -/* - * These are used in an Elf32_Versym field. - */ -#define VER_NDX_LOCAL 0 -#define VER_NDX_GLOBAL 1 -#define VER_NDX_GIVEN 2 - -/* - * These constants are used for Elf32_Verneed struct's version number. - */ -#define VER_NEED_NONE 0 -#define VER_NEED_CURRENT 1 - -/* - * 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 - -#define ELF_VER_CHR '@' - -/* - * These are current size independent. - */ - -typedef struct { - Elf32_Half vd_version; /* version number of structure */ - Elf32_Half vd_flags; /* flags (VER_FLG_*) */ - Elf32_Half vd_ndx; /* version index */ - Elf32_Half vd_cnt; /* number of verdaux entries */ - Elf32_Word vd_hash; /* hash of name */ - Elf32_Word vd_aux; /* offset to verdaux entries */ - Elf32_Word vd_next; /* offset to next verdef */ -} Elf32_Verdef; -typedef Elf32_Verdef Elf64_Verdef; - -typedef struct { - Elf32_Word vda_name; /* string table offset of name */ - Elf32_Word vda_next; /* offset to verdaux */ -} Elf32_Verdaux; -typedef Elf32_Verdaux Elf64_Verdaux; - -typedef struct { - Elf32_Half vn_version; /* version number of structure */ - Elf32_Half vn_cnt; /* number of vernaux entries */ - Elf32_Word vn_file; /* string table offset of library name*/ - Elf32_Word vn_aux; /* offset to vernaux entries */ - Elf32_Word vn_next; /* offset to next verneed */ -} Elf32_Verneed; -typedef Elf32_Verneed Elf64_Verneed; - -typedef struct { - Elf32_Word vna_hash; /* Hash of dependency name */ - Elf32_Half vna_flags; /* flags (VER_FLG_*) */ - Elf32_Half vna_other; /* unused */ - Elf32_Word vna_name; /* string table offset to version name*/ - Elf32_Word vna_next; /* offset to next vernaux */ -} Elf32_Vernaux; -typedef Elf32_Vernaux Elf64_Vernaux; - -typedef struct { - Elf32_Half vs_vers; -} Elf32_Versym; -typedef Elf32_Versym Elf64_Versym; - -#ifdef _KERNEL - -#define ELF_AUX_ENTRIES 15 /* 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 -#elif defined(ELFSIZE) && (ELFSIZE == 32) -#define ELF_NO_ADDR ELF32_NO_ADDR -#define ELF_LINK_ADDR ELF32_LINK_ADDR -#endif - -#ifndef ELF32_EHDR_FLAGS_OK -#define ELF32_EHDR_FLAGS_OK(eh) 1 -#endif - -#ifndef ELF64_EHDR_FLAGS_OK -#define ELF64_EHDR_FLAGS_OK(eh) 1 -#endif - -#if defined(ELFSIZE) && (ELFSIZE == 64) -#define ELF_EHDR_FLAGS_OK(eh) ELF64_EHDR_FLAGS_OK(eh) -#else -#define ELF_EHDR_FLAGS_OK(eh) ELF32_EHDR_FLAGS_OK(eh) -#endif - -#if defined(ELFSIZE) -struct elf_args { - Elf_Addr arg_entry; /* program entry point */ - Elf_Addr arg_interp; /* Interpreter load address */ - Elf_Addr arg_phaddr; /* program header address */ - Elf_Addr arg_phentsize; /* Size of program header */ - Elf_Addr arg_phnum; /* Number of program headers */ -}; -#endif - -#ifdef _KERNEL_OPT -#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 *, - struct ps_strings *, char **, void *); - -int coredump_elf32(struct lwp *, void *); -int coredump_writenote_elf32(struct proc *, void *, Elf32_Nhdr *, - const char *, void *); - -int elf32_check_header(Elf32_Ehdr *, int); -#endif - -#ifdef EXEC_ELF64 -int exec_elf64_makecmds(struct lwp *, struct exec_package *); -int elf64_copyargs(struct lwp *, struct exec_package *, - struct ps_strings *, char **, void *); - -int coredump_elf64(struct lwp *, void *); -int coredump_writenote_elf64(struct proc *, void *, Elf64_Nhdr *, - const char *, void *); - -int elf64_check_header(Elf64_Ehdr *, int); -#endif - -#endif /* _KERNEL */ - -#endif /* !_SYS_EXEC_ELF_H_ */ diff --git a/libc/private/KernelArgumentBlock.h b/libc/private/KernelArgumentBlock.h index 105965e04..4af52ab67 100644 --- a/libc/private/KernelArgumentBlock.h +++ b/libc/private/KernelArgumentBlock.h @@ -18,6 +18,7 @@ #define KERNEL_ARGUMENT_BLOCK_H #include +#include #include #include @@ -43,14 +44,14 @@ class KernelArgumentBlock { } ++p; // Skip second NULL; - auxv = reinterpret_cast(p); + auxv = reinterpret_cast(p); } // Similar to ::getauxval but doesn't require the libc global variables to be set up, // so it's safe to call this really early on. This function also lets you distinguish // between the inability to find the given type and its value just happening to be 0. unsigned long getauxval(unsigned long type, bool* found_match = NULL) { - for (Elf_auxv_t* v = auxv; v->a_type != AT_NULL; ++v) { + for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) { if (v->a_type == type) { if (found_match != NULL) { *found_match = true; @@ -67,7 +68,7 @@ class KernelArgumentBlock { int argc; char** argv; char** envp; - Elf_auxv_t* auxv; + ElfW(auxv_t)* auxv; abort_msg_t** abort_message_ptr; diff --git a/libc/private/bionic_auxv.h b/libc/private/bionic_auxv.h index 69c53413c..53fcc491b 100644 --- a/libc/private/bionic_auxv.h +++ b/libc/private/bionic_auxv.h @@ -29,11 +29,12 @@ #define _PRIVATE_BIONIC_AUXV_H_ #include +#include #include __BEGIN_DECLS -extern Elf_auxv_t* __libc_auxv; +extern ElfW(auxv_t)* __libc_auxv; __END_DECLS diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index 1e9d9bc83..14ce113dc 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -87,7 +87,7 @@ void* dlsym(void* handle, const char* symbol) { } soinfo* found = NULL; - Elf_Sym* sym = NULL; + ElfW(Sym)* sym = NULL; if (handle == RTLD_DEFAULT) { sym = dlsym_linear_lookup(symbol, &found, NULL); } else if (handle == RTLD_NEXT) { @@ -134,7 +134,7 @@ int dladdr(const void* addr, Dl_info* info) { info->dli_fbase = (void*) si->base; // Determine if any symbol in the library contains the specified address. - Elf_Sym *sym = dladdr_find_symbol(si, addr); + ElfW(Sym)* sym = dladdr_find_symbol(si, addr); if (sym != NULL) { info->dli_sname = si->strtab + sym->st_name; info->dli_saddr = (void*)(si->load_bias + sym->st_value); @@ -167,12 +167,6 @@ int dlclose(void* handle) { /* st_size */ 0, \ } -#if defined(__LP64__) -# define ELF_SYM_INITIALIZER ELF64_SYM_INITIALIZER -#else -# define ELF_SYM_INITIALIZER ELF32_SYM_INITIALIZER -#endif - #if defined(__arm__) // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1 // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1 @@ -187,22 +181,22 @@ int dlclose(void* handle) { # error Unsupported architecture. Only arm, arm64, mips, x86, and x86_64 are presently supported. #endif -static Elf_Sym gLibDlSymtab[] = { +static ElfW(Sym) gLibDlSymtab[] = { // Total length of libdl_info.strtab, including trailing 0. // This is actually the STH_UNDEF entry. Technically, it's // supposed to have st_name == 0, but instead, it points to an index // in the strtab with a \0 to make iterating through the symtab easier. - ELF_SYM_INITIALIZER(sizeof(ANDROID_LIBDL_STRTAB) - 1, NULL, 0), - ELF_SYM_INITIALIZER( 0, &dlopen, 1), - ELF_SYM_INITIALIZER( 7, &dlclose, 1), - ELF_SYM_INITIALIZER( 15, &dlsym, 1), - ELF_SYM_INITIALIZER( 21, &dlerror, 1), - ELF_SYM_INITIALIZER( 29, &dladdr, 1), - ELF_SYM_INITIALIZER( 36, &android_update_LD_LIBRARY_PATH, 1), - ELF_SYM_INITIALIZER( 67, &android_get_LD_LIBRARY_PATH, 1), - ELF_SYM_INITIALIZER( 95, &dl_iterate_phdr, 1), + ELFW(SYM_INITIALIZER)(sizeof(ANDROID_LIBDL_STRTAB) - 1, NULL, 0), + ELFW(SYM_INITIALIZER)( 0, &dlopen, 1), + ELFW(SYM_INITIALIZER)( 7, &dlclose, 1), + ELFW(SYM_INITIALIZER)( 15, &dlsym, 1), + ELFW(SYM_INITIALIZER)( 21, &dlerror, 1), + ELFW(SYM_INITIALIZER)( 29, &dladdr, 1), + ELFW(SYM_INITIALIZER)( 36, &android_update_LD_LIBRARY_PATH, 1), + ELFW(SYM_INITIALIZER)( 67, &android_get_LD_LIBRARY_PATH, 1), + ELFW(SYM_INITIALIZER)( 95, &dl_iterate_phdr, 1), #if defined(__arm__) - ELF_SYM_INITIALIZER(111, &dl_unwind_find_exidx, 1), + ELFW(SYM_INITIALIZER)(111, &dl_unwind_find_exidx, 1), #endif }; diff --git a/linker/linker.cpp b/linker/linker.cpp index 2058050a6..a133d1b8e 100755 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -29,9 +29,8 @@ #include #include #include -#include +#include #include -#include #include #include #include @@ -67,7 +66,7 @@ */ static bool soinfo_link_image(soinfo* si); -static Elf_Addr get_elf_exec_load_bias(const Elf_Ehdr* elf); +static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf); // We can't use malloc(3) in the dynamic linker. We use a linked list of anonymous // maps, each a single page in size. The pages are broken up into as many struct soinfo @@ -451,33 +450,33 @@ dl_iterate_phdr(int (*cb)(dl_phdr_info *info, size_t size, void *data), return rv; } -static Elf_Sym* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) { - Elf_Sym* symtab = si->symtab; - const char* strtab = si->strtab; +static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) { + ElfW(Sym)* symtab = si->symtab; + const char* strtab = si->strtab; - TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p %x %zd", - name, si->name, reinterpret_cast(si->base), hash, hash % si->nbucket); + TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p %x %zd", + name, si->name, reinterpret_cast(si->base), hash, hash % si->nbucket); - for (unsigned n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]) { - Elf_Sym* s = symtab + n; - if (strcmp(strtab + s->st_name, name)) continue; + for (unsigned n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]) { + ElfW(Sym)* s = symtab + n; + if (strcmp(strtab + s->st_name, name)) continue; - /* only concern ourselves with global and weak symbol definitions */ - switch (ELF_ST_BIND(s->st_info)) { - case STB_GLOBAL: - case STB_WEAK: - if (s->st_shndx == SHN_UNDEF) { - continue; - } + /* only concern ourselves with global and weak symbol definitions */ + switch (ELF_ST_BIND(s->st_info)) { + case STB_GLOBAL: + case STB_WEAK: + if (s->st_shndx == SHN_UNDEF) { + continue; + } - TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd", - name, si->name, reinterpret_cast(s->st_value), - static_cast(s->st_size)); - return s; - } + TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd", + name, si->name, reinterpret_cast(s->st_value), + static_cast(s->st_size)); + return s; } + } - return NULL; + return NULL; } static unsigned elfhash(const char* _name) { @@ -493,9 +492,9 @@ static unsigned elfhash(const char* _name) { return h; } -static Elf_Sym* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi, soinfo* needed[]) { +static ElfW(Sym)* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi, soinfo* needed[]) { unsigned elf_hash = elfhash(name); - Elf_Sym* s = NULL; + ElfW(Sym)* s = NULL; if (si != NULL && somain != NULL) { @@ -603,7 +602,7 @@ done: Binary Interface) where in Chapter 5 it discuss resolving "Shared Object Dependencies" in breadth first search order. */ -Elf_Sym* dlsym_handle_lookup(soinfo* si, const char* name) { +ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name) { return soinfo_elf_lookup(si, elfhash(name), name); } @@ -612,14 +611,14 @@ Elf_Sym* dlsym_handle_lookup(soinfo* si, const char* name) { beginning of the global solist. Otherwise the search starts at the specified soinfo (for RTLD_NEXT). */ -Elf_Sym* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start) { +ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start) { unsigned elf_hash = elfhash(name); if (start == NULL) { start = solist; } - Elf_Sym* s = NULL; + ElfW(Sym)* s = NULL; for (soinfo* si = start; (s == NULL) && (si != NULL); si = si->next) { s = soinfo_elf_lookup(si, elf_hash, name); if (s != NULL) { @@ -637,7 +636,7 @@ Elf_Sym* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start) { } soinfo* find_containing_library(const void* p) { - Elf_Addr address = reinterpret_cast(p); + ElfW(Addr) address = reinterpret_cast(p); for (soinfo* si = solist; si != NULL; si = si->next) { if (address >= si->base && address - si->base < si->size) { return si; @@ -646,13 +645,13 @@ soinfo* find_containing_library(const void* p) { return NULL; } -Elf_Sym* dladdr_find_symbol(soinfo* si, const void* addr) { - Elf_Addr soaddr = reinterpret_cast(addr) - si->base; +ElfW(Sym)* dladdr_find_symbol(soinfo* si, const void* addr) { + ElfW(Addr) soaddr = reinterpret_cast(addr) - si->base; // Search the library's symbol table for any defined symbol which // contains this address. for (size_t i = 0; i < si->nchain; ++i) { - Elf_Sym* sym = &si->symtab[i]; + ElfW(Sym)* sym = &si->symtab[i]; if (sym->st_shndx != SHN_UNDEF && soaddr >= sym->st_value && soaddr < sym->st_value + sym->st_size) { @@ -666,13 +665,13 @@ Elf_Sym* dladdr_find_symbol(soinfo* si, const void* addr) { #if 0 static void dump(soinfo* si) { - Elf_Sym* s = si->symtab; - for (unsigned n = 0; n < si->nchain; n++) { - TRACE("%04d> %08x: %02x %04x %08x %08x %s", n, s, - s->st_info, s->st_shndx, s->st_value, s->st_size, - si->strtab + s->st_name); - s++; - } + ElfW(Sym)* s = si->symtab; + for (unsigned n = 0; n < si->nchain; n++) { + TRACE("%04d> %08x: %02x %04x %08x %08x %s", n, s, + s->st_info, s->st_shndx, s->st_value, s->st_size, + si->strtab + s->st_name); + s++; + } } #endif @@ -808,7 +807,7 @@ static int soinfo_unload(soinfo* si) { TRACE("unloading '%s'", si->name); si->CallDestructors(); - for (Elf_Dyn* d = si->dynamic; d->d_tag != DT_NULL; ++d) { + for (ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) { if (d->d_tag == DT_NEEDED) { const char* library_name = si->strtab + d->d_un.d_val; TRACE("%s needs to unload %s", si->name, library_name); @@ -859,18 +858,18 @@ int do_dlclose(soinfo* si) { } #if defined(USE_RELA) -static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* needed[]) { - Elf_Sym* symtab = si->symtab; +static int soinfo_relocate_a(soinfo* si, ElfW(Rela)* rela, unsigned count, soinfo* needed[]) { + ElfW(Sym)* symtab = si->symtab; const char* strtab = si->strtab; - Elf_Sym* s; - Elf_Rela* start = rela; + ElfW(Sym)* s; + ElfW(Rela)* start = rela; soinfo* lsi; for (size_t idx = 0; idx < count; ++idx, ++rela) { - unsigned type = ELF_R_TYPE(rela->r_info); - unsigned sym = ELF_R_SYM(rela->r_info); - Elf_Addr reloc = static_cast(rela->r_offset + si->load_bias); - Elf_Addr sym_addr = 0; + unsigned type = ELFW(R_TYPE)(rela->r_info); + unsigned sym = ELFW(R_SYM)(rela->r_info); + ElfW(Addr) reloc = static_cast(rela->r_offset + si->load_bias); + ElfW(Addr) sym_addr = 0; char* sym_name = NULL; DEBUG("Processing '%s' relocation at index %zd", si->name, idx); @@ -931,7 +930,7 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* } } else { // We got a definition. - sym_addr = static_cast(s->st_value + lsi->load_bias); + sym_addr = static_cast(s->st_value + lsi->load_bias); } count_relocation(kRelocSymbol); } else { @@ -943,117 +942,92 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* case R_AARCH64_JUMP_SLOT: count_relocation(kRelocAbsolute); MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO JMP_SLOT %16lx <- %16lx %s\n", - reloc, - (sym_addr + rela->r_addend), - sym_name); - *reinterpret_cast(reloc) = (sym_addr + rela->r_addend); + TRACE_TYPE(RELO, "RELO JMP_SLOT %16llx <- %16llx %s\n", + reloc, (sym_addr + rela->r_addend), sym_name); + *reinterpret_cast(reloc) = (sym_addr + rela->r_addend); break; case R_AARCH64_GLOB_DAT: count_relocation(kRelocAbsolute); MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO GLOB_DAT %16lx <- %16lx %s\n", - reloc, - (sym_addr + rela->r_addend), - sym_name); - *reinterpret_cast(reloc) = (sym_addr + rela->r_addend); + TRACE_TYPE(RELO, "RELO GLOB_DAT %16llx <- %16llx %s\n", + reloc, (sym_addr + rela->r_addend), sym_name); + *reinterpret_cast(reloc) = (sym_addr + rela->r_addend); break; case R_AARCH64_ABS64: count_relocation(kRelocAbsolute); MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO ABS64 %16lx <- %16lx %s\n", - reloc, - (sym_addr + rela->r_addend), - sym_name); - *reinterpret_cast(reloc) += (sym_addr + rela->r_addend); + TRACE_TYPE(RELO, "RELO ABS64 %16llx <- %16llx %s\n", + reloc, (sym_addr + rela->r_addend), sym_name); + *reinterpret_cast(reloc) += (sym_addr + rela->r_addend); break; case R_AARCH64_ABS32: count_relocation(kRelocAbsolute); MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO ABS32 %16lx <- %16lx %s\n", - reloc, - (sym_addr + rela->r_addend), - sym_name); - if ((static_cast(INT32_MIN) <= - (*reinterpret_cast(reloc) + (sym_addr + rela->r_addend))) && - ((*reinterpret_cast(reloc) + (sym_addr + rela->r_addend)) <= - static_cast(UINT32_MAX))) { - *reinterpret_cast(reloc) += (sym_addr + rela->r_addend); + TRACE_TYPE(RELO, "RELO ABS32 %16llx <- %16llx %s\n", + reloc, (sym_addr + rela->r_addend), sym_name); + if ((static_cast(INT32_MIN) <= (*reinterpret_cast(reloc) + (sym_addr + rela->r_addend))) && + ((*reinterpret_cast(reloc) + (sym_addr + rela->r_addend)) <= static_cast(UINT32_MAX))) { + *reinterpret_cast(reloc) += (sym_addr + rela->r_addend); } else { - DL_ERR("0x%016lx out of range 0x%016lx to 0x%016lx", - (*reinterpret_cast(reloc) + (sym_addr + rela->r_addend)), - static_cast(INT32_MIN), - static_cast(UINT32_MAX)); + DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", + (*reinterpret_cast(reloc) + (sym_addr + rela->r_addend)), + static_cast(INT32_MIN), + static_cast(UINT32_MAX)); return -1; } break; case R_AARCH64_ABS16: count_relocation(kRelocAbsolute); MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO ABS16 %16lx <- %16lx %s\n", - reloc, - (sym_addr + rela->r_addend), - sym_name); - if ((static_cast(INT16_MIN) <= - (*reinterpret_cast(reloc) + (sym_addr + rela->r_addend))) && - ((*reinterpret_cast(reloc) + (sym_addr + rela->r_addend)) <= - static_cast(UINT16_MAX))) { - *reinterpret_cast(reloc) += (sym_addr + rela->r_addend); + TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n", + reloc, (sym_addr + rela->r_addend), sym_name); + if ((static_cast(INT16_MIN) <= (*reinterpret_cast(reloc) + (sym_addr + rela->r_addend))) && + ((*reinterpret_cast(reloc) + (sym_addr + rela->r_addend)) <= static_cast(UINT16_MAX))) { + *reinterpret_cast(reloc) += (sym_addr + rela->r_addend); } else { - DL_ERR("0x%016lx out of range 0x%016lx to 0x%016lx", - (*reinterpret_cast(reloc) + (sym_addr + rela->r_addend)), - static_cast(INT16_MIN), - static_cast(UINT16_MAX)); + DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", + (*reinterpret_cast(reloc) + (sym_addr + rela->r_addend)), + static_cast(INT16_MIN), + static_cast(UINT16_MAX)); return -1; } break; case R_AARCH64_PREL64: count_relocation(kRelocRelative); MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO REL64 %16lx <- %16lx - %16lx %s\n", - reloc, - (sym_addr + rela->r_addend), - rela->r_offset, - sym_name); - *reinterpret_cast(reloc) += (sym_addr + rela->r_addend) - rela->r_offset; + TRACE_TYPE(RELO, "RELO REL64 %16llx <- %16llx - %16llx %s\n", + reloc, (sym_addr + rela->r_addend), rela->r_offset, sym_name); + *reinterpret_cast(reloc) += (sym_addr + rela->r_addend) - rela->r_offset; break; case R_AARCH64_PREL32: count_relocation(kRelocRelative); MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO REL32 %16lx <- %16lx - %16lx %s\n", - reloc, - (sym_addr + rela->r_addend), - rela->r_offset, sym_name); - if ((static_cast(INT32_MIN) <= - (*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset))) && - ((*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset)) <= - static_cast(UINT32_MAX))) { - *reinterpret_cast(reloc) += ((sym_addr + rela->r_addend) - rela->r_offset); + TRACE_TYPE(RELO, "RELO REL32 %16llx <- %16llx - %16llx %s\n", + reloc, (sym_addr + rela->r_addend), rela->r_offset, sym_name); + if ((static_cast(INT32_MIN) <= (*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset))) && + ((*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset)) <= static_cast(UINT32_MAX))) { + *reinterpret_cast(reloc) += ((sym_addr + rela->r_addend) - rela->r_offset); } else { - DL_ERR("0x%016lx out of range 0x%016lx to 0x%016lx", - (*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset)), - static_cast(INT32_MIN), - static_cast(UINT32_MAX)); + DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", + (*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset)), + static_cast(INT32_MIN), + static_cast(UINT32_MAX)); return -1; } break; case R_AARCH64_PREL16: count_relocation(kRelocRelative); MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO REL16 %16lx <- %16lx - %16lx %s\n", - reloc, - (sym_addr + rela->r_addend), - rela->r_offset, sym_name); - if ((static_cast(INT16_MIN) <= - (*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset))) && - ((*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset)) <= - static_cast(UINT16_MAX))) { - *reinterpret_cast(reloc) += ((sym_addr + rela->r_addend) - rela->r_offset); + TRACE_TYPE(RELO, "RELO REL16 %16llx <- %16llx - %16llx %s\n", + reloc, (sym_addr + rela->r_addend), rela->r_offset, sym_name); + if ((static_cast(INT16_MIN) <= (*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset))) && + ((*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset)) <= static_cast(UINT16_MAX))) { + *reinterpret_cast(reloc) += ((sym_addr + rela->r_addend) - rela->r_offset); } else { - DL_ERR("0x%016lx out of range 0x%016lx to 0x%016lx", - (*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset)), - static_cast(INT16_MIN), - static_cast(UINT16_MAX)); + DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", + (*reinterpret_cast(reloc) + ((sym_addr + rela->r_addend) - rela->r_offset)), + static_cast(INT16_MIN), + static_cast(UINT16_MAX)); return -1; } break; @@ -1065,10 +1039,9 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* DL_ERR("odd RELATIVE form..."); return -1; } - TRACE_TYPE(RELO, "RELO RELATIVE %16lx <- %16lx\n", - reloc, - (si->base + rela->r_addend)); - *reinterpret_cast(reloc) = (si->base + rela->r_addend); + TRACE_TYPE(RELO, "RELO RELATIVE %16llx <- %16llx\n", + reloc, (si->base + rela->r_addend)); + *reinterpret_cast(reloc) = (si->base + rela->r_addend); break; case R_AARCH64_COPY: @@ -1089,13 +1062,13 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* } count_relocation(kRelocCopy); MARK(rela->r_offset); - TRACE_TYPE(RELO, "RELO COPY %16lx <- %ld @ %16lx %s\n", - reloc, - s->st_size, - (sym_addr + rela->r_addend), - sym_name); + TRACE_TYPE(RELO, "RELO COPY %16llx <- %lld @ %16llx %s\n", + reloc, + s->st_size, + (sym_addr + rela->r_addend), + sym_name); if (reloc == (sym_addr + rela->r_addend)) { - Elf_Sym *src = soinfo_do_lookup(NULL, sym_name, &lsi, needed); + ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed); if (src == NULL) { DL_ERR("%s R_AARCH64_COPY relocation source cannot be resolved", si->name); @@ -1103,12 +1076,12 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* } if (lsi->has_DT_SYMBOLIC) { DL_ERR("%s invalid R_AARCH64_COPY relocation against DT_SYMBOLIC shared " - "library %s (built with -Bsymbolic?)", si->name, lsi->name); + "library %s (built with -Bsymbolic?)", si->name, lsi->name); return -1; } if (s->st_size < src->st_size) { - DL_ERR("%s R_AARCH64_COPY relocation size mismatch (%ld < %ld)", - si->name, s->st_size, src->st_size); + DL_ERR("%s R_AARCH64_COPY relocation size mismatch (%lld < %lld)", + si->name, s->st_size, src->st_size); return -1; } memcpy((void*)reloc, (void*)(src->st_value + lsi->load_bias), src->st_size); @@ -1118,16 +1091,12 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* } break; case R_AARCH64_TLS_TPREL64: - TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16lx <- %16lx - %16lx\n", - reloc, - (sym_addr + rela->r_addend), - rela->r_offset); + TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16llx <- %16llx - %16llx\n", + reloc, (sym_addr + rela->r_addend), rela->r_offset); break; case R_AARCH64_TLS_DTPREL32: - TRACE_TYPE(RELO, "RELO TLS_DTPREL32 *** %16lx <- %16lx - %16lx\n", - reloc, - (sym_addr + rela->r_addend), - rela->r_offset); + TRACE_TYPE(RELO, "RELO TLS_DTPREL32 *** %16llx <- %16llx - %16llx\n", + reloc, (sym_addr + rela->r_addend), rela->r_offset); break; #elif defined(__x86_64__) case R_X86_64_JUMP_SLOT: @@ -1135,14 +1104,14 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* MARK(rela->r_offset); TRACE_TYPE(RELO, "RELO JMP_SLOT %08zx <- %08zx %s", static_cast(reloc), static_cast(sym_addr + rela->r_addend), sym_name); - *reinterpret_cast(reloc) = sym_addr + rela->r_addend; + *reinterpret_cast(reloc) = sym_addr + rela->r_addend; break; case R_X86_64_GLOB_DAT: count_relocation(kRelocAbsolute); MARK(rela->r_offset); TRACE_TYPE(RELO, "RELO GLOB_DAT %08zx <- %08zx %s", static_cast(reloc), static_cast(sym_addr + rela->r_addend), sym_name); - *reinterpret_cast(reloc) = sym_addr + rela->r_addend; + *reinterpret_cast(reloc) = sym_addr + rela->r_addend; break; case R_X86_64_RELATIVE: count_relocation(kRelocRelative); @@ -1153,21 +1122,21 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* } TRACE_TYPE(RELO, "RELO RELATIVE %08zx <- +%08zx", static_cast(reloc), static_cast(si->base)); - *reinterpret_cast(reloc) = si->base + rela->r_addend; + *reinterpret_cast(reloc) = si->base + rela->r_addend; break; case R_X86_64_32: count_relocation(kRelocRelative); MARK(rela->r_offset); TRACE_TYPE(RELO, "RELO R_X86_64_32 %08zx <- +%08zx %s", static_cast(reloc), static_cast(sym_addr), sym_name); - *reinterpret_cast(reloc) = sym_addr + rela->r_addend; + *reinterpret_cast(reloc) = sym_addr + rela->r_addend; break; case R_X86_64_64: count_relocation(kRelocRelative); MARK(rela->r_offset); TRACE_TYPE(RELO, "RELO R_X86_64_64 %08zx <- +%08zx %s", static_cast(reloc), static_cast(sym_addr), sym_name); - *reinterpret_cast(reloc) = sym_addr + rela->r_addend; + *reinterpret_cast(reloc) = sym_addr + rela->r_addend; break; case R_X86_64_PC32: count_relocation(kRelocRelative); @@ -1175,7 +1144,7 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* TRACE_TYPE(RELO, "RELO R_X86_64_PC32 %08zx <- +%08zx (%08zx - %08zx) %s", static_cast(reloc), static_cast(sym_addr - reloc), static_cast(sym_addr), static_cast(reloc), sym_name); - *reinterpret_cast(reloc) = sym_addr + rela->r_addend - reloc; + *reinterpret_cast(reloc) = sym_addr + rela->r_addend - reloc; break; #endif @@ -1187,21 +1156,19 @@ static int soinfo_relocate_a(soinfo* si, Elf_Rela* rela, unsigned count, soinfo* return 0; } #else -static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, - soinfo* needed[]) -{ - Elf_Sym* symtab = si->symtab; +static int soinfo_relocate(soinfo* si, ElfW(Rel)* rel, unsigned count, soinfo* needed[]) { + ElfW(Sym)* symtab = si->symtab; const char* strtab = si->strtab; - Elf_Sym* s; - Elf_Rel* start = rel; + ElfW(Sym)* s; + ElfW(Rel)* start = rel; soinfo* lsi; for (size_t idx = 0; idx < count; ++idx, ++rel) { - unsigned type = ELF_R_TYPE(rel->r_info); - // TODO: don't use unsigned for 'sym'. Use uint32_t or Elf_Addr instead. - unsigned sym = ELF_R_SYM(rel->r_info); - Elf_Addr reloc = static_cast(rel->r_offset + si->load_bias); - Elf_Addr sym_addr = 0; + unsigned type = ELFW(R_TYPE)(rel->r_info); + // TODO: don't use unsigned for 'sym'. Use uint32_t or ElfW(Addr) instead. + unsigned sym = ELFW(R_SYM)(rel->r_info); + ElfW(Addr) reloc = static_cast(rel->r_offset + si->load_bias); + ElfW(Addr) sym_addr = 0; char* sym_name = NULL; DEBUG("Processing '%s' relocation at index %zd", si->name, idx); @@ -1266,7 +1233,7 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, } } else { // We got a definition. - sym_addr = static_cast(s->st_value + lsi->load_bias); + sym_addr = static_cast(s->st_value + lsi->load_bias); } count_relocation(kRelocSymbol); } else { @@ -1279,26 +1246,26 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast(reloc) = sym_addr; + *reinterpret_cast(reloc) = sym_addr; break; case R_ARM_GLOB_DAT: count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO GLOB_DAT %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast(reloc) = sym_addr; + *reinterpret_cast(reloc) = sym_addr; break; case R_ARM_ABS32: count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO ABS %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast(reloc) += sym_addr; + *reinterpret_cast(reloc) += sym_addr; break; case R_ARM_REL32: count_relocation(kRelocRelative); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x - %08x %s", reloc, sym_addr, rel->r_offset, sym_name); - *reinterpret_cast(reloc) += sym_addr - rel->r_offset; + *reinterpret_cast(reloc) += sym_addr - rel->r_offset; break; case R_ARM_COPY: if ((si->flags & FLAG_EXE) == 0) { @@ -1320,7 +1287,7 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO %08x <- %d @ %08x %s", reloc, s->st_size, sym_addr, sym_name); if (reloc == sym_addr) { - Elf_Sym *src = soinfo_do_lookup(NULL, sym_name, &lsi, needed); + ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed); if (src == NULL) { DL_ERR("%s R_ARM_COPY relocation source cannot be resolved", si->name); @@ -1347,26 +1314,26 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast(reloc) = sym_addr; + *reinterpret_cast(reloc) = sym_addr; break; case R_386_GLOB_DAT: count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO GLOB_DAT %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast(reloc) = sym_addr; + *reinterpret_cast(reloc) = sym_addr; break; case R_386_32: count_relocation(kRelocRelative); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO R_386_32 %08x <- +%08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast(reloc) += sym_addr; + *reinterpret_cast(reloc) += sym_addr; break; case R_386_PC32: count_relocation(kRelocRelative); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO R_386_PC32 %08x <- +%08x (%08x - %08x) %s", reloc, (sym_addr - reloc), sym_addr, reloc, sym_name); - *reinterpret_cast(reloc) += (sym_addr - reloc); + *reinterpret_cast(reloc) += (sym_addr - reloc); break; #elif defined(__mips__) case R_MIPS_REL32: @@ -1375,9 +1342,9 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x %s", reloc, sym_addr, (sym_name) ? sym_name : "*SECTIONHDR*"); if (s) { - *reinterpret_cast(reloc) += sym_addr; + *reinterpret_cast(reloc) += sym_addr; } else { - *reinterpret_cast(reloc) += si->base; + *reinterpret_cast(reloc) += si->base; } break; #endif @@ -1395,7 +1362,7 @@ static int soinfo_relocate(soinfo* si, Elf_Rel* rel, unsigned count, } TRACE_TYPE(RELO, "RELO RELATIVE %p <- +%p", reinterpret_cast(reloc), reinterpret_cast(si->base)); - *reinterpret_cast(reloc) += si->base; + *reinterpret_cast(reloc) += si->base; break; default: @@ -1416,7 +1383,7 @@ static bool mips_relocate_got(soinfo* si, soinfo* needed[]) { unsigned local_gotno = si->mips_local_gotno; unsigned gotsym = si->mips_gotsym; unsigned symtabno = si->mips_symtabno; - Elf_Sym* symtab = si->symtab; + ElfW(Sym)* symtab = si->symtab; /* * got[0] is address of lazy resolver function @@ -1441,11 +1408,11 @@ static bool mips_relocate_got(soinfo* si, soinfo* needed[]) { } /* Now for the global GOT entries */ - Elf_Sym* sym = symtab + gotsym; + ElfW(Sym)* sym = symtab + gotsym; got = si->plt_got + local_gotno; for (size_t g = gotsym; g < symtabno; g++, sym++, got++) { const char* sym_name; - Elf_Sym* s; + ElfW(Sym)* s; soinfo* lsi; /* This is an undefined reference... try to locate it */ @@ -1536,7 +1503,7 @@ void soinfo::CallConstructors() { } if (dynamic != NULL) { - for (Elf_Dyn* d = dynamic; d->d_tag != DT_NULL; ++d) { + for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) { if (d->d_tag == DT_NEEDED) { const char* library_name = strtab + d->d_un.d_val; TRACE("\"%s\": calling constructors in DT_NEEDED \"%s\"", name, library_name); @@ -1625,8 +1592,8 @@ static int nullify_closed_stdio() { static bool soinfo_link_image(soinfo* si) { /* "base" might wrap around UINT32_MAX. */ - Elf_Addr base = si->load_bias; - const Elf_Phdr *phdr = si->phdr; + ElfW(Addr) base = si->load_bias; + const ElfW(Phdr)* phdr = si->phdr; int phnum = si->phnum; bool relocating_linker = (si->flags & FLAG_LINKER) != 0; @@ -1638,7 +1605,7 @@ static bool soinfo_link_image(soinfo* si) { /* Extract dynamic section */ size_t dynamic_count; - Elf_Word dynamic_flags; + ElfW(Word) dynamic_flags; phdr_table_get_dynamic_section(phdr, phnum, base, &si->dynamic, &dynamic_count, &dynamic_flags); if (si->dynamic == NULL) { @@ -1659,7 +1626,7 @@ static bool soinfo_link_image(soinfo* si) { // Extract useful information from dynamic section. uint32_t needed_count = 0; - for (Elf_Dyn* d = si->dynamic; d->d_tag != DT_NULL; ++d) { + for (ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) { DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p", d, reinterpret_cast(d->d_tag), reinterpret_cast(d->d_un.d_val)); switch (d->d_tag) { @@ -1673,7 +1640,7 @@ static bool soinfo_link_image(soinfo* si) { si->strtab = (const char *) (base + d->d_un.d_ptr); break; case DT_SYMTAB: - si->symtab = (Elf_Sym *) (base + d->d_un.d_ptr); + si->symtab = (ElfW(Sym)*) (base + d->d_un.d_ptr); break; #if !defined(__LP64__) case DT_PLTREL: @@ -1685,16 +1652,16 @@ static bool soinfo_link_image(soinfo* si) { #endif case DT_JMPREL: #if defined(USE_RELA) - si->plt_rela = (Elf_Rela*) (base + d->d_un.d_ptr); + si->plt_rela = (ElfW(Rela)*) (base + d->d_un.d_ptr); #else - si->plt_rel = (Elf_Rel*) (base + d->d_un.d_ptr); + si->plt_rel = (ElfW(Rel)*) (base + d->d_un.d_ptr); #endif break; case DT_PLTRELSZ: #if defined(USE_RELA) - si->plt_rela_count = d->d_un.d_val / sizeof(Elf_Rela); + si->plt_rela_count = d->d_un.d_val / sizeof(ElfW(Rela)); #else - si->plt_rel_count = d->d_un.d_val / sizeof(Elf_Rel); + si->plt_rel_count = d->d_un.d_val / sizeof(ElfW(Rel)); #endif break; #if !defined(__LP64__) @@ -1712,10 +1679,10 @@ static bool soinfo_link_image(soinfo* si) { break; #if defined(USE_RELA) case DT_RELA: - si->rela = (Elf_Rela*) (base + d->d_un.d_ptr); + si->rela = (ElfW(Rela)*) (base + d->d_un.d_ptr); break; case DT_RELASZ: - si->rela_count = d->d_un.d_val / sizeof(Elf_Rela); + si->rela_count = d->d_un.d_val / sizeof(ElfW(Rela)); break; case DT_REL: DL_ERR("unsupported DT_REL in \"%s\"", si->name); @@ -1725,10 +1692,10 @@ static bool soinfo_link_image(soinfo* si) { return false; #else case DT_REL: - si->rel = (Elf_Rel*) (base + d->d_un.d_ptr); + si->rel = (ElfW(Rel)*) (base + d->d_un.d_ptr); break; case DT_RELSZ: - si->rel_count = d->d_un.d_val / sizeof(Elf_Rel); + si->rel_count = d->d_un.d_val / sizeof(ElfW(Rel)); break; case DT_RELA: DL_ERR("unsupported DT_RELA in \"%s\"", si->name); @@ -1747,21 +1714,21 @@ static bool soinfo_link_image(soinfo* si) { DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", si->name, si->init_array); break; case DT_INIT_ARRAYSZ: - si->init_array_count = ((unsigned)d->d_un.d_val) / sizeof(Elf_Addr); + si->init_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr)); break; case DT_FINI_ARRAY: si->fini_array = reinterpret_cast(base + d->d_un.d_ptr); DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", si->name, si->fini_array); break; case DT_FINI_ARRAYSZ: - si->fini_array_count = ((unsigned)d->d_un.d_val) / sizeof(Elf_Addr); + si->fini_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr)); break; case DT_PREINIT_ARRAY: si->preinit_array = reinterpret_cast(base + d->d_un.d_ptr); DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", si->name, si->preinit_array); break; case DT_PREINIT_ARRAYSZ: - si->preinit_array_count = ((unsigned)d->d_un.d_val) / sizeof(Elf_Addr); + si->preinit_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr)); break; case DT_TEXTREL: #if defined(__LP64__) @@ -1868,7 +1835,7 @@ static bool soinfo_link_image(soinfo* si) { soinfo** needed = (soinfo**) alloca((1 + needed_count) * sizeof(soinfo*)); soinfo** pneeded = needed; - for (Elf_Dyn* d = si->dynamic; d->d_tag != DT_NULL; ++d) { + for (ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) { if (d->d_tag == DT_NEEDED) { const char* library_name = si->strtab + d->d_un.d_val; DEBUG("%s needs %s", si->name, library_name); @@ -1964,21 +1931,21 @@ static bool soinfo_link_image(soinfo* si) { */ static void add_vdso(KernelArgumentBlock& args UNUSED) { #if defined(AT_SYSINFO_EHDR) - Elf_Ehdr* ehdr_vdso = reinterpret_cast(args.getauxval(AT_SYSINFO_EHDR)); - if (ehdr_vdso == NULL) { - return; - } + ElfW(Ehdr)* ehdr_vdso = reinterpret_cast(args.getauxval(AT_SYSINFO_EHDR)); + if (ehdr_vdso == NULL) { + return; + } - soinfo* si = soinfo_alloc("[vdso]"); + soinfo* si = soinfo_alloc("[vdso]"); - si->phdr = reinterpret_cast(reinterpret_cast(ehdr_vdso) + ehdr_vdso->e_phoff); - si->phnum = ehdr_vdso->e_phnum; - si->base = reinterpret_cast(ehdr_vdso); - si->size = phdr_table_get_load_size(si->phdr, si->phnum); - si->flags = 0; - si->load_bias = get_elf_exec_load_bias(ehdr_vdso); + si->phdr = reinterpret_cast(reinterpret_cast(ehdr_vdso) + ehdr_vdso->e_phoff); + si->phnum = ehdr_vdso->e_phnum; + si->base = reinterpret_cast(ehdr_vdso); + si->size = phdr_table_get_load_size(si->phdr, si->phnum); + si->flags = 0; + si->load_bias = get_elf_exec_load_bias(ehdr_vdso); - soinfo_link_image(si); + soinfo_link_image(si); #endif } @@ -1987,7 +1954,7 @@ static void add_vdso(KernelArgumentBlock& args UNUSED) { * fixed it's own GOT. It is safe to make references to externs * and other non-local data at this point. */ -static Elf_Addr __linker_init_post_relocation(KernelArgumentBlock& args, Elf_Addr linker_base) { +static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(Addr) linker_base) { /* NOTE: we store the args pointer on a special location * of the temporary TLS area in order to pass it to * the C Library's runtime initializer. @@ -2071,15 +2038,15 @@ static Elf_Addr __linker_init_post_relocation(KernelArgumentBlock& args, Elf_Add * warning: .dynamic section for "/system/bin/linker" is not at the * expected address (wrong library or version mismatch?) */ - Elf_Ehdr *elf_hdr = (Elf_Ehdr *) linker_base; - Elf_Phdr *phdr = (Elf_Phdr*)((unsigned char*) linker_base + elf_hdr->e_phoff); + ElfW(Ehdr)* elf_hdr = reinterpret_cast(linker_base); + ElfW(Phdr)* phdr = reinterpret_cast((unsigned char*) linker_base + elf_hdr->e_phoff); phdr_table_get_dynamic_section(phdr, elf_hdr->e_phnum, linker_base, &linker_soinfo.dynamic, NULL, NULL); insert_soinfo_into_debug_map(&linker_soinfo); } // Extract information passed from the kernel. - si->phdr = reinterpret_cast(args.getauxval(AT_PHDR)); + si->phdr = reinterpret_cast(args.getauxval(AT_PHDR)); si->phnum = args.getauxval(AT_PHNUM); si->entry = args.getauxval(AT_ENTRY); @@ -2092,8 +2059,8 @@ static Elf_Addr __linker_init_post_relocation(KernelArgumentBlock& args, Elf_Add si->load_bias = 0; for (size_t i = 0; i < si->phnum; ++i) { if (si->phdr[i].p_type == PT_PHDR) { - si->load_bias = reinterpret_cast(si->phdr) - si->phdr[i].p_vaddr; - si->base = reinterpret_cast(si->phdr) - si->phdr[i].p_offset; + si->load_bias = reinterpret_cast(si->phdr) - si->phdr[i].p_vaddr; + si->base = reinterpret_cast(si->phdr) - si->phdr[i].p_offset; break; } } @@ -2183,14 +2150,14 @@ static Elf_Addr __linker_init_post_relocation(KernelArgumentBlock& args, Elf_Add * load bias, i.e. add the value of any p_vaddr in the file to get * the corresponding address in memory. */ -static Elf_Addr get_elf_exec_load_bias(const Elf_Ehdr* elf) { - Elf_Addr offset = elf->e_phoff; - const Elf_Phdr* phdr_table = (const Elf_Phdr*)((char*)elf + offset); - const Elf_Phdr* phdr_end = phdr_table + elf->e_phnum; +static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf) { + ElfW(Addr) offset = elf->e_phoff; + const ElfW(Phdr)* phdr_table = reinterpret_cast((char*)elf + offset); + const ElfW(Phdr)* phdr_end = phdr_table + elf->e_phnum; - for (const Elf_Phdr* phdr = phdr_table; phdr < phdr_end; phdr++) { + for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_end; phdr++) { if (phdr->p_type == PT_LOAD) { - return reinterpret_cast(elf) + phdr->p_offset - phdr->p_vaddr; + return reinterpret_cast(elf) + phdr->p_offset - phdr->p_vaddr; } } return 0; @@ -2205,12 +2172,12 @@ static Elf_Addr get_elf_exec_load_bias(const Elf_Ehdr* elf) { * relocations, any attempt to reference an extern variable, extern * function, or other GOT reference will generate a segfault. */ -extern "C" Elf_Addr __linker_init(void* raw_args) { +extern "C" ElfW(Addr) __linker_init(void* raw_args) { KernelArgumentBlock args(raw_args); - Elf_Addr linker_addr = args.getauxval(AT_BASE); - Elf_Ehdr* elf_hdr = reinterpret_cast(linker_addr); - Elf_Phdr* phdr = (Elf_Phdr*)((unsigned char*) linker_addr + elf_hdr->e_phoff); + ElfW(Addr) linker_addr = args.getauxval(AT_BASE); + ElfW(Ehdr)* elf_hdr = reinterpret_cast(linker_addr); + ElfW(Phdr)* phdr = reinterpret_cast((unsigned char*) linker_addr + elf_hdr->e_phoff); soinfo linker_so; memset(&linker_so, 0, sizeof(soinfo)); @@ -2239,7 +2206,7 @@ extern "C" Elf_Addr __linker_init(void* raw_args) { // We have successfully fixed our own relocations. It's safe to run // the main part of the linker now. args.abort_message_ptr = &gAbortMessage; - Elf_Addr start_address = __linker_init_post_relocation(args, linker_addr); + ElfW(Addr) start_address = __linker_init_post_relocation(args, linker_addr); set_soinfo_pool_protection(PROT_READ); diff --git a/linker/linker.h b/linker/linker.h index 654ee5f2b..bb35ffcbc 100644 --- a/linker/linker.h +++ b/linker/linker.h @@ -50,6 +50,11 @@ __libc_format_fd(2, "\n"); \ } while (false) +#if defined(__LP64__) +#define ELFW(what) ELF64_ ## what +#else +#define ELFW(what) ELF32_ ## what +#endif // Returns the address of the page containing address 'x'. #define PAGE_START(x) ((x) & PAGE_MASK) @@ -77,17 +82,17 @@ typedef void (*linker_function_t)(); struct soinfo { public: char name[SOINFO_NAME_LEN]; - const Elf_Phdr* phdr; + const ElfW(Phdr)* phdr; size_t phnum; - Elf_Addr entry; - Elf_Addr base; + ElfW(Addr) entry; + ElfW(Addr) base; size_t size; #ifndef __LP64__ uint32_t unused1; // DO NOT USE, maintained for compatibility. #endif - Elf_Dyn* dynamic; + ElfW(Dyn)* dynamic; #ifndef __LP64__ uint32_t unused2; // DO NOT USE, maintained for compatibility @@ -98,7 +103,7 @@ struct soinfo { unsigned flags; const char* strtab; - Elf_Sym* symtab; + ElfW(Sym)* symtab; size_t nbucket; size_t nchain; @@ -112,16 +117,16 @@ struct soinfo { #endif #if defined(USE_RELA) - Elf_Rela* plt_rela; + ElfW(Rela)* plt_rela; size_t plt_rela_count; - Elf_Rela* rela; + ElfW(Rela)* rela; size_t rela_count; #else - Elf_Rel* plt_rel; + ElfW(Rel)* plt_rel; size_t plt_rel_count; - Elf_Rel* rel; + ElfW(Rel)* rel; size_t rel_count; #endif @@ -153,7 +158,7 @@ struct soinfo { // When you read a virtual address from the ELF file, add this // value to get the corresponding address in the process' address space. - Elf_Addr load_bias; + ElfW(Addr) load_bias; #if !defined(__LP64__) bool has_text_relocations; @@ -176,11 +181,11 @@ void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path); soinfo* do_dlopen(const char* name, int flags); int do_dlclose(soinfo* si); -Elf_Sym* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start); +ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start); soinfo* find_containing_library(const void* addr); -Elf_Sym* dladdr_find_symbol(soinfo* si, const void* addr); -Elf_Sym* dlsym_handle_lookup(soinfo* si, const char* name); +ElfW(Sym)* dladdr_find_symbol(soinfo* si, const void* addr); +ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name); void debuggerd_init(); extern "C" abort_msg_t* gAbortMessage; diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp index 310151199..391e4cf79 100644 --- a/linker/linker_phdr.cpp +++ b/linker/linker_phdr.cpp @@ -50,7 +50,7 @@ p_vaddr -> segment's virtual address p_flags -> segment flags (e.g. readable, writable, executable) - We will ignore the p_paddr and p_align fields of Elf_Phdr for now. + We will ignore the p_paddr and p_align fields of ElfW(Phdr) for now. The loadable segments can be seen as a list of [p_vaddr ... p_vaddr+p_memsz) ranges of virtual addresses. A few rules apply: @@ -217,14 +217,14 @@ bool ElfReader::ReadProgramHeader() { // Like the kernel, we only accept program header tables that // are smaller than 64KiB. - if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(Elf_Phdr)) { + if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) { DL_ERR("\"%s\" has invalid e_phnum: %zd", name_, phdr_num_); return false; } - Elf_Addr page_min = PAGE_START(header_.e_phoff); - Elf_Addr page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(Elf_Phdr))); - Elf_Addr page_offset = PAGE_OFFSET(header_.e_phoff); + ElfW(Addr) page_min = PAGE_START(header_.e_phoff); + ElfW(Addr) page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(ElfW(Phdr)))); + ElfW(Addr) page_offset = PAGE_OFFSET(header_.e_phoff); phdr_size_ = page_max - page_min; @@ -235,7 +235,7 @@ bool ElfReader::ReadProgramHeader() { } phdr_mmap_ = mmap_result; - phdr_table_ = reinterpret_cast(reinterpret_cast(mmap_result) + page_offset); + phdr_table_ = reinterpret_cast(reinterpret_cast(mmap_result) + page_offset); return true; } @@ -249,50 +249,50 @@ bool ElfReader::ReadProgramHeader() { * set to the minimum and maximum addresses of pages to be reserved, * or 0 if there is nothing to load. */ -size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table, size_t phdr_count, - Elf_Addr* out_min_vaddr, - Elf_Addr* out_max_vaddr) { - Elf_Addr min_vaddr = UINTPTR_MAX; - Elf_Addr max_vaddr = 0; +size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, + ElfW(Addr)* out_min_vaddr, + ElfW(Addr)* out_max_vaddr) { + ElfW(Addr) min_vaddr = UINTPTR_MAX; + ElfW(Addr) max_vaddr = 0; - bool found_pt_load = false; - for (size_t i = 0; i < phdr_count; ++i) { - const Elf_Phdr* phdr = &phdr_table[i]; + bool found_pt_load = false; + for (size_t i = 0; i < phdr_count; ++i) { + const ElfW(Phdr)* phdr = &phdr_table[i]; - if (phdr->p_type != PT_LOAD) { - continue; - } - found_pt_load = true; - - if (phdr->p_vaddr < min_vaddr) { - min_vaddr = phdr->p_vaddr; - } - - if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) { - max_vaddr = phdr->p_vaddr + phdr->p_memsz; - } + if (phdr->p_type != PT_LOAD) { + continue; } - if (!found_pt_load) { - min_vaddr = 0; + found_pt_load = true; + + if (phdr->p_vaddr < min_vaddr) { + min_vaddr = phdr->p_vaddr; } - min_vaddr = PAGE_START(min_vaddr); - max_vaddr = PAGE_END(max_vaddr); + if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) { + max_vaddr = phdr->p_vaddr + phdr->p_memsz; + } + } + if (!found_pt_load) { + min_vaddr = 0; + } - if (out_min_vaddr != NULL) { - *out_min_vaddr = min_vaddr; - } - if (out_max_vaddr != NULL) { - *out_max_vaddr = max_vaddr; - } - return max_vaddr - min_vaddr; + min_vaddr = PAGE_START(min_vaddr); + max_vaddr = PAGE_END(max_vaddr); + + if (out_min_vaddr != NULL) { + *out_min_vaddr = min_vaddr; + } + if (out_max_vaddr != NULL) { + *out_max_vaddr = max_vaddr; + } + return max_vaddr - min_vaddr; } // Reserve a virtual address range big enough to hold all loadable // segments of a program header table. This is done by creating a // private anonymous mmap() with PROT_NONE. bool ElfReader::ReserveAddressSpace() { - Elf_Addr min_vaddr; + ElfW(Addr) min_vaddr; load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr); if (load_size_ == 0) { DL_ERR("\"%s\" has no loadable segments", name_); @@ -314,27 +314,27 @@ bool ElfReader::ReserveAddressSpace() { bool ElfReader::LoadSegments() { for (size_t i = 0; i < phdr_num_; ++i) { - const Elf_Phdr* phdr = &phdr_table_[i]; + const ElfW(Phdr)* phdr = &phdr_table_[i]; if (phdr->p_type != PT_LOAD) { continue; } // Segment addresses in memory. - Elf_Addr seg_start = phdr->p_vaddr + load_bias_; - Elf_Addr seg_end = seg_start + phdr->p_memsz; + ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_; + ElfW(Addr) seg_end = seg_start + phdr->p_memsz; - Elf_Addr seg_page_start = PAGE_START(seg_start); - Elf_Addr seg_page_end = PAGE_END(seg_end); + ElfW(Addr) seg_page_start = PAGE_START(seg_start); + ElfW(Addr) seg_page_end = PAGE_END(seg_end); - Elf_Addr seg_file_end = seg_start + phdr->p_filesz; + ElfW(Addr) seg_file_end = seg_start + phdr->p_filesz; // File offsets. - Elf_Addr file_start = phdr->p_offset; - Elf_Addr file_end = file_start + phdr->p_filesz; + ElfW(Addr) file_start = phdr->p_offset; + ElfW(Addr) file_end = file_start + phdr->p_filesz; - Elf_Addr file_page_start = PAGE_START(file_start); - Elf_Addr file_length = file_end - file_page_start; + ElfW(Addr) file_page_start = PAGE_START(file_start); + ElfW(Addr) file_length = file_end - file_page_start; if (file_length != 0) { void* seg_addr = mmap((void*)seg_page_start, @@ -381,26 +381,27 @@ bool ElfReader::LoadSegments() { * with optional extra flags (i.e. really PROT_WRITE). Used by * phdr_table_protect_segments and phdr_table_unprotect_segments. */ -static int _phdr_table_set_load_prot(const Elf_Phdr* phdr_table, size_t phdr_count, - Elf_Addr load_bias, int extra_prot_flags) { - const Elf_Phdr* phdr = phdr_table; - const Elf_Phdr* phdr_limit = phdr + phdr_count; +static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count, + ElfW(Addr) load_bias, int extra_prot_flags) { + const ElfW(Phdr)* phdr = phdr_table; + const ElfW(Phdr)* phdr_limit = phdr + phdr_count; - for (; phdr < phdr_limit; phdr++) { - if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) - continue; - - Elf_Addr seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; - Elf_Addr seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; - - int ret = mprotect((void*)seg_page_start, - seg_page_end - seg_page_start, - PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags); - if (ret < 0) { - return -1; - } + for (; phdr < phdr_limit; phdr++) { + if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) { + continue; } - return 0; + + ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; + ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; + + int ret = mprotect((void*)seg_page_start, + seg_page_end - seg_page_start, + PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags); + if (ret < 0) { + return -1; + } + } + return 0; } /* Restore the original protection modes for all loadable segments. @@ -414,8 +415,8 @@ static int _phdr_table_set_load_prot(const Elf_Phdr* phdr_table, size_t phdr_cou * Return: * 0 on error, -1 on failure (error code in errno). */ -int phdr_table_protect_segments(const Elf_Phdr* phdr_table, size_t phdr_count, Elf_Addr load_bias) { - return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0); +int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) { + return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0); } /* Change the protection of all loaded segments in memory to writable. @@ -434,50 +435,50 @@ int phdr_table_protect_segments(const Elf_Phdr* phdr_table, size_t phdr_count, E * Return: * 0 on error, -1 on failure (error code in errno). */ -int phdr_table_unprotect_segments(const Elf_Phdr* phdr_table, size_t phdr_count, Elf_Addr load_bias) { - return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE); +int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) { + return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE); } /* Used internally by phdr_table_protect_gnu_relro and * phdr_table_unprotect_gnu_relro. */ -static int _phdr_table_set_gnu_relro_prot(const Elf_Phdr* phdr_table, size_t phdr_count, - Elf_Addr load_bias, int prot_flags) { - const Elf_Phdr* phdr = phdr_table; - const Elf_Phdr* phdr_limit = phdr + phdr_count; +static int _phdr_table_set_gnu_relro_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count, + ElfW(Addr) load_bias, int prot_flags) { + const ElfW(Phdr)* phdr = phdr_table; + const ElfW(Phdr)* phdr_limit = phdr + phdr_count; - for (phdr = phdr_table; phdr < phdr_limit; phdr++) { - if (phdr->p_type != PT_GNU_RELRO) - continue; - - /* Tricky: what happens when the relro segment does not start - * or end at page boundaries?. We're going to be over-protective - * here and put every page touched by the segment as read-only. - * - * This seems to match Ian Lance Taylor's description of the - * feature at http://www.airs.com/blog/archives/189. - * - * Extract: - * Note that the current dynamic linker code will only work - * correctly if the PT_GNU_RELRO segment starts on a page - * boundary. This is because the dynamic linker rounds the - * p_vaddr field down to the previous page boundary. If - * there is anything on the page which should not be read-only, - * the program is likely to fail at runtime. So in effect the - * linker must only emit a PT_GNU_RELRO segment if it ensures - * that it starts on a page boundary. - */ - Elf_Addr seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; - Elf_Addr seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; - - int ret = mprotect((void*)seg_page_start, - seg_page_end - seg_page_start, - prot_flags); - if (ret < 0) { - return -1; - } + for (phdr = phdr_table; phdr < phdr_limit; phdr++) { + if (phdr->p_type != PT_GNU_RELRO) { + continue; } - return 0; + + // Tricky: what happens when the relro segment does not start + // or end at page boundaries? We're going to be over-protective + // here and put every page touched by the segment as read-only. + + // This seems to match Ian Lance Taylor's description of the + // feature at http://www.airs.com/blog/archives/189. + + // Extract: + // Note that the current dynamic linker code will only work + // correctly if the PT_GNU_RELRO segment starts on a page + // boundary. This is because the dynamic linker rounds the + // p_vaddr field down to the previous page boundary. If + // there is anything on the page which should not be read-only, + // the program is likely to fail at runtime. So in effect the + // linker must only emit a PT_GNU_RELRO segment if it ensures + // that it starts on a page boundary. + ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; + ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; + + int ret = mprotect((void*)seg_page_start, + seg_page_end - seg_page_start, + prot_flags); + if (ret < 0) { + return -1; + } + } + return 0; } /* Apply GNU relro protection if specified by the program header. This will @@ -496,8 +497,8 @@ static int _phdr_table_set_gnu_relro_prot(const Elf_Phdr* phdr_table, size_t phd * Return: * 0 on error, -1 on failure (error code in errno). */ -int phdr_table_protect_gnu_relro(const Elf_Phdr* phdr_table, size_t phdr_count, Elf_Addr load_bias) { - return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ); +int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) { + return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ); } #if defined(__arm__) @@ -519,23 +520,24 @@ int phdr_table_protect_gnu_relro(const Elf_Phdr* phdr_table, size_t phdr_count, * Return: * 0 on error, -1 on failure (_no_ error code in errno) */ -int phdr_table_get_arm_exidx(const Elf_Phdr* phdr_table, size_t phdr_count, - Elf_Addr load_bias, - Elf_Addr** arm_exidx, unsigned* arm_exidx_count) { - const Elf_Phdr* phdr = phdr_table; - const Elf_Phdr* phdr_limit = phdr + phdr_count; +int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, + ElfW(Addr) load_bias, + ElfW(Addr)** arm_exidx, unsigned* arm_exidx_count) { + const ElfW(Phdr)* phdr = phdr_table; + const ElfW(Phdr)* phdr_limit = phdr + phdr_count; - for (phdr = phdr_table; phdr < phdr_limit; phdr++) { - if (phdr->p_type != PT_ARM_EXIDX) - continue; - - *arm_exidx = (Elf_Addr*)(load_bias + phdr->p_vaddr); - *arm_exidx_count = (unsigned)(phdr->p_memsz / 8); - return 0; + for (phdr = phdr_table; phdr < phdr_limit; phdr++) { + if (phdr->p_type != PT_ARM_EXIDX) { + continue; } - *arm_exidx = NULL; - *arm_exidx_count = 0; - return -1; + + *arm_exidx = reinterpret_cast(load_bias + phdr->p_vaddr); + *arm_exidx_count = (unsigned)(phdr->p_memsz / 8); + return 0; + } + *arm_exidx = NULL; + *arm_exidx_count = 0; + return -1; } #endif @@ -553,40 +555,40 @@ int phdr_table_get_arm_exidx(const Elf_Phdr* phdr_table, size_t phdr_count, * Return: * void */ -void phdr_table_get_dynamic_section(const Elf_Phdr* phdr_table, size_t phdr_count, - Elf_Addr load_bias, - Elf_Dyn** dynamic, size_t* dynamic_count, Elf_Word* dynamic_flags) { - const Elf_Phdr* phdr = phdr_table; - const Elf_Phdr* phdr_limit = phdr + phdr_count; +void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count, + ElfW(Addr) load_bias, + ElfW(Dyn)** dynamic, size_t* dynamic_count, ElfW(Word)* dynamic_flags) { + const ElfW(Phdr)* phdr = phdr_table; + const ElfW(Phdr)* phdr_limit = phdr + phdr_count; - for (phdr = phdr_table; phdr < phdr_limit; phdr++) { - if (phdr->p_type != PT_DYNAMIC) { - continue; - } - - *dynamic = reinterpret_cast(load_bias + phdr->p_vaddr); - if (dynamic_count) { - *dynamic_count = (unsigned)(phdr->p_memsz / 8); - } - if (dynamic_flags) { - *dynamic_flags = phdr->p_flags; - } - return; + for (phdr = phdr_table; phdr < phdr_limit; phdr++) { + if (phdr->p_type != PT_DYNAMIC) { + continue; } - *dynamic = NULL; + + *dynamic = reinterpret_cast(load_bias + phdr->p_vaddr); if (dynamic_count) { - *dynamic_count = 0; + *dynamic_count = (unsigned)(phdr->p_memsz / 8); } + if (dynamic_flags) { + *dynamic_flags = phdr->p_flags; + } + return; + } + *dynamic = NULL; + if (dynamic_count) { + *dynamic_count = 0; + } } // Returns the address of the program header table as it appears in the loaded // segments in memory. This is in contrast with 'phdr_table_' which // is temporary and will be released before the library is relocated. bool ElfReader::FindPhdr() { - const Elf_Phdr* phdr_limit = phdr_table_ + phdr_num_; + const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_; // If there is a PT_PHDR, use it directly. - for (const Elf_Phdr* phdr = phdr_table_; phdr < phdr_limit; ++phdr) { + for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) { if (phdr->p_type == PT_PHDR) { return CheckPhdr(load_bias_ + phdr->p_vaddr); } @@ -595,13 +597,13 @@ bool ElfReader::FindPhdr() { // Otherwise, check the first loadable segment. If its file offset // is 0, it starts with the ELF header, and we can trivially find the // loaded program header from it. - for (const Elf_Phdr* phdr = phdr_table_; phdr < phdr_limit; ++phdr) { + for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) { if (phdr->p_type == PT_LOAD) { if (phdr->p_offset == 0) { - Elf_Addr elf_addr = load_bias_ + phdr->p_vaddr; - const Elf_Ehdr* ehdr = (const Elf_Ehdr*)(void*)elf_addr; - Elf_Addr offset = ehdr->e_phoff; - return CheckPhdr((Elf_Addr)ehdr + offset); + ElfW(Addr) elf_addr = load_bias_ + phdr->p_vaddr; + const ElfW(Ehdr)* ehdr = (const ElfW(Ehdr)*)(void*)elf_addr; + ElfW(Addr) offset = ehdr->e_phoff; + return CheckPhdr((ElfW(Addr))ehdr + offset); } break; } @@ -614,17 +616,17 @@ bool ElfReader::FindPhdr() { // Ensures that our program header is actually within a loadable // segment. This should help catch badly-formed ELF files that // would cause the linker to crash later when trying to access it. -bool ElfReader::CheckPhdr(Elf_Addr loaded) { - const Elf_Phdr* phdr_limit = phdr_table_ + phdr_num_; - Elf_Addr loaded_end = loaded + (phdr_num_ * sizeof(Elf_Phdr)); - for (Elf_Phdr* phdr = phdr_table_; phdr < phdr_limit; ++phdr) { +bool ElfReader::CheckPhdr(ElfW(Addr) loaded) { + const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_; + ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr))); + for (ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) { if (phdr->p_type != PT_LOAD) { continue; } - Elf_Addr seg_start = phdr->p_vaddr + load_bias_; - Elf_Addr seg_end = phdr->p_filesz + seg_start; + ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_; + ElfW(Addr) seg_end = phdr->p_filesz + seg_start; if (seg_start <= loaded && loaded_end <= seg_end) { - loaded_phdr_ = reinterpret_cast(loaded); + loaded_phdr_ = reinterpret_cast(loaded); return true; } } diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h index db15ac969..6b72caf17 100644 --- a/linker/linker_phdr.h +++ b/linker/linker_phdr.h @@ -45,10 +45,10 @@ class ElfReader { bool Load(); size_t phdr_count() { return phdr_num_; } - Elf_Addr load_start() { return reinterpret_cast(load_start_); } + ElfW(Addr) load_start() { return reinterpret_cast(load_start_); } size_t load_size() { return load_size_; } - Elf_Addr load_bias() { return load_bias_; } - const Elf_Phdr* loaded_phdr() { return loaded_phdr_; } + ElfW(Addr) load_bias() { return load_bias_; } + const ElfW(Phdr)* loaded_phdr() { return loaded_phdr_; } private: bool ReadElfHeader(); @@ -57,46 +57,46 @@ class ElfReader { bool ReserveAddressSpace(); bool LoadSegments(); bool FindPhdr(); - bool CheckPhdr(Elf_Addr); + bool CheckPhdr(ElfW(Addr)); const char* name_; int fd_; - Elf_Ehdr header_; + ElfW(Ehdr) header_; size_t phdr_num_; void* phdr_mmap_; - Elf_Phdr* phdr_table_; - Elf_Addr phdr_size_; + ElfW(Phdr)* phdr_table_; + ElfW(Addr) phdr_size_; // First page of reserved address space. void* load_start_; // Size in bytes of reserved address space. size_t load_size_; // Load bias. - Elf_Addr load_bias_; + ElfW(Addr) load_bias_; // Loaded phdr. - const Elf_Phdr* loaded_phdr_; + const ElfW(Phdr)* loaded_phdr_; }; -size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table, size_t phdr_count, - Elf_Addr* min_vaddr = NULL, Elf_Addr* max_vaddr = NULL); +size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, + ElfW(Addr)* min_vaddr = NULL, ElfW(Addr)* max_vaddr = NULL); -int phdr_table_protect_segments(const Elf_Phdr* phdr_table, size_t phdr_count, Elf_Addr load_bias); +int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias); -int phdr_table_unprotect_segments(const Elf_Phdr* phdr_table, size_t phdr_count, Elf_Addr load_bias); +int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias); -int phdr_table_protect_gnu_relro(const Elf_Phdr* phdr_table, size_t phdr_count, Elf_Addr load_bias); +int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias); #if defined(__arm__) -int phdr_table_get_arm_exidx(const Elf_Phdr* phdr_table, size_t phdr_count, Elf_Addr load_bias, - Elf_Addr** arm_exidx, unsigned* arm_exidix_count); +int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias, + ElfW(Addr)** arm_exidx, unsigned* arm_exidix_count); #endif -void phdr_table_get_dynamic_section(const Elf_Phdr* phdr_table, size_t phdr_count, - Elf_Addr load_bias, - Elf_Dyn** dynamic, size_t* dynamic_count, Elf_Word* dynamic_flags); +void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count, + ElfW(Addr) load_bias, + ElfW(Dyn)** dynamic, size_t* dynamic_count, ElfW(Word)* dynamic_flags); #endif /* LINKER_PHDR_H */