[kernel] Hide kernel symbols by default
Using `-fvisibility=hidden` when building the kernel, and then `--discard-all` when stripping it, we shave almost 100KiB off of the resulting ELF file. Also dropped some unused symbols from the linker script, and rearranged the sections so that the file is able to be mapped directly into memory instead of having each section copied.
This commit is contained in:
@@ -15,11 +15,14 @@ variables:
|
||||
"-ffreestanding",
|
||||
"-nodefaultlibs",
|
||||
"-fno-builtin",
|
||||
"-fno-plt",
|
||||
|
||||
"-mno-sse",
|
||||
"-fno-omit-frame-pointer",
|
||||
"-mno-red-zone",
|
||||
"-mcmodel=kernel",
|
||||
"-fvisibility=hidden",
|
||||
"-fvisibility-inlines-hidden",
|
||||
|
||||
"-g3",
|
||||
"-ggdb",
|
||||
|
||||
@@ -75,7 +75,7 @@ rule strip
|
||||
command = $
|
||||
cp $in $out; $
|
||||
objcopy --only-keep-debug $out $debug; $
|
||||
strip -g $out; $
|
||||
strip --discard-all -g $out; $
|
||||
objcopy --add-gnu-debuglink=$debug $out
|
||||
|
||||
rule touch
|
||||
|
||||
2
external/uefi/boot_services.h
vendored
2
external/uefi/boot_services.h
vendored
@@ -22,7 +22,7 @@ namespace bs_impl {
|
||||
using create_event = status (*)(evt, tpl, event_notify, void*, event*);
|
||||
using exit_boot_services = status (*)(handle, size_t);
|
||||
using locate_protocol = status (*)(const guid*, void*, void**);
|
||||
using copy_mem = void (*)(void*, void*, size_t);
|
||||
using copy_mem = void (*)(void*, const void*, size_t);
|
||||
using set_mem = void (*)(void*, uint64_t, uint8_t);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ allocator::memset(void *start, size_t size, uint8_t value)
|
||||
}
|
||||
|
||||
void
|
||||
allocator::copy(void *to, void *from, size_t size)
|
||||
allocator::copy(void *to, const void *from, size_t size)
|
||||
{
|
||||
m_bs.copy_mem(to, from, size);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
module * allocate_module();
|
||||
|
||||
void memset(void *start, size_t size, uint8_t value);
|
||||
void copy(void *to, void *from, size_t size);
|
||||
void copy(void *to, const void *from, size_t size);
|
||||
|
||||
inline void zero(void *start, size_t size) { memset(start, size, 0); }
|
||||
|
||||
|
||||
@@ -35,15 +35,42 @@ load_file(
|
||||
return b;
|
||||
}
|
||||
|
||||
void
|
||||
verify_kernel_header(elf::file &kernel, util::const_buffer data)
|
||||
{
|
||||
status_line status {L"Verifying kernel header"};
|
||||
|
||||
// The header should be the first non-null section
|
||||
const elf::section_header § = kernel.sections()[1];
|
||||
|
||||
const bootproto::header *header =
|
||||
reinterpret_cast<const bootproto::header *>(
|
||||
util::offset_pointer(data.pointer, sect.offset));
|
||||
|
||||
if (header->magic != bootproto::header_magic)
|
||||
error::raise(uefi::status::load_error, L"Bad kernel magic number");
|
||||
|
||||
if (header->length < sizeof(bootproto::header))
|
||||
error::raise(uefi::status::load_error, L"Bad kernel header length");
|
||||
|
||||
if (header->version < bootproto::min_header_version)
|
||||
error::raise(uefi::status::unsupported, L"Kernel header version not supported");
|
||||
|
||||
console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n",
|
||||
header->version_major, header->version_minor, header->version_patch,
|
||||
header->version_gitsha);
|
||||
}
|
||||
|
||||
bootproto::program *
|
||||
load_program(
|
||||
fs::file &disk,
|
||||
const wchar_t *name,
|
||||
const descriptor &desc)
|
||||
const descriptor &desc,
|
||||
bool verify)
|
||||
{
|
||||
status_line status(L"Loading program", name);
|
||||
|
||||
util::buffer data = load_file(disk, desc.path);
|
||||
util::const_buffer data = load_file(disk, desc.path);
|
||||
|
||||
elf::file program(data.pointer, data.count);
|
||||
if (!program.valid()) {
|
||||
@@ -60,6 +87,9 @@ load_program(
|
||||
error::raise(uefi::status::load_error, L"ELF file not valid");
|
||||
}
|
||||
|
||||
if (verify)
|
||||
verify_kernel_header(program, data);
|
||||
|
||||
size_t num_sections = 0;
|
||||
for (auto &seg : program.programs()) {
|
||||
if (seg.type == elf::segment_type::load)
|
||||
@@ -85,7 +115,7 @@ load_program(
|
||||
|
||||
size_t page_count = memory::bytes_to_pages(mem_size);
|
||||
void *pages = g_alloc.allocate_pages(page_count, alloc_type::program, true);
|
||||
void *source = util::offset_pointer(data.pointer, seg.offset);
|
||||
const void *source = util::offset_pointer(data.pointer, seg.offset);
|
||||
g_alloc.copy(util::offset_pointer(pages, prelude), source, seg.file_size);
|
||||
section.phys_addr = reinterpret_cast<uintptr_t>(pages);
|
||||
section.virt_addr = virt_addr;
|
||||
@@ -116,33 +146,5 @@ load_module(
|
||||
mod->data = load_file(disk, path);
|
||||
}
|
||||
|
||||
void
|
||||
verify_kernel_header(bootproto::program &program)
|
||||
{
|
||||
status_line status(L"Verifying kernel header");
|
||||
|
||||
const bootproto::header *header =
|
||||
reinterpret_cast<const bootproto::header *>(program.sections[0].phys_addr);
|
||||
|
||||
if (header->magic != bootproto::header_magic)
|
||||
error::raise(uefi::status::load_error, L"Bad kernel magic number");
|
||||
|
||||
if (header->length < sizeof(bootproto::header))
|
||||
error::raise(uefi::status::load_error, L"Bad kernel header length");
|
||||
|
||||
if (header->version < bootproto::min_header_version)
|
||||
error::raise(uefi::status::unsupported, L"Kernel header version not supported");
|
||||
|
||||
console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n",
|
||||
header->version_major, header->version_minor, header->version_patch,
|
||||
header->version_gitsha);
|
||||
|
||||
/*
|
||||
for (auto §ion : program.sections)
|
||||
console::print(L" Section: p:0x%lx v:0x%lx fs:0x%x ms:0x%x\r\n",
|
||||
section.phys_addr, section.virt_addr, section.file_size, section.mem_size);
|
||||
*/
|
||||
}
|
||||
|
||||
} // namespace loader
|
||||
} // namespace boot
|
||||
|
||||
@@ -31,11 +31,13 @@ load_file(
|
||||
/// \arg disk The opened UEFI filesystem to load from
|
||||
/// \arg desc The descriptor identifying the program
|
||||
/// \arg name The human-readable name of the program to load
|
||||
/// \arg verify If this is the kernel and should have its header verified
|
||||
bootproto::program *
|
||||
load_program(
|
||||
fs::file &disk,
|
||||
const wchar_t *name,
|
||||
const descriptor &desc);
|
||||
const descriptor &desc,
|
||||
bool verify = false);
|
||||
|
||||
/// Load a file from disk into memory, creating an init args module
|
||||
/// \arg disk The opened UEFI filesystem to load from
|
||||
@@ -51,10 +53,5 @@ load_module(
|
||||
bootproto::module_type type,
|
||||
uint16_t subtype);
|
||||
|
||||
/// Verify that a loaded ELF has the j6 kernel header
|
||||
/// \arg program The program to check for a header
|
||||
void
|
||||
verify_kernel_header(bootproto::program &program);
|
||||
|
||||
} // namespace loader
|
||||
} // namespace boot
|
||||
|
||||
@@ -75,7 +75,7 @@ load_resources(bootproto::args *args, video::screen *screen, uefi::handle image,
|
||||
fs::file bc_data = disk.open(L"jsix\\boot.conf");
|
||||
bootconfig bc {bc_data.load(), bs};
|
||||
|
||||
args->kernel = loader::load_program(disk, L"kernel", bc.kernel());
|
||||
args->kernel = loader::load_program(disk, L"kernel", bc.kernel(), true);
|
||||
args->init = loader::load_program(disk, L"init server", bc.init());
|
||||
args->flags = static_cast<bootproto::boot_flags>(bc.flags());
|
||||
|
||||
@@ -106,8 +106,6 @@ load_resources(bootproto::args *args, video::screen *screen, uefi::handle image,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loader::verify_kernel_header(*args->kernel);
|
||||
}
|
||||
|
||||
memory::efi_mem_map
|
||||
|
||||
@@ -2,7 +2,7 @@ MAGIC equ 'j6KERNEL' ; jsix kernel header magic number
|
||||
|
||||
section .header
|
||||
align 8
|
||||
global _kernel_header
|
||||
global _kernel_header: data hidden
|
||||
_kernel_header:
|
||||
dq MAGIC ; Kernel header magic
|
||||
dw 32 ; Kernel header length
|
||||
@@ -16,8 +16,8 @@ _kernel_header:
|
||||
|
||||
section .text
|
||||
align 16
|
||||
global _kernel_start:function (_kernel_start.end - _kernel_start)
|
||||
global _kernel_start.real
|
||||
global _kernel_start: function hidden (_kernel_start.end - _kernel_start)
|
||||
global _kernel_start.real: function hidden
|
||||
_kernel_start:
|
||||
push rbp ; Never executed, fake function prelude
|
||||
mov rbp, rsp ; to calm down gdb
|
||||
@@ -36,18 +36,18 @@ _kernel_start:
|
||||
; the scheduler to take over
|
||||
.end:
|
||||
|
||||
global bsp_idle:function (bsp_idle.end - bsp_idle)
|
||||
global bsp_idle: function hidden (bsp_idle.end - bsp_idle)
|
||||
bsp_idle:
|
||||
hlt
|
||||
jmp bsp_idle
|
||||
.end:
|
||||
|
||||
global interrupts_enable
|
||||
global interrupts_enable: function hidden
|
||||
interrupts_enable:
|
||||
sti
|
||||
ret
|
||||
|
||||
global interrupts_disable
|
||||
global interrupts_disable: function hidden
|
||||
interrupts_disable:
|
||||
cli
|
||||
ret
|
||||
@@ -57,5 +57,5 @@ align 0x100
|
||||
idle_stack_begin:
|
||||
resb 0x4000 ; 16KiB stack space
|
||||
|
||||
global idle_stack_end
|
||||
global idle_stack_end: data hidden
|
||||
idle_stack_end:
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
global get_rsp
|
||||
global get_rsp: function hidden
|
||||
get_rsp:
|
||||
mov rax, rsp
|
||||
ret
|
||||
|
||||
global get_rip
|
||||
global get_rip: function hidden
|
||||
get_rip:
|
||||
pop rax ; do the same thing as 'ret', except with 'jmp'
|
||||
jmp rax ; with the return address still in rax
|
||||
|
||||
global get_caller
|
||||
global get_caller: function hidden
|
||||
get_caller:
|
||||
; No prelude - don't touch rsp or rbp
|
||||
mov rax, [rbp+8]
|
||||
ret
|
||||
|
||||
global get_grandcaller
|
||||
global get_grandcaller: function hidden
|
||||
get_grandcaller:
|
||||
; No prelude - don't touch rsp or rbp
|
||||
mov rax, [rbp]
|
||||
mov rax, [rax+8]
|
||||
ret
|
||||
|
||||
global get_gsbase
|
||||
global get_gsbase: function hidden
|
||||
get_gsbase:
|
||||
rdgsbase rax
|
||||
ret
|
||||
|
||||
global _halt
|
||||
global _halt: function hidden
|
||||
_halt:
|
||||
hlt
|
||||
jmp _halt
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
|
||||
global idt_write
|
||||
global idt_write: function hidden
|
||||
idt_write:
|
||||
lidt [rdi] ; first arg is the IDT pointer location
|
||||
ret
|
||||
|
||||
global idt_load
|
||||
global idt_load: function hidden
|
||||
idt_load:
|
||||
sidt [rdi] ; first arg is where to write the idtr value
|
||||
ret
|
||||
|
||||
global gdt_write
|
||||
global gdt_write: function hidden
|
||||
gdt_write:
|
||||
lgdt [rdi] ; first arg is the GDT pointer location
|
||||
|
||||
@@ -28,7 +28,7 @@ gdt_write:
|
||||
ltr cx ; fourth arg is the TSS
|
||||
ret
|
||||
|
||||
global gdt_load
|
||||
global gdt_load: function hidden
|
||||
gdt_load:
|
||||
sgdt [rdi] ; first arg is where to write the gdtr value
|
||||
ret
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
section .text
|
||||
|
||||
extern isr_handler
|
||||
global isr_handler_prelude:function (isr_handler_prelude.end - isr_handler_prelude)
|
||||
global isr_handler_prelude: function hidden (isr_handler_prelude.end - isr_handler_prelude)
|
||||
isr_handler_prelude:
|
||||
push rbp ; Never executed, fake function prelude
|
||||
mov rbp, rsp ; to calm down gdb
|
||||
@@ -19,7 +19,7 @@ isr_handler_prelude:
|
||||
.end:
|
||||
|
||||
extern irq_handler
|
||||
global irq_handler_prelude:function (irq_handler_prelude.end - irq_handler_prelude)
|
||||
global irq_handler_prelude: function hidden (irq_handler_prelude.end - irq_handler_prelude)
|
||||
irq_handler_prelude:
|
||||
push rbp ; Never executed, fake function prelude
|
||||
mov rbp, rsp ; to calm down gdb
|
||||
@@ -35,7 +35,7 @@ irq_handler_prelude:
|
||||
; fall through to isr_handler_return
|
||||
.end:
|
||||
|
||||
global isr_handler_return:function (isr_handler_return.end - isr_handler_return)
|
||||
global isr_handler_return: function hidden (isr_handler_return.end - isr_handler_return)
|
||||
isr_handler_return:
|
||||
check_swap_gs
|
||||
pop_all
|
||||
@@ -45,7 +45,7 @@ isr_handler_return:
|
||||
.end:
|
||||
|
||||
%macro EMIT_ISR 2
|
||||
global %1:function (%1.end - %1)
|
||||
global %1:function hidden (%1.end - %1)
|
||||
%1:
|
||||
push 0
|
||||
push %2
|
||||
@@ -54,7 +54,7 @@ isr_handler_return:
|
||||
%endmacro
|
||||
|
||||
%macro EMIT_EISR 2
|
||||
global %1:function (%1.end - %1)
|
||||
global %1:function hidden (%1.end - %1)
|
||||
%1:
|
||||
push %2
|
||||
jmp isr_handler_prelude.real
|
||||
@@ -62,7 +62,7 @@ isr_handler_return:
|
||||
%endmacro
|
||||
|
||||
%macro EMIT_IRQ 2
|
||||
global %1:function (%1.end - %1)
|
||||
global %1:function hidden (%1.end - %1)
|
||||
%1:
|
||||
push 0
|
||||
push %2
|
||||
|
||||
@@ -1,53 +1,59 @@
|
||||
PHDRS
|
||||
{
|
||||
rodata PT_LOAD PHDRS FILEHDR FLAGS (4) /* read-only */;
|
||||
text PT_LOAD ;
|
||||
rwdata PT_LOAD ;
|
||||
bss PT_LOAD ;
|
||||
}
|
||||
|
||||
MEMORY
|
||||
{
|
||||
kernel (rwxa) : ORIGIN = 0xFFFF800000000000, LENGTH = 256M
|
||||
}
|
||||
|
||||
ENTRY(_kernel_start.real)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xFFFF800000000000;
|
||||
|
||||
.header : {
|
||||
__header_start = .;
|
||||
.header ORIGIN(kernel) + SIZEOF_HEADERS : {
|
||||
HIDDEN(__header_start = .);
|
||||
KEEP(*(.header))
|
||||
__header_end = .;
|
||||
}
|
||||
HIDDEN(__header_end = .);
|
||||
} :rodata
|
||||
|
||||
.text ALIGN(4096) : {
|
||||
*(.text*)
|
||||
KEEP(*(.isrs))
|
||||
}
|
||||
|
||||
.data ALIGN(4096) : {
|
||||
*(.data*)
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
} :rodata
|
||||
|
||||
.ctors : ALIGN(8) {
|
||||
__ctors = .;
|
||||
.ap_startup : {
|
||||
*(.ap_startup*)
|
||||
} :rodata
|
||||
|
||||
.ctors ALIGN(8) : {
|
||||
HIDDEN(__ctors = .);
|
||||
KEEP(*(.ctors))
|
||||
KEEP(*(.init_array))
|
||||
__ctors_end = .;
|
||||
}
|
||||
HIDDEN(__ctors_end = .);
|
||||
} :rodata
|
||||
|
||||
.bss ALIGN(4096) : {
|
||||
__bss_start = .;
|
||||
.text ALIGN(4K) : {
|
||||
*(.text*)
|
||||
KEEP(*(.isrs))
|
||||
} :text
|
||||
|
||||
.data ALIGN(4K) : {
|
||||
*(.data*)
|
||||
} :rwdata
|
||||
|
||||
.syscall_registry : {
|
||||
*(.syscall_registry*)
|
||||
} :rwdata
|
||||
|
||||
.bss ALIGN(4K) : {
|
||||
HIDDEN(__bss_start = .);
|
||||
*(.bss*)
|
||||
__bss_end = .;
|
||||
}
|
||||
HIDDEN(__bss_end = .);
|
||||
} :bss
|
||||
|
||||
.note : {
|
||||
*(.note.*)
|
||||
}
|
||||
|
||||
.eh_frame : {
|
||||
__eh_frame_start = .;
|
||||
KEEP(*(.eh_frame))
|
||||
__eh_frame_end = .;
|
||||
}
|
||||
|
||||
.eh_frame_hdr : {
|
||||
KEEP(*(.eh_frame_hdr))
|
||||
}
|
||||
|
||||
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
|
||||
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
|
||||
|
||||
kernel_end = ALIGN(4096);
|
||||
HIDDEN(__kernel_end = ALIGN(4096));
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ bits 16
|
||||
default rel
|
||||
align 8
|
||||
|
||||
global ap_startup
|
||||
global ap_startup: function hidden
|
||||
ap_startup:
|
||||
jmp .start_real
|
||||
|
||||
@@ -104,13 +104,13 @@ align 8
|
||||
jmp rax
|
||||
|
||||
|
||||
global ap_startup_code_size
|
||||
global ap_startup_code_size: function hidden
|
||||
ap_startup_code_size:
|
||||
dq ($ - ap_startup)
|
||||
|
||||
|
||||
section .text
|
||||
global init_ap_trampoline
|
||||
global init_ap_trampoline: function hidden
|
||||
init_ap_trampoline:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
@@ -131,7 +131,7 @@ init_ap_trampoline:
|
||||
ret
|
||||
|
||||
extern long_ap_startup
|
||||
global ap_idle:function (ap_idle.end - ap_idle)
|
||||
global ap_idle:function hidden (ap_idle.end - ap_idle)
|
||||
ap_idle:
|
||||
call long_ap_startup
|
||||
sti
|
||||
|
||||
@@ -22,7 +22,7 @@ extern syscall_registry
|
||||
extern syscall_invalid
|
||||
|
||||
|
||||
global syscall_handler_prelude:function (syscall_handler_prelude.end - syscall_handler_prelude)
|
||||
global syscall_handler_prelude: function hidden (syscall_handler_prelude.end - syscall_handler_prelude)
|
||||
syscall_handler_prelude:
|
||||
push rbp ; Never executed, fake function prelude
|
||||
mov rbp, rsp ; to calm down gdb
|
||||
@@ -77,7 +77,7 @@ syscall_handler_prelude:
|
||||
call syscall_invalid
|
||||
.end:
|
||||
|
||||
global kernel_to_user_trampoline:function (kernel_to_user_trampoline.end - kernel_to_user_trampoline)
|
||||
global kernel_to_user_trampoline: function hidden (kernel_to_user_trampoline.end - kernel_to_user_trampoline)
|
||||
kernel_to_user_trampoline:
|
||||
pop r15
|
||||
pop r14
|
||||
@@ -98,7 +98,7 @@ kernel_to_user_trampoline:
|
||||
o64 sysret
|
||||
.end:
|
||||
|
||||
global syscall_enable:function (syscall_enable.end - syscall_enable)
|
||||
global syscall_enable: function hidden (syscall_enable.end - syscall_enable)
|
||||
syscall_enable:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%include "tasking.inc"
|
||||
|
||||
global task_switch
|
||||
global task_switch: function hidden
|
||||
task_switch:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
@@ -61,7 +61,7 @@ task_switch:
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
global _current_gsbase
|
||||
global _current_gsbase: function hidden
|
||||
_current_gsbase:
|
||||
mov rax, [gs:CPU_DATA.self]
|
||||
ret
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
inline size_t size() const { return m_size; }
|
||||
inline unsigned count() const { return m_count; }
|
||||
|
||||
inline const T & operator [] (int i) const { return *util::offset_pointer<T>(m_start, m_size*i); }
|
||||
inline const T & operator [] (int i) const { return *util::offset_pointer<const T>(m_start, m_size*i); }
|
||||
inline const iterator begin() const { return iterator(m_start, m_size); }
|
||||
inline const iterator end() const { return util::offset_pointer(m_start, m_size*m_count); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user