From 57417a3d6efe872d26cc790c5cc009dac3a3c8be Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Mon, 26 Jul 2021 15:10:51 +0200 Subject: [PATCH] Kernel: Support loading the kernel at almost arbitrary virtual addresses This enables further work on implementing KASLR by adding relocation support to the pre-kernel and updating the kernel to be less dependent on specific virtual memory layouts. --- Kernel/Arch/x86/i386/Boot/ap_setup.S | 2 +- Kernel/Arch/x86/x86_64/Boot/ap_setup.S | 2 +- Kernel/BootInfo.h | 3 +- Kernel/CMakeLists.txt | 6 +- Kernel/GlobalProcessExposed.cpp | 2 +- Kernel/KSyms.cpp | 4 +- Kernel/Prekernel/CMakeLists.txt | 3 + Kernel/Prekernel/Prekernel.h | 5 +- Kernel/Prekernel/boot.S | 7 +- Kernel/Prekernel/init.cpp | 95 ++++++++++++------- Kernel/Process.cpp | 2 +- Kernel/Sections.h | 6 +- Kernel/VM/MemoryManager.cpp | 2 +- Kernel/VM/PageDirectory.cpp | 6 +- Kernel/VM/Region.h | 2 +- Kernel/init.cpp | 6 +- Kernel/linker.ld | 38 ++++---- Meta/debug-kernel.sh | 9 +- Userland/DevTools/Profiler/Profile.cpp | 2 +- .../LibSymbolication/Symbolication.cpp | 8 +- 20 files changed, 123 insertions(+), 87 deletions(-) diff --git a/Kernel/Arch/x86/i386/Boot/ap_setup.S b/Kernel/Arch/x86/i386/Boot/ap_setup.S index d7de94ea3c..0a7df2f280 100644 --- a/Kernel/Arch/x86/i386/Boot/ap_setup.S +++ b/Kernel/Arch/x86/i386/Boot/ap_setup.S @@ -109,7 +109,7 @@ apic_ap_start32_2: /* push the Processor pointer this CPU is going to use */ movl (ap_cpu_init_processor_info_array - apic_ap_start)(%ebp), %eax - addl kernel_base, %eax + addl kernel_load_base, %eax movl 0(%eax, %esi, 4), %eax push %eax diff --git a/Kernel/Arch/x86/x86_64/Boot/ap_setup.S b/Kernel/Arch/x86/x86_64/Boot/ap_setup.S index d34fa9b9ee..47c7f0aa86 100644 --- a/Kernel/Arch/x86/x86_64/Boot/ap_setup.S +++ b/Kernel/Arch/x86/x86_64/Boot/ap_setup.S @@ -141,7 +141,7 @@ apic_ap_start64: /* push the Processor pointer this CPU is going to use */ movq (ap_cpu_init_processor_info_array - apic_ap_start)(%ebp), %rax - leaq kernel_base(%rip), %r8 + leaq kernel_load_base(%rip), %r8 movq (%r8), %r8 addq %r8, %rax movq 0(%rax, %rsi, 4), %rax diff --git a/Kernel/BootInfo.h b/Kernel/BootInfo.h index 2b6399998c..6ecc813788 100644 --- a/Kernel/BootInfo.h +++ b/Kernel/BootInfo.h @@ -14,7 +14,8 @@ extern "C" PhysicalAddress start_of_prekernel_image; extern "C" PhysicalAddress end_of_prekernel_image; extern "C" size_t physical_to_virtual_offset; -extern "C" FlatPtr kernel_base; +extern "C" FlatPtr kernel_mapping_base; +extern "C" FlatPtr kernel_load_base; #if ARCH(X86_64) extern "C" u32 gdt64ptr; extern "C" u16 code64_sel; diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index c10e3a0088..285b5ff950 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -16,8 +16,6 @@ set(KERNEL_HEAP_SOURCES Heap/kmalloc.cpp ) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_STATIC}") - set(KERNEL_SOURCES ACPI/DynamicParser.cpp ACPI/Initialize.cpp @@ -350,7 +348,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-80387 -mno-mmx -mno-sse -mno-sse2") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-asynchronous-unwind-tables") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-strong") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib -nostdinc -nostdinc++") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nodefaultlibs -nostdlib -nostdinc -nostdinc++") # Apply any flags that are only available on >= GCC 11.1 if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.1) @@ -365,7 +363,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -faligned-new=4") endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pie -Wl,--no-dynamic-linker") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-pie") # Kernel Coverage (KCOV) is an API to collect and expose program counters of # kernel code that has been run to user space. It's rather slow and likely not diff --git a/Kernel/GlobalProcessExposed.cpp b/Kernel/GlobalProcessExposed.cpp index 5243264654..6cdb3f2a7d 100644 --- a/Kernel/GlobalProcessExposed.cpp +++ b/Kernel/GlobalProcessExposed.cpp @@ -720,7 +720,7 @@ private: { if (!Process::current()->is_superuser()) return false; - builder.append(String::number(kernel_base)); + builder.append(String::number(kernel_load_base)); return true; } }; diff --git a/Kernel/KSyms.cpp b/Kernel/KSyms.cpp index 2e309aa3b4..c4f32b9beb 100644 --- a/Kernel/KSyms.cpp +++ b/Kernel/KSyms.cpp @@ -83,7 +83,7 @@ UNMAP_AFTER_INIT static void load_kernel_symbols_from_data(ReadonlyBytes const& } } auto& ksym = s_symbols[current_symbol_index]; - ksym.address = address; + ksym.address = kernel_load_base + address; char* name = static_cast(kmalloc_eternal((bufptr - start_of_name) + 1)); memcpy(name, start_of_name, bufptr - start_of_name); name[bufptr - start_of_name] = '\0'; @@ -118,7 +118,7 @@ NEVER_INLINE static void dump_backtrace_impl(FlatPtr base_pointer, bool use_ksym if (use_ksyms) { FlatPtr copied_stack_ptr[2]; for (FlatPtr* stack_ptr = (FlatPtr*)base_pointer; stack_ptr && recognized_symbol_count < max_recognized_symbol_count; stack_ptr = (FlatPtr*)copied_stack_ptr[0]) { - if ((FlatPtr)stack_ptr < kernel_base) + if ((FlatPtr)stack_ptr < kernel_load_base) break; void* fault_at; diff --git a/Kernel/Prekernel/CMakeLists.txt b/Kernel/Prekernel/CMakeLists.txt index 1f86a2aa17..cc059d8792 100644 --- a/Kernel/Prekernel/CMakeLists.txt +++ b/Kernel/Prekernel/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCES init.cpp UBSanitizer.cpp ../MiniStdLib.cpp + ../../Userland/Libraries/LibELF/Relocation.cpp ) if ("${SERENITY_ARCH}" STREQUAL "i686") @@ -12,6 +13,8 @@ else() set(PREKERNEL_TARGET Prekernel64) endif() +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static") + add_executable(${PREKERNEL_TARGET} ${SOURCES}) target_compile_options(${PREKERNEL_TARGET} PRIVATE -no-pie -fno-pic) diff --git a/Kernel/Prekernel/Prekernel.h b/Kernel/Prekernel/Prekernel.h index 69d90faf66..92d1239a71 100644 --- a/Kernel/Prekernel/Prekernel.h +++ b/Kernel/Prekernel/Prekernel.h @@ -12,7 +12,7 @@ # include #endif -#define MAX_KERNEL_SIZE 0x3000000 +#define MAX_KERNEL_SIZE 0x4000000 #ifdef __cplusplus namespace Kernel { @@ -21,7 +21,8 @@ struct [[gnu::packed]] BootInfo { u32 start_of_prekernel_image; u32 end_of_prekernel_image; u64 physical_to_virtual_offset; - u64 kernel_base; + u64 kernel_mapping_base; + u64 kernel_load_base; # if ARCH(X86_64) u32 gdt64ptr; u16 code64_sel; diff --git a/Kernel/Prekernel/boot.S b/Kernel/Prekernel/boot.S index ae4c8b8288..28da45d577 100644 --- a/Kernel/Prekernel/boot.S +++ b/Kernel/Prekernel/boot.S @@ -31,8 +31,11 @@ boot_pd0_pts: .global boot_pd_kernel boot_pd_kernel: .skip 4096 -.global boot_pd_kernel_pts -boot_pd_kernel_pts: +.global boot_pd_kernel_pt0 +boot_pd_kernel_pt0: +.skip 4096 +.global boot_pd_kernel_image_pts +boot_pd_kernel_image_pts: .skip 4096 * (MAX_KERNEL_SIZE >> 21) .global boot_pd_kernel_pt1023 boot_pd_kernel_pt1023: diff --git a/Kernel/Prekernel/init.cpp b/Kernel/Prekernel/init.cpp index 952461a2f4..a4e9dc7fbc 100644 --- a/Kernel/Prekernel/init.cpp +++ b/Kernel/Prekernel/init.cpp @@ -12,6 +12,7 @@ #include #include #include +#include // Defined in the linker script extern size_t __stack_chk_guard; @@ -28,7 +29,8 @@ extern "C" u64 boot_pdpt[512]; extern "C" u64 boot_pd0[512]; extern "C" u64 boot_pd0_pts[512 * (MAX_KERNEL_SIZE >> 21 & 0x1ff)]; extern "C" u64 boot_pd_kernel[512]; -extern "C" u64 boot_pd_kernel_pts[512 * (MAX_KERNEL_SIZE >> 21 & 0x1ff)]; +extern "C" u64 boot_pd_kernel_pt0[512]; +extern "C" u64 boot_pd_kernel_image_pts[512 * (MAX_KERNEL_SIZE >> 21 & 0x1ff)]; extern "C" u64 boot_pd_kernel_pt1023[512]; extern "C" char const kernel_cmdline[4096]; @@ -38,10 +40,20 @@ extern "C" { multiboot_info_t* multiboot_info_ptr; } +[[noreturn]] static void halt() +{ + asm volatile("hlt"); + __builtin_unreachable(); +} + void __stack_chk_fail() { - asm("ud2"); - __builtin_unreachable(); + halt(); +} + +void __assertion_failed(char const*, char const*, unsigned int, char const*) +{ + halt(); } namespace Kernel { @@ -50,11 +62,6 @@ namespace Kernel { // We declare them here to ensure their signatures don't accidentally change. extern "C" [[noreturn]] void init(); -static void halt() -{ - asm volatile("hlt"); -} - // SerenityOS Pre-Kernel Environment C++ entry point :^) // // This is where C++ execution begins, after boot.S transfers control here. @@ -75,50 +82,63 @@ extern "C" [[noreturn]] void init() halt(); __builtin_memcpy(kernel_program_headers, kernel_image + kernel_elf_header.e_phoff, sizeof(ElfW(Phdr)) * kernel_elf_header.e_phnum); - FlatPtr kernel_load_base = 0; + FlatPtr kernel_physical_base = 0x200000; +#if ARCH(I386) + FlatPtr kernel_load_base = 0xc0200000; +#else + FlatPtr kernel_load_base = 0x2000200000; +#endif + FlatPtr kernel_load_end = 0; for (size_t i = 0; i < kernel_elf_header.e_phnum; i++) { auto& kernel_program_header = kernel_program_headers[i]; if (kernel_program_header.p_type != PT_LOAD) continue; - auto start = kernel_program_header.p_vaddr; + auto start = kernel_load_base + kernel_program_header.p_vaddr; auto end = start + kernel_program_header.p_memsz; if (start < (FlatPtr)end_of_prekernel_image) halt(); - if (kernel_program_header.p_paddr < (FlatPtr)end_of_prekernel_image) + if (kernel_physical_base + kernel_program_header.p_paddr < (FlatPtr)end_of_prekernel_image) halt(); - if (kernel_load_base == 0 || start < kernel_load_base) - kernel_load_base = start; if (end > kernel_load_end) kernel_load_end = end; } // align to 1GB - kernel_load_base &= ~(FlatPtr)0x3fffffff; + FlatPtr kernel_mapping_base = kernel_load_base & ~(FlatPtr)0x3fffffff; + + VERIFY(kernel_load_base % 0x1000 == 0); + VERIFY(kernel_load_base >= kernel_mapping_base + 0x200000); #if ARCH(I386) int pdpt_flags = 0x1; #else int pdpt_flags = 0x3; #endif - boot_pdpt[(kernel_load_base >> 30) & 0x1ffu] = (FlatPtr)boot_pd_kernel | pdpt_flags; + boot_pdpt[(kernel_mapping_base >> 30) & 0x1ffu] = (FlatPtr)boot_pd_kernel | pdpt_flags; - for (size_t i = 0; i <= (kernel_load_end - kernel_load_base) >> 21; i++) - boot_pd_kernel[i] = (FlatPtr)&boot_pd_kernel_pts[i * 512] | 0x3; + boot_pd_kernel[0] = (FlatPtr)boot_pd_kernel_pt0 | 0x3; - __builtin_memset(boot_pd_kernel_pts, 0, sizeof(boot_pd_kernel_pts)); + for (FlatPtr vaddr = kernel_load_base; vaddr <= kernel_load_end; vaddr += PAGE_SIZE * 512) + boot_pd_kernel[(vaddr - kernel_mapping_base) >> 21] = (FlatPtr)(&boot_pd_kernel_image_pts[(vaddr - kernel_load_base) >> 12]) | 0x3; + + __builtin_memset(boot_pd_kernel_pt0, 0, sizeof(boot_pd_kernel_pt0)); + + VERIFY((size_t)end_of_prekernel_image < array_size(boot_pd_kernel_pt0) * PAGE_SIZE); /* pseudo-identity map 0M - end_of_prekernel_image */ for (size_t i = 0; i < (FlatPtr)end_of_prekernel_image / PAGE_SIZE; i++) - boot_pd_kernel_pts[i] = i * PAGE_SIZE | 0x3; + boot_pd_kernel_pt0[i] = i * PAGE_SIZE | 0x3; + + __builtin_memset(boot_pd_kernel_image_pts, 0, sizeof(boot_pd_kernel_image_pts)); for (size_t i = 0; i < kernel_elf_header.e_phnum; i++) { auto& kernel_program_header = kernel_program_headers[i]; if (kernel_program_header.p_type != PT_LOAD) continue; for (FlatPtr offset = 0; offset < kernel_program_header.p_memsz; offset += PAGE_SIZE) { - auto pte_index = (kernel_program_header.p_vaddr + offset - kernel_load_base) >> 12; - boot_pd_kernel_pts[pte_index] = (kernel_program_header.p_paddr + offset) | 0x3; + auto pte_index = ((kernel_load_base & 0x1fffff) + kernel_program_header.p_vaddr + offset) >> 12; + boot_pd_kernel_image_pts[pte_index] = (kernel_physical_base + kernel_program_header.p_paddr + offset) | 0x3; } } @@ -130,28 +150,29 @@ extern "C" [[noreturn]] void init() auto& kernel_program_header = kernel_program_headers[i]; if (kernel_program_header.p_type != PT_LOAD) continue; - __builtin_memmove((u8*)kernel_program_header.p_vaddr, kernel_image + kernel_program_header.p_offset, kernel_program_header.p_filesz); + __builtin_memmove((u8*)kernel_load_base + kernel_program_header.p_vaddr, kernel_image + kernel_program_header.p_offset, kernel_program_header.p_filesz); } for (ssize_t i = kernel_elf_header.e_phnum - 1; i >= 0; i--) { auto& kernel_program_header = kernel_program_headers[i]; if (kernel_program_header.p_type != PT_LOAD) continue; - __builtin_memset((u8*)kernel_program_header.p_vaddr + kernel_program_header.p_filesz, 0, kernel_program_header.p_memsz - kernel_program_header.p_filesz); + __builtin_memset((u8*)kernel_load_base + kernel_program_header.p_vaddr + kernel_program_header.p_filesz, 0, kernel_program_header.p_memsz - kernel_program_header.p_filesz); } multiboot_info_ptr->mods_count--; multiboot_info_ptr->mods_addr += sizeof(multiboot_module_entry_t); - auto adjust_by_load_base = [kernel_load_base](auto ptr) { - return (decltype(ptr))((FlatPtr)ptr + kernel_load_base); + auto adjust_by_mapping_base = [kernel_mapping_base](auto ptr) { + return (decltype(ptr))((FlatPtr)ptr + kernel_mapping_base); }; BootInfo info; info.start_of_prekernel_image = (PhysicalPtr)start_of_prekernel_image; info.end_of_prekernel_image = (PhysicalPtr)end_of_prekernel_image; - info.physical_to_virtual_offset = kernel_load_base; - info.kernel_base = kernel_load_base; + info.physical_to_virtual_offset = kernel_load_base - kernel_physical_base; + info.kernel_mapping_base = kernel_mapping_base; + info.kernel_load_base = kernel_load_base; #if ARCH(X86_64) info.gdt64ptr = (PhysicalPtr)gdt64ptr; info.code64_sel = code64_sel; @@ -160,12 +181,12 @@ extern "C" [[noreturn]] void init() info.boot_pdpt = (PhysicalPtr)boot_pdpt; info.boot_pd0 = (PhysicalPtr)boot_pd0; info.boot_pd_kernel = (PhysicalPtr)boot_pd_kernel; - info.boot_pd_kernel_pt1023 = (FlatPtr)adjust_by_load_base(boot_pd_kernel_pt1023); - info.kernel_cmdline = (FlatPtr)adjust_by_load_base(kernel_cmdline); + info.boot_pd_kernel_pt1023 = (FlatPtr)adjust_by_mapping_base(boot_pd_kernel_pt1023); + info.kernel_cmdline = (FlatPtr)adjust_by_mapping_base(kernel_cmdline); info.multiboot_flags = multiboot_info_ptr->flags; - info.multiboot_memory_map = adjust_by_load_base((FlatPtr)multiboot_info_ptr->mmap_addr); + info.multiboot_memory_map = adjust_by_mapping_base((FlatPtr)multiboot_info_ptr->mmap_addr); info.multiboot_memory_map_count = multiboot_info_ptr->mmap_length / sizeof(multiboot_memory_map_t); - info.multiboot_modules = adjust_by_load_base((FlatPtr)multiboot_info_ptr->mods_addr); + info.multiboot_modules = adjust_by_mapping_base((FlatPtr)multiboot_info_ptr->mods_addr); info.multiboot_modules_count = multiboot_info_ptr->mods_count; info.multiboot_framebuffer_addr = multiboot_info_ptr->framebuffer_addr; info.multiboot_framebuffer_pitch = multiboot_info_ptr->framebuffer_pitch; @@ -178,9 +199,11 @@ extern "C" [[noreturn]] void init() #if ARCH(I386) "add %0, %%esp" #else - "add %0, %%rsp" + "movabs %0, %%rax\n" + "add %%rax, %%rsp" #endif - ::"g"(kernel_load_base)); + ::"g"(kernel_mapping_base) + : "ax"); // unmap the 0-1MB region for (size_t i = 0; i < 256; i++) @@ -192,8 +215,10 @@ extern "C" [[noreturn]] void init() reload_cr3(); - void (*entry)(BootInfo const&) = (void (*)(BootInfo const&))kernel_elf_header.e_entry; - entry(*adjust_by_load_base(&info)); + ELF::perform_relative_relocations(kernel_load_base); + + void (*entry)(BootInfo const&) = (void (*)(BootInfo const&))(kernel_load_base + kernel_elf_header.e_entry); + entry(*adjust_by_mapping_base(&info)); __builtin_unreachable(); } diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index a543ca32e6..0bdd9ee9e9 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -375,7 +375,7 @@ void Process::crash(int signal, FlatPtr ip, bool out_of_memory) if (out_of_memory) { dbgln("\033[31;1mOut of memory\033[m, killing: {}", *this); } else { - if (ip >= kernel_base && g_kernel_symbols_available) { + if (ip >= kernel_load_base && g_kernel_symbols_available) { auto* symbol = symbolicate_kernel_address(ip); dbgln("\033[31;1m{:p} {} +{}\033[0m\n", ip, (symbol ? symbol->name : "(k?)"), (symbol ? ip - symbol->address : 0)); } else { diff --git a/Kernel/Sections.h b/Kernel/Sections.h index 99d17965f1..4606e7c6ca 100644 --- a/Kernel/Sections.h +++ b/Kernel/Sections.h @@ -15,10 +15,10 @@ #define READONLY_AFTER_INIT __attribute__((section(".ro_after_init"))) #define UNMAP_AFTER_INIT NEVER_INLINE __attribute__((section(".unmap_after_init"))) -#define KERNEL_PD_END (kernel_base + 0x31000000) -#define KERNEL_PT1024_BASE (kernel_base + 0x3FE00000) +#define KERNEL_PD_END (kernel_mapping_base + 0x31000000) +#define KERNEL_PT1024_BASE (kernel_mapping_base + 0x3FE00000) #define KERNEL_QUICKMAP_PT (KERNEL_PT1024_BASE + 0x6000) #define KERNEL_QUICKMAP_PD (KERNEL_PT1024_BASE + 0x7000) #define KERNEL_QUICKMAP_PER_CPU_BASE (KERNEL_PT1024_BASE + 0x8000) -#define USER_RANGE_CEILING (kernel_base - 0x2000000) +#define USER_RANGE_CEILING (kernel_mapping_base - 0x2000000) diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp index bd4eeeb974..ac6f7b9228 100644 --- a/Kernel/VM/MemoryManager.cpp +++ b/Kernel/VM/MemoryManager.cpp @@ -954,7 +954,7 @@ RefPtr MemoryManager::allocate_supervisor_physical_page() return {}; } - fast_u32_fill((u32*)page->paddr().offset(kernel_base).as_ptr(), 0, PAGE_SIZE / sizeof(u32)); + fast_u32_fill((u32*)page->paddr().offset(physical_to_virtual_offset).as_ptr(), 0, PAGE_SIZE / sizeof(u32)); ++m_system_memory_info.super_physical_pages_used; return page; } diff --git a/Kernel/VM/PageDirectory.cpp b/Kernel/VM/PageDirectory.cpp index 7cf36707ae..f599e7717b 100644 --- a/Kernel/VM/PageDirectory.cpp +++ b/Kernel/VM/PageDirectory.cpp @@ -51,7 +51,7 @@ UNMAP_AFTER_INIT void PageDirectory::allocate_kernel_directory() dmesgln("MM: boot_pd_kernel @ {}", boot_pd_kernel); m_directory_table = PhysicalPage::create(boot_pdpt, MayReturnToFreeList::No); m_directory_pages[0] = PhysicalPage::create(boot_pd0, MayReturnToFreeList::No); - m_directory_pages[(kernel_base >> 30) & 0x1ff] = PhysicalPage::create(boot_pd_kernel, MayReturnToFreeList::No); + m_directory_pages[(kernel_mapping_base >> 30) & 0x1ff] = PhysicalPage::create(boot_pd_kernel, MayReturnToFreeList::No); } PageDirectory::PageDirectory(const RangeAllocator* parent_range_allocator) @@ -77,13 +77,13 @@ PageDirectory::PageDirectory(const RangeAllocator* parent_range_allocator) m_directory_table = MM.allocate_user_physical_page(); if (!m_directory_table) return; - auto kernel_pd_index = (kernel_base >> 30) & 0x1ffu; + auto kernel_pd_index = (kernel_mapping_base >> 30) & 0x1ffu; for (size_t i = 0; i < kernel_pd_index; i++) { m_directory_pages[i] = MM.allocate_user_physical_page(); if (!m_directory_pages[i]) return; } - // Share the top 1 GiB of kernel-only mappings (>=kernel_base) + // Share the top 1 GiB of kernel-only mappings (>=kernel_mapping_base) m_directory_pages[kernel_pd_index] = MM.kernel_page_directory().m_directory_pages[kernel_pd_index]; #if ARCH(X86_64) diff --git a/Kernel/VM/Region.h b/Kernel/VM/Region.h index 9f3029ea1c..4be4906083 100644 --- a/Kernel/VM/Region.h +++ b/Kernel/VM/Region.h @@ -83,7 +83,7 @@ public: void set_mmap(bool mmap) { m_mmap = mmap; } bool is_user() const { return !is_kernel(); } - bool is_kernel() const { return vaddr().get() < 0x00800000 || vaddr().get() >= kernel_base; } + bool is_kernel() const { return vaddr().get() < 0x00800000 || vaddr().get() >= kernel_mapping_base; } PageFaultResponse handle_fault(PageFault const&); diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 6a821e9c0b..3dda9f51e5 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -110,8 +110,9 @@ static Processor s_bsp_processor; // global but let's keep it "private" extern "C" { READONLY_AFTER_INIT PhysicalAddress start_of_prekernel_image; READONLY_AFTER_INIT PhysicalAddress end_of_prekernel_image; -READONLY_AFTER_INIT FlatPtr kernel_base; READONLY_AFTER_INIT size_t physical_to_virtual_offset; +READONLY_AFTER_INIT FlatPtr kernel_mapping_base; +READONLY_AFTER_INIT FlatPtr kernel_load_base; #if ARCH(X86_64) READONLY_AFTER_INIT PhysicalAddress boot_pml4t; #endif @@ -140,7 +141,8 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info) start_of_prekernel_image = PhysicalAddress { boot_info.start_of_prekernel_image }; end_of_prekernel_image = PhysicalAddress { boot_info.end_of_prekernel_image }; physical_to_virtual_offset = boot_info.physical_to_virtual_offset; - kernel_base = boot_info.kernel_base; + kernel_mapping_base = boot_info.kernel_mapping_base; + kernel_load_base = boot_info.kernel_load_base; #if ARCH(X86_64) gdt64ptr = boot_info.gdt64ptr; code64_sel = boot_info.code64_sel; diff --git a/Kernel/linker.ld b/Kernel/linker.ld index 2ec733f082..4fa765068b 100644 --- a/Kernel/linker.ld +++ b/Kernel/linker.ld @@ -2,39 +2,37 @@ ENTRY(init) -#if ARCH(I386) -# define KERNEL_BASE 0xc0000000 -#else -# define KERNEL_BASE 0x2000000000 -#endif - #define PF_X 0x1 #define PF_W 0x2 #define PF_R 0x4 -KERNEL_VIRTUAL_BASE = KERNEL_BASE; - PHDRS { + elf_headers PT_LOAD FILEHDR PHDRS FLAGS(PF_R) ; super_pages PT_LOAD FLAGS(PF_R | PF_W) ; text PT_LOAD FLAGS(PF_R | PF_X) ; data PT_LOAD FLAGS(PF_R | PF_W) ; bss PT_LOAD FLAGS(PF_R | PF_W) ; + dynamic_segment PT_LOAD FLAGS(PF_R | PF_W) ; + dynamic PT_DYNAMIC FLAGS(PF_R | PF_W) ; ksyms PT_LOAD FLAGS(PF_R) ; } SECTIONS { - . = KERNEL_VIRTUAL_BASE + 0x00200000; - start_of_kernel_image = .; - .super_pages ALIGN(4K) (NOLOAD) : AT (ADDR(.super_pages) - KERNEL_VIRTUAL_BASE) + .elf_headers (SIZEOF_HEADERS) : AT (ADDR(.elf_headers) + SIZEOF_HEADERS) + { + start_of_elf_headers = .; + } :elf_headers + + .super_pages ALIGN(4K) (NOLOAD) : AT (ADDR(.super_pages)) { *(.super_pages) } :super_pages - .text ALIGN(4K) : AT (ADDR(.text) - KERNEL_VIRTUAL_BASE) + .text ALIGN(4K) : AT (ADDR(.text)) { start_of_kernel_text = .; @@ -48,7 +46,7 @@ SECTIONS *(.text*) } :text - .unmap_after_init ALIGN(4K) : AT (ADDR(.unmap_after_init) - KERNEL_VIRTUAL_BASE) + .unmap_after_init ALIGN(4K) : AT (ADDR(.unmap_after_init)) { start_of_unmap_after_init = .; *(.unmap_after_init*); @@ -57,7 +55,7 @@ SECTIONS end_of_kernel_text = .; } :text - .rodata ALIGN(4K) : AT (ADDR(.rodata) - KERNEL_VIRTUAL_BASE) + .rodata ALIGN(4K) : AT (ADDR(.rodata)) { start_heap_ctors = .; *libkernel_heap.a:*(.ctors) @@ -70,21 +68,21 @@ SECTIONS *(.rodata*) } :data - .data ALIGN(4K) : AT (ADDR(.data) - KERNEL_VIRTUAL_BASE) + .data ALIGN(4K) : AT (ADDR(.data)) { start_of_kernel_data = .; *(.data*) end_of_kernel_data = .; } :data - .ro_after_init ALIGN(4K) (NOLOAD) : AT(ADDR(.ro_after_init) - KERNEL_VIRTUAL_BASE) + .ro_after_init ALIGN(4K) (NOLOAD) : AT(ADDR(.ro_after_init)) { start_of_ro_after_init = .; *(.ro_after_init); end_of_ro_after_init = .; } :data - .bss ALIGN(4K) (NOLOAD) : AT (ADDR(.bss) - KERNEL_VIRTUAL_BASE) + .bss ALIGN(4K) (NOLOAD) : AT (ADDR(.bss)) { start_of_kernel_bss = .; *(page_tables) @@ -96,8 +94,12 @@ SECTIONS *(.heap) } :bss + .dynamic ALIGN(4K) : AT (ADDR(.dynamic)) + { + *(.dynamic) + } :dynamic_segment :dynamic - .ksyms ALIGN(4K) : AT (ADDR(.ksyms) - KERNEL_VIRTUAL_BASE) + .ksyms ALIGN(4K) : AT (ADDR(.ksyms)) { start_of_kernel_ksyms = .; *(.kernel_symbols) diff --git a/Meta/debug-kernel.sh b/Meta/debug-kernel.sh index c33c3da4a0..f7dd66b0a8 100755 --- a/Meta/debug-kernel.sh +++ b/Meta/debug-kernel.sh @@ -10,12 +10,19 @@ # if [ "$SERENITY_ARCH" = "x86_64" ]; then gdb_arch=i386:x86-64 + prekernel_image=Prekernel64 + kernel_base=0x2000200000 else gdb_arch=i386:intel + prekernel_image=Prekernel + kernel_base=0xc0200000 fi exec $SERENITY_KERNEL_DEBUGGER \ - -ex "file $(dirname "$0")/../Build/${SERENITY_ARCH:-i686}/Kernel/Kernel" \ + -ex "file $(dirname "$0")/../Build/${SERENITY_ARCH:-i686}/Kernel/Prekernel/$prekernel_image" \ + -ex "set confirm off" \ + -ex "add-symbol-file $(dirname "$0")/../Build/${SERENITY_ARCH:-i686}/Kernel/Kernel -o $kernel_base" \ + -ex "set confirm on" \ -ex "set arch $gdb_arch" \ -ex 'target remote localhost:1234' \ -ex "source $(dirname "$0")/serenity_gdb.py" \ diff --git a/Userland/DevTools/Profiler/Profile.cpp b/Userland/DevTools/Profiler/Profile.cpp index f4a7f630f4..86464140b4 100644 --- a/Userland/DevTools/Profiler/Profile.cpp +++ b/Userland/DevTools/Profiler/Profile.cpp @@ -316,7 +316,7 @@ Result, String> Profile::load_from_perfcore_file(const St if (maybe_kernel_base.has_value() && ptr >= maybe_kernel_base.value()) { if (kernel_elf) { - symbol = kernel_elf->symbolicate(ptr, &offset); + symbol = kernel_elf->symbolicate(ptr - maybe_kernel_base.value(), &offset); } else { symbol = String::formatted("?? <{:p}>", ptr); } diff --git a/Userland/Libraries/LibSymbolication/Symbolication.cpp b/Userland/Libraries/LibSymbolication/Symbolication.cpp index 745b14fb0c..13bc9840d4 100644 --- a/Userland/Libraries/LibSymbolication/Symbolication.cpp +++ b/Userland/Libraries/LibSymbolication/Symbolication.cpp @@ -112,7 +112,6 @@ Vector symbolicate_thread(pid_t pid, pid_t tid) FlatPtr base { 0 }; size_t size { 0 }; String path; - bool is_relative { true }; }; Vector stack; @@ -123,7 +122,6 @@ Vector symbolicate_thread(pid_t pid, pid_t tid) .base = maybe_kernel_base.value(), .size = 0x3fffffff, .path = "/boot/Kernel.debug", - .is_relative = false, }); } @@ -209,11 +207,7 @@ Vector symbolicate_thread(pid_t pid, pid_t tid) continue; } - FlatPtr adjusted_address; - if (found_region->is_relative) - adjusted_address = address - found_region->base; - else - adjusted_address = address; + FlatPtr adjusted_address = address - found_region->base; // We're subtracting 1 from the address because this is the return address, // i.e. it is one instruction past the call instruction.