mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
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:
parent
c917fcbac4
commit
efe4da57df
Notes:
sideshowbarker
2024-07-19 00:51:20 +09:00
Author: https://github.com/itamar8910 Commit: https://github.com/SerenityOS/serenity/commit/efe4da57dfc Pull-request: https://github.com/SerenityOS/serenity/pull/3738 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/alimpfard Reviewed-by: https://github.com/awesomekling
28 changed files with 401 additions and 173 deletions
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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("/.."))
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__));
|
||||
|
|
|
@ -33,4 +33,4 @@ set(SOURCES
|
|||
)
|
||||
|
||||
serenity_lib(LibCore core)
|
||||
target_link_libraries(LibCore LibC)
|
||||
target_link_libraries(LibCore LibC LibCrypt)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -33,4 +33,4 @@ set(SOURCES
|
|||
)
|
||||
|
||||
serenity_lib(LibGfx gfx)
|
||||
target_link_libraries(LibGfx LibM LibCore)
|
||||
target_link_libraries(LibGfx LibM LibCore LibIPC)
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__));
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue