mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[ld.so] Add a minimal dynamic linker
This commit includes a number of changes to enable loading of PIE executables: - The loader in srv.init checks for a `PT_INTERP` segment in the program its loading, and if it exists, loads the specified interpreter and passes control to it instead of the program itself. - Added ld.so the dynamic linker executable and set it as the interpreter for all user-target programs. - Program initial stack changed again to now contain a number of possible tagged structures, including a new one for ld.so's arguments, and for passing handles tagged with protocol ids. - Added a stub for a new VFS protocol. Unused so far, but srv.init will need to serve VFS requests from ld.so once I transition libraries to shared libs for user-target programs. (Right now all executables are PIE but statically linked, so they only need internal relocations.) - Added 16 and 8 bit variants of `util::bitset`. This ended up not being used, but could be useful.
This commit is contained in:
70
src/user/ld.so/main.cpp
Normal file
70
src/user/ld.so/main.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <elf/headers.h>
|
||||
#include <j6/init.h>
|
||||
#include <j6/syslog.hh>
|
||||
#include <util/pointers.h>
|
||||
#include "relocate.h"
|
||||
|
||||
uintptr_t
|
||||
locate_dyn_section(uintptr_t base, uintptr_t phdr, size_t phdr_size, size_t phdr_count)
|
||||
{
|
||||
if (!phdr || !phdr_count)
|
||||
return 0;
|
||||
|
||||
const elf::segment_header *ph_base =
|
||||
reinterpret_cast<const elf::segment_header*>(phdr + base);
|
||||
|
||||
for (size_t i = 0; i < phdr_count; ++i) {
|
||||
const elf::segment_header *ph =
|
||||
util::offset_pointer(ph_base, i*phdr_size);
|
||||
|
||||
if (ph->type == elf::segment_type::dynamic)
|
||||
return ph->vaddr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" uintptr_t
|
||||
ldso_init(j6_arg_header *stack_args, uintptr_t const *got)
|
||||
{
|
||||
j6_arg_loader *arg_loader = nullptr;
|
||||
j6_arg_handles *arg_handles = nullptr;
|
||||
|
||||
j6_arg_header *arg = stack_args;
|
||||
while (arg && arg->type != j6_arg_type_none) {
|
||||
switch (arg->type)
|
||||
{
|
||||
case j6_arg_type_loader:
|
||||
arg_loader = reinterpret_cast<j6_arg_loader*>(arg);
|
||||
break;
|
||||
|
||||
case j6_arg_type_handles:
|
||||
arg_handles = reinterpret_cast<j6_arg_handles*>(arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
arg = util::offset_pointer(arg, arg->size);
|
||||
}
|
||||
|
||||
if (!arg_loader) {
|
||||
j6::syslog("ld.so: error: did not get j6_arg_loader");
|
||||
exit(127);
|
||||
}
|
||||
|
||||
relocate_image(arg_loader->loader_base, got[0]);
|
||||
|
||||
uintptr_t dyn_section = locate_dyn_section(
|
||||
arg_loader->image_base,
|
||||
arg_loader->phdr,
|
||||
arg_loader->phdr_size,
|
||||
arg_loader->phdr_count);
|
||||
relocate_image(arg_loader->image_base, dyn_section);
|
||||
|
||||
return arg_loader->entrypoint + arg_loader->image_base;
|
||||
}
|
||||
Reference in New Issue
Block a user