summaryrefslogtreecommitdiff
path: root/Libraries/LibELF
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-12 12:17:30 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-12 12:17:46 +0100
commit13d7c09125f8eec703d0a43a9a87fc8aa08f7319 (patch)
tree70fd643c429cea5c1f9362c2674511d17a53f3b5 /Libraries/LibELF
parentdc28c07fa526841e05e16161c74a6c23984f1dd5 (diff)
downloadserenity-13d7c09125f8eec703d0a43a9a87fc8aa08f7319.zip
Libraries: Move to Userland/Libraries/
Diffstat (limited to 'Libraries/LibELF')
-rw-r--r--Libraries/LibELF/Arch/i386/plt_trampoline.S58
-rw-r--r--Libraries/LibELF/AuxiliaryVector.h123
-rw-r--r--Libraries/LibELF/CMakeLists.txt1
-rw-r--r--Libraries/LibELF/CoreDump.h87
-rw-r--r--Libraries/LibELF/DynamicLinker.cpp287
-rw-r--r--Libraries/LibELF/DynamicLinker.h45
-rw-r--r--Libraries/LibELF/DynamicLoader.cpp530
-rw-r--r--Libraries/LibELF/DynamicLoader.h164
-rw-r--r--Libraries/LibELF/DynamicObject.cpp527
-rw-r--r--Libraries/LibELF/DynamicObject.h414
-rw-r--r--Libraries/LibELF/Image.cpp419
-rw-r--r--Libraries/LibELF/Image.h299
-rw-r--r--Libraries/LibELF/Validation.cpp267
-rw-r--r--Libraries/LibELF/Validation.h36
-rw-r--r--Libraries/LibELF/exec_elf.h792
15 files changed, 0 insertions, 4049 deletions
diff --git a/Libraries/LibELF/Arch/i386/plt_trampoline.S b/Libraries/LibELF/Arch/i386/plt_trampoline.S
deleted file mode 100644
index 6eb5e96a5f..0000000000
--- a/Libraries/LibELF/Arch/i386/plt_trampoline.S
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-
- * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Christos Zoulas and by Charles M. Hannum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * This asm method is copied from NetBSD. We changed the internal method that
- * gets called and the name, but it's still essentially the same as
- * _rtld_bind_start from libexec/ld.elf_so/arch/i386/rtld_start.S
- */
-
-.align 4
- .globl _plt_trampoline
- .hidden _plt_trampoline
- .type _plt_trampoline,@function
-_plt_trampoline: # (obj, reloff)
- pushf # save registers
- pushl %eax
- pushl %ecx
- pushl %edx
-
- pushl 20(%esp) # Copy of reloff
- pushl 20(%esp) # Copy of obj
- call _fixup_plt_entry # Call the binder
- addl $8,%esp # pop binder args
- movl %eax,20(%esp) # Store function to be called in obj
-
- popl %edx
- popl %ecx
- popl %eax
- popf
-
- leal 4(%esp),%esp # Discard reloff, do not change eflags
- ret
diff --git a/Libraries/LibELF/AuxiliaryVector.h b/Libraries/LibELF/AuxiliaryVector.h
deleted file mode 100644
index 24a5f0924c..0000000000
--- a/Libraries/LibELF/AuxiliaryVector.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2020, The SerenityOS developers.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
- */
-
-#pragma once
-
-#include <AK/String.h>
-#include <AK/Types.h>
-
-/* Auxiliary Vector types, from Intel386 ABI ver 1.0 section 2.3.3 */
-typedef struct
-{
- long a_type; /* Note: Extended to long from int, for ease of comaptibility w/64 bit */
- union {
- long a_val;
- void* a_ptr;
- void (*a_fnc)(); /* In spec, not used */
- } a_un;
-} auxv_t;
-
-// clang-format off
-#define AT_NULL 0 /* No length, last entry's a_type has this value */
-#define AT_IGNORE 1 /* Entry has no meaning, a_un undefined */
-#define AT_EXECFD 2 /* a_val contains a file descriptor of the main program image */
-#define AT_PHDR 3 /* a_ptr contains pointer to program header table of main program image */
-#define AT_PHENT 4 /* a_val holds size of program header table entries */
-#define AT_PHNUM 5 /* a_val holds number of program header table entries */
-#define AT_PAGESZ 6 /* a_val gives system page size in bytes */
-#define AT_BASE 7 /* a_ptr holds base address that Loader was loaded into memory */
-#define AT_FLAGS 8 /* a_val holds 1 bit flags. Undefined flags are 0 */
-#define AT_ENTRY 9 /* a_ptr holds entry point of the main program */
-#define AT_NOTELF 10 /* a_val non-zero if the program is not ELF */
-#define AT_UID 11 /* a_val holds real user id of process */
-#define AT_EUID 12 /* a_val holds effective user id of process */
-#define AT_GID 13 /* a_val holds real group id of process */
-#define AT_EGID 14 /* a_val holds effective group id of process */
-#define AT_PLATFORM 15 /* a_val points to a string containing platform name */
-#define AT_HWCAP 16 /* a_val contains bitmask of CPU features. Equivalent to CPUID 1.EDX*/
-#define AT_CLKTCK 17 /* a_val contains frequence at which times() increments. (Re: Spec. What is times()?) */
-#define AT_SECURE 23 /* a_val holds 1 if program in secure mode (e.g. suid). Otherwise 0 */
-#define AT_BASE_PLATFORM 24 /* a_ptr points to a string identifying base platform name, which might be different from platform (e.g x86_64 when in i386 compat) */
-#define AT_RANDOM 25 /* a_ptr points to 16 securely generated random bytes */
-#define AT_HWCAP2 26 /* a_val holds extended hw feature mask. Currently 0 */
-#define AT_EXECFN 31 /* a_ptr points to file name of executed program */
-#define AT_EXE_BASE 32 /* a_ptr holds base address where main program was loaded into memory */
-#define AT_EXE_SIZE 33 /* a_val holds the size of the main program in memory */
-// clang-format on
-
-namespace ELF {
-
-struct AuxiliaryValue {
- enum Type {
- Null = AT_NULL,
- Ignore = AT_IGNORE,
- ExecFileDescriptor = AT_EXECFD,
- Phdr = AT_PHDR,
- Phent = AT_PHENT,
- Phnum = AT_PHNUM,
- PageSize = AT_PAGESZ,
- BaseAddress = AT_BASE,
- Flags = AT_FLAGS,
- Entry = AT_ENTRY,
- NotELF = AT_NOTELF,
- Uid = AT_UID,
- EUid = AT_EUID,
- Gid = AT_GID,
- EGid = AT_EGID,
- Platform = AT_PLATFORM,
- HwCap = AT_HWCAP,
- ClockTick = AT_CLKTCK,
- Secure = AT_SECURE,
- BasePlatform = AT_BASE_PLATFORM,
- Random = AT_RANDOM,
- HwCap2 = AT_HWCAP2,
- ExecFilename = AT_EXECFN,
- ExeBaseAddress = AT_EXE_BASE,
- ExeSize = AT_EXE_SIZE
- };
-
- AuxiliaryValue(Type type, long val)
- {
- auxv.a_type = type;
- auxv.a_un.a_val = val;
- }
- AuxiliaryValue(Type type, void* ptr)
- {
- auxv.a_type = type;
- auxv.a_un.a_ptr = (void*)ptr;
- }
- AuxiliaryValue(Type type, String string)
- {
- auxv.a_type = type;
- auxv.a_un.a_ptr = nullptr;
- optional_string = string;
- }
-
- auxv_t auxv {};
- String optional_string;
-};
-
-}
diff --git a/Libraries/LibELF/CMakeLists.txt b/Libraries/LibELF/CMakeLists.txt
deleted file mode 100644
index 3c0959e7e9..0000000000
--- a/Libraries/LibELF/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-serenity_install_sources(Libraries/LibELF)
diff --git a/Libraries/LibELF/CoreDump.h b/Libraries/LibELF/CoreDump.h
deleted file mode 100644
index 4978430306..0000000000
--- a/Libraries/LibELF/CoreDump.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2020, The SerenityOS developers.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
- */
-
-#pragma once
-
-#include <AK/String.h>
-#include <AK/Types.h>
-#include <LibC/sys/arch/i386/regs.h>
-
-namespace ELF::Core {
-
-struct [[gnu::packed]] NotesEntryHeader {
- enum Type : u8 {
- Null = 0, // Terminates segment
- ProcessInfo,
- ThreadInfo,
- MemoryRegionInfo,
- Metadata,
- };
- Type type;
-};
-
-struct [[gnu::packed]] NotesEntry {
- NotesEntryHeader header;
- char data[];
-};
-
-struct [[gnu::packed]] ProcessInfo {
- NotesEntryHeader header;
- int pid;
- u8 termination_signal;
- char executable_path[]; // Null terminated
-};
-
-struct [[gnu::packed]] ThreadInfo {
- NotesEntryHeader header;
- int tid;
- PtraceRegisters regs;
-};
-
-struct [[gnu::packed]] MemoryRegionInfo {
- NotesEntryHeader header;
- uint32_t region_start;
- uint32_t region_end;
- uint16_t program_header_index;
- char region_name[]; // Null terminated
-
- String object_name() const
- {
- StringView memory_region_name { region_name };
- if (memory_region_name.contains("Loader.so"))
- return "Loader.so";
- if (!memory_region_name.contains(":"))
- return {};
- return memory_region_name.substring_view(0, memory_region_name.find_first_of(":").value()).to_string();
- }
-};
-
-struct [[gnu::packed]] Metadata {
- NotesEntryHeader header;
- char json_data[]; // Null terminated
-};
-
-}
diff --git a/Libraries/LibELF/DynamicLinker.cpp b/Libraries/LibELF/DynamicLinker.cpp
deleted file mode 100644
index 3513645d07..0000000000
--- a/Libraries/LibELF/DynamicLinker.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
- * Copyright (c) 2021, the SerenityOS developers.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <AK/HashMap.h>
-#include <AK/HashTable.h>
-#include <AK/LexicalPath.h>
-#include <AK/LogStream.h>
-#include <AK/ScopeGuard.h>
-#include <LibC/mman.h>
-#include <LibC/stdio.h>
-#include <LibC/sys/internals.h>
-#include <LibC/unistd.h>
-#include <LibCore/File.h>
-#include <LibELF/AuxiliaryVector.h>
-#include <LibELF/DynamicLinker.h>
-#include <LibELF/DynamicLoader.h>
-#include <LibELF/DynamicObject.h>
-#include <LibELF/Image.h>
-#include <LibELF/exec_elf.h>
-#include <dlfcn.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-// #define DYNAMIC_LOAD_VERBOSE
-
-#ifdef DYNAMIC_LOAD_VERBOSE
-# define VERBOSE(fmt, ...) dbgprintf(fmt, ##__VA_ARGS__)
-#else
-# define VERBOSE(fmt, ...) \
- do { \
- } while (0)
-#endif
-#define TLS_VERBOSE(fmt, ...) dbgprintf(fmt, ##__VA_ARGS__)
-
-namespace ELF {
-
-namespace {
-HashMap<String, NonnullRefPtr<ELF::DynamicLoader>> g_loaders;
-HashMap<String, NonnullRefPtr<ELF::DynamicObject>> g_loaded_objects;
-Vector<NonnullRefPtr<ELF::DynamicObject>> g_global_objects;
-
-using MainFunction = int (*)(int, char**, char**);
-using LibCExitFunction = void (*)(int);
-
-size_t g_current_tls_offset = 0;
-size_t g_total_tls_size = 0;
-char** g_envp = nullptr;
-LibCExitFunction g_libc_exit = nullptr;
-
-bool g_allowed_to_check_environment_variables { false };
-bool g_do_breakpoint_trap_before_entry { false };
-}
-
-DynamicObject::SymbolLookupResult DynamicLinker::lookup_global_symbol(const char* symbol_name)
-{
- DynamicObject::SymbolLookupResult weak_result = {};
- for (auto& lib : g_global_objects) {
- auto res = lib->lookup_symbol(symbol_name);
- if (res.found) {
- if (res.bind == STB_GLOBAL) {
- return res;
- } else if (res.bind == STB_WEAK && !weak_result.found) {
- weak_result = res;
- }
- // We don't want to allow local symbols to be pulled in to other modules
- }
- }
- return weak_result;
-}
-
-static void map_library(const String& name, int fd)
-{
- struct stat lib_stat;
- int rc = fstat(fd, &lib_stat);
- ASSERT(!rc);
-
- auto loader = ELF::DynamicLoader::construct(name.characters(), fd, lib_stat.st_size);
- loader->set_tls_offset(g_current_tls_offset);
-
- g_loaders.set(name, loader);
-
- g_current_tls_offset += loader->tls_size();
-}
-
-static void map_library(const String& name)
-{
- // TODO: Do we want to also look for libs in other paths too?
- String path = String::format("/usr/lib/%s", name.characters());
- int fd = open(path.characters(), O_RDONLY);
- ASSERT(fd >= 0);
- map_library(name, fd);
-}
-
-static String get_library_name(const StringView& path)
-{
- return LexicalPath(path).basename();
-}
-
-static Vector<String> get_dependencies(const String& name)
-{
- auto lib = g_loaders.get(name).value();
- Vector<String> dependencies;
-
- lib->for_each_needed_library([&dependencies, &name](auto needed_name) {
- if (name == needed_name)
- return IterationDecision::Continue;
- dependencies.append(needed_name);
- return IterationDecision::Continue;
- });
- return dependencies;
-}
-
-static void map_dependencies(const String& name)
-{
- VERBOSE("mapping dependencies for: %s\n", name.characters());
-
- for (const auto& needed_name : get_dependencies(name)) {
- VERBOSE("needed library: %s\n", needed_name.characters());
- String library_name = get_library_name(needed_name);
-
- if (!g_loaders.contains(library_name)) {
- map_library(library_name);
- map_dependencies(library_name);
- }
- }
- VERBOSE("mapped dependencies for %s\n", name.characters());
-}
-
-static void allocate_tls()
-{
- size_t total_tls_size = 0;
- for (const auto& data : g_loaders) {
- VERBOSE("%s: TLS Size: %zu\n", data.key.characters(), data.value->tls_size());
- total_tls_size += data.value->tls_size();
- }
- if (total_tls_size) {
- [[maybe_unused]] void* tls_address = ::allocate_tls(total_tls_size);
- VERBOSE("from userspace, tls_address: %p\n", tls_address);
- }
- g_total_tls_size = total_tls_size;
-}
-
-static void initialize_libc(DynamicObject& libc)
-{
- // Traditionally, `_start` of the main program initializes libc.
- // However, since some libs use malloc() and getenv() in global constructors,
- // we have to initialize libc just after it is loaded.
- // Also, we can't just mark `__libc_init` with "__attribute__((constructor))"
- // because it uses getenv() internally, so `environ` has to be initialized before we call `__libc_init`.
- auto res = libc.lookup_symbol("environ");
- ASSERT(res.found);
- *((char***)res.address) = g_envp;
-
- res = libc.lookup_symbol("__environ_is_malloced");
- ASSERT(res.found);
- *((bool*)res.address) = false;
-
- res = libc.lookup_symbol("exit");
- ASSERT(res.found);
- g_libc_exit = (LibCExitFunction)res.address;
-
- res = libc.lookup_symbol("__libc_init");
- ASSERT(res.found);
- typedef void libc_init_func();
- ((libc_init_func*)res.address)();
-}
-
-static void load_elf(const String& name)
-{
- VERBOSE("load_elf: %s\n", name.characters());
- auto loader = g_loaders.get(name).value();
- VERBOSE("a1\n");
- for (const auto& needed_name : get_dependencies(name)) {
- VERBOSE("needed library: %s\n", needed_name.characters());
- String library_name = get_library_name(needed_name);
- if (!g_loaded_objects.contains(library_name)) {
- load_elf(library_name);
- }
- }
-
- auto dynamic_object = loader->load_from_image(RTLD_GLOBAL | RTLD_LAZY, g_total_tls_size);
- ASSERT(dynamic_object);
-
- g_loaded_objects.set(name, *dynamic_object);
- g_global_objects.append(*dynamic_object);
-
- VERBOSE("load_elf: done %s\n", name.characters());
-}
-
-static NonnullRefPtr<DynamicLoader> commit_elf(const String& name)
-{
- auto loader = g_loaders.get(name).value();
- for (const auto& needed_name : get_dependencies(name)) {
- String library_name = get_library_name(needed_name);
- if (g_loaders.contains(library_name)) {
- commit_elf(library_name);
- }
- }
-
- auto object = loader->load_stage_3(RTLD_GLOBAL | RTLD_LAZY, g_total_tls_size);
- ASSERT(object);
- if (name == "libc.so") {
- initialize_libc(*object);
- }
- g_loaders.remove(name);
- return loader;
-}
-
-static void read_environment_variables()
-{
- for (char** env = g_envp; *env; ++env) {
- if (StringView { *env } == "_LOADER_BREAKPOINT=1") {
- g_do_breakpoint_trap_before_entry = true;
- }
- }
-}
-
-void ELF::DynamicLinker::linker_main(String&& main_program_name, int main_program_fd, bool is_secure, int argc, char** argv, char** envp)
-{
- g_envp = envp;
-
- g_allowed_to_check_environment_variables = !is_secure;
- if (g_allowed_to_check_environment_variables)
- read_environment_variables();
-
- map_library(main_program_name, main_program_fd);
- map_dependencies(main_program_name);
-
- VERBOSE("loaded all dependencies");
- for ([[maybe_unused]] auto& lib : g_loaders) {
- VERBOSE("%s - tls size: %zu, tls offset: %zu\n", lib.key.characters(), lib.value->tls_size(), lib.value->tls_offset());
- }
-
- allocate_tls();
-
- load_elf(main_program_name);
- auto main_program_lib = commit_elf(main_program_name);
-
- FlatPtr entry_point = reinterpret_cast<FlatPtr>(main_program_lib->image().entry().as_ptr());
- if (main_program_lib->is_dynamic())
- entry_point += reinterpret_cast<FlatPtr>(main_program_lib->text_segment_load_address().as_ptr());
-
- VERBOSE("entry point: %p\n", (void*)entry_point);
- g_loaders.clear();
-
- MainFunction main_function = (MainFunction)(entry_point);
- VERBOSE("jumping to main program entry point: %p\n", main_function);
- if (g_do_breakpoint_trap_before_entry) {
- asm("int3");
- }
- int rc = main_function(argc, argv, envp);
- VERBOSE("rc: %d\n", rc);
- if (g_libc_exit != nullptr) {
- g_libc_exit(rc);
- } else {
- _exit(rc);
- }
-
- ASSERT_NOT_REACHED();
-}
-
-}
diff --git a/Libraries/LibELF/DynamicLinker.h b/Libraries/LibELF/DynamicLinker.h
deleted file mode 100644
index d476443976..0000000000
--- a/Libraries/LibELF/DynamicLinker.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2021 (c), the SerenityOS developers.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
- */
-
-#pragma once
-
-#include <AK/Result.h>
-#include <AK/Vector.h>
-#include <LibELF/DynamicObject.h>
-
-namespace ELF {
-
-class DynamicLinker {
-public:
- static DynamicObject::SymbolLookupResult lookup_global_symbol(const char* symbol);
- [[noreturn]] static void linker_main(String&& main_program_name, int fd, bool is_secure, int argc, char** argv, char** envp);
-
-private:
- DynamicLinker() = delete;
- ~DynamicLinker() = delete;
-};
-
-}
diff --git a/Libraries/LibELF/DynamicLoader.cpp b/Libraries/LibELF/DynamicLoader.cpp
deleted file mode 100644
index e7c56a370c..0000000000
--- a/Libraries/LibELF/DynamicLoader.cpp
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Copyright (c) 2019-2020, Andrew Kaster <andrewdkaster@gmail.com>
- * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 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 HOLDER 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 <AK/StringBuilder.h>
-#include <LibELF/DynamicLoader.h>
-#include <LibELF/Validation.h>
-
-#include <assert.h>
-#include <dlfcn.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-
-#ifndef DYNAMIC_LOAD_DEBUG
-# define DYNAMIC_LOAD_DEBUG
-#endif
-
-// #define DYNAMIC_LOAD_VERBOSE
-
-#ifdef DYNAMIC_LOAD_VERBOSE
-# define VERBOSE(fmt, ...) dbgprintf(fmt, ##__VA_ARGS__)
-#else
-# define VERBOSE(fmt, ...) \
- do { \
- } while (0)
-#endif
-
-#ifndef __serenity__
-static void* mmap_with_name(void* addr, size_t length, int prot, int flags, int fd, off_t offset, const char*)
-{
- return mmap(addr, length, prot, flags, fd, offset);
-}
-#endif
-
-namespace ELF {
-
-static bool s_always_bind_now = false;
-
-NonnullRefPtr<DynamicLoader> DynamicLoader::construct(const char* filename, int fd, size_t size)
-{
- return adopt(*new DynamicLoader(filename, fd, size));
-}
-
-void* DynamicLoader::do_mmap(int fd, size_t size, const String& name)
-{
- if (size < sizeof(Elf32_Ehdr))
- return MAP_FAILED;
-
- String file_mmap_name = String::format("ELF_DYN: %s", name.characters());
- return mmap_with_name(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0, file_mmap_name.characters());
-}
-
-DynamicLoader::DynamicLoader(const char* filename, int fd, size_t size)
- : m_filename(filename)
- , m_file_size(size)
- , m_image_fd(fd)
- , m_file_mapping(do_mmap(m_image_fd, m_file_size, m_filename))
- , m_elf_image((u8*)m_file_mapping, m_file_size)
-{
-
- if (m_file_mapping == MAP_FAILED) {
- m_valid = false;
- return;
- }
-
- m_tls_size = calculate_tls_size();
-
- m_valid = validate();
-}
-
-RefPtr<DynamicObject> DynamicLoader::dynamic_object_from_image() const
-{
- VirtualAddress dynamic_section_address;
-
- m_elf_image.for_each_program_header([&dynamic_section_address](auto program_header) {
- if (program_header.type() == PT_DYNAMIC) {
- dynamic_section_address = VirtualAddress(program_header.raw_data());
- }
- return IterationDecision::Continue;
- });
- ASSERT(!dynamic_section_address.is_null());
-
- return ELF::DynamicObject::construct(VirtualAddress(m_elf_image.base_address()), dynamic_section_address);
-}
-
-size_t DynamicLoader::calculate_tls_size() const
-{
- size_t tls_size = 0;
- m_elf_image.for_each_program_header([&tls_size](auto program_header) {
- if (program_header.type() == PT_TLS) {
- tls_size = program_header.size_in_memory();
- }
- return IterationDecision::Continue;
- });
- return tls_size;
-}
-
-bool DynamicLoader::validate()
-{
- auto* elf_header = (Elf32_Ehdr*)m_file_mapping;
- return validate_elf_header(*elf_header, m_file_size) && validate_program_headers(*elf_header, m_file_size, (u8*)m_file_mapping, m_file_size, &m_program_interpreter);
-}
-
-DynamicLoader::~DynamicLoader()
-{
- if (MAP_FAILED != m_file_mapping)
- munmap(m_file_mapping, m_file_size);
- close(m_image_fd);
-}
-
-void* DynamicLoader::symbol_for_name(const char* name)
-{
- auto symbol = m_dynamic_object->hash_section().lookup_symbol(name);
-
- if (symbol.is_undefined())
- return nullptr;
-
- return m_dynamic_object->base_address().offset(symbol.value()).as_ptr();
-}
-
-RefPtr<DynamicObject> DynamicLoader::load_from_image(unsigned flags, size_t total_tls_size)
-{
-
- m_valid = m_elf_image.is_valid();
-
- if (!m_valid) {
- dbgprintf("DynamicLoader::load_from_image failed: image is invalid\n");
- return nullptr;
- }
-
-#ifdef DYNAMIC_LOAD_VERBOSE
- // m_image->dump();
-#endif
-
- load_program_headers();
-
- m_dynamic_object = DynamicObject::construct(m_text_segment_load_address, m_dynamic_section_address);
- m_dynamic_object->set_tls_offset(m_tls_offset);
- m_dynamic_object->set_tls_size(m_tls_size);
-
- auto rc = load_stage_2(flags, total_tls_size);
- if (!rc) {
- dbgprintf("DynamicLoader::load_from_image failed at load_stage_2\n");
- return nullptr;
- }
- return m_dynamic_object;
-}
-
-bool DynamicLoader::load_stage_2(unsigned flags, size_t total_tls_size)
-{
- ASSERT(flags & RTLD_GLOBAL);
-
-#ifdef DYNAMIC_LOAD_DEBUG
- m_dynamic_object->dump();
-#endif
-
- if (m_dynamic_object->has_text_relocations()) {
- ASSERT(m_text_segment_load_address.get() != 0);
-
-#ifndef AK_OS_MACOS
- // Remap this text region as private.
- if (mremap(m_text_segment_load_address.as_ptr(), m_text_segment_size, m_text_segment_size, MAP_PRIVATE) == MAP_FAILED) {
- perror("mremap .text: MAP_PRIVATE");
- return false;
- }
-#endif
-
- if (0 > mprotect(m_text_segment_load_address.as_ptr(), m_text_segment_size, PROT_READ | PROT_WRITE)) {
- perror("mprotect .text: PROT_READ | PROT_WRITE"); // FIXME: dlerror?
- return false;
- }
- }
- do_main_relocations(total_tls_size);
- return true;
-}
-
-void DynamicLoader::do_main_relocations(size_t total_tls_size)
-{
- auto do_single_relocation = [&](ELF::DynamicObject::Relocation relocation) {
- switch (do_relocation(total_tls_size, relocation)) {
- case RelocationResult::Failed:
- dbgln("Loader.so: {} unresolved symbol '{}'", m_filename, relocation.symbol().name());
- ASSERT_NOT_REACHED();
- break;
- case RelocationResult::ResolveLater:
- m_unresolved_relocations.append(relocation);
- break;
- case RelocationResult::Success:
- break;
- }
- return IterationDecision::Continue;
- };
- m_dynamic_object->relocation_section().for_each_relocation(do_single_relocation);
- m_dynamic_object->plt_relocation_section().for_each_relocation(do_single_relocation);
-}
-
-RefPtr<DynamicObject> DynamicLoader::load_stage_3(unsigned flags, size_t total_tls_size)
-{
-
- do_lazy_relocations(total_tls_size);
- if (flags & RTLD_LAZY) {
- setup_plt_trampoline();
- }
-
- // Clean up our setting of .text to PROT_READ | PROT_WRITE
- if (m_dynamic_object->has_text_relocations()) {
- if (0 > mprotect(m_text_segment_load_address.as_ptr(), m_text_segment_size, PROT_READ | PROT_EXEC)) {
- perror("mprotect .text: PROT_READ | PROT_EXEC"); // FIXME: dlerror?
- return nullptr;
- }
- }
-
- call_object_init_functions();
-
- VERBOSE("Loaded %s\n", m_filename.characters());
- return m_dynamic_object;
-}
-
-void DynamicLoader::do_lazy_relocations(size_t total_tls_size)
-{
- for (const auto& relocation : m_unresolved_relocations) {
- if (auto res = do_relocation(total_tls_size, relocation); res != RelocationResult::Success) {
- dbgln("Loader.so: {} unresolved symbol '{}'", m_filename, relocation.symbol().name());
- ASSERT_NOT_REACHED();
- }
- }
-}
-
-void DynamicLoader::load_program_headers()
-{
- Vector<ProgramHeaderRegion> program_headers;
-
- ProgramHeaderRegion* text_region_ptr = nullptr;
- ProgramHeaderRegion* data_region_ptr = nullptr;
- ProgramHeaderRegion* tls_region_ptr = nullptr;
- VirtualAddress dynamic_region_desired_vaddr;
-
- m_elf_image.for_each_program_header([&](const Image::ProgramHeader& program_header) {
- ProgramHeaderRegion new_region;
- new_region.set_program_header(program_header.raw_header());
- program_headers.append(move(new_region));
- auto& region = program_headers.last();
- if (region.is_tls_template())
- tls_region_ptr = &region;
- else if (region.is_load()) {
- if (region.is_executable())
- text_region_ptr = &region;
- else
- data_region_ptr = &region;
- } else if (region.is_dynamic()) {
- dynamic_region_desired_vaddr = region.desired_load_address();
- }
- return IterationDecision::Continue;
- });
-
- ASSERT(text_region_ptr && data_region_ptr);
-
- // Process regions in order: .text, .data, .tls
- auto* region = text_region_ptr;
- void* requested_load_address = m_elf_image.is_dynamic() ? nullptr : region->desired_load_address().as_ptr();
-
- ASSERT(!region->is_writable());
-
- void* text_segment_begin = mmap_with_name(
- requested_load_address,
- region->required_load_size(),
- region->mmap_prot(),
- MAP_SHARED,
- m_image_fd,
- region->offset(),
- String::format("%s: .text", m_filename.characters()).characters());
- if (MAP_FAILED == text_segment_begin) {
- ASSERT_NOT_REACHED();
- }
- ASSERT(requested_load_address == nullptr || requested_load_address == text_segment_begin);
- m_text_segment_size = region->required_load_size();
- m_text_segment_load_address = VirtualAddress { (FlatPtr)text_segment_begin };
-
- if (m_elf_image.is_dynamic())
- m_dynamic_section_address = dynamic_region_desired_vaddr.offset(m_text_segment_load_address.get());
- else
- m_dynamic_section_address = dynamic_region_desired_vaddr;
-
- region = data_region_ptr;
- void* data_segment_begin = mmap_with_name(
- (u8*)text_segment_begin + m_text_segment_size,
- region->required_load_size(),
- region->mmap_prot(),
- MAP_ANONYMOUS | MAP_PRIVATE,
- 0,
- 0,
- String::format("%s: .data", m_filename.characters()).characters());
- if (MAP_FAILED == data_segment_begin) {
- ASSERT_NOT_REACHED();
- }
- VirtualAddress data_segment_actual_addr;
- if (m_elf_image.is_dynamic()) {
- data_segment_actual_addr = region->desired_load_address().offset((FlatPtr)text_segment_begin);
- } else {
- data_segment_actual_addr = region->desired_load_address();
- }
- memcpy(data_segment_actual_addr.as_ptr(), (u8*)m_file_mapping + region->offset(), region->size_in_image());
- // FIXME: Initialize the values in the TLS section. Currently, it is zeroed.
-}
-
-DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_size, ELF::DynamicObject::Relocation relocation)
-{
- VERBOSE("Relocation symbol: %s, type: %d\n", relocation.symbol().name(), relocation.type());
- FlatPtr* patch_ptr = nullptr;
- if (is_dynamic())
- patch_ptr = (FlatPtr*)(m_dynamic_object->base_address().as_ptr() + relocation.offset());
- else
- patch_ptr = (FlatPtr*)(FlatPtr)relocation.offset();
-
- // VERBOSE("dynamic object name: %s\n", dynamic_object.object_name());
- VERBOSE("dynamic object base address: %p\n", m_dynamic_object->base_address());
- VERBOSE("relocation offset: 0x%x\n", relocation.offset());
- VERBOSE("patch_ptr: %p\n", patch_ptr);
- switch (relocation.type()) {
- case R_386_NONE:
- // Apparently most loaders will just skip these?
- // Seems if the 'link editor' generates one something is funky with your code
- VERBOSE("None relocation. No symbol, no nothing.\n");
- break;
- case R_386_32: {
- auto symbol = relocation.symbol();
- VERBOSE("Absolute relocation: name: '%s', value: %p\n", symbol.name(), symbol.value());
- auto res = lookup_symbol(symbol);
- if (!res.found) {
- if (symbol.bind() == STB_WEAK) {
- return RelocationResult::ResolveLater;
- }
- dbgln("ERROR: symbol not found: {}.", symbol.name());
- ASSERT_NOT_REACHED();
- }
- u32 symbol_address = res.address;
- *patch_ptr += symbol_address;
- VERBOSE(" Symbol address: %p\n", *patch_ptr);
- break;
- }
- case R_386_PC32: {
- auto symbol = relocation.symbol();
- VERBOSE("PC-relative relocation: '%s', value: %p\n", symbol.name(), symbol.value());
- auto res = lookup_symbol(symbol);
- ASSERT(res.found);
- u32 relative_offset = (res.address - (FlatPtr)(m_dynamic_object->base_address().as_ptr() + relocation.offset()));
- *patch_ptr += relative_offset;
- VERBOSE(" Symbol address: %p\n", *patch_ptr);
- break;
- }
- case R_386_GLOB_DAT: {
- auto symbol = relocation.symbol();
- VERBOSE("Global data relocation: '%s', value: %p\n", symbol.name(), symbol.value());
- auto res = lookup_symbol(symbol);
- if (!res.found) {
- // We do not support these
- // TODO: Can we tell gcc not to generate the piece of code that uses these?
- // (--disable-tm-clone-registry flag in gcc conifugraion?)
- if (!strcmp(symbol.name(), "__deregister_frame_info") || !strcmp(symbol.name(), "_ITM_registerTMCloneTable")
- || !strcmp(symbol.name(), "_ITM_deregisterTMCloneTable") || !strcmp(symbol.name(), "__register_frame_info")) {
- break;
- }
-
- if (symbol.bind() == STB_WEAK) {
- return RelocationResult::ResolveLater;
- }
-
- // Symbol not found
- return RelocationResult::Failed;
- }
- VERBOSE("was symbol found? %d, address: 0x%x\n", res.found, res.address);
- VERBOSE("object: %s\n", m_filename.characters());
-
- u32 symbol_location = res.address;
- ASSERT(symbol_location != (FlatPtr)m_dynamic_object->base_address().as_ptr());
- *patch_ptr = symbol_location;
- VERBOSE(" Symbol address: %p\n", *patch_ptr);
- break;
- }
- case R_386_RELATIVE: {
- // FIXME: According to the spec, R_386_relative ones must be done first.
- // We could explicitly do them first using m_number_of_relocatoins from DT_RELCOUNT
- // However, our compiler is nice enough to put them at the front of the relocations for us :)
- VERBOSE("Load address relocation at offset %X\n", relocation.offset());
- VERBOSE(" patch ptr == %p, adding load base address (%p) to it and storing %p\n", *patch_ptr, m_dynamic_object->base_address().as_ptr(), *patch_ptr + m_dynamic_object->base_address().as_ptr());
- *patch_ptr += (FlatPtr)m_dynamic_object->base_address().as_ptr(); // + addend for RelA (addend for Rel is stored at addr)
- break;
- }
- case R_386_TLS_TPOFF32:
- case R_386_TLS_TPOFF: {
- VERBOSE("Relocation type: R_386_TLS_TPOFF at offset %X\n", relocation.offset());
- auto symbol = relocation.symbol();
- // For some reason, LibC has a R_386_TLS_TPOFF that refers to the undefined symbol.. huh
- if (relocation.symbol_index() == 0)
- break;
- VERBOSE("Symbol index: %d\n", symbol.index());
- VERBOSE("Symbol is_undefined?: %d\n", symbol.is_undefined());
- VERBOSE("TLS relocation: '%s', value: %p\n", symbol.name(), symbol.value());
- auto res = lookup_symbol(symbol);
- if (!res.found)
- break;
- ASSERT(res.found);
- u32 symbol_value = res.value;
- VERBOSE("symbol value: %d\n", symbol_value);
- const auto dynamic_object_of_symbol = res.dynamic_object;
- ASSERT(dynamic_object_of_symbol);
- size_t offset_of_tls_end = dynamic_object_of_symbol->tls_offset().value() + dynamic_object_of_symbol->tls_size().value();
- // size_t offset_of_tls_end = tls_offset() + tls_size();
- VERBOSE("patch ptr: 0x%x\n", patch_ptr);
- VERBOSE("tls end offset: %d, total tls size: %d\n", offset_of_tls_end, total_tls_size);
- *patch_ptr = (offset_of_tls_end - total_tls_size - symbol_value - sizeof(Elf32_Addr));
- VERBOSE("*patch ptr: %d\n", (i32)*patch_ptr);
- break;
- }
- case R_386_JMP_SLOT: {
- // FIXME: Or BIND_NOW flag passed in?
- if (m_dynamic_object->must_bind_now() || s_always_bind_now) {
- // Eagerly BIND_NOW the PLT entries, doing all the symbol looking goodness
- // The patch method returns the address for the LAZY fixup path, but we don't need it here
- VERBOSE("patching plt reloaction: 0x%x\n", relocation.offset_in_section());
- [[maybe_unused]] auto rc = m_dynamic_object->patch_plt_entry(relocation.offset_in_section());
- } else {
- u8* relocation_address = relocation.address().as_ptr();
-
- if (m_elf_image.is_dynamic())
- *(u32*)relocation_address += (FlatPtr)m_dynamic_object->base_address().as_ptr();
- }
- break;
- }
- default:
- // Raise the alarm! Someone needs to implement this relocation type
- VERBOSE("Found a new exciting relocation type %d\n", relocation.type());
- // printf("DynamicLoader: Found unknown relocation type %d\n", relocation.type());
- ASSERT_NOT_REACHED();
- break;
- }
- return RelocationResult::Success;
-}
-
-// Defined in <arch>/plt_trampoline.S
-extern "C" void _plt_trampoline(void) __attribute__((visibility("hidden")));
-
-void DynamicLoader::setup_plt_trampoline()
-{
- ASSERT(m_dynamic_object);
- VirtualAddress got_address = m_dynamic_object->plt_got_base_address();
-
- FlatPtr* got_ptr = (FlatPtr*)got_address.as_ptr();
- got_ptr[1] = (FlatPtr)m_dynamic_object.ptr();
- got_ptr[2] = (FlatPtr)&_plt_trampoline;
-
- VERBOSE("Set GOT PLT entries at %p: [0] = %p [1] = %p, [2] = %p\n", got_ptr, (void*)got_ptr[0], (void*)got_ptr[1], (void*)got_ptr[2]);
-}
-
-// Called from our ASM routine _plt_trampoline.
-// Tell the compiler that it might be called from other places:
-extern "C" Elf32_Addr _fixup_plt_entry(DynamicObject* object, u32 relocation_offset);
-extern "C" Elf32_Addr _fixup_plt_entry(DynamicObject* object, u32 relocation_offset)
-{
- return object->patch_plt_entry(relocation_offset);
-}
-
-void DynamicLoader::call_object_init_functions()
-{
- typedef void (*InitFunc)();
-
- if (m_dynamic_object->has_init_section()) {
- auto init_function = (InitFunc)(m_dynamic_object->init_section().address().as_ptr());
-
- VERBOSE("Calling DT_INIT at %p\n", init_function);
- (init_function)();
- }
-
- if (m_dynamic_object->has_init_array_section()) {
- auto init_array_section = m_dynamic_object->init_array_section();
-
- InitFunc* init_begin = (InitFunc*)(init_array_section.address().as_ptr());
- InitFunc* init_end = init_begin + init_array_section.entry_count();
- while (init_begin != init_end) {
- // Android sources claim that these can be -1, to be ignored.
- // 0 definitely shows up. Apparently 0/-1 are valid? Confusing.
- if (!*init_begin || ((FlatPtr)*init_begin == (FlatPtr)-1))
- continue;
- VERBOSE("Calling DT_INITARRAY entry at %p\n", *init_begin);
- (*init_begin)();
- ++init_begin;
- }
- }
-}
-
-u32 DynamicLoader::ProgramHeaderRegion::mmap_prot() const
-{
- int prot = 0;
- prot |= is_executable() ? PROT_EXEC : 0;
- prot |= is_readable() ? PROT_READ : 0;
- prot |= is_writable() ? PROT_WRITE : 0;
- return prot;
-}
-
-DynamicObject::SymbolLookupResult DynamicLoader::lookup_symbol(const ELF::DynamicObject::Symbol& symbol) const
-{
- return m_dynamic_object->lookup_symbol(symbol);
-}
-
-} // end namespace ELF
diff --git a/Libraries/LibELF/DynamicLoader.h b/Libraries/LibELF/DynamicLoader.h
deleted file mode 100644
index 6c9f984296..0000000000
--- a/Libraries/LibELF/DynamicLoader.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2019-2020, Andrew Kaster <andrewdkaster@gmail.com>
- * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 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 HOLDER 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.
- */
-
-#pragma once
-
-#include <AK/Assertions.h>
-#include <AK/OwnPtr.h>
-#include <AK/RefCounted.h>
-#include <AK/String.h>
-#include <LibELF/DynamicObject.h>
-#include <LibELF/Image.h>
-#include <LibELF/exec_elf.h>
-#include <sys/mman.h>
-
-namespace ELF {
-
-#define ALIGN_ROUND_UP(x, align) ((((size_t)(x)) + align - 1) & (~(align - 1)))
-
-class DynamicLoader : public RefCounted<DynamicLoader> {
-public:
- static NonnullRefPtr<DynamicLoader> construct(const char* filename, int fd, size_t file_size);
-
- ~DynamicLoader();
-
- bool is_valid() const { return m_valid; }
-
- // Load a full ELF image from file into the current process and create an DynamicObject
- // from the SHT_DYNAMIC in the file.
- RefPtr<DynamicObject> load_from_image(unsigned flags, size_t total_tls_size);
-
- // Stage 2 of loading: dynamic object loading and primary relocations
- bool load_stage_2(unsigned flags, size_t total_tls_size);
-
- // Stage 3 of loading: lazy relocations and initializers
- RefPtr<DynamicObject> load_stage_3(unsigned flags, size_t total_tls_size);
- // Intended for use by dlsym or other internal methods
- void* symbol_for_name(const char*);
-
- void dump();
-
- // Requested program interpreter from program headers. May be empty string
- StringView program_interpreter() const { return m_program_interpreter; }
-
- VirtualAddress text_segment_load_addresss() const { return m_text_segment_load_address; }
-
- void set_tls_offset(size_t offset) { m_tls_offset = offset; };
- size_t tls_size() const { return m_tls_size; }
- size_t tls_offset() const { return m_tls_offset; }
- const ELF::Image& image() const { return m_elf_image; }
-
- template<typename F>
- void for_each_needed_library(F) const;
-
- VirtualAddress text_segment_load_address() const { return m_text_segment_load_address; }
- bool is_dynamic() const { return m_elf_image.is_dynamic(); }
-
-private:
- class ProgramHeaderRegion {
- public:
- void set_program_header(const Elf32_Phdr& header) { m_program_header = header; }
-
- // Information from ELF Program header
- u32 type() const { return m_program_header.p_type; }
- u32 flags() const { return m_program_header.p_flags; }
- u32 offset() const { return m_program_header.p_offset; }
- VirtualAddress desired_load_address() const { return VirtualAddress(m_program_header.p_vaddr); }
- u32 size_in_memory() const { return m_program_header.p_memsz; }
- u32 size_in_image() const { return m_program_header.p_filesz; }
- u32 alignment() const { return m_program_header.p_align; }
- u32 mmap_prot() const;
- bool is_readable() const { return flags() & PF_R; }
- bool is_writable() const { return flags() & PF_W; }
- bool is_executable() const { return flags() & PF_X; }
- bool is_tls_template() const { return type() == PT_TLS; }
- bool is_load() const { return type() == PT_LOAD; }
- bool is_dynamic() const { return type() == PT_DYNAMIC; }
-
- u32 required_load_size() { return ALIGN_ROUND_UP(m_program_header.p_memsz, m_program_header.p_align); }
-
- private:
- Elf32_Phdr m_program_header; // Explicitly a copy of the PHDR in the image
- };
-
- static void* do_mmap(int fd, size_t size, const String& name);
- RefPtr<DynamicObject> dynamic_object_from_image() const;
-
- explicit DynamicLoader(const char* filename, int fd, size_t file_size);
-
- // Stage 1
- void load_program_headers();
-
- // Stage 2
- void do_main_relocations(size_t total_tls_size);
-
- // Stage 3
- void do_lazy_relocations(size_t total_tls_size);
- void setup_plt_trampoline();
- void call_object_init_functions();
-
- bool validate();
-
- enum class RelocationResult : uint8_t {
- Failed = 0,
- Success = 1,
- ResolveLater = 2,
- };
- RelocationResult do_relocation(size_t total_tls_size, DynamicObject::Relocation relocation);
- size_t calculate_tls_size() const;
-
- DynamicObject::SymbolLookupResult lookup_symbol(const ELF::DynamicObject::Symbol& symbol) const;
-
- String m_filename;
- String m_program_interpreter;
- size_t m_file_size { 0 };
- int m_image_fd { -1 };
- void* m_file_mapping { MAP_FAILED };
- ELF::Image m_elf_image;
- bool m_valid { true };
-
- RefPtr<DynamicObject> m_dynamic_object;
-
- VirtualAddress m_text_segment_load_address;
- size_t m_text_segment_size { 0 };
-
- VirtualAddress m_tls_segment_address;
- VirtualAddress m_dynamic_section_address;
-
- size_t m_tls_offset { 0 };
- size_t m_tls_size { 0 };
-
- Vector<DynamicObject::Relocation> m_unresolved_relocations;
-};
-
-template<typename F>
-void DynamicLoader::for_each_needed_library(F func) const
-{
- dynamic_object_from_image()->for_each_needed_library(move(func));
-}
-
-} // end namespace ELF
diff --git a/Libraries/LibELF/DynamicObject.cpp b/Libraries/LibELF/DynamicObject.cpp
deleted file mode 100644
index 39b06beba2..0000000000
--- a/Libraries/LibELF/DynamicObject.cpp
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (c) 2019-2020, Andrew Kaster <andrewdkaster@gmail.com>
- * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 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 HOLDER 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 <AK/String.h>
-#include <AK/StringBuilder.h>
-#include <LibELF/DynamicLinker.h>
-#include <LibELF/DynamicObject.h>
-#include <LibELF/exec_elf.h>
-#include <stdio.h>
-#include <string.h>
-
-// #define DYNAMIC_OBJECT_VERBOSE
-
-#ifdef DYNAMIC_OBJECT_VERBOSE
-# define VERBOSE(fmt, ...) dbgprintf(fmt, ##__VA_ARGS__)
-#else
-# define VERBOSE(fmt, ...) \
- do { \
- } while (0)
-#endif
-
-namespace ELF {
-
-static const char* name_for_dtag(Elf32_Sword d_tag);
-
-DynamicObject::DynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_addresss)
- : m_base_address(base_address)
- , m_dynamic_address(dynamic_section_addresss)
-{
- Elf32_Ehdr* header = (Elf32_Ehdr*)base_address.as_ptr();
- Elf32_Phdr* pheader = (Elf32_Phdr*)(base_address.as_ptr() + header->e_phoff);
- m_elf_base_address = VirtualAddress(pheader->p_vaddr - pheader->p_offset);
- if (header->e_type == ET_DYN)
- m_is_elf_dynamic = true;
- else
- m_is_elf_dynamic = false;
-
- parse();
-}
-
-DynamicObject::~DynamicObject()
-{
-}
-
-void DynamicObject::dump() const
-{
- StringBuilder builder;
- builder.append("\nd_tag tag_name value\n");
- size_t num_dynamic_sections = 0;
-
- for_each_dynamic_entry([&](const DynamicObject::DynamicEntry& entry) {
- String name_field = String::format("(%s)", name_for_dtag(entry.tag()));
- builder.appendf("0x%08X %-17s0x%X\n", entry.tag(), name_field.characters(), entry.val());
- num_dynamic_sections++;
- return IterationDecision::Continue;
- });
-
- if (m_has_soname)
- builder.appendf("DT_SONAME: %s\n", soname()); // FIXME: Valdidate that this string is null terminated?
-
- VERBOSE("Dynamic section at address %p contains %zu entries:\n", m_dynamic_address.as_ptr(), num_dynamic_sections);
- VERBOSE("%s", builder.to_string().characters());
-}
-
-void DynamicObject::parse()
-{
- for_each_dynamic_entry([&](const DynamicEntry& entry) {
- switch (entry.tag()) {
- case DT_INIT:
- m_init_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_FINI:
- m_fini_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_INIT_ARRAY:
- m_init_array_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_INIT_ARRAYSZ:
- m_init_array_size = entry.val();
- break;
- case DT_FINI_ARRAY:
- m_fini_array_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_FINI_ARRAYSZ:
- m_fini_array_size = entry.val();
- break;
- case DT_HASH:
- // Use SYSV hash only if GNU hash is not available
- if (m_hash_type == HashType::SYSV) {
- m_hash_table_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- }
- break;
- case DT_GNU_HASH:
- m_hash_type = HashType::GNU;
- m_hash_table_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_SYMTAB:
- m_symbol_table_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_STRTAB:
- m_string_table_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_STRSZ:
- m_size_of_string_table = entry.val();
- break;
- case DT_SYMENT:
- m_size_of_symbol_table_entry = entry.val();
- break;
- case DT_PLTGOT:
- m_procedure_linkage_table_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_PLTRELSZ:
- m_size_of_plt_relocation_entry_list = entry.val();
- break;
- case DT_PLTREL:
- m_procedure_linkage_table_relocation_type = entry.val();
- ASSERT(m_procedure_linkage_table_relocation_type & (DT_REL | DT_RELA));
- break;
- case DT_JMPREL:
- m_plt_relocation_offset_location = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_RELA:
- case DT_REL:
- m_relocation_table_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
- break;
- case DT_RELASZ:
- case DT_RELSZ:
- m_size_of_relocation_table = entry.val();
- break;
- case DT_RELAENT:
- case DT_RELENT:
- m_size_of_relocation_entry = entry.val();
- break;
- case DT_RELACOUNT:
- case DT_RELCOUNT:
- m_number_of_relocations = entry.val();
- break;
- case DT_FLAGS:
- m_dt_flags = entry.val();
- break;
- case DT_TEXTREL:
- m_dt_flags |= DF_TEXTREL; // This tag seems to exist for legacy reasons only?
- break;
- case DT_SONAME:
- m_soname_index = entry.val();
- m_has_soname = true;
- break;
- case DT_DEBUG:
- break;
- case DT_FLAGS_1:
- break;
- case DT_NEEDED:
- // We handle these in for_each_needed_library
- break;
- default:
- dbgprintf("DynamicObject: DYNAMIC tag handling not implemented for DT_%s\n", name_for_dtag(entry.tag()));
- printf("DynamicObject: DYNAMIC tag handling not implemented for DT_%s\n", name_for_dtag(entry.tag()));
- ASSERT_NOT_REACHED(); // FIXME: Maybe just break out here and return false?
- break;
- }
- return IterationDecision::Continue;
- });
-
- if (!m_size_of_relocation_entry) {
- // TODO: FIXME, this shouldn't be hardcoded
- // The reason we need this here is that for some reason, when there only PLT relocations, the compiler
- // doesn't insert a 'PLTRELSZ' entry to the dynamic section
- m_size_of_relocation_entry = sizeof(Elf32_Rel);
- }
-
- auto hash_section_address = hash_section().address().as_ptr();
- // TODO: consider base address - it might not be zero
- auto num_hash_chains = ((u32*)hash_section_address)[1];
- m_symbol_count = num_hash_chains;
-}
-
-const DynamicObject::Relocation DynamicObject::RelocationSection::relocation(unsigned index) const
-{
- ASSERT(index < entry_count());
- unsigned offset_in_section = index * entry_size();
- auto relocation_address = (Elf32_Rel*)address().offset(offset_in_section).as_ptr();
- return Relocation(m_dynamic, *relocation_address, offset_in_section);
-}
-
-const DynamicObject::Relocation DynamicObject::RelocationSection::relocation_at_offset(unsigned offset) const
-{
- ASSERT(offset <= (m_section_size_bytes - m_entry_size));
- auto relocation_address = (Elf32_Rel*)address().offset(offset).as_ptr();
- return Relocation(m_dynamic, *relocation_address, offset);
-}
-
-const DynamicObject::Symbol DynamicObject::symbol(unsigned index) const
-{
- auto symbol_section = Section(*this, m_symbol_table_offset, (m_symbol_count * m_size_of_symbol_table_entry), m_size_of_symbol_table_entry, "DT_SYMTAB");
- auto symbol_entry = (Elf32_Sym*)symbol_section.address().offset(index * symbol_section.entry_size()).as_ptr();
- return Symbol(*this, index, *symbol_entry);
-}
-
-const DynamicObject::Section DynamicObject::init_section() const
-{
- return Section(*this, m_init_offset, sizeof(void (*)()), sizeof(void (*)()), "DT_INIT");
-}
-
-const DynamicObject::Section DynamicObject::fini_section() const
-{
- return Section(*this, m_fini_offset, sizeof(void (*)()), sizeof(void (*)()), "DT_FINI");
-}
-
-const DynamicObject::Section DynamicObject::init_array_section() const
-{
- return Section(*this, m_init_array_offset, m_init_array_size, sizeof(void (*)()), "DT_INIT_ARRAY");
-}
-
-const DynamicObject::Section DynamicObject::fini_array_section() const
-{
- return Section(*this, m_fini_array_offset, m_fini_array_size, sizeof(void (*)()), "DT_FINI_ARRAY");
-}
-
-const DynamicObject::HashSection DynamicObject::hash_section() const
-{
- const char* section_name = m_hash_type == HashType::SYSV ? "DT_HASH" : "DT_GNU_HASH";
- return HashSection(Section(*this, m_hash_table_offset, 0, 0, section_name), m_hash_type);
-}
-
-const DynamicObject::RelocationSection DynamicObject::relocation_section() const
-{
- return RelocationSection(Section(*this, m_relocation_table_offset, m_size_of_relocation_table, m_size_of_relocation_entry, "DT_REL"));
-}
-
-const DynamicObject::RelocationSection DynamicObject::plt_relocation_section() const
-{
- return RelocationSection(Section(*this, m_plt_relocation_offset_location, m_size_of_plt_relocation_entry_list, m_size_of_relocation_entry, "DT_JMPREL"));
-}
-
-u32 DynamicObject::HashSection::calculate_elf_hash(const char* name) const
-{
- // SYSV ELF hash algorithm
- // Note that the GNU HASH algorithm has less collisions
-
- uint32_t hash = 0;
-
- while (*name != '\0') {
- hash = hash << 4;
- hash += *name;
- name++;
-
- const uint32_t top_nibble_of_hash = hash & 0xF0000000U;
- hash ^= top_nibble_of_hash >> 24;
- hash &= ~top_nibble_of_hash;
- }
-
- return hash;
-}
-
-u32 DynamicObject::HashSection::calculate_gnu_hash(const char* name) const
-{
- // GNU ELF hash algorithm
- u32 hash = 5381;
-
- for (; *name != '\0'; ++name) {
- hash = hash * 33 + *name;
- }
-
- return hash;
-}
-
-const DynamicObject::Symbol DynamicObject::HashSection::lookup_symbol(const char* name) const
-{
- return (this->*(m_lookup_function))(name);
-}
-
-const DynamicObject::Symbol DynamicObject::HashSection::lookup_elf_symbol(const char* name) const
-{
- u32 hash_value = calculate_elf_hash(name);
-
- u32* hash_table_begin = (u32*)address().as_ptr();
-
- size_t num_buckets = hash_table_begin[0];
-
- // This is here for completeness, but, since we're using the fact that every chain
- // will end at chain 0 (which means 'not found'), we don't need to check num_chains.
- // Interestingly, num_chains is required to be num_symbols
-
- // size_t num_chains = hash_table_begin[1];
-
- u32* buckets = &hash_table_begin[2];
- u32* chains = &buckets[num_buckets];
-
- for (u32 i = buckets[hash_value % num_buckets]; i; i = chains[i]) {
- auto symbol = m_dynamic.symbol(i);
- if (strcmp(name, symbol.name()) == 0) {
- VERBOSE("Returning SYSV dynamic symbol with index %u for %s: %p\n", i, symbol.name(), symbol.address().as_ptr());
- return symbol;
- }
- }
- return Symbol::create_undefined(m_dynamic);
-}
-
-const DynamicObject::Symbol DynamicObject::HashSection::lookup_gnu_symbol(const char* name) const
-{
- // Algorithm reference: https://ent-voy.blogspot.com/2011/02/
- // TODO: Handle 64bit bloomwords for ELF_CLASS64
- using BloomWord = u32;
- constexpr size_t bloom_word_size = sizeof(BloomWord) * 8;
-
- const u32* hash_table_begin = (u32*)address().as_ptr();
-
- const size_t num_buckets = hash_table_begin[0];
- const size_t num_omitted_symbols = hash_table_begin[1];
- const u32 num_maskwords = hash_table_begin[2];
- // This works because num_maskwords is required to be a power of 2
- const u32 num_maskwords_bitmask = num_maskwords - 1;
- const u32 shift2 = hash_table_begin[3];
-
- const BloomWord* bloom_words = &hash_table_begin[4];
- const u32* const buckets = &bloom_words[num_maskwords];
- const u32* const chains = &buckets[num_buckets];
-
- BloomWord hash1 = calculate_gnu_hash(name);
- BloomWord hash2 = hash1 >> shift2;
- const BloomWord bitmask = (1 << (hash1 % bloom_word_size)) | (1 << (hash2 % bloom_word_size));
-
- if ((bloom_words[(hash1 / bloom_word_size) & num_maskwords_bitmask] & bitmask) != bitmask) {
- return Symbol::create_undefined(m_dynamic);
- }
-
- size_t current_sym = buckets[hash1 % num_buckets];
- if (current_sym == 0) {
- return Symbol::create_undefined(m_dynamic);
- }
- const u32* current_chain = &chains[current_sym - num_omitted_symbols];
-
- for (hash1 &= ~1;; ++current_sym) {
- hash2 = *(current_chain++);
- const auto symbol = m_dynamic.symbol(current_sym);
- if ((hash1 == (hash2 & ~1)) && strcmp(name, symbol.name()) == 0) {
- VERBOSE("Returning GNU dynamic symbol with index %zu for %s: %p\n", current_sym, symbol.name(), symbol.address().as_ptr());
- return symbol;
- }
- if (hash2 & 1) {
- break;
- }
- }
-
- return Symbol::create_undefined(m_dynamic);
-}
-
-const char* DynamicObject::symbol_string_table_string(Elf32_Word index) const
-{
- return (const char*)base_address().offset(m_string_table_offset + index).as_ptr();
-}
-
-DynamicObject::InitializationFunction DynamicObject::init_section_function() const
-{
- ASSERT(has_init_section());
- return (InitializationFunction)init_section().address().as_ptr();
-}
-
-static const char* name_for_dtag(Elf32_Sword d_tag)
-{
- switch (d_tag) {
- case DT_NULL:
- return "NULL"; /* marks end of _DYNAMIC array */
- case DT_NEEDED:
- return "NEEDED"; /* string table offset of needed lib */
- case DT_PLTRELSZ:
- return "PLTRELSZ"; /* size of relocation entries in PLT */
- case DT_PLTGOT:
- return "PLTGOT"; /* address PLT/GOT */
- case DT_HASH:
- return "HASH"; /* address of symbol hash table */
- case DT_STRTAB:
- return "STRTAB"; /* address of string table */
- case DT_SYMTAB:
- return "SYMTAB"; /* address of symbol table */
- case DT_RELA:
- return "RELA"; /* address of relocation table */
- case DT_RELASZ:
- return "RELASZ"; /* size of relocation table */
- case DT_RELAENT:
- return "RELAENT"; /* size of relocation entry */
- case DT_STRSZ:
- return "STRSZ"; /* size of string table */
- case DT_SYMENT:
- return "SYMENT"; /* size of symbol table entry */
- case DT_INIT:
- return "INIT"; /* address of initialization func. */
- case DT_FINI:
- return "FINI"; /* address of termination function */
- case DT_SONAME:
- return "SONAME"; /* string table offset of shared obj */
- case DT_RPATH:
- return "RPATH"; /* string table offset of library search path */
- case DT_SYMBOLIC:
- return "SYMBOLIC"; /* start sym search in shared obj. */
- case DT_REL:
- return "REL"; /* address of rel. tbl. w addends */
- case DT_RELSZ:
- return "RELSZ"; /* size of DT_REL relocation table */
- case DT_RELENT:
- return "RELENT"; /* size of DT_REL relocation entry */
- case DT_PLTREL:
- return "PLTREL"; /* PLT referenced relocation entry */
- case DT_DEBUG:
- return "DEBUG"; /* bugger */
- case DT_TEXTREL:
- return "TEXTREL"; /* Allow rel. mod. to unwritable seg */
- case DT_JMPREL:
- return "JMPREL"; /* add. of PLT's relocation entries */
- case DT_BIND_NOW:
- return "BIND_NOW"; /* Bind now regardless of env setting */
- case DT_INIT_ARRAY:
- return "INIT_ARRAY"; /* address of array of init func */
- case DT_FINI_ARRAY:
- return "FINI_ARRAY"; /* address of array of term func */
- case DT_INIT_ARRAYSZ:
- return "INIT_ARRAYSZ"; /* size of array of init func */
- case DT_FINI_ARRAYSZ:
- return "FINI_ARRAYSZ"; /* size of array of term func */
- case DT_RUNPATH:
- return "RUNPATH"; /* strtab offset of lib search path */
- case DT_FLAGS:
- return "FLAGS"; /* Set of DF_* flags */
- case DT_ENCODING:
- return "ENCODING"; /* further DT_* follow encoding rules */
- case DT_PREINIT_ARRAY:
- return "PREINIT_ARRAY"; /* address of array of preinit func */
- case DT_PREINIT_ARRAYSZ:
- return "PREINIT_ARRAYSZ"; /* size of array of preinit func */
- case DT_LOOS:
- return "LOOS"; /* reserved range for OS */
- case DT_HIOS:
- return "HIOS"; /* specific dynamic array tags */
- case DT_LOPROC:
- return "LOPROC"; /* reserved range for processor */
- case DT_HIPROC:
- return "HIPROC"; /* specific dynamic array tags */
- case DT_GNU_HASH:
- return "GNU_HASH"; /* address of GNU hash table */
- case DT_RELACOUNT:
- return "RELACOUNT"; /* if present, number of RELATIVE */
- case DT_RELCOUNT:
- return "RELCOUNT"; /* relocs, which must come first */
- case DT_FLAGS_1:
- return "FLAGS_1";
- default:
- return "??";
- }
-}
-
-DynamicObject::SymbolLookupResult DynamicObject::lookup_symbol(const char* name) const
-{
- auto res = hash_section().lookup_symbol(name);
- if (res.is_undefined())
- return {};
- return SymbolLookupResult { true, res.value(), (FlatPtr)res.address().as_ptr(), res.bind(), this };
-}
-
-NonnullRefPtr<DynamicObject> DynamicObject::construct(VirtualAddress base_address, VirtualAddress dynamic_section_address)
-{
- return adopt(*new DynamicObject(base_address, dynamic_section_address));
-}
-
-// offset is in PLT relocation table
-Elf32_Addr DynamicObject::patch_plt_entry(u32 relocation_offset)
-{
- auto relocation = plt_relocation_section().relocation_at_offset(relocation_offset);
-
- ASSERT(relocation.type() == R_386_JMP_SLOT);
-
- auto sym = relocation.symbol();
-
- u8* relocation_address = relocation.address().as_ptr();
- auto res = lookup_symbol(sym);
-
- if (!res.found) {
- dbgln("did not find symbol: {} ", sym.name());
- ASSERT_NOT_REACHED();
- }
-
- u32 symbol_location = res.address;
-
- VERBOSE("DynamicLoader: Jump slot relocation: putting %s (%p) into PLT at %p\n", sym.name(), (void*)symbol_location, (void*)relocation_address);
-
- *(u32*)relocation_address = symbol_location;
-
- return symbol_location;
-}
-
-DynamicObject::SymbolLookupResult DynamicObject::lookup_symbol(const ELF::DynamicObject::Symbol& symbol) const
-{
- VERBOSE("looking up symbol: %s\n", symbol.name());
- if (symbol.is_undefined() || symbol.bind() == STB_WEAK)
- return DynamicLinker::lookup_global_symbol(symbol.name());
-
- if (!symbol.is_undefined()) {
- VERBOSE("symbol is defined in its object\n");
- return { true, symbol.value(), (FlatPtr)symbol.address().as_ptr(), symbol.bind(), &symbol.object() };
- }
- return DynamicLinker::lookup_global_symbol(symbol.name());
-}
-
-} // end namespace ELF
diff --git a/Libraries/LibELF/DynamicObject.h b/Libraries/LibELF/DynamicObject.h
deleted file mode 100644
index 7b03c43c6d..0000000000
--- a/Libraries/LibELF/DynamicObject.h
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (c) 2019-2020, Andrew Kaster <andrewdkaster@gmail.com>
- * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 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 HOLDER 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.
- */
-
-#pragma once
-
-#include <AK/Assertions.h>
-#include <AK/RefCounted.h>
-#include <Kernel/VirtualAddress.h>
-#include <LibELF/exec_elf.h>
-
-namespace ELF {
-
-class DynamicObject : public RefCounted<DynamicObject> {
-public:
- static NonnullRefPtr<DynamicObject> construct(VirtualAddress base_address, VirtualAddress dynamic_section_address);
-
- ~DynamicObject();
- void dump() const;
-
- class DynamicEntry;
- class Section;
- class RelocationSection;
- class Symbol;
- class Relocation;
- class HashSection;
-
- class DynamicEntry {
- public:
- DynamicEntry(const Elf32_Dyn& dyn)
- : m_dyn(dyn)
- {
- }
-
- ~DynamicEntry() { }
-
- Elf32_Sword tag() const { return m_dyn.d_tag; }
- Elf32_Addr ptr() const { return m_dyn.d_un.d_ptr; }
- Elf32_Word val() const { return m_dyn.d_un.d_val; }
-
- private:
- const Elf32_Dyn& m_dyn;
- };
-
- class Symbol {
- public:
- Symbol(const DynamicObject& dynamic, unsigned index, const Elf32_Sym& sym)
- : m_dynamic(dynamic)
- , m_sym(sym)
- , m_index(index)
- {
- if (section_index() == 0)
- m_is_undefined = true;
- }
-
- Symbol(const Symbol& other)
- : m_dynamic(other.m_dynamic)
- , m_sym(other.m_sym)
- , m_index(other.m_index)
- , m_is_undefined(other.m_is_undefined)
- {
- }
-
- static Symbol create_undefined(const DynamicObject& dynamic)
- {
- auto s = Symbol(dynamic, 0, {});
- s.m_is_undefined = true;
- return s;
- }
-
- ~Symbol() { }
-
- const char* name() const { return m_dynamic.symbol_string_table_string(m_sym.st_name); }
- unsigned section_index() const { return m_sym.st_shndx; }
- unsigned value() const { return m_sym.st_value; }
- unsigned size() const { return m_sym.st_size; }
- unsigned index() const { return m_index; }
- unsigned type() const { return ELF32_ST_TYPE(m_sym.st_info); }
- unsigned bind() const { return ELF32_ST_BIND(m_sym.st_info); }
-
- bool is_undefined() const
- {
- return m_is_undefined;
- }
- VirtualAddress address() const
- {
- if (m_dynamic.elf_is_dynamic())
- return m_dynamic.base_address().offset(value());
- return VirtualAddress { value() };
- }
- const DynamicObject& object() const { return m_dynamic; }
-
- private:
- const DynamicObject& m_dynamic;
- const Elf32_Sym& m_sym;
- const unsigned m_index;
- bool m_is_undefined { false };
- };
-
- class Section {
- public:
- Section(const DynamicObject& dynamic, unsigned section_offset, unsigned section_size_bytes, unsigned entry_size, const char* name)
- : m_dynamic(dynamic)
- , m_section_offset(section_offset)
- , m_section_size_bytes(section_size_bytes)
- , m_entry_size(entry_size)
- , m_name(name)
- {
- }
- ~Section() { }
-
- const char* name() const { return m_name; }
- unsigned offset() const { return m_section_offset; }
- unsigned size() const { return m_section_size_bytes; }
- unsigned entry_size() const { return m_entry_size; }
- unsigned entry_count() const
- {
- return !entry_size() ? 0 : size() / entry_size();
- }
- VirtualAddress address() const
- {
- return m_dynamic.base_address().offset(m_section_offset);
- }
-
- protected:
- friend class RelocationSection;
- friend class HashSection;
- const DynamicObject& m_dynamic;
- unsigned m_section_offset;
- unsigned m_section_size_bytes;
- unsigned m_entry_size;
- const char* m_name { nullptr };
- };
-
- class RelocationSection : public Section {
- public:
- RelocationSection(const Section& section)
- : Section(section.m_dynamic, section.m_section_offset, section.m_section_size_bytes, section.m_entry_size, section.m_name)
- {
- }
- unsigned relocation_count() const { return entry_count(); }
- const Relocation relocation(unsigned index) const;
- const Relocation relocation_at_offset(unsigned offset) const;
- template<typename F>
- void for_each_relocation(F) const;
- };
-
- class Relocation {
- public:
- Relocation(const DynamicObject& dynamic, const Elf32_Rel& rel, unsigned offset_in_section)
- : m_dynamic(dynamic)
- , m_rel(rel)
- , m_offset_in_section(offset_in_section)
- {
- }
-
- ~Relocation() { }
-
- unsigned offset_in_section() const { return m_offset_in_section; }
- unsigned offset() const { return m_rel.r_offset; }
- unsigned type() const { return ELF32_R_TYPE(m_rel.r_info); }
- unsigned symbol_index() const { return ELF32_R_SYM(m_rel.r_info); }
- const Symbol symbol() const { return m_dynamic.symbol(symbol_index()); }
- VirtualAddress address() const
- {
- if (m_dynamic.elf_is_dynamic())
- return m_dynamic.base_address().offset(offset());
- return VirtualAddress { offset() };
- }
-
- private:
- const DynamicObject& m_dynamic;
- const Elf32_Rel& m_rel;
- const unsigned m_offset_in_section;
- };
-
- enum class HashType {
- SYSV,
- GNU
- };
-
- class HashSection : public Section {
- public:
- HashSection(const Section& section, HashType hash_type)
- : Section(section.m_dynamic, section.m_section_offset, section.m_section_size_bytes, section.m_entry_size, section.m_name)
- {
- switch (hash_type) {
- case HashType::SYSV:
- m_lookup_function = &HashSection::lookup_elf_symbol;
- break;
- case HashType::GNU:
- m_lookup_function = &HashSection::lookup_gnu_symbol;
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
- }
- }
-
- const Symbol lookup_symbol(const char*) const;
-
- private:
- u32 calculate_elf_hash(const char* name) const;
- u32 calculate_gnu_hash(const char* name) const;
-
- const DynamicObject::Symbol lookup_elf_symbol(const char* name) const;
- const DynamicObject::Symbol lookup_gnu_symbol(const char* name) const;
-
- typedef const DynamicObject::Symbol (HashSection::*LookupFunction)(const char*) const;
- LookupFunction m_lookup_function;
- };
-
- unsigned symbol_count() const { return m_symbol_count; }
-
- const Symbol symbol(unsigned) const;
-
- typedef void (*InitializationFunction)();
-
- bool has_init_section() const { return m_init_offset != 0; }
- bool has_init_array_section() const { return m_init_array_offset != 0; }
- const Section init_section() const;
- InitializationFunction init_section_function() const;
- const Section fini_section() const;
- const Section init_array_section() const;
- const Section fini_array_section() const;
-
- const HashSection hash_section() const;
-
- const RelocationSection relocation_section() const;
- const RelocationSection plt_relocation_section() const;
-
- bool should_process_origin() const { return m_dt_flags & DF_ORIGIN; }
- bool requires_symbolic_symbol_resolution() const { return m_dt_flags & DF_SYMBOLIC; }
- // Text relocations meaning: we need to edit the .text section which is normally mapped PROT_READ
- bool has_text_relocations() const { return m_dt_flags & DF_TEXTREL; }
- bool must_bind_now() const { return m_dt_flags & DF_BIND_NOW; }
- bool has_static_thread_local_storage() const { return m_dt_flags & DF_STATIC_TLS; }
-
- VirtualAddress plt_got_base_address() const { return m_base_address.offset(m_procedure_linkage_table_offset); }
- VirtualAddress base_address() const { return m_base_address; }
-
- const char* soname() const { return m_has_soname ? symbol_string_table_string(m_soname_index) : nullptr; }
-
- Optional<FlatPtr> tls_offset() const { return m_tls_offset; }
- Optional<FlatPtr> tls_size() const { return m_tls_size; }
- void set_tls_offset(FlatPtr offset) { m_tls_offset = offset; }
- void set_tls_size(FlatPtr size) { m_tls_size = size; }
-
- template<typename F>
- void for_each_needed_library(F) const;
-
- template<typename F>
- void for_each_initialization_array_function(F f) const;
-
- struct SymbolLookupResult {
- bool found { false };
- FlatPtr value { 0 };
- FlatPtr address { 0 };
- unsigned bind { STB_LOCAL };
- const ELF::DynamicObject* dynamic_object { nullptr }; // The object in which the symbol is defined
- };
- SymbolLookupResult lookup_symbol(const char* name) const;
-
- // Will be called from _fixup_plt_entry, as part of the PLT trampoline
- Elf32_Addr patch_plt_entry(u32 relocation_offset);
-
- SymbolLookupResult lookup_symbol(const ELF::DynamicObject::Symbol& symbol) const;
- using SymbolLookupFunction = DynamicObject::SymbolLookupResult (*)(const char*);
- SymbolLookupFunction m_global_symbol_lookup_func { nullptr };
-
- bool elf_is_dynamic() const { return m_is_elf_dynamic; }
-
-private:
- explicit DynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_address);
-
- const char* symbol_string_table_string(Elf32_Word) const;
- void parse();
-
- template<typename F>
- void for_each_symbol(F) const;
-
- template<typename F>
- void for_each_dynamic_entry(F) const;
-
- VirtualAddress m_base_address;
- VirtualAddress m_dynamic_address;
- VirtualAddress m_elf_base_address;
-
- unsigned m_symbol_count { 0 };
-
- // Begin Section information collected from DT_* entries
- FlatPtr m_init_offset { 0 };
- FlatPtr m_fini_offset { 0 };
-
- FlatPtr m_init_array_offset { 0 };
- size_t m_init_array_size { 0 };
- FlatPtr m_fini_array_offset { 0 };
- size_t m_fini_array_size { 0 };
-
- FlatPtr m_hash_table_offset { 0 };
- HashType m_hash_type { HashType::SYSV };
-
- FlatPtr m_string_table_offset { 0 };
- size_t m_size_of_string_table { 0 };
- FlatPtr m_symbol_table_offset { 0 };
- size_t m_size_of_symbol_table_entry { 0 };
-
- Elf32_Sword m_procedure_linkage_table_relocation_type { -1 };
- FlatPtr m_plt_relocation_offset_location { 0 }; // offset of PLT relocations, at end of relocations
- size_t m_size_of_plt_relocation_entry_list { 0 };
- FlatPtr m_procedure_linkage_table_offset { 0 };
-
- // NOTE: We'll only ever either RELA or REL entries, not both (thank god)
- // NOTE: The x86 ABI will only ever genrerate REL entries.
- size_t m_number_of_relocations { 0 };
- size_t m_size_of_relocation_entry { 0 };
- size_t m_size_of_relocation_table { 0 };
- FlatPtr m_relocation_table_offset { 0 };
- bool m_is_elf_dynamic { false };
-
- // DT_FLAGS
- Elf32_Word m_dt_flags { 0 };
-
- bool m_has_soname { false };
- Elf32_Word m_soname_index { 0 }; // Index into dynstr table for SONAME
-
- Optional<FlatPtr> m_tls_offset;
- Optional<FlatPtr> m_tls_size;
- // End Section information from DT_* entries
-};
-
-template<typename F>
-inline void DynamicObject::RelocationSection::for_each_relocation(F func) const
-{
- for (unsigned i = 0; i < relocation_count(); ++i) {
- const auto reloc = relocation(i);
- if (reloc.type() == 0)
- continue;
- if (func(reloc) == IterationDecision::Break)
- break;
- }
-}
-
-template<typename F>
-inline void DynamicObject::for_each_symbol(F func) const
-{
- for (unsigned i = 0; i < symbol_count(); ++i) {
- if (func(symbol(i)) == IterationDecision::Break)
- break;
- }
-}
-
-template<typename F>
-inline void DynamicObject::for_each_dynamic_entry(F func) const
-{
- auto* dyns = reinterpret_cast<const Elf32_Dyn*>(m_dynamic_address.as_ptr());
- for (unsigned i = 0;; ++i) {
- auto&& dyn = DynamicEntry(dyns[i]);
- if (dyn.tag() == DT_NULL)
- break;
- if (func(dyn) == IterationDecision::Break)
- break;
- }
-}
-template<typename F>
-inline void DynamicObject::for_each_needed_library(F func) const
-{
- for_each_dynamic_entry([func, this](auto entry) {
- if (entry.tag() != DT_NEEDED)
- return IterationDecision::Continue;
- Elf32_Word offset = entry.val();
- const char* name = (const char*)(m_base_address.offset(m_string_table_offset).offset(offset)).as_ptr();
- if (func(StringView(name)) == IterationDecision::Break)
- return IterationDecision::Break;
- return IterationDecision::Continue;
- });
-}
-
-template<typename F>
-void DynamicObject::for_each_initialization_array_function(F f) const
-{
- if (!has_init_array_section())
- return;
- FlatPtr init_array = (FlatPtr)init_array_section().address().as_ptr();
- for (size_t i = 0; i < (m_init_array_size / sizeof(void*)); ++i) {
- InitializationFunction current = ((InitializationFunction*)(init_array))[i];
- f(current);
- }
-}
-
-} // end namespace ELF
diff --git a/Libraries/LibELF/Image.cpp b/Libraries/LibELF/Image.cpp
deleted file mode 100644
index 27bf519353..0000000000
--- a/Libraries/LibELF/Image.cpp
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <AK/Demangle.h>
-#include <AK/Memory.h>
-#include <AK/QuickSort.h>
-#include <AK/StringBuilder.h>
-#include <AK/StringView.h>
-#include <LibELF/Image.h>
-#include <LibELF/Validation.h>
-
-//#define ELF_IMAGE_DEBUG
-
-namespace ELF {
-
-Image::Image(ReadonlyBytes bytes, bool verbose_logging)
- : m_buffer(bytes.data())
- , m_size(bytes.size())
- , m_verbose_logging(verbose_logging)
-{
- parse();
-}
-
-Image::Image(const u8* buffer, size_t size, bool verbose_logging)
- : Image(ReadonlyBytes { buffer, size }, verbose_logging)
-{
-}
-
-Image::~Image()
-{
-}
-
-#ifdef ELF_IMAGE_DEBUG
-static const char* object_file_type_to_string(Elf32_Half type)
-{
- switch (type) {
- case ET_NONE:
- return "None";
- case ET_REL:
- return "Relocatable";
- case ET_EXEC:
- return "Executable";
- case ET_DYN:
- return "Shared object";
- case ET_CORE:
- return "Core";
- default:
- return "(?)";
- }
-}
-#endif
-
-StringView Image::section_index_to_string(unsigned index) const
-{
- ASSERT(m_valid);
- if (index == SHN_UNDEF)
- return "Undefined";
- if (index >= SHN_LORESERVE)
- return "Reserved";
- return section(index).name();
-}
-
-unsigned Image::symbol_count() const
-{
- ASSERT(m_valid);
- if (!section_count())
- return 0;
- return section(m_symbol_table_section_index).entry_count();
-}
-
-void Image::dump() const
-{
-#ifdef ELF_IMAGE_DEBUG
- dbgln("ELF::Image({:p}) {{", this);
- dbgln(" is_valid: {}", is_valid());
-
- if (!is_valid()) {
- dbgln("}}");
- return;
- }
-
- dbgln(" type: {}", object_file_type_to_string(header().e_type));
- dbgln(" machine: {}", header().e_machine);
- dbgln(" entry: {:x}", header().e_entry);
- dbgln(" shoff: {}", header().e_shoff);
- dbgln(" shnum: {}", header().e_shnum);
- dbgln(" phoff: {}", header().e_phoff);
- dbgln(" phnum: {}", header().e_phnum);
- dbgln(" shstrndx: {}", header().e_shstrndx);
-
- for_each_program_header([&](const ProgramHeader& program_header) {
- dbgln(" Program Header {}: {{", program_header.index());
- dbgln(" type: {:x}", program_header.type());
- dbgln(" offset: {:x}", program_header.offset());
- dbgln(" flags: {:x}", program_header.flags());
- dbgln(" }}");
- return IterationDecision::Continue;
- });
-
- for (unsigned i = 0; i < header().e_shnum; ++i) {
- auto& section = this->section(i);
- dbgln(" Section {}: {{", i);
- dbgln(" name: {}", section.name());
- dbgln(" type: {:x}", section.type());
- dbgln(" offset: {:x}", section.offset());
- dbgln(" size: {}", section.size());
- dbgln(" ");
- dbgln(" }}");
- }
-
- dbgln("Symbol count: {} (table is {})", symbol_count(), m_symbol_table_section_index);
- for (unsigned i = 1; i < symbol_count(); ++i) {
- auto& sym = symbol(i);
- dbgln("Symbol @{}:", i);
- dbgln(" Name: {}", sym.name());
- dbgln(" In section: {}", section_index_to_string(sym.section_index()));
- dbgln(" Value: {}", sym.value());
- dbgln(" Size: {}", sym.size());
- }
-
- dbgln("}}");
-#endif
-}
-
-unsigned Image::section_count() const
-{
- ASSERT(m_valid);
- return header().e_shnum;
-}
-
-unsigned Image::program_header_count() const
-{
- ASSERT(m_valid);
- return header().e_phnum;
-}
-
-bool Image::parse()
-{
- if (m_size < sizeof(Elf32_Ehdr) || !validate_elf_header(header(), m_size, m_verbose_logging)) {
- if (m_verbose_logging)
- dbgln("ELF::Image::parse(): ELF Header not valid");
- return m_valid = false;
- }
-
- if (!validate_program_headers(header(), m_size, m_buffer, m_size, nullptr, m_verbose_logging)) {
- if (m_verbose_logging)
- dbgln("ELF::Image::parse(): ELF Program Headers not valid");
- return m_valid = false;
- }
-
- m_valid = true;
-
- // First locate the string tables.
- for (unsigned i = 0; i < section_count(); ++i) {
- auto& sh = section_header(i);
- if (sh.sh_type == SHT_SYMTAB) {
- if (m_symbol_table_section_index && m_symbol_table_section_index != i)
- return m_valid = false;
- m_symbol_table_section_index = i;
- }
- if (sh.sh_type == SHT_STRTAB && i != header().e_shstrndx) {
- if (section_header_table_string(sh.sh_name) == ELF_STRTAB)
- m_string_table_section_index = i;
- }
- }
-
- // Then create a name-to-index map.
- for (unsigned i = 0; i < section_count(); ++i) {
- auto& section = this->section(i);
- m_sections.set(section.name(), move(i));
- }
-
- return m_valid;
-}
-
-StringView Image::table_string(unsigned table_index, unsigned offset) const
-{
- ASSERT(m_valid);
- auto& sh = section_header(table_index);
- if (sh.sh_type != SHT_STRTAB)
- return nullptr;
- size_t computed_offset = sh.sh_offset + offset;
- if (computed_offset >= m_size) {
- if (m_verbose_logging)
- dbgln("SHENANIGANS! Image::table_string() computed offset outside image.");
- return {};
- }
- size_t max_length = m_size - computed_offset;
- size_t length = strnlen(raw_data(sh.sh_offset + offset), max_length);
- return { raw_data(sh.sh_offset + offset), length };
-}
-
-StringView Image::section_header_table_string(unsigned offset) const
-{
- ASSERT(m_valid);
- return table_string(header().e_shstrndx, offset);
-}
-
-StringView Image::table_string(unsigned offset) const
-{
- ASSERT(m_valid);
- return table_string(m_string_table_section_index, offset);
-}
-
-const char* Image::raw_data(unsigned offset) const
-{
- ASSERT(offset < m_size); // Callers must check indices into raw_data()'s result are also in bounds.
- return reinterpret_cast<const char*>(m_buffer) + offset;
-}
-
-const Elf32_Ehdr& Image::header() const
-{
- ASSERT(m_size >= sizeof(Elf32_Ehdr));
- return *reinterpret_cast<const Elf32_Ehdr*>(raw_data(0));
-}
-
-const Elf32_Phdr& Image::program_header_internal(unsigned index) const
-{
- ASSERT(m_valid);
- ASSERT(index < header().e_phnum);
- return *reinterpret_cast<const Elf32_Phdr*>(raw_data(header().e_phoff + (index * sizeof(Elf32_Phdr))));
-}
-
-const Elf32_Shdr& Image::section_header(unsigned index) const
-{
- ASSERT(m_valid);
- ASSERT(index < header().e_shnum);
- return *reinterpret_cast<const Elf32_Shdr*>(raw_data(header().e_shoff + (index * header().e_shentsize)));
-}
-
-const Image::Symbol Image::symbol(unsigned index) const
-{
- ASSERT(m_valid);
- ASSERT(index < symbol_count());
- auto* raw_syms = reinterpret_cast<const Elf32_Sym*>(raw_data(section(m_symbol_table_section_index).offset()));
- return Symbol(*this, index, raw_syms[index]);
-}
-
-const Image::Section Image::section(unsigned index) const
-{
- ASSERT(m_valid);
- ASSERT(index < section_count());
- return Section(*this, index);
-}
-
-const Image::ProgramHeader Image::program_header(unsigned index) const
-{
- ASSERT(m_valid);
- ASSERT(index < program_header_count());
- return ProgramHeader(*this, index);
-}
-
-FlatPtr Image::program_header_table_offset() const
-{
- return header().e_phoff;
-}
-
-const Image::Relocation Image::RelocationSection::relocation(unsigned index) const
-{
- ASSERT(index < relocation_count());
- auto* rels = reinterpret_cast<const Elf32_Rel*>(m_image.raw_data(offset()));
- return Relocation(m_image, rels[index]);
-}
-
-const Image::RelocationSection Image::Section::relocations() const
-{
- StringBuilder builder;
- builder.append(".rel");
- builder.append(name());
-
- auto relocation_section = m_image.lookup_section(builder.to_string());
- if (relocation_section.type() != SHT_REL)
- return static_cast<const RelocationSection>(m_image.section(0));
-
-#ifdef ELF_IMAGE_DEBUG
- dbgln("Found relocations for {} in {}", name(), relocation_section.name());
-#endif
- return static_cast<const RelocationSection>(relocation_section);
-}
-
-const Image::Section Image::lookup_section(const String& name) const
-{
- ASSERT(m_valid);
- if (auto it = m_sections.find(name); it != m_sections.end())
- return section((*it).value);
- return section(0);
-}
-
-StringView Image::Symbol::raw_data() const
-{
- auto& section = this->section();
- return { section.raw_data() + (value() - section.address()), size() };
-}
-
-Optional<Image::Symbol> Image::find_demangled_function(const String& name) const
-{
- Optional<Image::Symbol> found;
- for_each_symbol([&](const Image::Symbol symbol) {
- if (symbol.type() != STT_FUNC)
- return IterationDecision::Continue;
- if (symbol.is_undefined())
- return IterationDecision::Continue;
- auto demangled = demangle(symbol.name());
- auto index_of_paren = demangled.index_of("(");
- if (index_of_paren.has_value()) {
- demangled = demangled.substring(0, index_of_paren.value());
- }
- if (demangled != name)
- return IterationDecision::Continue;
- found = symbol;
- return IterationDecision::Break;
- });
- return found;
-}
-
-Optional<Image::Symbol> Image::find_symbol(u32 address, u32* out_offset) const
-{
- auto symbol_count = this->symbol_count();
- if (!symbol_count)
- return {};
-
- SortedSymbol* sorted_symbols = nullptr;
- if (m_sorted_symbols.is_empty()) {
- m_sorted_symbols.ensure_capacity(symbol_count);
- for_each_symbol([this](auto& symbol) {
- m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, symbol });
- return IterationDecision::Continue;
- });
- quick_sort(m_sorted_symbols, [](auto& a, auto& b) {
- return a.address < b.address;
- });
- }
- sorted_symbols = m_sorted_symbols.data();
-
- for (size_t i = 0; i < symbol_count; ++i) {
- if (sorted_symbols[i].address > address) {
- if (i == 0)
- return {};
- auto& symbol = sorted_symbols[i - 1];
- if (out_offset)
- *out_offset = address - symbol.address;
- return symbol.symbol;
- }
- }
- return {};
-}
-
-String Image::symbolicate(u32 address, u32* out_offset) const
-{
- auto symbol_count = this->symbol_count();
- if (!symbol_count) {
- if (out_offset)
- *out_offset = 0;
- return "??";
- }
- SortedSymbol* sorted_symbols = nullptr;
-
- if (m_sorted_symbols.is_empty()) {
- m_sorted_symbols.ensure_capacity(symbol_count);
- for_each_symbol([this](auto& symbol) {
- m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, symbol });
- return IterationDecision::Continue;
- });
- quick_sort(m_sorted_symbols, [](auto& a, auto& b) {
- return a.address < b.address;
- });
- }
- sorted_symbols = m_sorted_symbols.data();
-
- for (size_t i = 0; i < symbol_count; ++i) {
- if (sorted_symbols[i].address > address) {
- if (i == 0) {
- if (out_offset)
- *out_offset = 0;
- return "!!";
- }
- auto& symbol = sorted_symbols[i - 1];
-
- auto& demangled_name = symbol.demangled_name;
- if (demangled_name.is_null()) {
- demangled_name = demangle(symbol.name);
- }
-
- if (out_offset) {
- *out_offset = address - symbol.address;
- return demangled_name;
- }
- return String::format("%s +0x%x", demangled_name.characters(), address - symbol.address);
- }
- }
- if (out_offset)
- *out_offset = 0;
- return "??";
-}
-
-} // end namespace ELF
diff --git a/Libraries/LibELF/Image.h b/Libraries/LibELF/Image.h
deleted file mode 100644
index 3250cf4deb..0000000000
--- a/Libraries/LibELF/Image.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
- */
-
-#pragma once
-
-#include <AK/ByteBuffer.h>
-#include <AK/HashMap.h>
-#include <AK/OwnPtr.h>
-#include <AK/String.h>
-#include <Kernel/VirtualAddress.h>
-#include <LibELF/exec_elf.h>
-
-namespace ELF {
-
-class Image {
-public:
- explicit Image(ReadonlyBytes, bool verbose_logging = true);
- explicit Image(const u8*, size_t, bool verbose_logging = true);
-
- ~Image();
- void dump() const;
- bool is_valid() const { return m_valid; }
- bool parse();
-
- bool is_within_image(const void* address, size_t size) const
- {
- if (address < m_buffer)
- return false;
- if (((const u8*)address + size) > m_buffer + m_size)
- return false;
- return true;
- }
-
- class Section;
- class RelocationSection;
- class Symbol;
- class Relocation;
-
- class Symbol {
- public:
- Symbol(const Image& image, unsigned index, const Elf32_Sym& sym)
- : m_image(image)
- , m_sym(sym)
- , m_index(index)
- {
- }
-
- ~Symbol() { }
-
- StringView name() const { return m_image.table_string(m_sym.st_name); }
- unsigned section_index() const { return m_sym.st_shndx; }
- unsigned value() const { return m_sym.st_value; }
- unsigned size() const { return m_sym.st_size; }
- unsigned index() const { return m_index; }
- unsigned type() const { return ELF32_ST_TYPE(m_sym.st_info); }
- unsigned bind() const { return ELF32_ST_BIND(m_sym.st_info); }
- const Section section() const { return m_image.section(section_index()); }
- bool is_undefined() const { return section_index() == 0; }
- StringView raw_data() const;
-
- private:
- const Image& m_image;
- const Elf32_Sym& m_sym;
- const unsigned m_index;
- };
-
- class ProgramHeader {
- public:
- ProgramHeader(const Image& image, unsigned program_header_index)
- : m_image(image)
- , m_program_header(image.program_header_internal(program_header_index))
- , m_program_header_index(program_header_index)
- {
- }
- ~ProgramHeader() { }
-
- unsigned index() const { return m_program_header_index; }
- u32 type() const { return m_program_header.p_type; }
- u32 flags() const { return m_program_header.p_flags; }
- u32 offset() const { return m_program_header.p_offset; }
- VirtualAddress vaddr() const { return VirtualAddress(m_program_header.p_vaddr); }
- u32 size_in_memory() const { return m_program_header.p_memsz; }
- u32 size_in_image() const { return m_program_header.p_filesz; }
- u32 alignment() const { return m_program_header.p_align; }
- bool is_readable() const { return flags() & PF_R; }
- bool is_writable() const { return flags() & PF_W; }
- bool is_executable() const { return flags() & PF_X; }
- const char* raw_data() const { return m_image.raw_data(m_program_header.p_offset); }
- Elf32_Phdr raw_header() const { return m_program_header; }
-
- private:
- const Image& m_image;
- const Elf32_Phdr& m_program_header;
- unsigned m_program_header_index { 0 };
- };
-
- class Section {
- public:
- Section(const Image& image, unsigned sectionIndex)
- : m_image(image)
- , m_section_header(image.section_header(sectionIndex))
- , m_section_index(sectionIndex)
- {
- }
- ~Section() { }
-
- StringView name() const { return m_image.section_header_table_string(m_section_header.sh_name); }
- unsigned type() const { return m_section_header.sh_type; }
- unsigned offset() const { return m_section_header.sh_offset; }
- unsigned size() const { return m_section_header.sh_size; }
- unsigned entry_size() const { return m_section_header.sh_entsize; }
- unsigned entry_count() const { return !entry_size() ? 0 : size() / entry_size(); }
- u32 address() const { return m_section_header.sh_addr; }
- const char* raw_data() const { return m_image.raw_data(m_section_header.sh_offset); }
- ReadonlyBytes bytes() const { return { raw_data(), size() }; }
- bool is_undefined() const { return m_section_index == SHN_UNDEF; }
- const RelocationSection relocations() const;
- u32 flags() const { return m_section_header.sh_flags; }
- bool is_writable() const { return flags() & SHF_WRITE; }
- bool is_executable() const { return flags() & PF_X; }
-
- protected:
- friend class RelocationSection;
- const Image& m_image;
- const Elf32_Shdr& m_section_header;
- unsigned m_section_index;
- };
-
- class RelocationSection : public Section {
- public:
- RelocationSection(const Section& section)
- : Section(section.m_image, section.m_section_index)
- {
- }
- unsigned relocation_count() const { return entry_count(); }
- const Relocation relocation(unsigned index) const;
- template<typename F>
- void for_each_relocation(F) const;
- };
-
- class Relocation {
- public:
- Relocation(const Image& image, const Elf32_Rel& rel)
- : m_image(image)
- , m_rel(rel)
- {
- }
-
- ~Relocation() { }
-
- unsigned offset() const { return m_rel.r_offset; }
- unsigned type() const { return ELF32_R_TYPE(m_rel.r_info); }
- unsigned symbol_index() const { return ELF32_R_SYM(m_rel.r_info); }
- const Symbol symbol() const { return m_image.symbol(symbol_index()); }
-
- private:
- const Image& m_image;
- const Elf32_Rel& m_rel;
- };
-
- unsigned symbol_count() const;
- unsigned section_count() const;
- unsigned program_header_count() const;
-
- const Symbol symbol(unsigned) const;
- const Section section(unsigned) const;
- const ProgramHeader program_header(unsigned const) const;
- FlatPtr program_header_table_offset() const;
-
- template<typename F>
- void for_each_section(F) const;
- template<typename F>
- void for_each_section_of_type(unsigned, F) const;
- template<typename F>
- void for_each_symbol(F) const;
- template<typename F>
- void for_each_program_header(F) const;
-
- // NOTE: Returns section(0) if section with name is not found.
- // FIXME: I don't love this API.
- const Section lookup_section(const String& name) const;
-
- bool is_executable() const { return header().e_type == ET_EXEC; }
- bool is_relocatable() const { return header().e_type == ET_REL; }
- bool is_dynamic() const { return header().e_type == ET_DYN; }
-
- VirtualAddress entry() const { return VirtualAddress(header().e_entry); }
- FlatPtr base_address() const { return (FlatPtr)m_buffer; }
- size_t size() const { return m_size; }
-
- Optional<Symbol> find_demangled_function(const String& name) const;
-
- bool has_symbols() const { return symbol_count(); }
- String symbolicate(u32 address, u32* offset = nullptr) const;
- Optional<Image::Symbol> find_symbol(u32 address, u32* offset = nullptr) const;
-
-private:
- const char* raw_data(unsigned offset) const;
- const Elf32_Ehdr& header() const;
- const Elf32_Shdr& section_header(unsigned) const;
- const Elf32_Phdr& program_header_internal(unsigned) const;
- StringView table_string(unsigned offset) const;
- StringView section_header_table_string(unsigned offset) const;
- StringView section_index_to_string(unsigned index) const;
- StringView table_string(unsigned table_index, unsigned offset) const;
-
- const u8* m_buffer { nullptr };
- size_t m_size { 0 };
- bool m_verbose_logging { true };
- HashMap<String, unsigned> m_sections;
- bool m_valid { false };
- unsigned m_symbol_table_section_index { 0 };
- unsigned m_string_table_section_index { 0 };
-
- struct SortedSymbol {
- u32 address;
- StringView name;
- String demangled_name;
- Optional<Image::Symbol> symbol;
- };
-
- mutable Vector<SortedSymbol> m_sorted_symbols;
-};
-
-template<typename F>
-inline void Image::for_each_section(F func) const
-{
- auto section_count = this->section_count();
- for (unsigned i = 0; i < section_count; ++i)
- func(section(i));
-}
-
-template<typename F>
-inline void Image::for_each_section_of_type(unsigned type, F func) const
-{
- auto section_count = this->section_count();
- for (unsigned i = 0; i < section_count; ++i) {
- auto& section = this->section(i);
- if (section.type() == type) {
- if (func(section) == IterationDecision::Break)
- break;
- }
- }
-}
-
-template<typename F>
-inline void Image::RelocationSection::for_each_relocation(F func) const
-{
- auto relocation_count = this->relocation_count();
- for (unsigned i = 0; i < relocation_count; ++i) {
- if (func(relocation(i)) == IterationDecision::Break)
- break;
- }
-}
-
-template<typename F>
-inline void Image::for_each_symbol(F func) const
-{
- auto symbol_count = this->symbol_count();
- for (unsigned i = 0; i < symbol_count; ++i) {
- if (func(symbol(i)) == IterationDecision::Break)
- break;
- }
-}
-
-template<typename F>
-inline void Image::for_each_program_header(F func) const
-{
- auto program_header_count = this->program_header_count();
- for (unsigned i = 0; i < program_header_count; ++i) {
- if (func(program_header(i)) == IterationDecision::Break)
- return;
- }
-}
-
-} // end namespace ELF
diff --git a/Libraries/LibELF/Validation.cpp b/Libraries/LibELF/Validation.cpp
deleted file mode 100644
index 1700a48b1e..0000000000
--- a/Libraries/LibELF/Validation.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (c) 2020, Andrew Kaster <andrewdkaster@gmail.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 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 HOLDER 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 <AK/Assertions.h>
-#include <AK/String.h>
-#include <LibELF/Validation.h>
-#include <LibELF/exec_elf.h>
-
-namespace ELF {
-
-bool validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size, bool verbose)
-{
- if (!IS_ELF(elf_header)) {
- if (verbose)
- dbgln("File is not an ELF file.");
- return false;
- }
-
- if (ELFCLASS32 != elf_header.e_ident[EI_CLASS]) {
- if (verbose)
- dbgln("File is not a 32 bit ELF file.");
- return false;
- }
-
- if (ELFDATA2LSB != elf_header.e_ident[EI_DATA]) {
- if (verbose)
- dbgln("File is not a little endian ELF file.");
- return false;
- }
-
- if (EV_CURRENT != elf_header.e_ident[EI_VERSION]) {
- if (verbose)
- dbgln("File has unrecognized ELF version ({}), expected ({})!", elf_header.e_ident[EI_VERSION], EV_CURRENT);
- return false;
- }
-
- if (ELFOSABI_SYSV != elf_header.e_ident[EI_OSABI]) {
- if (verbose)
- dbgln("File has unknown OS ABI ({}), expected SYSV(0)!", elf_header.e_ident[EI_OSABI]);
- return false;
- }
-
- if (0 != elf_header.e_ident[EI_ABIVERSION]) {
- if (verbose)
- dbgln("File has unknown SYSV ABI version ({})!", elf_header.e_ident[EI_ABIVERSION]);
- return false;
- }
-
- if (EM_386 != elf_header.e_machine) {
- if (verbose)
- dbgln("File has unknown machine ({}), expected i386 (3)!", elf_header.e_machine);
- return false;
- }
-
- if (ET_EXEC != elf_header.e_type && ET_DYN != elf_header.e_type && ET_REL != elf_header.e_type && ET_CORE != elf_header.e_type) {
- if (verbose)
- dbgln("File has unloadable ELF type ({}), expected REL (1), EXEC (2), DYN (3) or CORE(4)!", elf_header.e_type);
- return false;
- }
-
- if (EV_CURRENT != elf_header.e_version) {
- if (verbose)
- dbgln("File has unrecognized ELF version ({}), expected ({})!", elf_header.e_version, EV_CURRENT);
- return false;
- }
-
- if (sizeof(Elf32_Ehdr) != elf_header.e_ehsize) {
- if (verbose)
- dbgln("File has incorrect ELF header size..? ({}), expected ({})!", elf_header.e_ehsize, sizeof(Elf32_Ehdr));
- return false;
- }
-
- if (elf_header.e_phoff < elf_header.e_ehsize || (elf_header.e_shnum != SHN_UNDEF && elf_header.e_shoff < elf_header.e_ehsize)) {
- if (verbose) {
- dbgln("SHENANIGANS! program header offset ({}) or section header offset ({}) overlap with ELF header!",
- elf_header.e_phoff, elf_header.e_shoff);
- }
- return false;
- }
-
- if (elf_header.e_phoff > file_size || elf_header.e_shoff > file_size) {
- if (verbose) {
- dbgln("SHENANIGANS! program header offset ({}) or section header offset ({}) are past the end of the file!",
- elf_header.e_phoff, elf_header.e_shoff);
- }
- return false;
- }
-
- if (elf_header.e_phnum == 0 && elf_header.e_phoff != 0) {
- if (verbose)
- dbgln("SHENANIGANS! File has no program headers, but it does have a program header offset ({})!", elf_header.e_phoff);
- return false;
- }
-
- if (elf_header.e_phnum != 0 && elf_header.e_phoff != elf_header.e_ehsize) {
- if (verbose) {
- dbgln("File does not have program headers directly after the ELF header? program header offset ({}), expected ({}).",
- elf_header.e_phoff, elf_header.e_ehsize);
- }
- return false;
- }
-
- if (0 != elf_header.e_flags) {
- if (verbose)
- dbgln("File has incorrect ELF header flags...? ({}), expected ({}).", elf_header.e_flags, 0);
- return false;
- }
-
- if (0 != elf_header.e_phnum && sizeof(Elf32_Phdr) != elf_header.e_phentsize) {
- if (verbose)
- dbgln("File has incorrect program header size..? ({}), expected ({}).", elf_header.e_phentsize, sizeof(Elf32_Phdr));
- return false;
- }
-
- if (sizeof(Elf32_Shdr) != elf_header.e_shentsize) {
- if (verbose)
- dbgln("File has incorrect section header size..? ({}), expected ({}).", elf_header.e_shentsize, sizeof(Elf32_Shdr));
- return false;
- }
-
- size_t end_of_last_program_header = elf_header.e_phoff + (elf_header.e_phnum * elf_header.e_phentsize);
- if (end_of_last_program_header > file_size) {
- if (verbose)
- dbgln("SHENANIGANS! End of last program header ({}) is past the end of the file!", end_of_last_program_header);
- return false;
- }
-
- if (elf_header.e_shoff != SHN_UNDEF && elf_header.e_shoff < end_of_last_program_header) {
- if (verbose) {
- dbgln("SHENANIGANS! Section header table begins at file offset {}, which is within program headers [ {} - {} ]!",
- elf_header.e_shoff, elf_header.e_phoff, end_of_last_program_header);
- }
- return false;
- }
-
- size_t end_of_last_section_header = elf_header.e_shoff + (elf_header.e_shnum * elf_header.e_shentsize);
- if (end_of_last_section_header > file_size) {
- if (verbose)
- dbgln("SHENANIGANS! End of last section header ({}) is past the end of the file!", end_of_last_section_header);
- return false;
- }
-
- if (elf_header.e_shstrndx != SHN_UNDEF && elf_header.e_shstrndx >= elf_header.e_shnum) {
- if (verbose)
- dbgln("SHENANIGANS! Section header string table index ({}) is not a valid index given we have {} section headers!", elf_header.e_shstrndx, elf_header.e_shnum);
- return false;
- }
-
- return true;
-}
-
-bool validate_program_headers(const Elf32_Ehdr& elf_header, size_t file_size, const u8* buffer, size_t buffer_size, String* interpreter_path, bool verbose)
-{
- // Can we actually parse all the program headers in the given buffer?
- size_t end_of_last_program_header = elf_header.e_phoff + (elf_header.e_phnum * elf_header.e_phentsize);
- if (end_of_last_program_header > buffer_size) {
- if (verbose)
- dbgln("Unable to parse program headers from buffer, buffer too small! Buffer size: {}, End of program headers {}",
- buffer_size, end_of_last_program_header);
- return false;
- }
-
- if (file_size < buffer_size) {
- dbgln("We somehow read more from a file than was in the file in the first place!");
- ASSERT_NOT_REACHED();
- }
-
- size_t num_program_headers = elf_header.e_phnum;
- auto program_header_begin = (const Elf32_Phdr*)&(buffer[elf_header.e_phoff]);
-
- for (size_t header_index = 0; header_index < num_program_headers; ++header_index) {
- auto& program_header = program_header_begin[header_index];
-
- if (program_header.p_filesz > program_header.p_memsz) {
- if (verbose)
- dbgln("Program header ({}) has p_filesz ({}) larger than p_memsz ({})", header_index, program_header.p_filesz, program_header.p_memsz);
- return false;
- }
-
- if (program_header.p_memsz <= 0 && (program_header.p_type == PT_TLS || program_header.p_type == PT_LOAD)) {
- if (verbose)
- dbgln("Program header ({}) has invalid size in memory ({})", header_index, program_header.p_memsz);
- return false;
- }
-
- if (program_header.p_type == PT_LOAD && program_header.p_align != PAGE_SIZE) {
- if (elf_header.e_type != ET_CORE) {
- if (verbose)
- dbgln("Program header ({}) with p_type PT_LOAD has p_align ({}) not equal to page size ({})", header_index, program_header.p_align, PAGE_SIZE);
- return false;
- }
- }
-
- switch (program_header.p_type) {
- case PT_INTERP:
- // We checked above that file_size was >= buffer size. We only care about buffer size anyway, we're trying to read this!
- if (program_header.p_offset + program_header.p_filesz > buffer_size) {
- if (verbose)
- dbgln("Found PT_INTERP header ({}), but the .interp section was not within the buffer :(", header_index);
- return false;
- }
- if (interpreter_path)
- *interpreter_path = String((const char*)&buffer[program_header.p_offset], program_header.p_filesz - 1);
- break;
- case PT_LOAD:
- case PT_DYNAMIC:
- case PT_NOTE:
- case PT_PHDR:
- case PT_TLS:
- if (program_header.p_offset + program_header.p_filesz > file_size) {
- if (verbose)
- dbgln("SHENANIGANS! Program header {} segment leaks beyond end of file!", header_index);
- return false;
- }
- if ((program_header.p_flags & PF_X) && (program_header.p_flags & PF_W)) {
- if (verbose)
- dbgln("SHENANIGANS! Program header {} segment is marked write and execute", header_index);
- return false;
- }
- break;
- case PT_GNU_STACK:
- if (program_header.p_flags & PF_X) {
- if (verbose)
- dbgln("Possible shenanigans! Validating an ELF with executable stack.");
- }
- break;
- case PT_GNU_RELRO:
- if ((program_header.p_flags & PF_X) && (program_header.p_flags & PF_W)) {
- if (verbose)
- dbgln("SHENANIGANS! Program header {} segment is marked write and execute", header_index);
- return false;
- }
- break;
- default:
- // Not handling other program header types in other code so... let's not surprise them
- if (verbose)
- dbgln("Found program header ({}) of unrecognized type {}!", header_index, program_header.p_type);
- return false;
- }
- }
- return true;
-}
-
-} // end namespace ELF
diff --git a/Libraries/LibELF/Validation.h b/Libraries/LibELF/Validation.h
deleted file mode 100644
index fe49c80b82..0000000000
--- a/Libraries/LibELF/Validation.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2020, Andrew Kaster <andrewdkaster@gmail.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 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 HOLDER 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.
- */
-
-#pragma once
-
-#include <LibELF/exec_elf.h>
-
-namespace ELF {
-
-bool validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size, bool verbose = true);
-bool validate_program_headers(const Elf32_Ehdr& elf_header, size_t file_size, const u8* buffer, size_t buffer_size, String* interpreter_path, bool verbose = true);
-
-} // end namespace ELF
diff --git a/Libraries/LibELF/exec_elf.h b/Libraries/LibELF/exec_elf.h
deleted file mode 100644
index 45a0e9401f..0000000000
--- a/Libraries/LibELF/exec_elf.h
+++ /dev/null
@@ -1,792 +0,0 @@
-/* $OpenBSD: exec_elf.h,v 1.83 2019/01/22 23:23:18 jsg Exp $ */
-/*
- * Copyright (c) 1995, 1996 Erik Theisen. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This is the ELF ABI header file
- * formerly known as "elf_abi.h".
- */
-
-#ifndef _SYS_EXEC_ELF_H_
-#define _SYS_EXEC_ELF_H_
-
-#include <AK/Types.h>
-
-typedef uint8_t Elf_Byte;
-
-typedef uint32_t Elf32_Addr; /* Unsigned program address */
-typedef uint32_t Elf32_Off; /* Unsigned file offset */
-typedef int32_t Elf32_Sword; /* Signed large integer */
-typedef uint32_t Elf32_Word; /* Unsigned large integer */
-typedef uint16_t Elf32_Half; /* Unsigned medium integer */
-typedef uint64_t Elf32_Lword;
-
-typedef uint64_t Elf64_Addr;
-typedef uint64_t Elf64_Off;
-typedef int32_t Elf64_Shalf;
-
-#ifdef __alpha__
-typedef int64_t Elf64_Sword;
-typedef uint64_t Elf64_Word;
-#else
-typedef int32_t Elf64_Sword;
-typedef uint32_t Elf64_Word;
-#endif
-
-typedef int64_t Elf64_Sxword;
-typedef uint64_t Elf64_Xword;
-typedef uint64_t Elf64_Lword;
-
-typedef uint32_t Elf64_Half;
-typedef uint16_t Elf64_Quarter;
-
-/*
- * e_ident[] identification indexes
- * See http://www.sco.com/developers/gabi/latest/ch4.eheader.html
- */
-#define EI_MAG0 0 /* file ID */
-#define EI_MAG1 1 /* file ID */
-#define EI_MAG2 2 /* file ID */
-#define EI_MAG3 3 /* file ID */
-#define EI_CLASS 4 /* file class */
-#define EI_DATA 5 /* data encoding */
-#define EI_VERSION 6 /* ELF header version */
-#define EI_OSABI 7 /* OS/ABI ID */
-#define EI_ABIVERSION 8 /* ABI version */
-#define EI_PAD 9 /* start of pad bytes */
-#define EI_NIDENT 16 /* Gfx::Size of e_ident[] */
-
-/* e_ident[] magic number */
-#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
-#define ELFMAG1 'E' /* e_ident[EI_MAG1] */
-#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
-#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
-#define ELFMAG "\177ELF" /* magic */
-#define SELFMAG 4 /* size of magic */
-
-/* e_ident[] file class */
-#define ELFCLASSNONE 0 /* invalid */
-#define ELFCLASS32 1 /* 32-bit objs */
-#define ELFCLASS64 2 /* 64-bit objs */
-#define ELFCLASSNUM 3 /* number of classes */
-
-/* e_ident[] data encoding */
-#define ELFDATANONE 0 /* invalid */
-#define ELFDATA2LSB 1 /* Little-Endian */
-#define ELFDATA2MSB 2 /* Big-Endian */
-#define ELFDATANUM 3 /* number of data encode defines */
-
-/* e_ident[] Operating System/ABI */
-#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 common IA32 ABI */
-#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_ARM 97 /* ARM */
-#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
-
-/* e_ident */
-#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && (ehdr).e_ident[EI_MAG1] == ELFMAG1 && (ehdr).e_ident[EI_MAG2] == ELFMAG2 && (ehdr).e_ident[EI_MAG3] == ELFMAG3)
-
-/* ELF Header */
-typedef struct elfhdr {
- unsigned char e_ident[EI_NIDENT]; /* ELF Identification */
- Elf32_Half e_type; /* object file type */
- Elf32_Half e_machine; /* machine */
- Elf32_Word e_version; /* object file version */
- Elf32_Addr e_entry; /* virtual entry point */
- Elf32_Off e_phoff; /* program header table offset */
- Elf32_Off e_shoff; /* section header table offset */
- Elf32_Word e_flags; /* processor-specific flags */
- Elf32_Half e_ehsize; /* ELF header size */
- Elf32_Half e_phentsize; /* program header entry size */
- Elf32_Half e_phnum; /* number of program header entries */
- Elf32_Half e_shentsize; /* section header entry size */
- Elf32_Half e_shnum; /* number of section header entries */
- Elf32_Half e_shstrndx; /* section header table's "section
- header string table" entry offset */
-} Elf32_Ehdr;
-
-typedef struct {
- unsigned char e_ident[EI_NIDENT]; /* Id bytes */
- Elf64_Quarter e_type; /* file type */
- Elf64_Quarter e_machine; /* machine type */
- Elf64_Half 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_Half e_flags; /* Processor flags */
- Elf64_Quarter e_ehsize; /* sizeof ehdr */
- Elf64_Quarter e_phentsize; /* Program header entry size */
- Elf64_Quarter e_phnum; /* Number of program headers */
- Elf64_Quarter e_shentsize; /* Section header entry size */
- Elf64_Quarter e_shnum; /* Number of section headers */
- Elf64_Quarter e_shstrndx; /* String table index */
-} Elf64_Ehdr;
-
-/* 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 /* number of types */
-#define ET_LOPROC 0xff00 /* reserved range for processor */
-#define ET_HIPROC 0xffff /* specific e_type */
-
-/* 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 - unused? */
-#define EM_860 7 /* Intel 80860 */
-#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */
-/*
- * Don't know if EM_MIPS_RS4_BE,
- * EM_SPARC64, EM_PARISC,
- * or EM_PPC are ABI compliant
- */
-#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
-#define EM_SPARC64 11 /* SPARC v9 64-bit unofficial */
-#define EM_PARISC 15 /* HPPA */
-#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
-#define EM_PPC 20 /* PowerPC */
-#define EM_PPC64 21 /* PowerPC 64 */
-#define EM_ARM 40 /* Advanced RISC Machines ARM */
-#define EM_ALPHA 41 /* DEC ALPHA */
-#define EM_SH 42 /* Hitachi/Renesas Super-H */
-#define EM_SPARCV9 43 /* SPARC version 9 */
-#define EM_IA_64 50 /* Intel IA-64 Processor */
-#define EM_AMD64 62 /* AMD64 architecture */
-#define EM_X86_64 EM_AMD64
-#define EM_VAX 75 /* DEC VAX */
-#define EM_AARCH64 183 /* ARM 64-bit architecture (AArch64) */
-
-/* Non-standard */
-#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */
-#define EM__LAST__ (EM_ALPHA_EXP + 1)
-
-#define EM_NUM 22 /* number of machine types */
-
-/* Version */
-#define EV_NONE 0 /* Invalid */
-#define EV_CURRENT 1 /* Current */
-#define EV_NUM 2 /* number of versions */
-
-/* Magic for e_phnum: get real value from sh_info of first section header */
-#define PN_XNUM 0xffff
-
-/* Section Header */
-typedef struct {
- Elf32_Word sh_name; /* name - index into section header
- string table section */
- Elf32_Word sh_type; /* type */
- Elf32_Word sh_flags; /* flags */
- Elf32_Addr sh_addr; /* address */
- Elf32_Off sh_offset; /* file offset */
- Elf32_Word sh_size; /* section size */
- Elf32_Word sh_link; /* section header table index link */
- Elf32_Word sh_info; /* extra information */
- Elf32_Word sh_addralign; /* address alignment */
- Elf32_Word sh_entsize; /* section entry size */
-} Elf32_Shdr;
-
-typedef struct {
- Elf64_Half sh_name; /* section name */
- Elf64_Half 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_Half sh_link; /* link to another */
- Elf64_Half sh_info; /* misc info */
- Elf64_Xword sh_addralign; /* memory alignment */
- Elf64_Xword sh_entsize; /* table entry size */
-} Elf64_Shdr;
-
-/* Special Section Indexes */
-#define SHN_UNDEF 0 /* undefined */
-#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */
-#define SHN_LOPROC 0xff00 /* reserved range for processor */
-#define SHN_HIPROC 0xff1f /* specific section indexes */
-#define SHN_ABS 0xfff1 /* absolute value */
-#define SHN_COMMON 0xfff2 /* common symbol */
-#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */
-#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */
-
-/* sh_type */
-#define SHT_NULL 0 /* inactive */
-#define SHT_PROGBITS 1 /* program defined information */
-#define SHT_SYMTAB 2 /* symbol table section */
-#define SHT_STRTAB 3 /* string table section */
-#define SHT_RELA 4 /* relocation section with addends*/
-#define SHT_HASH 5 /* symbol hash table section */
-#define SHT_DYNAMIC 6 /* dynamic section */
-#define SHT_NOTE 7 /* note section */
-#define SHT_NOBITS 8 /* no space section */
-#define SHT_REL 9 /* relation section without addends */
-#define SHT_SHLIB 10 /* reserved - purpose unknown */
-#define SHT_DYNSYM 11 /* dynamic symbol table section */
-#define SHT_NUM 12 /* number of section types */
-#define SHT_INIT_ARRAY 14 /* pointers to init functions */
-#define SHT_FINI_ARRAY 15 /* pointers to termination functions */
-#define SHT_PREINIT_ARRAY 16 /* ptrs to funcs called before init */
-#define SHT_GROUP 17 /* defines a section group */
-#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */
-#define SHT_LOOS 0x60000000 /* reserved range for OS specific */
-#define SHT_SUNW_dof 0x6ffffff4 /* used by dtrace */
-#define SHT_GNU_LIBLIST 0x6ffffff7 /* libraries to be prelinked */
-#define SHT_SUNW_move 0x6ffffffa /* inf for partially init'ed symbols */
-#define SHT_SUNW_syminfo 0x6ffffffc /* ad symbol information */
-#define SHT_SUNW_verdef 0x6ffffffd /* symbol versioning inf */
-#define SHT_SUNW_verneed 0x6ffffffe /* symbol versioning req */
-#define SHT_SUNW_versym 0x6fffffff /* symbol versioning table */
-#define SHT_HIOS 0x6fffffff /* section header types */
-#define SHT_LOPROC 0x70000000 /* reserved range for processor */
-#define SHT_HIPROC 0x7fffffff /* specific section header types */
-#define SHT_LOUSER 0x80000000 /* reserved range for application */
-#define SHT_HIUSER 0xffffffff /* specific indexes */
-
-#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table section */
-
-/* Section names */
-#define ELF_BSS ".bss" /* uninitialized data */
-#define ELF_DATA ".data" /* initialized data */
-#define ELF_CTF ".SUNW_ctf" /* CTF data */
-#define ELF_DEBUG ".debug" /* debug */
-#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */
-#define ELF_DYNSTR ".dynstr" /* dynamic string table */
-#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */
-#define ELF_FINI ".fini" /* termination code */
-#define ELF_GOT ".got" /* global offset table */
-#define ELF_HASH ".hash" /* symbol hash table */
-#define ELF_INIT ".init" /* initialization code */
-#define ELF_REL_DATA ".rel.data" /* relocation data */
-#define ELF_REL_FINI ".rel.fini" /* relocation termination code */
-#define ELF_REL_INIT ".rel.init" /* relocation initialization code */
-#define ELF_REL_DYN ".rel.dyn" /* relocation dynamic link info */
-#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */
-#define ELF_REL_TEXT ".rel.text" /* relocation code */
-#define ELF_RODATA ".rodata" /* read-only data */
-#define ELF_SHSTRTAB ".shstrtab" /* section header string table */
-#define ELF_STRTAB ".strtab" /* string table */
-#define ELF_SYMTAB ".symtab" /* symbol table */
-#define ELF_TEXT ".text" /* code */
-#define ELF_OPENBSDRANDOMDATA ".openbsd.randomdata" /* constant randomdata */
-
-/* Section Attribute Flags - sh_flags */
-#define SHF_WRITE 0x1 /* Writable */
-#define SHF_ALLOC 0x2 /* occupies memory */
-#define SHF_EXECINSTR 0x4 /* executable */
-#define SHF_MERGE 0x10 /* may be merged */
-#define SHF_STRINGS 0x20 /* contains strings */
-#define SHF_INFO_LINK 0x40 /* sh_info holds section index */
-#define SHF_LINK_ORDER 0x80 /* ordering requirements */
-#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required */
-#define SHF_GROUP 0x200 /* member of section group */
-#define SHF_TLS 0x400 /* thread local storage */
-#define SHF_COMPRESSED 0x800 /* contains compressed data */
-#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics */
-#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */
- /* specific section attributes */
-
-/* Symbol Table Entry */
-typedef struct elf32_sym {
- Elf32_Word st_name; /* name - index into string table */
- Elf32_Addr st_value; /* symbol value */
- Elf32_Word st_size; /* symbol size */
- unsigned char st_info; /* type and binding */
- unsigned char st_other; /* 0 - no defined meaning */
- Elf32_Half st_shndx; /* section header index */
-} Elf32_Sym;
-
-typedef struct {
- Elf64_Half st_name; /* Symbol name index in str table */
- Elf_Byte st_info; /* type / binding attrs */
- Elf_Byte st_other; /* unused */
- Elf64_Quarter st_shndx; /* section index of symbol */
- Elf64_Xword st_value; /* value of symbol */
- Elf64_Xword st_size; /* size of symbol */
-} Elf64_Sym;
-
-/* Symbol table index */
-#define STN_UNDEF 0 /* undefined */
-
-/* Extract symbol info - st_info */
-#define ELF32_ST_BIND(x) ((x) >> 4)
-#define ELF32_ST_TYPE(x) (((unsigned int)x) & 0xf)
-#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
-
-#define ELF64_ST_BIND(x) ((x) >> 4)
-#define ELF64_ST_TYPE(x) (((unsigned int)x) & 0xf)
-#define ELF64_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
-
-/* Symbol Binding - ELF32_ST_BIND - st_info */
-#define STB_LOCAL 0 /* Local symbol */
-#define STB_GLOBAL 1 /* Global symbol */
-#define STB_WEAK 2 /* like global - lower precedence */
-#define STB_NUM 3 /* number of symbol bindings */
-#define STB_LOPROC 13 /* reserved range for processor */
-#define STB_HIPROC 15 /* specific symbol bindings */
-
-/* Symbol type - ELF32_ST_TYPE - st_info */
-#define STT_NOTYPE 0 /* not specified */
-#define STT_OBJECT 1 /* data object */
-#define STT_FUNC 2 /* function */
-#define STT_SECTION 3 /* section */
-#define STT_FILE 4 /* file */
-#define STT_TLS 6 /* thread local storage */
-#define STT_LOPROC 13 /* reserved range for processor */
-#define STT_HIPROC 15 /* specific symbol types */
-
-/* Extract symbol visibility - st_other */
-#define ELF_ST_VISIBILITY(v) ((v)&0x3)
-#define ELF32_ST_VISIBILITY ELF_ST_VISIBILITY
-#define ELF64_ST_VISIBILITY ELF_ST_VISIBILITY
-
-#define STV_DEFAULT 0 /* Visibility set by binding type */
-#define STV_INTERNAL 1 /* OS specific version of STV_HIDDEN */
-#define STV_HIDDEN 2 /* can only be seen inside own .so */
-#define STV_PROTECTED 3 /* HIDDEN inside, DEFAULT outside */
-
-/* Relocation entry with implicit addend */
-typedef struct {
- Elf32_Addr r_offset; /* offset of relocation */
- Elf32_Word r_info; /* symbol table index and type */
-} Elf32_Rel;
-
-/* Relocation entry with explicit addend */
-typedef struct {
- Elf32_Addr r_offset; /* offset of relocation */
- Elf32_Word r_info; /* symbol table index and type */
- Elf32_Sword r_addend;
-} Elf32_Rela;
-
-/* Extract relocation info - r_info */
-#define ELF32_R_SYM(i) ((i) >> 8)
-#define ELF32_R_TYPE(i) ((unsigned char)(i))
-#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
-
-typedef struct {
- Elf64_Xword r_offset; /* where to do it */
- Elf64_Xword r_info; /* index & type of relocation */
-} Elf64_Rel;
-
-typedef struct {
- Elf64_Xword r_offset; /* where to do it */
- Elf64_Xword r_info; /* index & type of relocation */
- Elf64_Sxword r_addend; /* adjustment value */
-} Elf64_Rela;
-
-#define ELF64_R_SYM(info) ((info) >> 32)
-#define ELF64_R_TYPE(info) ((info)&0xFFFFFFFF)
-#define ELF64_R_INFO(s, t) (((s) << 32) + (uint32_t)(t))
-
-#if defined(__mips64__) && defined(__MIPSEL__)
-/*
- * The 64-bit MIPS ELF ABI uses a slightly different relocation format
- * than the regular ELF ABI: the r_info field is split into several
- * pieces (see gnu/usr.bin/binutils-2.17/include/elf/mips.h for details).
- */
-# undef ELF64_R_SYM
-# undef ELF64_R_TYPE
-# undef ELF64_R_INFO
-# define ELF64_R_TYPE(info) ((uint64_t)swap32((info) >> 32))
-# define ELF64_R_SYM(info) ((info)&0xFFFFFFFF)
-# define ELF64_R_INFO(s, t) (((uint64_t)swap32(t) << 32) + (uint32_t)(s))
-#endif /* __mips64__ && __MIPSEL__ */
-
-/* Program Header */
-typedef struct {
- Elf32_Word p_type; /* segment type */
- Elf32_Off p_offset; /* segment offset */
- Elf32_Addr p_vaddr; /* virtual address of segment */
- Elf32_Addr p_paddr; /* physical address - ignored? */
- Elf32_Word p_filesz; /* number of bytes in file for seg. */
- Elf32_Word p_memsz; /* number of bytes in mem. for seg. */
- Elf32_Word p_flags; /* flags */
- Elf32_Word p_align; /* memory alignment */
-} Elf32_Phdr;
-
-typedef struct {
- Elf64_Half p_type; /* entry type */
- Elf64_Half 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;
-
-/* Segment types - p_type */
-#define PT_NULL 0 /* unused */
-#define PT_LOAD 1 /* loadable segment */
-#define PT_DYNAMIC 2 /* dynamic linking section */
-#define PT_INTERP 3 /* the RTLD */
-#define PT_NOTE 4 /* auxiliary information */
-#define PT_SHLIB 5 /* reserved - purpose undefined */
-#define PT_PHDR 6 /* program header */
-#define PT_TLS 7 /* thread local storage */
-#define PT_LOOS 0x60000000 /* reserved range for OS */
-#define PT_HIOS 0x6fffffff /* specific segment types */
-#define PT_LOPROC 0x70000000 /* reserved range for processor */
-#define PT_HIPROC 0x7fffffff /* specific segment types */
-
-#define PT_GNU_EH_FRAME 0x6474e550 /* Exception handling info */
-#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
-#define PT_GNU_STACK 0x6474e551 /* Stack permissions info */
-
-#define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */
-#define PT_OPENBSD_WXNEEDED 0x65a3dbe7 /* program performs W^X violations */
-#define PT_OPENBSD_BOOTDATA 0x65a41be6 /* section for boot arguments */
-
-/* Segment flags - p_flags */
-#define PF_X 0x1 /* Executable */
-#define PF_W 0x2 /* Writable */
-#define PF_R 0x4 /* Readable */
-#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */
- /* specific segment flags */
-
-/* Dynamic structure */
-typedef struct {
- Elf32_Sword d_tag; /* controls meaning of d_val */
- union {
- Elf32_Word d_val; /* Multiple meanings - see d_tag */
- Elf32_Addr d_ptr; /* program virtual address */
- } d_un;
-} Elf32_Dyn;
-
-typedef struct {
- Elf64_Xword d_tag; /* controls meaning of d_val */
- union {
- Elf64_Addr d_ptr;
- Elf64_Xword d_val;
- } d_un;
-} Elf64_Dyn;
-
-/* Dynamic Array Tags - d_tag */
-#define DT_NULL 0 /* marks end of _DYNAMIC array */
-#define DT_NEEDED 1 /* string table offset of needed lib */
-#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */
-#define DT_PLTGOT 3 /* address PLT/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 relocation table */
-#define DT_RELASZ 8 /* size of relocation table */
-#define DT_RELAENT 9 /* size of relocation entry */
-#define DT_STRSZ 10 /* size of string table */
-#define DT_SYMENT 11 /* size of symbol table entry */
-#define DT_INIT 12 /* address of initialization func. */
-#define DT_FINI 13 /* address of termination function */
-#define DT_SONAME 14 /* string table offset of shared obj */
-#define DT_RPATH 15 /* string table offset of library \
- search path */
-#define DT_SYMBOLIC 16 /* start sym search in shared obj. */
-#define DT_REL 17 /* address of rel. tbl. w addends */
-#define DT_RELSZ 18 /* size of DT_REL relocation table */
-#define DT_RELENT 19 /* size of DT_REL relocation entry */
-#define DT_PLTREL 20 /* PLT referenced relocation entry */
-#define DT_DEBUG 21 /* bugger */
-#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */
-#define DT_JMPREL 23 /* add. of PLT's relocation entries */
-#define DT_BIND_NOW 24 /* Bind now regardless of env setting */
-#define DT_INIT_ARRAY 25 /* address of array of init func */
-#define DT_FINI_ARRAY 26 /* address of array of term func */
-#define DT_INIT_ARRAYSZ 27 /* size of array of init func */
-#define DT_FINI_ARRAYSZ 28 /* size of array of term func */
-#define DT_RUNPATH 29 /* strtab offset of lib search path */
-#define DT_FLAGS 30 /* Set of DF_* flags */
-#define DT_ENCODING 31 /* further DT_* follow encoding rules */
-#define DT_PREINIT_ARRAY 32 /* address of array of preinit func */
-#define DT_PREINIT_ARRAYSZ 33 /* size of array of preinit func */
-#define DT_LOOS 0x6000000d /* reserved range for OS */
-#define DT_HIOS 0x6ffff000 /* specific dynamic array tags */
-#define DT_LOPROC 0x70000000 /* reserved range for processor */
-#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
-
-/* some other useful tags */
-#define DT_GNU_HASH 0x6ffffef5 /* address of GNU hash table */
-#define DT_RELACOUNT 0x6ffffff9 /* if present, number of RELATIVE */
-#define DT_RELCOUNT 0x6ffffffa /* relocs, which must come first */
-#define DT_FLAGS_1 0x6ffffffb
-
-/* Dynamic Flags - DT_FLAGS .dynamic entry */
-#define DF_ORIGIN 0x00000001
-#define DF_SYMBOLIC 0x00000002
-#define DF_TEXTREL 0x00000004
-#define DF_BIND_NOW 0x00000008
-#define DF_STATIC_TLS 0x00000010
-
-/* Dynamic Flags - DT_FLAGS_1 .dynamic entry */
-#define DF_1_NOW 0x00000001
-#define DF_1_GLOBAL 0x00000002
-#define DF_1_GROUP 0x00000004
-#define DF_1_NODELETE 0x00000008
-#define DF_1_LOADFLTR 0x00000010
-#define DF_1_INITFIRST 0x00000020
-#define DF_1_NOOPEN 0x00000040
-#define DF_1_ORIGIN 0x00000080
-#define DF_1_DIRECT 0x00000100
-#define DF_1_TRANS 0x00000200
-#define DF_1_INTERPOSE 0x00000400
-#define DF_1_NODEFLIB 0x00000800
-#define DF_1_NODUMP 0x00001000
-#define DF_1_CONLFAT 0x00002000
-
-/*
- * Note header
- */
-typedef struct {
- Elf32_Word n_namesz;
- Elf32_Word n_descsz;
- Elf32_Word n_type;
-} Elf32_Nhdr;
-
-typedef struct {
- Elf64_Half n_namesz;
- Elf64_Half n_descsz;
- Elf64_Half n_type;
-} Elf64_Nhdr;
-
-/*
- * Note Definitions
- */
-typedef struct {
- Elf32_Word namesz;
- Elf32_Word descsz;
- Elf32_Word type;
-} Elf32_Note;
-
-typedef struct {
- Elf64_Half namesz;
- Elf64_Half descsz;
- Elf64_Half type;
-} Elf64_Note;
-
-/* Values for n_type. */
-#define NT_PRSTATUS 1 /* Process status. */
-#define NT_FPREGSET 2 /* Floating point registers. */
-#define NT_PRPSINFO 3 /* Process state info. */
-
-/*
- * OpenBSD-specific core file information.
- *
- * OpenBSD ELF core files use notes to provide information about
- * the process's state. The note name is "OpenBSD" for information
- * that is global to the process, and "OpenBSD@nn", where "nn" is the
- * thread ID of the thread that the information belongs to (such as
- * register state).
- *
- * We use the following note identifiers:
- *
- * NT_OPENBSD_PROCINFO
- * Note is a "elfcore_procinfo" structure.
- * NT_OPENBSD_AUXV
- * Note is a a bunch of Auxiliary Vectors, terminated by
- * an AT_NULL entry.
- * NT_OPENBSD_REGS
- * Note is a "reg" structure.
- * NT_OPENBSD_FPREGS
- * Note is a "fpreg" structure.
- *
- * Please try to keep the members of the "elfcore_procinfo" structure
- * nicely aligned, and if you add elements, add them to the end and
- * bump the version.
- */
-
-#define NT_OPENBSD_PROCINFO 10
-#define NT_OPENBSD_AUXV 11
-
-#define NT_OPENBSD_REGS 20
-#define NT_OPENBSD_FPREGS 21
-#define NT_OPENBSD_XFPREGS 22
-#define NT_OPENBSD_WCOOKIE 23
-
-struct elfcore_procinfo {
- /* Version 1 fields start here. */
- uint32_t cpi_version; /* netbsd_elfcore_procinfo version */
-#define ELFCORE_PROCINFO_VERSION 1
- uint32_t cpi_cpisize; /* sizeof(netbsd_elfcore_procinfo) */
- uint32_t cpi_signo; /* killing signal */
- uint32_t cpi_sigcode; /* signal code */
- uint32_t cpi_sigpend; /* pending signals */
- uint32_t cpi_sigmask; /* blocked signals */
- uint32_t cpi_sigignore; /* ignored signals */
- uint32_t cpi_sigcatch; /* signals being caught by user */
- 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 */
- int8_t cpi_name[32]; /* copy of pr->ps_comm */
-};
-
-/*
- * XXX - these _KERNEL items aren't part of the ABI!
- */
-#if defined(_KERNEL) || defined(_DYN_LOADER)
-
-# define ELF32_NO_ADDR ((uint32_t)~0) /* Indicates addr. not yet filled in */
-
-typedef struct {
- Elf32_Sword au_id; /* 32-bit id */
- Elf32_Word au_v; /* 32-bit value */
-} Aux32Info;
-
-# define ELF64_NO_ADDR ((uint64_t)~0) /* Indicates addr. not yet filled in */
-
-typedef struct {
- Elf64_Shalf au_id; /* 32-bit id */
- Elf64_Xword au_v; /* 64-bit value */
-} Aux64Info;
-
-enum AuxID {
- AUX_null = 0,
- AUX_ignore = 1,
- AUX_execfd = 2,
- AUX_phdr = 3, /* &phdr[0] */
- AUX_phent = 4, /* sizeof(phdr[0]) */
- AUX_phnum = 5, /* # phdr entries */
- AUX_pagesz = 6, /* PAGESIZE */
- AUX_base = 7, /* ld.so base addr */
- AUX_flags = 8, /* processor flags */
- AUX_entry = 9, /* a.out entry */
- AUX_sun_uid = 2000, /* euid */
- AUX_sun_ruid = 2001, /* ruid */
- AUX_sun_gid = 2002, /* egid */
- AUX_sun_rgid = 2003 /* rgid */
-};
-
-struct elf_args {
- u_long arg_entry; /* program entry point */
- u_long arg_interp; /* Interpreter load address */
- u_long arg_phaddr; /* program header address */
- u_long arg_phentsize; /* Gfx::Size of program header */
- u_long arg_phnum; /* Number of program headers */
-};
-
-#endif
-
-#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 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_Half Elf32_Half
-# define Elf_Word Elf32_Word
-# define Elf_Sword Elf32_Sword
-# define Elf_Addr Elf32_Addr
-# define Elf_Off Elf32_Off
-# define Elf_Nhdr Elf32_Nhdr
-# define Elf_Note Elf32_Note
-
-# define ELF_R_SYM ELF32_R_SYM
-# define ELF_R_TYPE ELF32_R_TYPE
-# define ELF_R_INFO ELF32_R_INFO
-# define ELFCLASS ELFCLASS32
-
-# define ELF_ST_BIND ELF32_ST_BIND
-# define ELF_ST_TYPE ELF32_ST_TYPE
-# define ELF_ST_INFO ELF32_ST_INFO
-
-# define ELF_NO_ADDR ELF32_NO_ADDR
-# 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_Half Elf64_Half
-# define Elf_Word Elf64_Word
-# define Elf_Sword Elf64_Sword
-# define Elf_Addr Elf64_Addr
-# define Elf_Off Elf64_Off
-# define Elf_Nhdr Elf64_Nhdr
-# define Elf_Note Elf64_Note
-
-# define ELF_R_SYM ELF64_R_SYM
-# define ELF_R_TYPE ELF64_R_TYPE
-# define ELF_R_INFO ELF64_R_INFO
-# define ELFCLASS ELFCLASS64
-
-# define ELF_ST_BIND ELF64_ST_BIND
-# define ELF_ST_TYPE ELF64_ST_TYPE
-# define ELF_ST_INFO ELF64_ST_INFO
-
-# define ELF_NO_ADDR ELF64_NO_ADDR
-# define AuxInfo Aux64Info
-#endif
-
-#define ELF_TARG_VER 1 /* The ver for which this code is intended */
-
-/* Relocation types */
-#define R_386_NONE 0
-#define R_386_32 1 /* Symbol + Addend */
-#define R_386_PC32 2 /* Symbol + Addend - Section offset */
-#define R_386_GOT32 3 /* Used by build-time linker to create GOT entry */
-#define R_386_PLT32 4 /* Used by build-time linker to create PLT entry */
-#define R_386_COPY 5 /* https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter4-10454.html#chapter4-84604 */
-#define R_386_GLOB_DAT 6 /* Relation b/w GOT entry and symbol */
-#define R_386_JMP_SLOT 7 /* Fixed up by dynamic loader */
-#define R_386_RELATIVE 8 /* Base address + Addned */
-#define R_386_TLS_TPOFF 14 /* Negative offset into the static TLS storage */
-#define R_386_TLS_TPOFF32 37
-
-#endif /* _SYS_EXEC_ELF_H_ */