[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:
Justin C. Miller
2023-01-29 19:36:20 -08:00
parent e2e1696b7e
commit 5ea5978ee8
17 changed files with 126 additions and 120 deletions

View File

@@ -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);
}

View File

@@ -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); }

View File

@@ -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 &sect = 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 &section : 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

View File

@@ -28,14 +28,16 @@ load_file(
const wchar_t *path);
/// Parse and load an ELF file in memory into a loaded image.
/// \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 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

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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); }