Loader: Stabilize loader & Use shared libraries everywhere :^)

The dynamic loader is now stable enough to be used everywhere in the
system - so this commit does just that.
No More .a Files, Long Live .so's!
This commit is contained in:
Itamar 2020-10-17 14:39:36 +03:00 committed by Andreas Kling
parent c917fcbac4
commit efe4da57df
Notes: sideshowbarker 2024-07-19 00:51:20 +09:00
28 changed files with 401 additions and 173 deletions

View file

@ -212,8 +212,9 @@ int main(int argc, char** argv)
sa.sa_handler = handle_sigint;
sigaction(SIGINT, &sa, nullptr);
bool rc = g_debug_session->insert_breakpoint(g_debug_session->elf().entry().as_ptr());
ASSERT(rc);
// bool rc = g_debug_session->insert_breakpoint(g_debug_session->elf().entry().as_ptr());
// bool rc = g_debug_session->insert_breakpoint((void*)0x08048f49);
// ASSERT(rc);
Debug::DebugInfo::SourcePosition previous_source_position;
bool in_step_line = false;

View file

@ -119,8 +119,19 @@ endfunction()
function(serenity_lib target_name fs_name)
serenity_install_headers(${target_name})
serenity_install_sources("Libraries/${target_name}")
add_library(${target_name} ${SOURCES} ${GENERATED_SOURCES})
install(TARGETS ${target_name} ARCHIVE DESTINATION usr/lib)
#add_library(${target_name} SHARED ${SOURCES} ${GENERATED_SOURCES})
add_library(${target_name} SHARED ${SOURCES} ${GENERATED_SOURCES} ${CMAKE_SOURCE_DIR}/Libraries/LibC/crt0_shared.cpp)
#library_sources("{target_name}" PRIVATE ${CMAKE_SOURCE_DIR}/Libraries/LibC/crt0_shared.cpp)
install(TARGETS ${target_name} DESTINATION usr/lib)
set_target_properties(${target_name} PROPERTIES OUTPUT_NAME ${fs_name})
serenity_generated_sources(${target_name})
endfunction()
function(serenity_shared_lib target_name fs_name)
serenity_install_headers(${target_name})
serenity_install_sources("Libraries/${target_name}")
add_library(${target_name} SHARED ${SOURCES} ${GENERATED_SOURCES})
install(TARGETS ${target_name} DESTINATION usr/lib)
set_target_properties(${target_name} PROPERTIES OUTPUT_NAME ${fs_name})
serenity_generated_sources(${target_name})
endfunction()
@ -128,16 +139,7 @@ endfunction()
function(serenity_libc target_name fs_name)
serenity_install_headers("")
serenity_install_sources("Libraries/LibC")
add_library(${target_name} ${SOURCES})
install(TARGETS ${target_name} ARCHIVE DESTINATION usr/lib)
set_target_properties(${target_name} PROPERTIES OUTPUT_NAME ${fs_name})
target_link_directories(LibC PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
serenity_generated_sources(${target_name})
endfunction()
function(serenity_libc_shared target_name fs_name)
serenity_install_headers("")
serenity_install_sources("Libraries/LibC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib -fpic")
add_library(${target_name} SHARED ${SOURCES})
install(TARGETS ${target_name} DESTINATION usr/lib)
set_target_properties(${target_name} PROPERTIES OUTPUT_NAME ${fs_name})
@ -147,6 +149,7 @@ endfunction()
function(serenity_bin target_name)
add_executable(${target_name} ${SOURCES})
target_sources(${target_name} PRIVATE ${CMAKE_SOURCE_DIR}/Libraries/LibC/crt0_shared.cpp)
install(TARGETS ${target_name} RUNTIME DESTINATION bin)
serenity_generated_sources(${target_name})
endfunction()
@ -220,8 +223,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -g1 -fno-exceptions -fno-rtti -Wno-a
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffile-prefix-map=${CMAKE_SOURCE_DIR}=.")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG -DSANITIZE_PTRS")
set(CMAKE_CXX_FLAGS_WITHOUT_STATIC ${CMAKE_CXX_FLAGS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
set(CMAKE_CXX_FLAGS_STATIC ${CMAKE_CXX_FLAGS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostartfiles -lgcc_s -pie -fpic")
add_link_options(--sysroot ${CMAKE_BINARY_DIR}/Root)
include_directories(Libraries/LibC)

View file

@ -1,6 +1,6 @@
add_subdirectory(Cube)
add_subdirectory(DynamicObject)
add_subdirectory(DynamicLink)
#add_subdirectory(DynamicLink)
add_subdirectory(Eyes)
add_subdirectory(Fire)
add_subdirectory(HelloWorld)

View file

@ -3,9 +3,9 @@ set(SOURCES
../../Libraries/LibC/crt0_shared.cpp
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_WITHOUT_STATIC} -nostartfiles -pie -fpic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostartfiles -lgcc_s -pie -fpic ")
serenity_bin(DynamicObjectDemo)
target_link_libraries(DynamicObjectDemo SampleLib LibCShared)
target_link_libraries(DynamicObjectDemo SampleLib LibC LibCore LibGUI)
add_subdirectory(SampleLib)

View file

@ -3,9 +3,9 @@ set(SOURCES
lib.cpp
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_WIHTOUT_STATIC} -nostdlib -fpic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib -fpic")
add_library(SampleLib SHARED ${SOURCES})
target_link_libraries(SampleLib LibCShared)
target_link_libraries(SampleLib LibC)
#target_link_libraries(SampleLib)
install(TARGETS SampleLib DESTINATION usr/lib)

View file

@ -1,3 +1,28 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
* 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 "../lib.h"

View file

@ -1,3 +1,30 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
* 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
int func();

View file

@ -1,4 +1,37 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
* 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 "lib.h"
#include <LibCore/Command.h>
#include <LibGUI/Application.h>
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Button.h>
#include <LibGUI/Label.h>
#include <LibGUI/Widget.h>
#include <LibGUI/Window.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/internals.h>
@ -19,6 +52,34 @@ int main(int argc, char** argv, char** env)
int _errno = errno;
perror("open failed");
printf("rc: %d, errno: %d\n", rc, _errno);
return func() + g_tls1 + g_tls2;
}
printf("ls: %s\n", Core::command("ls", {}).characters());
auto app = GUI::Application::construct(argc, argv);
auto window = GUI::Window::construct();
window->resize(240, 160);
window->set_title("Hello World!");
window->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/app-hello-world.png"));
auto& main_widget = window->set_main_widget<GUI::Widget>();
main_widget.set_fill_with_background_color(true);
main_widget.set_background_color(Color::White);
auto& layout = main_widget.set_layout<GUI::VerticalBoxLayout>();
layout.set_margins({ 4, 4, 4, 4 });
auto& label = main_widget.add<GUI::Label>();
label.set_text("Hello\nWorld!");
auto& button = main_widget.add<GUI::Button>();
button.set_text("Good-bye");
button.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed);
button.set_preferred_size(0, 20);
button.on_click = [&](auto) {
app->quit();
};
window->show();
return app->exec();
// return func() + g_tls1 + g_tls2;
}

View file

@ -3,6 +3,8 @@ set(KERNEL_HEAP_SOURCES
Heap/kmalloc.cpp
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_STATIC}")
set(KERNEL_SOURCES
ACPI/DynamicParser.cpp
ACPI/Initialize.cpp

View file

@ -841,6 +841,8 @@ KResult VFS::validate_path_against_process_veil(StringView path, int options)
{
if (Process::current()->veil_state() == VeilState::None)
return KSuccess;
if (path == "/usr/lib/Loader.so")
return KSuccess;
// FIXME: Figure out a nicer way to do this.
if (String(path).contains("/.."))

View file

@ -423,7 +423,7 @@ public:
int exec(String path, Vector<String> arguments, Vector<String> environment, int recusion_depth = 0);
struct LoadResult {
FlatPtr load_offset { 0 };
FlatPtr load_base { 0 };
FlatPtr entry_eip { 0 };
size_t size { 0 };
FlatPtr program_headers { 0 };
@ -581,7 +581,7 @@ private:
gid_t m_sgid { 0 };
ThreadID m_exec_tid { 0 };
FlatPtr m_load_offset { 0U };
FlatPtr m_load_base { 0U };
FlatPtr m_entry_eip { 0U };
int m_main_program_fd { -1 };

View file

@ -80,6 +80,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_
size_t master_tls_size = 0;
size_t master_tls_alignment = 0;
m_entry_eip = 0;
FlatPtr load_base_address = 0;
MM.enter_process_paging_scope(*this);
String object_name = LexicalPath(object_description.absolute_path()).basename();
@ -96,6 +97,8 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_
prot |= PROT_EXEC;
if (auto* region = allocate_region_with_vmobject(vaddr.offset(load_offset), size, *vmobject, offset_in_image, String(name), prot)) {
region->set_shared(true);
if (offset_in_image == 0)
load_base_address = (FlatPtr)region->vaddr().as_ptr();
return region->vaddr().as_ptr();
}
return nullptr;
@ -137,7 +140,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_
// NOTE: At this point, we've committed to the new executable.
return LoadResult {
load_offset,
load_base_address,
loader->entry().offset(load_offset).get(),
(size_t)loader_metadata.size,
VirtualAddress(loader->image().program_header_table_offset()).offset(load_offset).get(),
@ -175,7 +178,7 @@ int Process::load(NonnullRefPtr<FileDescription> main_program_description, RefPt
if (result.is_error())
return result.error();
m_load_offset = result.value().load_offset;
m_load_base = result.value().load_base;
m_entry_eip = result.value().entry_eip;
m_master_tls_region = result.value().tls_region;
m_master_tls_size = result.value().tls_size;
@ -192,7 +195,7 @@ int Process::load(NonnullRefPtr<FileDescription> main_program_description, RefPt
if (interpreter_load_result.is_error())
return interpreter_load_result.error();
m_load_offset = interpreter_load_result.value().load_offset;
m_load_base = interpreter_load_result.value().load_base;
m_entry_eip = interpreter_load_result.value().entry_eip;
// TLS allocation will be done in userspace by the loader
@ -357,7 +360,7 @@ Vector<AuxiliaryValue> Process::generate_auxiliary_vector() const
// PHDR/EXECFD
// PH*
auxv.append({ AuxiliaryValue::PageSize, PAGE_SIZE });
auxv.append({ AuxiliaryValue::BaseAddress, (void*)m_load_offset });
auxv.append({ AuxiliaryValue::BaseAddress, (void*)m_load_base });
auxv.append({ AuxiliaryValue::Entry, (void*)m_entry_eip });
// NOTELF

View file

@ -422,8 +422,6 @@ void* Process::sys$allocate_tls(size_t size)
{
REQUIRE_PROMISE(stdio);
dbg() << "allocate TLS: " << size;
if (!size)
return (void*)-EINVAL;
@ -445,7 +443,6 @@ void* Process::sys$allocate_tls(size_t size)
return (void*)-EFAULT;
m_master_tls_region = tls_region->make_weak_ptr();
dbg() << "master_tls_region: " << m_master_tls_region->vaddr();
m_master_tls_size = size;
m_master_tls_alignment = PAGE_SIZE;

View file

@ -1,7 +1,7 @@
set(LIBC_SOURCES
arpa/inet.cpp
assert.cpp
#crt0.cpp
crt0_shared.cpp
ctype.cpp
cxxabi.cpp
dirent.cpp
@ -66,12 +66,7 @@ add_custom_command(
)
set(SOURCES ${LIBC_SOURCES} ${AK_SOURCES} ${ELF_SOURCES})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib")
serenity_libc(LibC c)
target_link_libraries(LibC crt0)
add_dependencies(LibC LibM)
set(SOURCES ${SOURCES} "crt0_shared.cpp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib")
serenity_libc_shared(LibCShared c)
#add_library(LibCShared SHARED ${SOURCES})
#install(TARGETS LibCShared DESTINATION usr/lib)

View file

@ -1,3 +1,29 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
* 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 <AK/Types.h>
#include <assert.h>
#include <stdio.h>
@ -17,16 +43,11 @@ extern bool __environ_is_malloced;
int _start(int argc, char** argv, char** env);
int _start(int argc, char** argv, char** env)
{
// asm("int3");
environ = env;
__environ_is_malloced = false;
_init();
__libc_init();
// _init();
int status = main(argc, argv, environ);
int status = main(argc, argv, env);
return status;
}
}
void* __dso_handle = nullptr;
void* __dso_handle __attribute__((__weak__));

View file

@ -33,4 +33,4 @@ set(SOURCES
)
serenity_lib(LibCore core)
target_link_libraries(LibCore LibC)
target_link_libraries(LibCore LibC LibCrypt)

View file

@ -59,7 +59,7 @@ static void* mmap_with_name(void* addr, size_t length, int prot, int flags, int
namespace ELF {
static bool s_always_bind_now = true;
static bool s_always_bind_now = false;
NonnullRefPtr<DynamicLoader> DynamicLoader::construct(const char* filename, int fd, size_t size)
{
@ -90,7 +90,7 @@ DynamicLoader::DynamicLoader(const char* filename, int fd, size_t size)
m_tls_size = calculate_tls_size();
m_valid = is_valid();
m_valid = validate();
}
RefPtr<DynamicObject> DynamicLoader::dynamic_object_from_image() const
@ -121,16 +121,14 @@ size_t DynamicLoader::calculate_tls_size() const
bool DynamicLoader::validate()
{
auto* elf_header = (Elf32_Ehdr*)m_file_mapping;
if (!validate_elf_header(*elf_header, m_file_size) || !validate_program_headers(*elf_header, m_file_size, (u8*)m_file_mapping, m_file_size, &m_program_interpreter)) {
m_valid = false;
}
return validate_elf_header(*elf_header, m_file_size) && validate_program_headers(*elf_header, m_file_size, (u8*)m_file_mapping, m_file_size, &m_program_interpreter);
}
DynamicLoader::~DynamicLoader()
{
if (MAP_FAILED != m_file_mapping)
munmap(m_file_mapping, m_file_size);
close(m_image_fd);
}
void* DynamicLoader::symbol_for_name(const char* name)
@ -161,6 +159,8 @@ RefPtr<DynamicObject> DynamicLoader::load_from_image(unsigned flags, size_t tota
m_dynamic_object = DynamicObject::construct(m_text_segment_load_address, m_dynamic_section_address);
m_dynamic_object->set_tls_offset(m_tls_offset);
m_dynamic_object->set_tls_size(m_tls_size);
ASSERT(m_global_symbol_lookup_func);
m_dynamic_object->m_global_symbol_lookup_func = m_global_symbol_lookup_func;
auto rc = load_stage_2(flags, total_tls_size);
if (!rc)
@ -171,14 +171,13 @@ RefPtr<DynamicObject> DynamicLoader::load_from_image(unsigned flags, size_t tota
bool DynamicLoader::load_stage_2(unsigned flags, size_t total_tls_size)
{
ASSERT(flags & RTLD_GLOBAL);
ASSERT(!(flags & RTLD_LAZY));
#ifdef DYNAMIC_LOAD_DEBUG
m_dynamic_object->dump();
#endif
if (m_dynamic_object->has_text_relocations()) {
dbg() << "Someone linked non -fPIC code into " << m_filename << " :(";
// dbg() << "Someone linked non -fPIC code into " << m_filename << " :(";
ASSERT(m_text_segment_load_address.get() != 0);
if (0 > mprotect(m_text_segment_load_address.as_ptr(), m_text_segment_size, PROT_READ | PROT_WRITE)) {
perror("mprotect .text: PROT_READ | PROT_WRITE"); // FIXME: dlerror?
@ -189,7 +188,6 @@ bool DynamicLoader::load_stage_2(unsigned flags, size_t total_tls_size)
do_relocations(total_tls_size);
if (flags & RTLD_LAZY) {
ASSERT_NOT_REACHED(); // TODO: Support lazy binding
setup_plt_trampoline();
}
@ -203,9 +201,7 @@ bool DynamicLoader::load_stage_2(unsigned flags, size_t total_tls_size)
call_object_init_functions();
#ifdef DYNAMIC_LOAD_DEBUG
dbgprintf("Loaded %s\n", m_filename.characters());
#endif
VERBOSE("Loaded %s\n", m_filename.characters());
return true;
}
@ -239,7 +235,13 @@ void DynamicLoader::load_program_headers()
// Process regions in order: .text, .data, .tls
auto* region = text_region_ptr;
void* text_segment_begin = mmap_with_name(nullptr, region->required_load_size(), region->mmap_prot(), MAP_PRIVATE, m_image_fd, region->offset(), String::format(".text: %s", m_filename.characters()).characters());
void* text_segment_begin = mmap_with_name(nullptr,
region->required_load_size(),
region->mmap_prot(),
MAP_PRIVATE,
m_image_fd,
region->offset(),
String::format("%s: .text", m_filename.characters()).characters());
if (MAP_FAILED == text_segment_begin) {
ASSERT_NOT_REACHED();
}
@ -249,7 +251,13 @@ void DynamicLoader::load_program_headers()
m_dynamic_section_address = dynamic_region_desired_vaddr.offset(m_text_segment_load_address.get());
region = data_region_ptr;
void* data_segment_begin = mmap_with_name((u8*)text_segment_begin + m_text_segment_size, region->required_load_size(), region->mmap_prot(), MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, String::format(".data: %s", m_filename.characters()).characters());
void* data_segment_begin = mmap_with_name((u8*)text_segment_begin + m_text_segment_size,
region->required_load_size(),
region->mmap_prot(),
MAP_ANONYMOUS | MAP_PRIVATE,
0,
0,
String::format("%s: .data", m_filename.characters()).characters());
if (MAP_FAILED == data_segment_begin) {
ASSERT_NOT_REACHED();
}
@ -279,7 +287,10 @@ void DynamicLoader::do_relocations(size_t total_tls_size)
auto symbol = relocation.symbol();
VERBOSE("Absolute relocation: name: '%s', value: %p\n", symbol.name(), symbol.value());
auto res = lookup_symbol(symbol);
ASSERT(res.found);
if (!res.found) {
dbgln("ERROR: symbol not found: {}", symbol.name());
ASSERT_NOT_REACHED();
}
u32 symbol_address = res.address;
*patch_ptr += symbol_address;
VERBOSE(" Symbol address: %p\n", *patch_ptr);
@ -298,13 +309,16 @@ void DynamicLoader::do_relocations(size_t total_tls_size)
case R_386_GLOB_DAT: {
auto symbol = relocation.symbol();
if (!strcmp(symbol.name(), "__deregister_frame_info") || !strcmp(symbol.name(), "_ITM_registerTMCloneTable")
|| !strcmp(symbol.name(), "_ITM_deregisterTMCloneTable") || !strcmp(symbol.name(), "__register_frame_info")) {
|| !strcmp(symbol.name(), "_ITM_deregisterTMCloneTable") || !strcmp(symbol.name(), "__register_frame_info")
|| !strcmp(symbol.name(), "__cxa_finalize") // __cxa_finalize will be called from libc's exit()
) {
// We do not support these
break;
}
VERBOSE("Global data relocation: '%s', value: %p\n", symbol.name(), symbol.value());
auto res = lookup_symbol(symbol);
VERBOSE("was symbol found? %d, address: 0x%x\n", res.found, res.address);
ASSERT(res.found);
if (!res.found) {
// TODO this is a hack
@ -331,28 +345,28 @@ void DynamicLoader::do_relocations(size_t total_tls_size)
}
case R_386_TLS_TPOFF32:
case R_386_TLS_TPOFF: {
dbgprintf("Relocation type: R_386_TLS_TPOFF at offset %X\n", relocation.offset());
VERBOSE("Relocation type: R_386_TLS_TPOFF at offset %X\n", relocation.offset());
auto symbol = relocation.symbol();
// For some reason, LibC has a R_386_TLS_TPOFF that referes to the undefined symbol.. huh
if (relocation.symbol_index() == 0)
break;
dbgprintf("Symbol index: %d\n", symbol.index());
dbgprintf("Symbol is_undefined?: %d\n", symbol.is_undefined());
dbgprintf("TLS relocation: '%s', value: %p\n", symbol.name(), symbol.value());
VERBOSE("Symbol index: %d\n", symbol.index());
VERBOSE("Symbol is_undefined?: %d\n", symbol.is_undefined());
VERBOSE("TLS relocation: '%s', value: %p\n", symbol.name(), symbol.value());
auto res = lookup_symbol(symbol);
if (!res.found)
break;
ASSERT(res.found);
u32 symbol_value = res.value;
dbgprintf("symbol value: %d\n", symbol_value);
VERBOSE("symbol value: %d\n", symbol_value);
const auto dynamic_object_of_symbol = res.dynamic_object;
ASSERT(dynamic_object_of_symbol);
size_t offset_of_tls_end = dynamic_object_of_symbol->tls_offset().value() + dynamic_object_of_symbol->tls_size().value();
// size_t offset_of_tls_end = tls_offset() + tls_size();
dbgprintf("patch ptr: 0x%x\n", patch_ptr);
dbgprintf("tls end offset: %d, total tls size: %d\n", offset_of_tls_end, total_tls_size);
VERBOSE("patch ptr: 0x%x\n", patch_ptr);
VERBOSE("tls end offset: %d, total tls size: %d\n", offset_of_tls_end, total_tls_size);
*patch_ptr = (offset_of_tls_end - total_tls_size - symbol_value - sizeof(Elf32_Addr));
dbgprintf("*patch ptr: %d\n", (i32)*patch_ptr);
VERBOSE("*patch ptr: %d\n", (i32)*patch_ptr);
break;
}
default:
@ -376,8 +390,8 @@ void DynamicLoader::do_relocations(size_t total_tls_size)
if (m_dynamic_object->must_bind_now() || s_always_bind_now) {
// Eagerly BIND_NOW the PLT entries, doing all the symbol looking goodness
// The patch method returns the address for the LAZY fixup path, but we don't need it here
VERBOSE("patching plt reloaction: 0x%x", relocation.offset_in_section());
(void)patch_plt_entry(relocation.offset_in_section());
VERBOSE("patching plt reloaction: 0x%x\n", relocation.offset_in_section());
(void)m_dynamic_object->patch_plt_entry(relocation.offset_in_section());
} else {
// LAZY-ily bind the PLT slots by just adding the base address to the offsets stored there
// This avoids doing symbol lookup, which might be expensive
@ -390,9 +404,7 @@ void DynamicLoader::do_relocations(size_t total_tls_size)
return IterationDecision::Continue;
});
#ifdef DYNAMIC_LOAD_DEBUG
dbgprintf("Done relocating!\n");
#endif
VERBOSE("Done relocating!\n");
}
// Defined in <arch>/plt_trampoline.S
@ -400,57 +412,32 @@ extern "C" void _plt_trampoline(void) __attribute__((visibility("hidden")));
void DynamicLoader::setup_plt_trampoline()
{
ASSERT(m_dynamic_object);
VirtualAddress got_address = m_dynamic_object->plt_got_base_address();
FlatPtr* got_ptr = (FlatPtr*)got_address.as_ptr();
got_ptr[1] = (FlatPtr)this;
got_ptr[1] = (FlatPtr)m_dynamic_object.ptr();
got_ptr[2] = (FlatPtr)&_plt_trampoline;
#ifdef DYNAMIC_LOAD_DEBUG
dbgprintf("Set GOT PLT entries at %p: [0] = %p [1] = %p, [2] = %p\n", got_ptr, (void*)got_ptr[0], (void*)got_ptr[1], (void*)got_ptr[2]);
#endif
VERBOSE("Set GOT PLT entries at %p: [0] = %p [1] = %p, [2] = %p\n", got_ptr, (void*)got_ptr[0], (void*)got_ptr[1], (void*)got_ptr[2]);
}
// Called from our ASM routine _plt_trampoline.
// Tell the compiler that it might be called from other places:
extern "C" Elf32_Addr _fixup_plt_entry(DynamicLoader* object, u32 relocation_offset);
extern "C" Elf32_Addr _fixup_plt_entry(DynamicLoader* object, u32 relocation_offset)
extern "C" Elf32_Addr _fixup_plt_entry(DynamicObject* object, u32 relocation_offset);
extern "C" Elf32_Addr _fixup_plt_entry(DynamicObject* object, u32 relocation_offset)
{
return object->patch_plt_entry(relocation_offset);
}
// offset is in PLT relocation table
Elf32_Addr DynamicLoader::patch_plt_entry(u32 relocation_offset)
{
auto relocation = m_dynamic_object->plt_relocation_section().relocation_at_offset(relocation_offset);
ASSERT(relocation.type() == R_386_JMP_SLOT);
auto sym = relocation.symbol();
u8* relocation_address = relocation.address().as_ptr();
auto res = lookup_symbol(sym);
ASSERT(res.found);
u32 symbol_location = res.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 DynamicLoader::call_object_init_functions()
{
dbg() << "inside call_object_init_functions of " << m_filename;
typedef void (*InitFunc)();
if (m_dynamic_object->has_init_section()) {
auto init_function = (InitFunc)(m_dynamic_object->init_section().address().as_ptr());
// #ifdef DYNAMIC_LOAD_DEBUG
dbgprintf("Calling DT_INIT at %p\n", init_function);
// #endif
VERBOSE("Calling DT_INIT at %p\n", init_function);
(init_function)();
}
@ -464,9 +451,7 @@ void DynamicLoader::call_object_init_functions()
// 0 definitely shows up. Apparently 0/-1 are valid? Confusing.
if (!*init_begin || ((FlatPtr)*init_begin == (FlatPtr)-1))
continue;
// #ifdef DYNAMIC_LOAD_DEBUG
dbgprintf("Calling DT_INITARRAY entry at %p\n", *init_begin);
// #endif
VERBOSE("Calling DT_INITARRAY entry at %p\n", *init_begin);
(*init_begin)();
++init_begin;
}
@ -484,22 +469,7 @@ u32 DynamicLoader::ProgramHeaderRegion::mmap_prot() const
DynamicObject::SymbolLookupResult DynamicLoader::lookup_symbol(const ELF::DynamicObject::Symbol& symbol) const
{
VERBOSE("looking up symbol: %s\n", symbol.name());
if (!symbol.is_undefined()) {
VERBOSE("symbol is defiend in its object\n");
return { true, symbol.value(), (FlatPtr)symbol.address().as_ptr(), &symbol.object() };
}
ASSERT(m_global_symbol_lookup_func);
return m_global_symbol_lookup_func(symbol.name());
return m_dynamic_object->lookup_symbol(symbol);
}
// Optional<DynamicLoader::SymbolLookupResult> DynamicLoader::lookup_symbol(const char* name) const
// {
// ASSERT(m_dynamic_object);
// auto res = m_dynamic_object->hash_section().lookup_symbol(name);
// if (res.is_undefined())
// return {};
// return SymbolLookupResult { true, res.value(), (FlatPtr)res.address().as_ptr(), m_dynamic_object.ptr() };
// }
} // end namespace ELF

View file

@ -62,9 +62,6 @@ public:
void dump();
// Will be called from _fixup_plt_entry, as part of the PLT trampoline
Elf32_Addr patch_plt_entry(u32 relocation_offset);
// Requested program interpreter from program headers. May be empty string
StringView program_interpreter() const { return m_program_interpreter; }
@ -78,8 +75,8 @@ public:
template<typename F>
void for_each_needed_library(F) const;
using SymbolLookupFunction = DynamicObject::SymbolLookupResult (*)(const char*);
SymbolLookupFunction m_global_symbol_lookup_func { nullptr };
DynamicObject::SymbolLookupFunction m_global_symbol_lookup_func { nullptr };
void set_global_symbol_lookup_function(DynamicObject::SymbolLookupFunction func) { m_global_symbol_lookup_func = func; }
VirtualAddress text_segment_load_address() const { return m_text_segment_load_address; }

View file

@ -32,6 +32,16 @@
#include <stdio.h>
#include <string.h>
// #define DYNAMIC_OBJECT_VERBOSE
#ifdef DYNAMIC_OBJECT_VERBOSE
# define VERBOSE(fmt, ...) dbgprintf(fmt, ##__VA_ARGS__)
#else
# define VERBOSE(fmt, ...) \
do { \
} while (0)
#endif
namespace ELF {
static const char* name_for_dtag(Elf32_Sword d_tag);
@ -63,8 +73,8 @@ void DynamicObject::dump() const
if (m_has_soname)
builder.appendf("DT_SONAME: %s\n", soname()); // FIXME: Valdidate that this string is null terminated?
dbgprintf("Dynamic section at address %p contains %zu entries:\n", m_dynamic_address.as_ptr(), num_dynamic_sections);
dbgprintf("%s", builder.to_string().characters());
VERBOSE("Dynamic section at address %p contains %zu entries:\n", m_dynamic_address.as_ptr(), num_dynamic_sections);
VERBOSE("%s", builder.to_string().characters());
}
void DynamicObject::parse()
@ -402,4 +412,46 @@ NonnullRefPtr<DynamicObject> DynamicObject::construct(VirtualAddress base_addres
return adopt(*new DynamicObject(base_address, dynamic_section_address));
}
// offset is in PLT relocation table
Elf32_Addr DynamicObject::patch_plt_entry(u32 relocation_offset)
{
auto relocation = plt_relocation_section().relocation_at_offset(relocation_offset);
ASSERT(relocation.type() == R_386_JMP_SLOT);
auto sym = relocation.symbol();
if (StringView { sym.name() } == "__cxa_demangle") {
dbgln("__cxa_demangle is currently not supported for shared objects");
// FIXME: Where is it defined?
ASSERT_NOT_REACHED();
}
u8* relocation_address = relocation.address().as_ptr();
auto res = lookup_symbol(sym);
if (!res.found) {
dbgln("did not find symbol: {} ", sym.name());
ASSERT_NOT_REACHED();
}
u32 symbol_location = res.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;
}
DynamicObject::SymbolLookupResult DynamicObject::lookup_symbol(const ELF::DynamicObject::Symbol& symbol) const
{
VERBOSE("looking up symbol: %s\n", symbol.name());
if (!symbol.is_undefined()) {
VERBOSE("symbol is defiend in its object\n");
return { true, symbol.value(), (FlatPtr)symbol.address().as_ptr(), &symbol.object() };
}
ASSERT(m_global_symbol_lookup_func);
return m_global_symbol_lookup_func(symbol.name());
}
} // end namespace ELF

View file

@ -267,6 +267,13 @@ public:
};
Optional<SymbolLookupResult> lookup_symbol(const char* name) const;
// Will be called from _fixup_plt_entry, as part of the PLT trampoline
Elf32_Addr patch_plt_entry(u32 relocation_offset);
SymbolLookupResult lookup_symbol(const ELF::DynamicObject::Symbol& symbol) const;
using SymbolLookupFunction = DynamicObject::SymbolLookupResult (*)(const char*);
SymbolLookupFunction m_global_symbol_lookup_func { nullptr };
private:
explicit DynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_address);

View file

@ -95,4 +95,4 @@ set(GENERATED_SOURCES
)
serenity_lib(LibGUI gui)
target_link_libraries(LibGUI LibCore LibGfx LibIPC LibThread LibCpp LibRegex)
target_link_libraries(LibGUI LibCore LibGfx LibIPC LibThread LibCpp LibShell LibRegex LibJS)

View file

@ -33,4 +33,4 @@ set(SOURCES
)
serenity_lib(LibGfx gfx)
target_link_libraries(LibGfx LibM LibCore)
target_link_libraries(LibGfx LibM LibCore LibIPC)

View file

@ -2,6 +2,9 @@ set(SOURCES
math.cpp
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib")
serenity_libc(LibM m)
target_include_directories(LibM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(LibM LibC)
#target_link_libraries(LibM)
#set_target_properties(LibM PROPERTIES OUTPUT_NAME m)
#target_link_directories(LibM PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

View file

@ -5,11 +5,13 @@ foreach(CMD_SRC ${CMD_SOURCES})
get_filename_component(CMD_NAME ${CMD_SRC} NAME_WE)
if (CMD_NAME IN_LIST SPECIAL_TARGETS)
add_executable("${CMD_NAME}-bin" ${CMD_SRC})
target_sources("${CMD_NAME}-bin" PRIVATE ${CMAKE_SOURCE_DIR}/Libraries/LibC/crt0_shared.cpp)
target_link_libraries("${CMD_NAME}-bin" LibCore)
install(TARGETS "${CMD_NAME}-bin" RUNTIME DESTINATION bin)
install(CODE "execute_process(COMMAND mv ${CMD_NAME}-bin ${CMD_NAME} WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin)")
else ()
add_executable(${CMD_NAME} ${CMD_SRC})
target_sources("${CMD_NAME}" PRIVATE ${CMAKE_SOURCE_DIR}/Libraries/LibC/crt0_shared.cpp)
target_link_libraries(${CMD_NAME} LibCore)
install(TARGETS ${CMD_NAME} RUNTIME DESTINATION bin)
endif()

View file

@ -63,6 +63,7 @@ static HashMap<String, NonnullRefPtr<ELF::DynamicObject>> g_loaded_objects;
static size_t g_current_tls_offset = 0;
static size_t g_total_tls_size = 0;
static char** g_envp = nullptr;
static void init_libc()
{
@ -72,30 +73,37 @@ static void init_libc()
__malloc_init();
}
static void perform_self_relocations()
static void perform_self_relocations(auxv_t* auxvp)
{
// We need to relocate ourselves.
// (these relocations seem to be generated because of our vtables)
// TODO: Pass this address in the Auxiliary Vector
u32 base = 0x08000000;
Elf32_Ehdr* header = (Elf32_Ehdr*)(base);
Elf32_Phdr* pheader = (Elf32_Phdr*)(base + header->e_phoff);
FlatPtr base_address = 0;
bool found_base_address = false;
for (; auxvp->a_type != AT_NULL; ++auxvp) {
if (auxvp->a_type == AuxiliaryValue::BaseAddress) {
base_address = auxvp->a_un.a_val;
found_base_address = true;
}
}
ASSERT(found_base_address);
Elf32_Ehdr* header = (Elf32_Ehdr*)(base_address);
Elf32_Phdr* pheader = (Elf32_Phdr*)(base_address + header->e_phoff);
u32 dynamic_section_addr = 0;
for (size_t i = 0; i < (size_t)header->e_phnum; ++i, ++pheader) {
if (pheader->p_type != PT_DYNAMIC)
continue;
dynamic_section_addr = pheader->p_vaddr + base;
dynamic_section_addr = pheader->p_vaddr + base_address;
}
if (!dynamic_section_addr)
exit(1);
auto dynamic_object = ELF::DynamicObject::construct((VirtualAddress(base)), (VirtualAddress(dynamic_section_addr)));
auto dynamic_object = ELF::DynamicObject::construct((VirtualAddress(base_address)), (VirtualAddress(dynamic_section_addr)));
dynamic_object->relocation_section().for_each_relocation([base](auto& reloc) {
dynamic_object->relocation_section().for_each_relocation([base_address](auto& reloc) {
if (reloc.type() != R_386_RELATIVE)
return IterationDecision::Continue;
*(u32*)reloc.address().as_ptr() += base;
*(u32*)reloc.address().as_ptr() += base_address;
return IterationDecision::Continue;
});
}
@ -110,7 +118,7 @@ static ELF::DynamicObject::SymbolLookupResult global_symbol_lookup(const char* s
continue;
return res.value();
}
ASSERT_NOT_REACHED();
// ASSERT_NOT_REACHED();
return {};
}
@ -122,7 +130,7 @@ static void map_library(const String& name, int fd)
auto loader = ELF::DynamicLoader::construct(name.characters(), fd, lib_stat.st_size);
loader->set_tls_offset(g_current_tls_offset);
loader->m_global_symbol_lookup_func = global_symbol_lookup;
loader->set_global_symbol_lookup_function(global_symbol_lookup);
g_loaders.set(name, loader);
@ -143,51 +151,94 @@ static String get_library_name(const StringView& path)
return LexicalPath(path).basename();
}
static Vector<String> get_dependencies(const String& name)
{
auto lib = g_loaders.get(name).value();
Vector<String> dependencies;
lib->for_each_needed_library([&dependencies](auto needed_name) {
dependencies.append(needed_name);
return IterationDecision::Continue;
});
return dependencies;
}
static void map_dependencies(const String& name)
{
dbg() << "mapping dependencies for: " << name;
auto lib = g_loaders.get(name).value();
lib->for_each_needed_library([](auto needed_name) {
dbg() << "needed library: " << needed_name;
VERBOSE("mapping dependencies for: %s", name.characters());
for (const auto& needed_name : get_dependencies(name)) {
VERBOSE("needed library: %s", needed_name.characters());
String library_name = get_library_name(needed_name);
if (!g_loaders.contains(library_name)) {
map_library(library_name);
map_dependencies(library_name);
}
return IterationDecision::Continue;
});
}
}
static void allocate_tls()
{
size_t total_tls_size = 0;
for (const auto& data : g_loaders) {
VERBOSE("%s: TLS Size: %u\n", data.key.characters(), data.value->tls_size());
total_tls_size += data.value->tls_size();
}
if (total_tls_size) {
void* tls_address = allocate_tls(total_tls_size);
dbg() << "from userspace, tls_address: " << tls_address;
(void)tls_address;
VERBOSE("from userspace, tls_address: %p", tls_address);
}
g_total_tls_size = total_tls_size;
}
static void initialize_libc()
{
// Traditionally, `_start` of the main program initializes libc.
// However, since some libs use malloc() and getenv() in global constructors,
// we have to initialize libc just after it is loaded.
// Also, we can't just mark `__libc_init` with "__attribute__((constructor))"
// because it uses getenv() internally, so `environ` has to be initialized before we call `__libc_init`.
auto res = global_symbol_lookup("environ");
*((char***)res.address) = g_envp;
ASSERT(res.found);
res = global_symbol_lookup("__environ_is_malloced");
ASSERT(res.found);
*((bool*)res.address) = false;
res = global_symbol_lookup("__libc_init");
ASSERT(res.found);
typedef void libc_init_func(void);
((libc_init_func*)res.address)();
}
static void load_elf(const String& name)
{
dbg() << "load_elf: " << name;
VERBOSE("load_elf: %s", name.characters());
auto loader = g_loaders.get(name).value();
loader->for_each_needed_library([](auto needed_name) {
dbg() << "needed library: " << needed_name;
for (const auto& needed_name : get_dependencies(name)) {
VERBOSE("needed library: %s", needed_name.characters());
String library_name = get_library_name(needed_name);
if (!g_loaded_objects.contains(library_name)) {
load_elf(library_name);
}
return IterationDecision::Continue;
});
}
auto dynamic_object = loader->load_from_image(RTLD_GLOBAL, g_total_tls_size);
VERBOSE("loading: %s", name.characters());
auto dynamic_object = loader->load_from_image(RTLD_GLOBAL | RTLD_LAZY, g_total_tls_size);
ASSERT(!dynamic_object.is_null());
g_loaded_objects.set(name, dynamic_object.release_nonnull());
if (name == "libc.so") {
initialize_libc();
}
}
static void clear_temporary_objects_mappings()
{
g_loaders.clear();
}
static FlatPtr loader_main(auxv_t* auxvp)
@ -205,9 +256,10 @@ static FlatPtr loader_main(auxv_t* auxvp)
map_library(main_program_name, main_program_fd);
map_dependencies(main_program_name);
dbg() << "loaded all dependencies";
VERBOSE("loaded all dependencies");
for (auto& lib : g_loaders) {
dbg() << lib.key << "- tls size: " << lib.value->tls_size() << ", tls offset: " << lib.value->tls_offset();
(void)lib;
VERBOSE("%s - tls size: $u, tls offset: %u", lib.key.characters(), lib.value->tls_size(), lib.value->tls_offset());
}
allocate_tls();
@ -216,10 +268,10 @@ static FlatPtr loader_main(auxv_t* auxvp)
auto main_program_lib = g_loaders.get(main_program_name).value();
FlatPtr entry_point = reinterpret_cast<FlatPtr>(main_program_lib->image().entry().as_ptr() + (FlatPtr)main_program_lib->text_segment_load_address().as_ptr());
dbg() << "entry point: " << (void*)entry_point;
VERBOSE("entry point: %p", entry_point);
// This will unmap the temporary memory maps we had for loading the libraries
g_loaders.clear();
clear_temporary_objects_mappings();
return entry_point;
}
@ -233,20 +285,26 @@ using MainFunction = int (*)(int, char**, char**);
void _start(int argc, char** argv, char** envp)
{
perform_self_relocations();
init_libc();
g_envp = envp;
char** env;
for (env = envp; *env; ++env) {
}
auxv_t* auxvp = (auxv_t*)++env;
perform_self_relocations(auxvp);
init_libc();
FlatPtr entry = loader_main(auxvp);
VERBOSE("Loaded libs:\n");
for (auto& obj : g_loaded_objects) {
(void)obj;
VERBOSE("%s: %p\n", obj.key.characters(), obj.value->base_address().as_ptr());
}
MainFunction main_function = (MainFunction)(entry);
dbg() << "jumping to main program entry point: " << (void*)main_function;
VERBOSE("jumping to main program entry point: %p", main_function);
int rc = main_function(argc, argv, envp);
dbg() << "rc: " << rc;
sleep(100);
VERBOSE("rc: %d", rc);
_exit(rc);
}
}

View file

@ -34,6 +34,5 @@ const char* __cxa_demangle(const char*, void*, void*, int*)
return "";
}
// FIXME: Is this correct?
void* __dso_handle = nullptr;
void* __dso_handle __attribute__((__weak__));
}

View file

@ -3,6 +3,7 @@ file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp")
foreach(CMD_SRC ${CMD_SOURCES})
get_filename_component(CMD_NAME ${CMD_SRC} NAME_WE)
add_executable(${CMD_NAME} ${CMD_SRC})
target_sources("${CMD_NAME}" PRIVATE ${CMAKE_SOURCE_DIR}/Libraries/LibC/crt0_shared.cpp)
target_link_libraries(${CMD_NAME} LibCore)
install(TARGETS ${CMD_NAME} RUNTIME DESTINATION usr/Tests/Kernel)
endforeach()

View file

@ -3,6 +3,7 @@ file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp")
foreach(CMD_SRC ${CMD_SOURCES})
get_filename_component(CMD_NAME ${CMD_SRC} NAME_WE)
add_executable(${CMD_NAME} ${CMD_SRC})
target_sources("${CMD_NAME}" PRIVATE ${CMAKE_SOURCE_DIR}/Libraries/LibC/crt0_shared.cpp)
target_link_libraries(${CMD_NAME} LibCore)
install(TARGETS ${CMD_NAME} RUNTIME DESTINATION usr/Tests/LibC)
endforeach()