diff --git a/Kernel/CoreDump.cpp b/Kernel/CoreDump.cpp index ade97291e44..c8c21c28e1f 100644 --- a/Kernel/CoreDump.cpp +++ b/Kernel/CoreDump.cpp @@ -37,8 +37,8 @@ #include #include #include +#include #include -#include namespace Kernel { diff --git a/Kernel/CoreDump.h b/Kernel/CoreDump.h index aeccc93dc6c..97bf3e45ba9 100644 --- a/Kernel/CoreDump.h +++ b/Kernel/CoreDump.h @@ -31,7 +31,6 @@ #include #include #include -#include namespace Kernel { diff --git a/Kernel/Process.h b/Kernel/Process.h index 925c5872cd3..043d145eb33 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -49,8 +49,8 @@ #include #include #include +#include #include -#include namespace Kernel { diff --git a/Meta/check-debug-flags.sh b/Meta/check-debug-flags.sh index c177a8433ba..b91a3e6b5cc 100755 --- a/Meta/check-debug-flags.sh +++ b/Meta/check-debug-flags.sh @@ -8,6 +8,11 @@ cd "${script_path}/.." MISSING_FLAGS=n while IFS= read -r FLAG; do + # Ignore ELF_DEBUG because it's not a debug flag. + if [ "$FLAG" = "ELF_DEBUG" ]; then + continue + fi + # We simply search whether the CMakeLists.txt *ever* sets the flag. # There are (basically) no false positives, but there might be false negatives, # for example we intentionally don't check for commented-out lines here. diff --git a/Userland/DynamicLoader/main.cpp b/Userland/DynamicLoader/main.cpp index 0f3685b434d..3b824451cf2 100644 --- a/Userland/DynamicLoader/main.cpp +++ b/Userland/DynamicLoader/main.cpp @@ -66,7 +66,7 @@ static void perform_self_relocations(auxv_t* auxvp) if (!dynamic_section_addr) exit(1); - auto dynamic_object = ELF::DynamicObject::create((VirtualAddress(base_address)), (VirtualAddress(dynamic_section_addr))); + auto dynamic_object = ELF::DynamicObject::create({}, (VirtualAddress(base_address)), (VirtualAddress(dynamic_section_addr))); dynamic_object->relocation_section().for_each_relocation([base_address](auto& reloc) { if (reloc.type() != R_386_RELATIVE) diff --git a/Userland/Libraries/LibC/CMakeLists.txt b/Userland/Libraries/LibC/CMakeLists.txt index 982d5787049..d13f6327cc6 100644 --- a/Userland/Libraries/LibC/CMakeLists.txt +++ b/Userland/Libraries/LibC/CMakeLists.txt @@ -13,6 +13,7 @@ set(LIBC_SOURCES ioctl.cpp libcinit.cpp libgen.cpp + link.cpp locale.cpp malloc.cpp mman.cpp diff --git a/Userland/Libraries/LibELF/exec_elf.h b/Userland/Libraries/LibC/elf.h similarity index 99% rename from Userland/Libraries/LibELF/exec_elf.h rename to Userland/Libraries/LibC/elf.h index 45a0e9401f4..6e3bcf729c9 100644 --- a/Userland/Libraries/LibELF/exec_elf.h +++ b/Userland/Libraries/LibC/elf.h @@ -30,10 +30,13 @@ * formerly known as "elf_abi.h". */ -#ifndef _SYS_EXEC_ELF_H_ -#define _SYS_EXEC_ELF_H_ +#pragma once -#include +#ifndef KERNEL +# include +#else +# include +#endif typedef uint8_t Elf_Byte; @@ -788,5 +791,3 @@ struct elf_args { #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_ */ diff --git a/Userland/Libraries/LibC/link.cpp b/Userland/Libraries/LibC/link.cpp new file mode 100644 index 00000000000..3a59e81d6cf --- /dev/null +++ b/Userland/Libraries/LibC/link.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Gunnar Beutner + * 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 +#include + +extern "C" { + +using DlIteratePhdrCallbackFunction = int (*)(struct dl_phdr_info*, size_t, void*); +using DlIteratePhdrFunction = int (*)(DlIteratePhdrCallbackFunction, void*); + +DlIteratePhdrFunction __dl_iterate_phdr; + +int dl_iterate_phdr(int (*callback)(struct dl_phdr_info* info, size_t size, void* data), void* data) +{ + return __dl_iterate_phdr(callback, data); +} +} diff --git a/Userland/Libraries/LibC/link.h b/Userland/Libraries/LibC/link.h new file mode 100644 index 00000000000..3c667aabd86 --- /dev/null +++ b/Userland/Libraries/LibC/link.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, Gunnar Beutner + * 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 + +#ifndef __serenity__ +# include +#else +# include +#endif +#include + +__BEGIN_DECLS + +#define ElfW(type) Elf32_##type + +struct dl_phdr_info { + Elf32_Addr dlpi_addr; + const char* dlpi_name; + const Elf32_Phdr* dlpi_phdr; + Elf32_Half dlpi_phnum; +}; + +int dl_iterate_phdr(int (*callback)(struct dl_phdr_info* info, size_t size, void* data), void* data); + +__END_DECLS diff --git a/Userland/Libraries/LibELF/DynamicLinker.cpp b/Userland/Libraries/LibELF/DynamicLinker.cpp index 56d538155b3..de46e2235ce 100644 --- a/Userland/Libraries/LibELF/DynamicLinker.cpp +++ b/Userland/Libraries/LibELF/DynamicLinker.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,8 @@ Vector> g_global_objects; using EntryPointFunction = int (*)(int, char**, char**); using LibCExitFunction = void (*)(int); +using DlIteratePhdrCallbackFunction = int (*)(struct dl_phdr_info*, size_t, void*); +using DlIteratePhdrFunction = int (*)(DlIteratePhdrCallbackFunction, void*); size_t g_current_tls_offset = 0; size_t g_total_tls_size = 0; @@ -162,6 +165,24 @@ static void allocate_tls() g_total_tls_size = total_tls_size; } +static int __dl_iterate_phdr(DlIteratePhdrCallbackFunction callback, void* data) +{ + for (auto& object : g_global_objects) { + auto info = dl_phdr_info { + .dlpi_addr = (ElfW(Addr))object->base_address().as_ptr(), + .dlpi_name = object->filename().characters(), + .dlpi_phdr = object->program_headers(), + .dlpi_phnum = object->program_header_count() + }; + + auto res = callback(&info, sizeof(info), data); + if (res != 0) + return res; + } + + return 0; +} + static void initialize_libc(DynamicObject& libc) { // Traditionally, `_start` of the main program initializes libc. @@ -181,6 +202,10 @@ static void initialize_libc(DynamicObject& libc) VERIFY(res.has_value()); g_libc_exit = (LibCExitFunction)res.value().address.as_ptr(); + res = libc.lookup_symbol("__dl_iterate_phdr"sv); + VERIFY(res.has_value()); + *((DlIteratePhdrFunction*)res.value().address.as_ptr()) = __dl_iterate_phdr; + res = libc.lookup_symbol("__libc_init"sv); VERIFY(res.has_value()); typedef void libc_init_func(); diff --git a/Userland/Libraries/LibELF/DynamicLinker.h b/Userland/Libraries/LibELF/DynamicLinker.h index 3220953efbb..8f73169dabd 100644 --- a/Userland/Libraries/LibELF/DynamicLinker.h +++ b/Userland/Libraries/LibELF/DynamicLinker.h @@ -27,7 +27,9 @@ #pragma once #include +#include #include +#include #include namespace ELF { diff --git a/Userland/Libraries/LibELF/DynamicLoader.cpp b/Userland/Libraries/LibELF/DynamicLoader.cpp index 6bd8d69eb77..cfc6e124b8f 100644 --- a/Userland/Libraries/LibELF/DynamicLoader.cpp +++ b/Userland/Libraries/LibELF/DynamicLoader.cpp @@ -113,7 +113,7 @@ const DynamicObject& DynamicLoader::dynamic_object() const }); VERIFY(!dynamic_section_address.is_null()); - m_cached_dynamic_object = ELF::DynamicObject::create(VirtualAddress(m_elf_image.base_address()), dynamic_section_address); + m_cached_dynamic_object = ELF::DynamicObject::create(m_filename, VirtualAddress(m_elf_image.base_address()), dynamic_section_address); } return *m_cached_dynamic_object; } @@ -170,7 +170,7 @@ RefPtr DynamicLoader::map() VERIFY(!m_base_address.is_null()); - m_dynamic_object = DynamicObject::create(m_base_address, m_dynamic_section_address); + m_dynamic_object = DynamicObject::create(m_filename, m_base_address, m_dynamic_section_address); m_dynamic_object->set_tls_offset(m_tls_offset); m_dynamic_object->set_tls_size(m_tls_size); diff --git a/Userland/Libraries/LibELF/DynamicLoader.h b/Userland/Libraries/LibELF/DynamicLoader.h index 3c3d17533d1..25c95902a1f 100644 --- a/Userland/Libraries/LibELF/DynamicLoader.h +++ b/Userland/Libraries/LibELF/DynamicLoader.h @@ -31,9 +31,9 @@ #include #include #include +#include #include #include -#include #include namespace ELF { diff --git a/Userland/Libraries/LibELF/DynamicObject.cpp b/Userland/Libraries/LibELF/DynamicObject.cpp index 25778fd19a7..067069ced88 100644 --- a/Userland/Libraries/LibELF/DynamicObject.cpp +++ b/Userland/Libraries/LibELF/DynamicObject.cpp @@ -28,18 +28,19 @@ #include #include #include +#include #include #include #include -#include #include namespace ELF { static const char* name_for_dtag(Elf32_Sword d_tag); -DynamicObject::DynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_address) - : m_base_address(base_address) +DynamicObject::DynamicObject(const String& filename, VirtualAddress base_address, VirtualAddress dynamic_section_address) + : m_filename(filename) + , m_base_address(base_address) , m_dynamic_address(dynamic_section_address) { auto* header = (Elf32_Ehdr*)base_address.as_ptr(); @@ -255,6 +256,18 @@ 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"sv)); } +Elf32_Half DynamicObject::program_header_count() const +{ + auto* header = (const Elf32_Ehdr*)m_base_address.as_ptr(); + return header->e_phnum; +} + +const Elf32_Phdr* DynamicObject::program_headers() const +{ + auto* header = (const Elf32_Ehdr*)m_base_address.as_ptr(); + return (const Elf32_Phdr*)(m_base_address.as_ptr() + header->e_phoff); +} + auto DynamicObject::HashSection::lookup_sysv_symbol(const StringView& name, u32 hash_value) const -> Optional { u32* hash_table_begin = (u32*)address().as_ptr(); @@ -447,9 +460,9 @@ auto DynamicObject::lookup_symbol(const StringView& name, u32 gnu_hash, u32 sysv return SymbolLookupResult { symbol.value(), symbol.address(), symbol.bind(), this }; } -NonnullRefPtr DynamicObject::create(VirtualAddress base_address, VirtualAddress dynamic_section_address) +NonnullRefPtr DynamicObject::create(const String& filename, VirtualAddress base_address, VirtualAddress dynamic_section_address) { - return adopt(*new DynamicObject(base_address, dynamic_section_address)); + return adopt(*new DynamicObject(filename, base_address, dynamic_section_address)); } // offset is in PLT relocation table diff --git a/Userland/Libraries/LibELF/DynamicObject.h b/Userland/Libraries/LibELF/DynamicObject.h index 8fa50bc18c7..ac99504402b 100644 --- a/Userland/Libraries/LibELF/DynamicObject.h +++ b/Userland/Libraries/LibELF/DynamicObject.h @@ -29,14 +29,15 @@ #include #include +#include #include -#include +#include namespace ELF { class DynamicObject : public RefCounted { public: - static NonnullRefPtr create(VirtualAddress base_address, VirtualAddress dynamic_section_address); + static NonnullRefPtr create(const String& filename, VirtualAddress base_address, VirtualAddress dynamic_section_address); ~DynamicObject(); void dump() const; @@ -238,6 +239,8 @@ public: VirtualAddress plt_got_base_address() const { return m_base_address.offset(m_procedure_linkage_table_offset.value()); } VirtualAddress base_address() const { return m_base_address; } + const String& filename() const { return m_filename; } + StringView rpath() const { return m_has_rpath ? symbol_string_table_string(m_rpath_index) : StringView {}; } StringView runpath() const { return m_has_runpath ? symbol_string_table_string(m_runpath_index) : StringView {}; } StringView soname() const { return m_has_soname ? symbol_string_table_string(m_soname_index) : StringView {}; } @@ -247,6 +250,9 @@ public: void set_tls_offset(FlatPtr offset) { m_tls_offset = offset; } void set_tls_size(FlatPtr size) { m_tls_size = size; } + Elf32_Half program_header_count() const; + const Elf32_Phdr* program_headers() const; + template void for_each_needed_library(F) const; @@ -275,12 +281,14 @@ public: bool elf_is_dynamic() const { return m_is_elf_dynamic; } private: - explicit DynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_address); + explicit DynamicObject(const String& filename, VirtualAddress base_address, VirtualAddress dynamic_section_address); StringView symbol_string_table_string(Elf32_Word) const; const char* raw_symbol_string_table_string(Elf32_Word) const; void parse(); + String m_filename; + VirtualAddress m_base_address; VirtualAddress m_dynamic_address; VirtualAddress m_elf_base_address; diff --git a/Userland/Libraries/LibELF/Image.h b/Userland/Libraries/LibELF/Image.h index 361be1a5c60..326f530ecc6 100644 --- a/Userland/Libraries/LibELF/Image.h +++ b/Userland/Libraries/LibELF/Image.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include namespace ELF { diff --git a/Userland/Libraries/LibELF/Validation.cpp b/Userland/Libraries/LibELF/Validation.cpp index 1336cb91f0e..e8cb2b86371 100644 --- a/Userland/Libraries/LibELF/Validation.cpp +++ b/Userland/Libraries/LibELF/Validation.cpp @@ -28,8 +28,8 @@ #include #include #include +#include #include -#include namespace ELF { diff --git a/Userland/Libraries/LibELF/Validation.h b/Userland/Libraries/LibELF/Validation.h index e5bc75eff9e..ceca8b81738 100644 --- a/Userland/Libraries/LibELF/Validation.h +++ b/Userland/Libraries/LibELF/Validation.h @@ -27,7 +27,7 @@ #pragma once #include -#include +#include namespace ELF { diff --git a/Userland/Tests/Kernel/elf-execve-mmap-race.cpp b/Userland/Tests/Kernel/elf-execve-mmap-race.cpp index 002b37fe6fe..c63a19e866e 100644 --- a/Userland/Tests/Kernel/elf-execve-mmap-race.cpp +++ b/Userland/Tests/Kernel/elf-execve-mmap-race.cpp @@ -24,7 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include #include #include #include diff --git a/Userland/Tests/Kernel/elf-symbolication-kernel-read-exploit.cpp b/Userland/Tests/Kernel/elf-symbolication-kernel-read-exploit.cpp index d4ccbf1ac69..6b610cc5fce 100644 --- a/Userland/Tests/Kernel/elf-symbolication-kernel-read-exploit.cpp +++ b/Userland/Tests/Kernel/elf-symbolication-kernel-read-exploit.cpp @@ -24,7 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include #include #include #include