2020-10-10 18:17:49 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
|
|
|
|
*
|
2021-04-22 11:24:48 +03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-10-10 18:17:49 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <LibELF/AuxiliaryVector.h>
|
2021-01-02 02:54:43 +03:00
|
|
|
#include <LibELF/DynamicLinker.h>
|
2021-07-26 16:03:29 +03:00
|
|
|
#include <LibELF/Relocation.h>
|
2023-01-03 17:30:44 +03:00
|
|
|
#include <sys/internals.h>
|
|
|
|
#include <unistd.h>
|
2020-10-10 18:17:49 +03:00
|
|
|
|
|
|
|
char* __static_environ[] = { nullptr }; // We don't get the environment without some libc workarounds..
|
|
|
|
|
|
|
|
static void init_libc()
|
|
|
|
{
|
|
|
|
environ = __static_environ;
|
|
|
|
__environ_is_malloced = false;
|
|
|
|
__stdio_is_initialized = false;
|
2021-01-02 02:54:43 +03:00
|
|
|
// Initialise the copy of libc included statically in Loader.so,
|
|
|
|
// initialisation of the dynamic libc.so is done by the DynamicLinker
|
|
|
|
__libc_init();
|
2020-10-10 18:17:49 +03:00
|
|
|
}
|
|
|
|
|
2020-10-17 14:39:36 +03:00
|
|
|
static void perform_self_relocations(auxv_t* auxvp)
|
2020-10-10 18:17:49 +03:00
|
|
|
{
|
|
|
|
// We need to relocate ourselves.
|
|
|
|
// (these relocations seem to be generated because of our vtables)
|
|
|
|
|
2020-10-17 14:39:36 +03:00
|
|
|
FlatPtr base_address = 0;
|
|
|
|
bool found_base_address = false;
|
|
|
|
for (; auxvp->a_type != AT_NULL; ++auxvp) {
|
2020-12-25 16:48:30 +03:00
|
|
|
if (auxvp->a_type == ELF::AuxiliaryValue::BaseAddress) {
|
2020-10-17 14:39:36 +03:00
|
|
|
base_address = auxvp->a_un.a_val;
|
|
|
|
found_base_address = true;
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 22:42:32 +03:00
|
|
|
VERIFY(found_base_address);
|
2021-07-26 16:03:29 +03:00
|
|
|
if (!ELF::perform_relative_relocations(base_address))
|
2021-07-06 11:17:11 +03:00
|
|
|
exit(1);
|
2020-10-10 18:17:49 +03:00
|
|
|
}
|
|
|
|
|
2020-12-31 00:48:42 +03:00
|
|
|
static void display_help()
|
|
|
|
{
|
2022-04-01 20:58:27 +03:00
|
|
|
char const message[] =
|
2020-12-31 00:48:42 +03:00
|
|
|
R"(You have invoked `Loader.so'. This is the helper program for programs that
|
|
|
|
use shared libraries. Special directives embedded in executables tell the
|
|
|
|
kernel to load this program.
|
|
|
|
|
|
|
|
This helper program loads the shared libraries needed by the program,
|
|
|
|
prepares the program to run, and runs it. You do not need to invoke
|
|
|
|
this helper program directly.
|
|
|
|
)";
|
2021-01-02 02:54:43 +03:00
|
|
|
fprintf(stderr, "%s", message);
|
2020-12-31 00:48:42 +03:00
|
|
|
}
|
|
|
|
|
2021-01-02 02:54:43 +03:00
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
// The compiler expects a previous declaration
|
2021-09-05 17:08:13 +03:00
|
|
|
void _start(int, char**, char**) __attribute__((used));
|
|
|
|
void _entry(int, char**, char**) __attribute__((used));
|
2021-01-02 02:54:43 +03:00
|
|
|
|
2021-07-11 16:57:56 +03:00
|
|
|
NAKED void _start(int, char**, char**)
|
|
|
|
{
|
2023-04-14 17:44:17 +03:00
|
|
|
#if ARCH(AARCH64)
|
2022-10-12 23:18:24 +03:00
|
|
|
asm(
|
|
|
|
"bl _entry\n");
|
|
|
|
#else
|
2021-07-11 16:57:56 +03:00
|
|
|
asm(
|
|
|
|
"push $0\n"
|
|
|
|
"jmp _entry@plt\n");
|
2022-10-12 23:18:24 +03:00
|
|
|
#endif
|
2021-07-11 16:57:56 +03:00
|
|
|
}
|
2021-07-09 01:58:43 +03:00
|
|
|
|
|
|
|
void _entry(int argc, char** argv, char** envp)
|
2020-10-10 18:17:49 +03:00
|
|
|
{
|
2021-01-02 02:54:43 +03:00
|
|
|
char** env;
|
|
|
|
for (env = envp; *env; ++env) {
|
|
|
|
}
|
|
|
|
|
|
|
|
auxv_t* auxvp = (auxv_t*)++env;
|
|
|
|
perform_self_relocations(auxvp);
|
|
|
|
init_libc();
|
|
|
|
|
2020-10-10 18:17:49 +03:00
|
|
|
int main_program_fd = -1;
|
2022-12-04 21:02:33 +03:00
|
|
|
DeprecatedString main_program_path;
|
2021-01-09 10:51:44 +03:00
|
|
|
bool is_secure = false;
|
2020-10-10 18:17:49 +03:00
|
|
|
for (; auxvp->a_type != AT_NULL; ++auxvp) {
|
2020-12-25 16:48:30 +03:00
|
|
|
if (auxvp->a_type == ELF::AuxiliaryValue::ExecFileDescriptor) {
|
2020-10-10 18:17:49 +03:00
|
|
|
main_program_fd = auxvp->a_un.a_val;
|
|
|
|
}
|
2020-12-25 16:48:30 +03:00
|
|
|
if (auxvp->a_type == ELF::AuxiliaryValue::ExecFilename) {
|
2022-10-28 17:30:27 +03:00
|
|
|
main_program_path = (char const*)auxvp->a_un.a_ptr;
|
2020-11-11 22:13:55 +03:00
|
|
|
}
|
2021-01-09 10:51:44 +03:00
|
|
|
if (auxvp->a_type == ELF::AuxiliaryValue::Secure) {
|
|
|
|
is_secure = auxvp->a_un.a_val == 1;
|
|
|
|
}
|
2020-10-10 18:17:49 +03:00
|
|
|
}
|
|
|
|
|
2022-10-28 17:30:27 +03:00
|
|
|
if (main_program_path == "/usr/lib/Loader.so"sv) {
|
2020-12-31 00:48:42 +03:00
|
|
|
// We've been invoked directly as an executable rather than as the
|
|
|
|
// ELF interpreter for some other binary. In the future we may want
|
|
|
|
// to support launching a program directly from the dynamic loader
|
|
|
|
// like ld.so on Linux.
|
|
|
|
display_help();
|
|
|
|
_exit(1);
|
|
|
|
}
|
|
|
|
|
2021-02-23 22:42:32 +03:00
|
|
|
VERIFY(main_program_fd >= 0);
|
2022-10-28 17:30:27 +03:00
|
|
|
VERIFY(!main_program_path.is_empty());
|
2021-01-03 00:31:01 +03:00
|
|
|
|
2022-10-28 17:30:27 +03:00
|
|
|
ELF::DynamicLinker::linker_main(move(main_program_path), main_program_fd, is_secure, argc, argv, envp);
|
2021-02-23 22:42:32 +03:00
|
|
|
VERIFY_NOT_REACHED();
|
2020-10-10 18:17:49 +03:00
|
|
|
}
|
|
|
|
}
|