1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-01 06:38:10 +00:00

LibELF+LibC: Split ELFDynamicObject into a Loader + Object

Separate some responsibilities:

ELFDynamicLoader is responsible for loading elf binaries from disk and
performing relocations, calling init functions, and eventually calling
finalizer functions.

ELFDynamicObject is a helper class to parse the .dynamic section of an
elf binary, or the table of Elf32_Dyn entries at the _DYNAMIC symbol.
ELFDynamicObject now owns the helper classes for Relocations, Symbols,
Sections and the like that ELFDynamicLoader will use to perform
relocations and symbol lookup.

Because these new helpers are constructed from offsets into the .dynamic
section within the loaded .data section of the binary, we don't need the
ELFImage for nearly as much of the loading processes as we did before.
Therefore we can remove most of the extra DynamicXXX classes and just
keep the one that lets us find the location of _DYNAMIC in the new ELF.

And finally, since we changed the name of the class that dlopen/dlsym
care about, we need to compile/link and use the new ELFDynamicLoader
class in LibC.
This commit is contained in:
Andrew Kaster 2020-01-03 23:31:51 -05:00 committed by Andreas Kling
parent 85b95f472d
commit 767f4c7421
8 changed files with 788 additions and 634 deletions

View file

@ -12,12 +12,12 @@
#include <AK/ScopeGuard.h>
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <LibELF/ELFDynamicObject.h>
#include <LibELF/ELFDynamicLoader.h>
// NOTE: The string here should never include a trailing newline (according to POSIX)
String g_dlerror_msg;
HashMap<String, RefPtr<ELFDynamicObject>> g_elf_objects;
HashMap<String, RefPtr<ELFDynamicLoader>> g_elf_objects;
extern "C" {
@ -68,19 +68,19 @@ void* dlopen(const char* filename, int flags)
return nullptr;
}
auto image = ELFDynamicObject::construct(filename, fd, file_stats.st_size);
auto loader = ELFDynamicLoader::construct(filename, fd, file_stats.st_size);
if (!image->is_valid()) {
if (!loader->is_valid()) {
g_dlerror_msg = String::format("%s is not a valid ELF dynamic shared object!", filename);
return nullptr;
}
if (!image->load(flags)) {
if (!loader->load_from_image(flags)) {
g_dlerror_msg = String::format("Failed to load ELF object %s", filename);
return nullptr;
}
g_elf_objects.set(file_path.basename(), move(image));
g_elf_objects.set(file_path.basename(), move(loader));
g_dlerror_msg = "Successfully loaded ELF object.";
// we have one refcount already
@ -91,7 +91,7 @@ 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<ELFDynamicObject*>(handle);
auto* dso = reinterpret_cast<ELFDynamicLoader*>(handle);
void* symbol = dso->symbol_for_name(symbol_name);
if (!symbol) {
g_dlerror_msg = "Symbol not found";