LibELF: Move ELF classes into namespace ELF
This is for consistency with other namespace changes that were made a while back to the other libraries :)
This commit is contained in:
parent
6b0f47683c
commit
21b5909dc6
Notes:
sideshowbarker
2024-07-19 07:42:08 +09:00
Author: https://github.com/ADKaster Commit: https://github.com/SerenityOS/serenity/commit/21b5909dc6c Pull-request: https://github.com/SerenityOS/serenity/pull/1750
18 changed files with 203 additions and 169 deletions
|
@ -27,7 +27,7 @@
|
|||
#include "DisassemblyModel.h"
|
||||
#include "Profile.h"
|
||||
#include <AK/MappedFile.h>
|
||||
#include <LibELF/ELFLoader.h>
|
||||
#include <LibELF/Loader.h>
|
||||
#include <LibGUI/Painter.h>
|
||||
#include <LibX86/Disassembler.h>
|
||||
#include <ctype.h>
|
||||
|
@ -55,7 +55,7 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node)
|
|||
, m_node(node)
|
||||
{
|
||||
m_file = make<MappedFile>(profile.executable_path());
|
||||
auto elf_loader = make<ELFLoader>((const u8*)m_file->data(), m_file->size());
|
||||
auto elf_loader = make<ELF::Loader>((const u8*)m_file->data(), m_file->size());
|
||||
|
||||
auto symbol = elf_loader->find_symbol(node.address());
|
||||
ASSERT(symbol.has_value());
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <AK/MappedFile.h>
|
||||
#include <AK/QuickSort.h>
|
||||
#include <LibCore/File.h>
|
||||
#include <LibELF/ELFLoader.h>
|
||||
#include <LibELF/Loader.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void sort_profile_nodes(Vector<NonnullRefPtr<ProfileNode>>& nodes)
|
||||
|
@ -185,12 +185,12 @@ OwnPtr<Profile> Profile::load_from_perfcore_file(const StringView& path)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
auto elf_loader = make<ELFLoader>(static_cast<const u8*>(elf_file.data()), elf_file.size());
|
||||
auto elf_loader = make<ELF::Loader>(static_cast<const u8*>(elf_file.data()), elf_file.size());
|
||||
|
||||
MappedFile kernel_elf_file("/boot/kernel");
|
||||
OwnPtr<ELFLoader> kernel_elf_loader;
|
||||
OwnPtr<ELF::Loader> kernel_elf_loader;
|
||||
if (kernel_elf_file.is_valid())
|
||||
kernel_elf_loader = make<ELFLoader>(static_cast<const u8*>(kernel_elf_file.data()), kernel_elf_file.size());
|
||||
kernel_elf_loader = make<ELF::Loader>(static_cast<const u8*>(kernel_elf_file.data()), kernel_elf_file.size());
|
||||
|
||||
auto events_value = object.get("events");
|
||||
if (!events_value.is_array())
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <Kernel/KSyms.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/Scheduler.h>
|
||||
#include <LibELF/ELFLoader.h>
|
||||
#include <LibELF/Loader.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ OBJS = \
|
|||
../AK/StringImpl.o \
|
||||
../AK/StringUtils.o \
|
||||
../AK/StringView.o \
|
||||
../Libraries/LibELF/ELFImage.o \
|
||||
../Libraries/LibELF/ELFLoader.o \
|
||||
../Libraries/LibELF/Image.o \
|
||||
../Libraries/LibELF/Loader.o \
|
||||
../Libraries/LibBareMetal/Output/Console.o \
|
||||
../Libraries/LibBareMetal/Output/kprintf.o \
|
||||
../Libraries/LibBareMetal/StdLib.o \
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
#include <LibC/errno_numbers.h>
|
||||
#include <LibC/limits.h>
|
||||
#include <LibC/signal_numbers.h>
|
||||
#include <LibELF/ELFLoader.h>
|
||||
#include <LibELF/Loader.h>
|
||||
|
||||
//#define PROCESS_DEBUG
|
||||
//#define DEBUG_POLL_SELECT
|
||||
|
@ -856,7 +856,7 @@ int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Ve
|
|||
u32 entry_eip = 0;
|
||||
|
||||
MM.enter_process_paging_scope(*this);
|
||||
OwnPtr<ELFLoader> loader;
|
||||
OwnPtr<ELF::Loader> loader;
|
||||
{
|
||||
ArmedScopeGuard rollback_regions_guard([&]() {
|
||||
ASSERT(Process::current == this);
|
||||
|
@ -864,7 +864,7 @@ int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Ve
|
|||
m_regions = move(old_regions);
|
||||
MM.enter_process_paging_scope(*this);
|
||||
});
|
||||
loader = make<ELFLoader>(region->vaddr().as_ptr(), loader_metadata.size);
|
||||
loader = make<ELF::Loader>(region->vaddr().as_ptr(), loader_metadata.size);
|
||||
// Load the correct executable -- either interp or main program.
|
||||
// FIXME: Once we actually load both interp and main, we'll need to be more clever about this.
|
||||
// In that case, both will be ET_DYN objects, so they'll both be completely relocatable.
|
||||
|
@ -1084,14 +1084,14 @@ KResultOr<NonnullRefPtr<FileDescription>> Process::find_elf_interpreter_for_exec
|
|||
return KResult(-ENOEXEC);
|
||||
|
||||
auto elf_header = (Elf32_Ehdr*)first_page;
|
||||
if (!ELFImage::validate_elf_header(*elf_header, file_size)) {
|
||||
if (!ELF::Image::validate_elf_header(*elf_header, file_size)) {
|
||||
dbg() << "exec(" << path << "): File has invalid ELF header";
|
||||
return KResult(-ENOEXEC);
|
||||
}
|
||||
|
||||
// Not using KResultOr here because we'll want to do the same thing in userspace in the RTLD
|
||||
String interpreter_path;
|
||||
if (!ELFImage::validate_program_headers(*elf_header, file_size, (u8*)first_page, nread, interpreter_path)) {
|
||||
if (!ELF::Image::validate_program_headers(*elf_header, file_size, (u8*)first_page, nread, interpreter_path)) {
|
||||
dbg() << "exec(" << path << "): File has invalid ELF Program headers";
|
||||
return KResult(-ENOEXEC);
|
||||
}
|
||||
|
@ -1124,14 +1124,14 @@ KResultOr<NonnullRefPtr<FileDescription>> Process::find_elf_interpreter_for_exec
|
|||
return KResult(-ENOEXEC);
|
||||
|
||||
elf_header = (Elf32_Ehdr*)first_page;
|
||||
if (!ELFImage::validate_elf_header(*elf_header, interp_metadata.size)) {
|
||||
if (!ELF::Image::validate_elf_header(*elf_header, interp_metadata.size)) {
|
||||
dbg() << "exec(" << path << "): Interpreter (" << interpreter_description->absolute_path() << ") has invalid ELF header";
|
||||
return KResult(-ENOEXEC);
|
||||
}
|
||||
|
||||
// Not using KResultOr here because we'll want to do the same thing in userspace in the RTLD
|
||||
String interpreter_interpreter_path;
|
||||
if (!ELFImage::validate_program_headers(*elf_header, interp_metadata.size, (u8*)first_page, nread, interpreter_interpreter_path)) {
|
||||
if (!ELF::Image::validate_program_headers(*elf_header, interp_metadata.size, (u8*)first_page, nread, interpreter_interpreter_path)) {
|
||||
dbg() << "exec(" << path << "): Interpreter (" << interpreter_description->absolute_path() << ") has invalid ELF Program headers";
|
||||
return KResult(-ENOEXEC);
|
||||
}
|
||||
|
@ -4378,7 +4378,7 @@ int Process::sys$module_load(const char* user_path, size_t path_length)
|
|||
memcpy(storage.data(), payload.data(), payload.size());
|
||||
payload.clear();
|
||||
|
||||
auto elf_image = make<ELFImage>(storage.data(), storage.size());
|
||||
auto elf_image = make<ELF::Image>(storage.data(), storage.size());
|
||||
if (!elf_image->parse())
|
||||
return -ENOEXEC;
|
||||
|
||||
|
@ -4386,7 +4386,7 @@ int Process::sys$module_load(const char* user_path, size_t path_length)
|
|||
|
||||
auto module = make<Module>();
|
||||
|
||||
elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELFImage::Section& section) {
|
||||
elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
|
||||
if (!section.size())
|
||||
return IterationDecision::Continue;
|
||||
auto section_storage = KBuffer::copy(section.raw_data(), section.size(), Region::Access::Read | Region::Access::Write | Region::Access::Execute);
|
||||
|
@ -4397,12 +4397,12 @@ int Process::sys$module_load(const char* user_path, size_t path_length)
|
|||
|
||||
bool missing_symbols = false;
|
||||
|
||||
elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELFImage::Section& section) {
|
||||
elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
|
||||
if (!section.size())
|
||||
return IterationDecision::Continue;
|
||||
auto* section_storage = section_storage_by_name.get(section.name()).value_or(nullptr);
|
||||
ASSERT(section_storage);
|
||||
section.relocations().for_each_relocation([&](const ELFImage::Relocation& relocation) {
|
||||
section.relocations().for_each_relocation([&](const ELF::Image::Relocation& relocation) {
|
||||
auto& patch_ptr = *reinterpret_cast<ptrdiff_t*>(section_storage + relocation.offset());
|
||||
switch (relocation.type()) {
|
||||
case R_386_PC32: {
|
||||
|
@ -4453,7 +4453,7 @@ int Process::sys$module_load(const char* user_path, size_t path_length)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
elf_image->for_each_symbol([&](const ELFImage::Symbol& symbol) {
|
||||
elf_image->for_each_symbol([&](const ELF::Image::Symbol& symbol) {
|
||||
dbg() << " - " << symbol.type() << " '" << symbol.name() << "' @ " << (void*)symbol.value() << ", size=" << symbol.size();
|
||||
if (symbol.name() == "module_init") {
|
||||
module->module_init = (ModuleInitPtr)(text_base + symbol.value());
|
||||
|
@ -4845,7 +4845,7 @@ OwnPtr<Process::ELFBundle> Process::elf_bundle() const
|
|||
bundle->region = MM.allocate_kernel_region_with_vmobject(const_cast<SharedInodeVMObject&>(vmobject), vmobject.size(), "ELF bundle", Region::Access::Read);
|
||||
if (!bundle->region)
|
||||
return nullptr;
|
||||
bundle->elf_loader = make<ELFLoader>(bundle->region->vaddr().as_ptr(), bundle->region->size());
|
||||
bundle->elf_loader = make<ELF::Loader>(bundle->region->vaddr().as_ptr(), bundle->region->size());
|
||||
return bundle;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,9 @@
|
|||
#include <Kernel/VM/RangeAllocator.h>
|
||||
#include <LibC/signal_numbers.h>
|
||||
|
||||
class ELFLoader;
|
||||
namespace ELF {
|
||||
class Loader;
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
@ -387,7 +389,7 @@ public:
|
|||
|
||||
struct ELFBundle {
|
||||
OwnPtr<Region> region;
|
||||
OwnPtr<ELFLoader> elf_loader;
|
||||
OwnPtr<ELF::Loader> elf_loader;
|
||||
};
|
||||
OwnPtr<ELFBundle> elf_bundle() const;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <Kernel/KSyms.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/Profiling.h>
|
||||
#include <LibELF/ELFLoader.h>
|
||||
#include <LibELF/Loader.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include <Kernel/VM/PageDirectory.h>
|
||||
#include <Kernel/VM/ProcessPagingScope.h>
|
||||
#include <LibC/signal_numbers.h>
|
||||
#include <LibELF/ELFLoader.h>
|
||||
#include <LibELF/Loader.h>
|
||||
|
||||
//#define SIGNAL_DEBUG
|
||||
//#define THREAD_DEBUG
|
||||
|
|
|
@ -61,10 +61,10 @@ LIBC_OBJS = \
|
|||
libcinit.o
|
||||
|
||||
ELF_OBJS = \
|
||||
../LibELF/ELFDynamicObject.o \
|
||||
../LibELF/ELFDynamicLoader.o \
|
||||
../LibELF/ELFLoader.o \
|
||||
../LibELF/ELFImage.o
|
||||
../LibELF/DynamicObject.o \
|
||||
../LibELF/DynamicLoader.o \
|
||||
../LibELF/Loader.o \
|
||||
../LibELF/Image.o
|
||||
|
||||
OBJS = $(AK_OBJS) $(LIBC_OBJS) $(ELF_OBJS)
|
||||
|
||||
|
|
|
@ -38,12 +38,12 @@
|
|||
#include <AK/ScopeGuard.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibELF/ELFDynamicLoader.h>
|
||||
#include <LibELF/DynamicLoader.h>
|
||||
|
||||
// NOTE: The string here should never include a trailing newline (according to POSIX)
|
||||
String g_dlerror_msg;
|
||||
|
||||
HashMap<String, RefPtr<ELFDynamicLoader>> g_elf_objects;
|
||||
HashMap<String, RefPtr<ELF::DynamicLoader>> g_elf_objects;
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
@ -74,7 +74,7 @@ void* dlopen(const char* filename, int flags)
|
|||
|
||||
auto existing_elf_object = g_elf_objects.get(file_path.basename());
|
||||
if (existing_elf_object.has_value()) {
|
||||
return const_cast<ELFDynamicLoader*>(existing_elf_object.value());
|
||||
return const_cast<ELF::DynamicLoader*>(existing_elf_object.value());
|
||||
}
|
||||
|
||||
int fd = open(filename, O_RDONLY);
|
||||
|
@ -93,7 +93,7 @@ void* dlopen(const char* filename, int flags)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
auto loader = ELFDynamicLoader::construct(filename, fd, file_stats.st_size);
|
||||
auto loader = ELF::DynamicLoader::construct(filename, fd, file_stats.st_size);
|
||||
|
||||
if (!loader->is_valid()) {
|
||||
g_dlerror_msg = String::format("%s is not a valid ELF dynamic shared object!", filename);
|
||||
|
@ -109,14 +109,14 @@ void* dlopen(const char* filename, int flags)
|
|||
g_dlerror_msg = "Successfully loaded ELF object.";
|
||||
|
||||
// we have one refcount already
|
||||
return const_cast<ELFDynamicLoader*>(g_elf_objects.get(file_path.basename()).value());
|
||||
return const_cast<ELF::DynamicLoader*>(g_elf_objects.get(file_path.basename()).value());
|
||||
}
|
||||
|
||||
void* dlsym(void* handle, const char* symbol_name)
|
||||
{
|
||||
// FIXME: When called with a NULL handle we're supposed to search every dso in the process... that'll get expensive
|
||||
ASSERT(handle);
|
||||
auto* dso = reinterpret_cast<ELFDynamicLoader*>(handle);
|
||||
auto* dso = reinterpret_cast<ELF::DynamicLoader*>(handle);
|
||||
void* symbol = dso->symbol_for_name(symbol_name);
|
||||
if (!symbol) {
|
||||
g_dlerror_msg = "Symbol not found";
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibELF/ELFDynamicLoader.h>
|
||||
#include <LibELF/DynamicLoader.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
|
@ -45,14 +45,16 @@
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
namespace ELF {
|
||||
|
||||
static bool s_always_bind_now = false;
|
||||
|
||||
NonnullRefPtr<ELFDynamicLoader> ELFDynamicLoader::construct(const char* filename, int fd, size_t size)
|
||||
NonnullRefPtr<DynamicLoader> DynamicLoader::construct(const char* filename, int fd, size_t size)
|
||||
{
|
||||
return adopt(*new ELFDynamicLoader(filename, fd, size));
|
||||
return adopt(*new DynamicLoader(filename, fd, size));
|
||||
}
|
||||
|
||||
ELFDynamicLoader::ELFDynamicLoader(const char* filename, int fd, size_t size)
|
||||
DynamicLoader::DynamicLoader(const char* filename, int fd, size_t size)
|
||||
: m_filename(filename)
|
||||
, m_file_size(size)
|
||||
, m_image_fd(fd)
|
||||
|
@ -65,13 +67,13 @@ ELFDynamicLoader::ELFDynamicLoader(const char* filename, int fd, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
ELFDynamicLoader::~ELFDynamicLoader()
|
||||
DynamicLoader::~DynamicLoader()
|
||||
{
|
||||
if (MAP_FAILED != m_file_mapping)
|
||||
munmap(m_file_mapping, m_file_size);
|
||||
}
|
||||
|
||||
void* ELFDynamicLoader::symbol_for_name(const char* name)
|
||||
void* DynamicLoader::symbol_for_name(const char* name)
|
||||
{
|
||||
auto symbol = m_dynamic_object->hash_section().lookup_symbol(name);
|
||||
|
||||
|
@ -81,9 +83,9 @@ void* ELFDynamicLoader::symbol_for_name(const char* name)
|
|||
return m_dynamic_object->base_address().offset(symbol.value()).as_ptr();
|
||||
}
|
||||
|
||||
bool ELFDynamicLoader::load_from_image(unsigned flags)
|
||||
bool DynamicLoader::load_from_image(unsigned flags)
|
||||
{
|
||||
ELFImage elf_image((u8*)m_file_mapping, m_file_size);
|
||||
Image elf_image((u8*)m_file_mapping, m_file_size);
|
||||
|
||||
m_valid = elf_image.is_valid() && elf_image.is_dynamic();
|
||||
|
||||
|
@ -101,12 +103,12 @@ bool ELFDynamicLoader::load_from_image(unsigned flags)
|
|||
munmap(m_file_mapping, m_file_size);
|
||||
m_file_mapping = MAP_FAILED;
|
||||
|
||||
m_dynamic_object = AK::make<ELFDynamicObject>(m_text_segment_load_address, m_dynamic_section_address);
|
||||
m_dynamic_object = AK::make<DynamicObject>(m_text_segment_load_address, m_dynamic_section_address);
|
||||
|
||||
return load_stage_2(flags);
|
||||
}
|
||||
|
||||
bool ELFDynamicLoader::load_stage_2(unsigned flags)
|
||||
bool DynamicLoader::load_stage_2(unsigned flags)
|
||||
{
|
||||
ASSERT(flags & RTLD_GLOBAL);
|
||||
ASSERT(flags & RTLD_LAZY);
|
||||
|
@ -143,7 +145,7 @@ bool ELFDynamicLoader::load_stage_2(unsigned flags)
|
|||
return true;
|
||||
}
|
||||
|
||||
void ELFDynamicLoader::load_program_headers(const ELFImage& elf_image)
|
||||
void DynamicLoader::load_program_headers(const Image& elf_image)
|
||||
{
|
||||
Vector<ProgramHeaderRegion> program_headers;
|
||||
|
||||
|
@ -152,7 +154,7 @@ void ELFDynamicLoader::load_program_headers(const ELFImage& elf_image)
|
|||
ProgramHeaderRegion* tls_region_ptr = nullptr;
|
||||
VirtualAddress dynamic_region_desired_vaddr;
|
||||
|
||||
elf_image.for_each_program_header([&](const ELFImage::ProgramHeader& program_header) {
|
||||
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));
|
||||
|
@ -200,7 +202,7 @@ void ELFDynamicLoader::load_program_headers(const ELFImage& elf_image)
|
|||
}
|
||||
}
|
||||
|
||||
void ELFDynamicLoader::do_relocations()
|
||||
void DynamicLoader::do_relocations()
|
||||
{
|
||||
u32 load_base_address = m_dynamic_object->base_address().get();
|
||||
|
||||
|
@ -208,7 +210,7 @@ void ELFDynamicLoader::do_relocations()
|
|||
|
||||
auto main_relocation_section = m_dynamic_object->relocation_section();
|
||||
|
||||
main_relocation_section.for_each_relocation([&](const ELFDynamicObject::Relocation& relocation) {
|
||||
main_relocation_section.for_each_relocation([&](const DynamicObject::Relocation& relocation) {
|
||||
VERBOSE("====== RELOCATION %d: offset 0x%08X, type %d, symidx %08X\n", relocation.offset_in_section() / main_relocation_section.entry_size(), relocation.offset(), relocation.type(), relocation.symbol_index());
|
||||
u32* patch_ptr = (u32*)(load_base_address + relocation.offset());
|
||||
switch (relocation.type()) {
|
||||
|
@ -260,7 +262,7 @@ void ELFDynamicLoader::do_relocations()
|
|||
default:
|
||||
// Raise the alarm! Someone needs to implement this relocation type
|
||||
dbgprintf("Found a new exciting relocation type %d\n", relocation.type());
|
||||
printf("ELFDynamicLoader: Found unknown relocation type %d\n", relocation.type());
|
||||
printf("DynamicLoader: Found unknown relocation type %d\n", relocation.type());
|
||||
ASSERT_NOT_REACHED();
|
||||
break;
|
||||
}
|
||||
|
@ -268,7 +270,7 @@ void ELFDynamicLoader::do_relocations()
|
|||
});
|
||||
|
||||
// Handle PLT Global offset table relocations.
|
||||
m_dynamic_object->plt_relocation_section().for_each_relocation([&](const ELFDynamicObject::Relocation& relocation) {
|
||||
m_dynamic_object->plt_relocation_section().for_each_relocation([&](const DynamicObject::Relocation& relocation) {
|
||||
// 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
|
||||
|
@ -294,7 +296,7 @@ void ELFDynamicLoader::do_relocations()
|
|||
// Defined in <arch>/plt_trampoline.S
|
||||
extern "C" void _plt_trampoline(void) __attribute__((visibility("hidden")));
|
||||
|
||||
void ELFDynamicLoader::setup_plt_trampoline()
|
||||
void DynamicLoader::setup_plt_trampoline()
|
||||
{
|
||||
VirtualAddress got_address = m_dynamic_object->plt_got_base_address();
|
||||
|
||||
|
@ -308,13 +310,13 @@ void ELFDynamicLoader::setup_plt_trampoline()
|
|||
}
|
||||
|
||||
// Called from our ASM routine _plt_trampoline
|
||||
extern "C" Elf32_Addr _fixup_plt_entry(ELFDynamicLoader* object, u32 relocation_offset)
|
||||
extern "C" Elf32_Addr _fixup_plt_entry(DynamicLoader* object, u32 relocation_offset)
|
||||
{
|
||||
return object->patch_plt_entry(relocation_offset);
|
||||
}
|
||||
|
||||
// offset is in PLT relocation table
|
||||
Elf32_Addr ELFDynamicLoader::patch_plt_entry(u32 relocation_offset)
|
||||
Elf32_Addr DynamicLoader::patch_plt_entry(u32 relocation_offset)
|
||||
{
|
||||
auto relocation = m_dynamic_object->plt_relocation_section().relocation_at_offset(relocation_offset);
|
||||
|
||||
|
@ -325,14 +327,14 @@ Elf32_Addr ELFDynamicLoader::patch_plt_entry(u32 relocation_offset)
|
|||
u8* relocation_address = relocation.address().as_ptr();
|
||||
u32 symbol_location = sym.address().get();
|
||||
|
||||
VERBOSE("ELFDynamicLoader: Jump slot relocation: putting %s (%p) into PLT at %p\n", sym.name(), symbol_location, relocation_address);
|
||||
VERBOSE("DynamicLoader: Jump slot relocation: putting %s (%p) into PLT at %p\n", sym.name(), symbol_location, relocation_address);
|
||||
|
||||
*(u32*)relocation_address = symbol_location;
|
||||
|
||||
return symbol_location;
|
||||
}
|
||||
|
||||
void ELFDynamicLoader::call_object_init_functions()
|
||||
void DynamicLoader::call_object_init_functions()
|
||||
{
|
||||
typedef void (*InitFunc)();
|
||||
auto init_function = (InitFunc)(m_dynamic_object->init_section().address().as_ptr());
|
||||
|
@ -359,7 +361,7 @@ void ELFDynamicLoader::call_object_init_functions()
|
|||
}
|
||||
}
|
||||
|
||||
u32 ELFDynamicLoader::ProgramHeaderRegion::mmap_prot() const
|
||||
u32 DynamicLoader::ProgramHeaderRegion::mmap_prot() const
|
||||
{
|
||||
int prot = 0;
|
||||
prot |= is_executable() ? PROT_EXEC : 0;
|
||||
|
@ -367,3 +369,5 @@ u32 ELFDynamicLoader::ProgramHeaderRegion::mmap_prot() const
|
|||
prot |= is_writable() ? PROT_WRITE : 0;
|
||||
return prot;
|
||||
}
|
||||
|
||||
} // end namespace ELF
|
|
@ -30,22 +30,24 @@
|
|||
#include <AK/OwnPtr.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibELF/ELFDynamicObject.h>
|
||||
#include <LibELF/ELFImage.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 ELFDynamicLoader : public RefCounted<ELFDynamicLoader> {
|
||||
class DynamicLoader : public RefCounted<DynamicLoader> {
|
||||
public:
|
||||
static NonnullRefPtr<ELFDynamicLoader> construct(const char* filename, int fd, size_t file_size);
|
||||
static NonnullRefPtr<DynamicLoader> construct(const char* filename, int fd, size_t file_size);
|
||||
|
||||
~ELFDynamicLoader();
|
||||
~DynamicLoader();
|
||||
|
||||
bool is_valid() const { return m_valid; }
|
||||
|
||||
// Load a full ELF image from file into the current process and create an ELFDynamicObject
|
||||
// Load a full ELF image from file into the current process and create an DynamicObject
|
||||
// from the SHT_DYNAMIC in the file.
|
||||
bool load_from_image(unsigned flags);
|
||||
|
||||
|
@ -89,11 +91,11 @@ private:
|
|||
Elf32_Phdr m_program_header; // Explictly a copy of the PHDR in the image
|
||||
};
|
||||
|
||||
explicit ELFDynamicLoader(const char* filename, int fd, size_t file_size);
|
||||
explicit ELFDynamicLoader(Elf32_Dyn* dynamic_location, Elf32_Addr load_address);
|
||||
explicit DynamicLoader(const char* filename, int fd, size_t file_size);
|
||||
explicit DynamicLoader(Elf32_Dyn* dynamic_location, Elf32_Addr load_address);
|
||||
|
||||
// Stage 1
|
||||
void load_program_headers(const ELFImage& elf_image);
|
||||
void load_program_headers(const Image& elf_image);
|
||||
|
||||
// Stage 2
|
||||
void do_relocations();
|
||||
|
@ -106,7 +108,7 @@ private:
|
|||
void* m_file_mapping { nullptr };
|
||||
bool m_valid { true };
|
||||
|
||||
OwnPtr<ELFDynamicObject> m_dynamic_object;
|
||||
OwnPtr<DynamicObject> m_dynamic_object;
|
||||
|
||||
VirtualAddress m_text_segment_load_address;
|
||||
size_t m_text_segment_size;
|
||||
|
@ -114,3 +116,5 @@ private:
|
|||
VirtualAddress m_tls_segment_address;
|
||||
VirtualAddress m_dynamic_section_address;
|
||||
};
|
||||
|
||||
} // end namespace ELF
|
|
@ -26,31 +26,33 @@
|
|||
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibELF/ELFDynamicObject.h>
|
||||
#include <LibELF/DynamicObject.h>
|
||||
#include <LibELF/exec_elf.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace ELF {
|
||||
|
||||
static const char* name_for_dtag(Elf32_Sword d_tag);
|
||||
|
||||
ELFDynamicObject::ELFDynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_addresss)
|
||||
DynamicObject::DynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_addresss)
|
||||
: m_base_address(base_address)
|
||||
, m_dynamic_address(dynamic_section_addresss)
|
||||
{
|
||||
parse();
|
||||
}
|
||||
|
||||
ELFDynamicObject::~ELFDynamicObject()
|
||||
DynamicObject::~DynamicObject()
|
||||
{
|
||||
}
|
||||
|
||||
void ELFDynamicObject::dump() const
|
||||
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 ELFDynamicObject::DynamicEntry& entry) {
|
||||
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++;
|
||||
|
@ -61,7 +63,7 @@ void ELFDynamicObject::dump() const
|
|||
dbgprintf(builder.to_string().characters());
|
||||
}
|
||||
|
||||
void ELFDynamicObject::parse()
|
||||
void DynamicObject::parse()
|
||||
{
|
||||
for_each_dynamic_entry([&](const DynamicEntry& entry) {
|
||||
switch (entry.tag()) {
|
||||
|
@ -134,8 +136,8 @@ void ELFDynamicObject::parse()
|
|||
m_dt_flags |= DF_TEXTREL; // This tag seems to exist for legacy reasons only?
|
||||
break;
|
||||
default:
|
||||
dbgprintf("ELFDynamicObject: DYNAMIC tag handling not implemented for DT_%s\n", name_for_dtag(entry.tag()));
|
||||
printf("ELFDynamicObject: DYNAMIC tag handling not implemented for DT_%s\n", name_for_dtag(entry.tag()));
|
||||
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;
|
||||
}
|
||||
|
@ -147,7 +149,7 @@ void ELFDynamicObject::parse()
|
|||
m_symbol_count = num_hash_chains;
|
||||
}
|
||||
|
||||
const ELFDynamicObject::Relocation ELFDynamicObject::RelocationSection::relocation(unsigned index) const
|
||||
const DynamicObject::Relocation DynamicObject::RelocationSection::relocation(unsigned index) const
|
||||
{
|
||||
ASSERT(index < entry_count());
|
||||
unsigned offset_in_section = index * entry_size();
|
||||
|
@ -155,56 +157,56 @@ const ELFDynamicObject::Relocation ELFDynamicObject::RelocationSection::relocati
|
|||
return Relocation(m_dynamic, *relocation_address, offset_in_section);
|
||||
}
|
||||
|
||||
const ELFDynamicObject::Relocation ELFDynamicObject::RelocationSection::relocation_at_offset(unsigned offset) const
|
||||
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 ELFDynamicObject::Symbol ELFDynamicObject::symbol(unsigned index) const
|
||||
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 ELFDynamicObject::Section ELFDynamicObject::init_section() const
|
||||
const DynamicObject::Section DynamicObject::init_section() const
|
||||
{
|
||||
return Section(*this, m_init_offset, sizeof(void (*)()), sizeof(void (*)()), "DT_INIT");
|
||||
}
|
||||
|
||||
const ELFDynamicObject::Section ELFDynamicObject::fini_section() const
|
||||
const DynamicObject::Section DynamicObject::fini_section() const
|
||||
{
|
||||
return Section(*this, m_fini_offset, sizeof(void (*)()), sizeof(void (*)()), "DT_FINI");
|
||||
}
|
||||
|
||||
const ELFDynamicObject::Section ELFDynamicObject::init_array_section() const
|
||||
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 ELFDynamicObject::Section ELFDynamicObject::fini_array_section() const
|
||||
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 ELFDynamicObject::HashSection ELFDynamicObject::hash_section() const
|
||||
const DynamicObject::HashSection DynamicObject::hash_section() const
|
||||
{
|
||||
return HashSection(Section(*this, m_hash_table_offset, 0, 0, "DT_HASH"), HashType::SYSV);
|
||||
}
|
||||
|
||||
const ELFDynamicObject::RelocationSection ELFDynamicObject::relocation_section() const
|
||||
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 ELFDynamicObject::RelocationSection ELFDynamicObject::plt_relocation_section() const
|
||||
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 ELFDynamicObject::HashSection::calculate_elf_hash(const char* name) const
|
||||
u32 DynamicObject::HashSection::calculate_elf_hash(const char* name) const
|
||||
{
|
||||
// SYSV ELF hash algorithm
|
||||
// Note that the GNU HASH algorithm has less collisions
|
||||
|
@ -226,13 +228,13 @@ u32 ELFDynamicObject::HashSection::calculate_elf_hash(const char* name) const
|
|||
return hash;
|
||||
}
|
||||
|
||||
u32 ELFDynamicObject::HashSection::calculate_gnu_hash(const char*) const
|
||||
u32 DynamicObject::HashSection::calculate_gnu_hash(const char*) const
|
||||
{
|
||||
// FIXME: Implement the GNU hash algorithm
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
const ELFDynamicObject::Symbol ELFDynamicObject::HashSection::lookup_symbol(const char* name) const
|
||||
const DynamicObject::Symbol DynamicObject::HashSection::lookup_symbol(const char* name) const
|
||||
{
|
||||
// FIXME: If we enable gnu hash in the compiler, we should use that here instead
|
||||
// The algo is way better with less collisions
|
||||
|
@ -262,7 +264,7 @@ const ELFDynamicObject::Symbol ELFDynamicObject::HashSection::lookup_symbol(cons
|
|||
return m_dynamic.the_undefined_symbol();
|
||||
}
|
||||
|
||||
const char* ELFDynamicObject::symbol_string_table_string(Elf32_Word index) const
|
||||
const char* DynamicObject::symbol_string_table_string(Elf32_Word index) const
|
||||
{
|
||||
return (const char*)base_address().offset(m_string_table_offset + index).as_ptr();
|
||||
}
|
||||
|
@ -358,3 +360,5 @@ static const char* name_for_dtag(Elf32_Sword d_tag)
|
|||
return "??";
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace ELF
|
|
@ -30,10 +30,12 @@
|
|||
#include <LibBareMetal/Memory/VirtualAddress.h>
|
||||
#include <LibELF/exec_elf.h>
|
||||
|
||||
class ELFDynamicObject {
|
||||
namespace ELF {
|
||||
|
||||
class DynamicObject {
|
||||
public:
|
||||
explicit ELFDynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_address);
|
||||
~ELFDynamicObject();
|
||||
explicit DynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_address);
|
||||
~DynamicObject();
|
||||
void dump() const;
|
||||
|
||||
class DynamicEntry;
|
||||
|
@ -62,7 +64,7 @@ public:
|
|||
|
||||
class Symbol {
|
||||
public:
|
||||
Symbol(const ELFDynamicObject& dynamic, unsigned index, const Elf32_Sym& sym)
|
||||
Symbol(const DynamicObject& dynamic, unsigned index, const Elf32_Sym& sym)
|
||||
: m_dynamic(dynamic)
|
||||
, m_sym(sym)
|
||||
, m_index(index)
|
||||
|
@ -82,14 +84,14 @@ public:
|
|||
VirtualAddress address() const { return m_dynamic.base_address().offset(value()); }
|
||||
|
||||
private:
|
||||
const ELFDynamicObject& m_dynamic;
|
||||
const DynamicObject& m_dynamic;
|
||||
const Elf32_Sym& m_sym;
|
||||
const unsigned m_index;
|
||||
};
|
||||
|
||||
class Section {
|
||||
public:
|
||||
Section(const ELFDynamicObject& dynamic, unsigned section_offset, unsigned section_size_bytes, unsigned entry_size, const char* name)
|
||||
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)
|
||||
|
@ -109,7 +111,7 @@ public:
|
|||
protected:
|
||||
friend class RelocationSection;
|
||||
friend class HashSection;
|
||||
const ELFDynamicObject& m_dynamic;
|
||||
const DynamicObject& m_dynamic;
|
||||
unsigned m_section_offset;
|
||||
unsigned m_section_size_bytes;
|
||||
unsigned m_entry_size;
|
||||
|
@ -131,7 +133,7 @@ public:
|
|||
|
||||
class Relocation {
|
||||
public:
|
||||
Relocation(const ELFDynamicObject& dynamic, const Elf32_Rel& rel, unsigned offset_in_section)
|
||||
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)
|
||||
|
@ -148,7 +150,7 @@ public:
|
|||
VirtualAddress address() const { return m_dynamic.base_address().offset(offset()); }
|
||||
|
||||
private:
|
||||
const ELFDynamicObject& m_dynamic;
|
||||
const DynamicObject& m_dynamic;
|
||||
const Elf32_Rel& m_rel;
|
||||
const unsigned m_offset_in_section;
|
||||
};
|
||||
|
@ -261,7 +263,7 @@ private:
|
|||
};
|
||||
|
||||
template<typename F>
|
||||
inline void ELFDynamicObject::RelocationSection::for_each_relocation(F func) const
|
||||
inline void DynamicObject::RelocationSection::for_each_relocation(F func) const
|
||||
{
|
||||
for (unsigned i = 0; i < relocation_count(); ++i) {
|
||||
if (func(relocation(i)) == IterationDecision::Break)
|
||||
|
@ -270,7 +272,7 @@ inline void ELFDynamicObject::RelocationSection::for_each_relocation(F func) con
|
|||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFDynamicObject::for_each_symbol(F func) const
|
||||
inline void DynamicObject::for_each_symbol(F func) const
|
||||
{
|
||||
for (unsigned i = 0; i < symbol_count(); ++i) {
|
||||
if (func(symbol(i)) == IterationDecision::Break)
|
||||
|
@ -279,7 +281,7 @@ inline void ELFDynamicObject::for_each_symbol(F func) const
|
|||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFDynamicObject::for_each_dynamic_entry(F func) const
|
||||
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) {
|
||||
|
@ -290,3 +292,5 @@ inline void ELFDynamicObject::for_each_dynamic_entry(F func) const
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace ELF
|
|
@ -27,16 +27,18 @@
|
|||
#include <AK/Memory.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <LibELF/ELFImage.h>
|
||||
#include <LibELF/Image.h>
|
||||
|
||||
ELFImage::ELFImage(const u8* buffer, size_t size)
|
||||
namespace ELF {
|
||||
|
||||
Image::Image(const u8* buffer, size_t size)
|
||||
: m_buffer(buffer)
|
||||
, m_size(size)
|
||||
{
|
||||
m_valid = parse();
|
||||
}
|
||||
|
||||
ELFImage::~ELFImage()
|
||||
Image::~Image()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -58,7 +60,7 @@ static const char* object_file_type_to_string(Elf32_Half type)
|
|||
}
|
||||
}
|
||||
|
||||
StringView ELFImage::section_index_to_string(unsigned index) const
|
||||
StringView Image::section_index_to_string(unsigned index) const
|
||||
{
|
||||
if (index == SHN_UNDEF)
|
||||
return "Undefined";
|
||||
|
@ -67,14 +69,14 @@ StringView ELFImage::section_index_to_string(unsigned index) const
|
|||
return section(index).name();
|
||||
}
|
||||
|
||||
unsigned ELFImage::symbol_count() const
|
||||
unsigned Image::symbol_count() const
|
||||
{
|
||||
return section(m_symbol_table_section_index).entry_count();
|
||||
}
|
||||
|
||||
void ELFImage::dump() const
|
||||
void Image::dump() const
|
||||
{
|
||||
dbgprintf("ELFImage{%p} {\n", this);
|
||||
dbgprintf("Image{%p} {\n", this);
|
||||
dbgprintf(" is_valid: %u\n", is_valid());
|
||||
|
||||
if (!is_valid()) {
|
||||
|
@ -124,20 +126,20 @@ void ELFImage::dump() const
|
|||
dbgprintf("}\n");
|
||||
}
|
||||
|
||||
unsigned ELFImage::section_count() const
|
||||
unsigned Image::section_count() const
|
||||
{
|
||||
return header().e_shnum;
|
||||
}
|
||||
|
||||
unsigned ELFImage::program_header_count() const
|
||||
unsigned Image::program_header_count() const
|
||||
{
|
||||
return header().e_phnum;
|
||||
}
|
||||
|
||||
bool ELFImage::parse()
|
||||
bool Image::parse()
|
||||
{
|
||||
if (!validate_elf_header(header(), m_size)) {
|
||||
dbgputstr("ELFImage::parse(): ELF Header not valid\n");
|
||||
dbgputstr("Image::parse(): ELF Header not valid\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -163,14 +165,14 @@ bool ELFImage::parse()
|
|||
return true;
|
||||
}
|
||||
|
||||
StringView ELFImage::table_string(unsigned table_index, unsigned offset) const
|
||||
StringView Image::table_string(unsigned table_index, unsigned offset) const
|
||||
{
|
||||
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) {
|
||||
dbgprintf("SHENANIGANS! ELFImage::table_string() computed offset outside image.\n");
|
||||
dbgprintf("SHENANIGANS! Image::table_string() computed offset outside image.\n");
|
||||
return {};
|
||||
}
|
||||
size_t max_length = m_size - computed_offset;
|
||||
|
@ -178,65 +180,65 @@ StringView ELFImage::table_string(unsigned table_index, unsigned offset) const
|
|||
return { raw_data(sh.sh_offset + offset), length };
|
||||
}
|
||||
|
||||
StringView ELFImage::section_header_table_string(unsigned offset) const
|
||||
StringView Image::section_header_table_string(unsigned offset) const
|
||||
{
|
||||
return table_string(header().e_shstrndx, offset);
|
||||
}
|
||||
|
||||
StringView ELFImage::table_string(unsigned offset) const
|
||||
StringView Image::table_string(unsigned offset) const
|
||||
{
|
||||
return table_string(m_string_table_section_index, offset);
|
||||
}
|
||||
|
||||
const char* ELFImage::raw_data(unsigned offset) const
|
||||
const char* Image::raw_data(unsigned offset) const
|
||||
{
|
||||
return reinterpret_cast<const char*>(m_buffer) + offset;
|
||||
}
|
||||
|
||||
const Elf32_Ehdr& ELFImage::header() const
|
||||
const Elf32_Ehdr& Image::header() const
|
||||
{
|
||||
return *reinterpret_cast<const Elf32_Ehdr*>(raw_data(0));
|
||||
}
|
||||
|
||||
const Elf32_Phdr& ELFImage::program_header_internal(unsigned index) const
|
||||
const Elf32_Phdr& Image::program_header_internal(unsigned index) const
|
||||
{
|
||||
ASSERT(index < header().e_phnum);
|
||||
return *reinterpret_cast<const Elf32_Phdr*>(raw_data(header().e_phoff + (index * sizeof(Elf32_Phdr))));
|
||||
}
|
||||
|
||||
const Elf32_Shdr& ELFImage::section_header(unsigned index) const
|
||||
const Elf32_Shdr& Image::section_header(unsigned index) const
|
||||
{
|
||||
ASSERT(index < header().e_shnum);
|
||||
return *reinterpret_cast<const Elf32_Shdr*>(raw_data(header().e_shoff + (index * header().e_shentsize)));
|
||||
}
|
||||
|
||||
const ELFImage::Symbol ELFImage::symbol(unsigned index) const
|
||||
const Image::Symbol Image::symbol(unsigned index) const
|
||||
{
|
||||
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 ELFImage::Section ELFImage::section(unsigned index) const
|
||||
const Image::Section Image::section(unsigned index) const
|
||||
{
|
||||
ASSERT(index < section_count());
|
||||
return Section(*this, index);
|
||||
}
|
||||
|
||||
const ELFImage::ProgramHeader ELFImage::program_header(unsigned index) const
|
||||
const Image::ProgramHeader Image::program_header(unsigned index) const
|
||||
{
|
||||
ASSERT(index < program_header_count());
|
||||
return ProgramHeader(*this, index);
|
||||
}
|
||||
|
||||
const ELFImage::Relocation ELFImage::RelocationSection::relocation(unsigned index) const
|
||||
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 ELFImage::RelocationSection ELFImage::Section::relocations() const
|
||||
const Image::RelocationSection Image::Section::relocations() const
|
||||
{
|
||||
StringBuilder builder;
|
||||
builder.append(".rel");
|
||||
|
@ -246,20 +248,20 @@ const ELFImage::RelocationSection ELFImage::Section::relocations() const
|
|||
if (relocation_section.type() != SHT_REL)
|
||||
return static_cast<const RelocationSection>(m_image.section(0));
|
||||
|
||||
#ifdef ELFIMAGE_DEBUG
|
||||
#ifdef Image_DEBUG
|
||||
dbgprintf("Found relocations for %s in %s\n", name(), relocation_section.name());
|
||||
#endif
|
||||
return static_cast<const RelocationSection>(relocation_section);
|
||||
}
|
||||
|
||||
const ELFImage::Section ELFImage::lookup_section(const String& name) const
|
||||
const Image::Section Image::lookup_section(const String& name) const
|
||||
{
|
||||
if (auto it = m_sections.find(name); it != m_sections.end())
|
||||
return section((*it).value);
|
||||
return section(0);
|
||||
}
|
||||
|
||||
bool ELFImage::validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size)
|
||||
bool Image::validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size)
|
||||
{
|
||||
if (!IS_ELF(elf_header)) {
|
||||
dbgputstr("File is not an ELF file.\n");
|
||||
|
@ -358,7 +360,7 @@ bool ELFImage::validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_siz
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ELFImage::validate_program_headers(const Elf32_Ehdr& elf_header, size_t file_size, u8* buffer, size_t buffer_size, String& interpreter_path)
|
||||
bool Image::validate_program_headers(const Elf32_Ehdr& elf_header, size_t file_size, u8* buffer, size_t buffer_size, String& interpreter_path)
|
||||
{
|
||||
// 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);
|
||||
|
@ -414,8 +416,10 @@ bool ELFImage::validate_program_headers(const Elf32_Ehdr& elf_header, size_t fil
|
|||
return true;
|
||||
}
|
||||
|
||||
StringView ELFImage::Symbol::raw_data() const
|
||||
StringView Image::Symbol::raw_data() const
|
||||
{
|
||||
auto& section = this->section();
|
||||
return { section.raw_data() + (value() - section.address()), size() };
|
||||
}
|
||||
|
||||
} // end namespace ELF
|
|
@ -32,10 +32,12 @@
|
|||
#include <LibBareMetal/Memory/VirtualAddress.h>
|
||||
#include <LibELF/exec_elf.h>
|
||||
|
||||
class ELFImage {
|
||||
namespace ELF {
|
||||
|
||||
class Image {
|
||||
public:
|
||||
explicit ELFImage(const u8*, size_t);
|
||||
~ELFImage();
|
||||
explicit Image(const u8*, size_t);
|
||||
~Image();
|
||||
void dump() const;
|
||||
bool is_valid() const { return m_valid; }
|
||||
bool parse();
|
||||
|
@ -56,7 +58,7 @@ public:
|
|||
|
||||
class Symbol {
|
||||
public:
|
||||
Symbol(const ELFImage& image, unsigned index, const Elf32_Sym& sym)
|
||||
Symbol(const Image& image, unsigned index, const Elf32_Sym& sym)
|
||||
: m_image(image)
|
||||
, m_sym(sym)
|
||||
, m_index(index)
|
||||
|
@ -76,14 +78,14 @@ public:
|
|||
StringView raw_data() const;
|
||||
|
||||
private:
|
||||
const ELFImage& m_image;
|
||||
const Image& m_image;
|
||||
const Elf32_Sym& m_sym;
|
||||
const unsigned m_index;
|
||||
};
|
||||
|
||||
class ProgramHeader {
|
||||
public:
|
||||
ProgramHeader(const ELFImage& image, unsigned program_header_index)
|
||||
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)
|
||||
|
@ -106,14 +108,14 @@ public:
|
|||
Elf32_Phdr raw_header() const { return m_program_header; }
|
||||
|
||||
private:
|
||||
const ELFImage& m_image;
|
||||
const Image& m_image;
|
||||
const Elf32_Phdr& m_program_header;
|
||||
unsigned m_program_header_index { 0 };
|
||||
};
|
||||
|
||||
class Section {
|
||||
public:
|
||||
Section(const ELFImage& image, unsigned sectionIndex)
|
||||
Section(const Image& image, unsigned sectionIndex)
|
||||
: m_image(image)
|
||||
, m_section_header(image.section_header(sectionIndex))
|
||||
, m_section_index(sectionIndex)
|
||||
|
@ -137,7 +139,7 @@ public:
|
|||
|
||||
protected:
|
||||
friend class RelocationSection;
|
||||
const ELFImage& m_image;
|
||||
const Image& m_image;
|
||||
const Elf32_Shdr& m_section_header;
|
||||
unsigned m_section_index;
|
||||
};
|
||||
|
@ -156,7 +158,7 @@ public:
|
|||
|
||||
class Relocation {
|
||||
public:
|
||||
Relocation(const ELFImage& image, const Elf32_Rel& rel)
|
||||
Relocation(const Image& image, const Elf32_Rel& rel)
|
||||
: m_image(image)
|
||||
, m_rel(rel)
|
||||
{
|
||||
|
@ -170,7 +172,7 @@ public:
|
|||
const Symbol symbol() const { return m_image.symbol(symbol_index()); }
|
||||
|
||||
private:
|
||||
const ELFImage& m_image;
|
||||
const Image& m_image;
|
||||
const Elf32_Rel& m_rel;
|
||||
};
|
||||
|
||||
|
@ -224,7 +226,7 @@ private:
|
|||
};
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::for_each_section(F func) const
|
||||
inline void Image::for_each_section(F func) const
|
||||
{
|
||||
auto section_count = this->section_count();
|
||||
for (unsigned i = 0; i < section_count; ++i)
|
||||
|
@ -232,7 +234,7 @@ inline void ELFImage::for_each_section(F func) const
|
|||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::for_each_section_of_type(unsigned type, F func) const
|
||||
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) {
|
||||
|
@ -245,7 +247,7 @@ inline void ELFImage::for_each_section_of_type(unsigned type, F func) const
|
|||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::RelocationSection::for_each_relocation(F func) const
|
||||
inline void Image::RelocationSection::for_each_relocation(F func) const
|
||||
{
|
||||
auto relocation_count = this->relocation_count();
|
||||
for (unsigned i = 0; i < relocation_count; ++i) {
|
||||
|
@ -255,7 +257,7 @@ inline void ELFImage::RelocationSection::for_each_relocation(F func) const
|
|||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::for_each_symbol(F func) const
|
||||
inline void Image::for_each_symbol(F func) const
|
||||
{
|
||||
auto symbol_count = this->symbol_count();
|
||||
for (unsigned i = 0; i < symbol_count; ++i) {
|
||||
|
@ -265,9 +267,11 @@ inline void ELFImage::for_each_symbol(F func) const
|
|||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::for_each_program_header(F func) const
|
||||
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)
|
||||
func(program_header(i));
|
||||
}
|
||||
|
||||
} // end namespace ELF
|
|
@ -24,7 +24,7 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ELFLoader.h"
|
||||
#include "Loader.h"
|
||||
#include <AK/Demangle.h>
|
||||
#include <AK/Memory.h>
|
||||
#include <AK/QuickSort.h>
|
||||
|
@ -36,21 +36,23 @@
|
|||
# define do_memcpy memcpy
|
||||
#endif
|
||||
|
||||
//#define ELFLOADER_DEBUG
|
||||
//#define Loader_DEBUG
|
||||
|
||||
ELFLoader::ELFLoader(const u8* buffer, size_t size)
|
||||
namespace ELF {
|
||||
|
||||
Loader::Loader(const u8* buffer, size_t size)
|
||||
: m_image(buffer, size)
|
||||
{
|
||||
m_symbol_count = m_image.symbol_count();
|
||||
}
|
||||
|
||||
ELFLoader::~ELFLoader()
|
||||
Loader::~Loader()
|
||||
{
|
||||
}
|
||||
|
||||
bool ELFLoader::load()
|
||||
bool Loader::load()
|
||||
{
|
||||
#ifdef ELFLOADER_DEBUG
|
||||
#ifdef Loader_DEBUG
|
||||
m_image.dump();
|
||||
#endif
|
||||
if (!m_image.is_valid())
|
||||
|
@ -62,10 +64,10 @@ bool ELFLoader::load()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ELFLoader::layout()
|
||||
bool Loader::layout()
|
||||
{
|
||||
bool failed = false;
|
||||
m_image.for_each_program_header([&](const ELFImage::ProgramHeader& program_header) {
|
||||
m_image.for_each_program_header([&](const Image::ProgramHeader& program_header) {
|
||||
if (program_header.type() == PT_TLS) {
|
||||
#ifdef KERNEL
|
||||
auto* tls_image = tls_section_hook(program_header.size_in_memory(), program_header.alignment());
|
||||
|
@ -84,7 +86,7 @@ bool ELFLoader::layout()
|
|||
}
|
||||
if (program_header.type() != PT_LOAD)
|
||||
return;
|
||||
#ifdef ELFLOADER_DEBUG
|
||||
#ifdef Loader_DEBUG
|
||||
kprintf("PH: V%p %u r:%u w:%u\n", program_header.vaddr().get(), program_header.size_in_memory(), program_header.is_readable(), program_header.is_writable());
|
||||
#endif
|
||||
#ifdef KERNEL
|
||||
|
@ -134,10 +136,10 @@ bool ELFLoader::layout()
|
|||
return !failed;
|
||||
}
|
||||
|
||||
char* ELFLoader::symbol_ptr(const char* name)
|
||||
char* Loader::symbol_ptr(const char* name)
|
||||
{
|
||||
char* found_ptr = nullptr;
|
||||
m_image.for_each_symbol([&](const ELFImage::Symbol symbol) {
|
||||
m_image.for_each_symbol([&](const Image::Symbol symbol) {
|
||||
if (symbol.type() != STT_FUNC)
|
||||
return IterationDecision::Continue;
|
||||
if (symbol.name() == name)
|
||||
|
@ -152,7 +154,7 @@ char* ELFLoader::symbol_ptr(const char* name)
|
|||
}
|
||||
|
||||
#ifndef KERNEL
|
||||
Optional<ELFImage::Symbol> ELFLoader::find_symbol(u32 address, u32* out_offset) const
|
||||
Optional<Image::Symbol> Loader::find_symbol(u32 address, u32* out_offset) const
|
||||
{
|
||||
if (!m_symbol_count)
|
||||
return {};
|
||||
|
@ -201,7 +203,7 @@ Optional<ELFImage::Symbol> ELFLoader::find_symbol(u32 address, u32* out_offset)
|
|||
}
|
||||
#endif
|
||||
|
||||
String ELFLoader::symbolicate(u32 address, u32* out_offset) const
|
||||
String Loader::symbolicate(u32 address, u32* out_offset) const
|
||||
{
|
||||
if (!m_symbol_count) {
|
||||
if (out_offset)
|
||||
|
@ -266,3 +268,5 @@ String ELFLoader::symbolicate(u32 address, u32* out_offset) const
|
|||
*out_offset = 0;
|
||||
return "??";
|
||||
}
|
||||
|
||||
} // end namespace ELF
|
|
@ -31,7 +31,7 @@
|
|||
#include <AK/OwnPtr.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibELF/ELFImage.h>
|
||||
#include <LibELF/Image.h>
|
||||
|
||||
#ifdef KERNEL
|
||||
# include <LibBareMetal/Memory/VirtualAddress.h>
|
||||
|
@ -40,10 +40,12 @@ class Region;
|
|||
}
|
||||
#endif
|
||||
|
||||
class ELFLoader {
|
||||
namespace ELF {
|
||||
|
||||
class Loader {
|
||||
public:
|
||||
explicit ELFLoader(const u8*, size_t);
|
||||
~ELFLoader();
|
||||
explicit Loader(const u8*, size_t);
|
||||
~Loader();
|
||||
|
||||
bool load();
|
||||
#if defined(KERNEL)
|
||||
|
@ -57,13 +59,13 @@ public:
|
|||
bool has_symbols() const { return m_symbol_count; }
|
||||
|
||||
String symbolicate(u32 address, u32* offset = nullptr) const;
|
||||
Optional<ELFImage::Symbol> find_symbol(u32 address, u32* offset = nullptr) const;
|
||||
Optional<Image::Symbol> find_symbol(u32 address, u32* offset = nullptr) const;
|
||||
|
||||
private:
|
||||
bool layout();
|
||||
bool perform_relocations();
|
||||
void* lookup(const ELFImage::Symbol&);
|
||||
char* area_for_section(const ELFImage::Section&);
|
||||
void* lookup(const ELF::Image::Symbol&);
|
||||
char* area_for_section(const ELF::Image::Section&);
|
||||
char* area_for_section_name(const char*);
|
||||
|
||||
struct PtrAndSize {
|
||||
|
@ -77,7 +79,7 @@ private:
|
|||
char* ptr { nullptr };
|
||||
unsigned size { 0 };
|
||||
};
|
||||
ELFImage m_image;
|
||||
Image m_image;
|
||||
|
||||
size_t m_symbol_count { 0 };
|
||||
|
||||
|
@ -86,7 +88,7 @@ private:
|
|||
StringView name;
|
||||
#ifndef KERNEL
|
||||
String demangled_name;
|
||||
Optional<ELFImage::Symbol> symbol;
|
||||
Optional<Image::Symbol> symbol;
|
||||
#endif
|
||||
};
|
||||
#ifdef KERNEL
|
||||
|
@ -95,3 +97,5 @@ private:
|
|||
mutable Vector<SortedSymbol> m_sorted_symbols;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // end namespace ELF
|
Loading…
Add table
Reference in a new issue