From da5d5d11c65364630f8214eba954c1393cf63a9c Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Thu, 26 Sep 2024 21:18:52 -0600 Subject: [PATCH] Understand .gnu.version_r --- bootstrap/lib.h | 39 +++++++++++++-- bootstrap/main.c | 121 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 120 insertions(+), 40 deletions(-) diff --git a/bootstrap/lib.h b/bootstrap/lib.h index 3c96da6..0ddb8f2 100644 --- a/bootstrap/lib.h +++ b/bootstrap/lib.h @@ -1610,13 +1610,29 @@ may_be_unused fn void calibrate_cpu_timer() #endif } -fn u8* os_reserve(u64 size) +STRUCT(OSReserveProtectionFlags) +{ + u32 read:1; + u32 write:1; + u32 execute:1; + u32 reserved:29; +}; + +STRUCT(OSReserveMapFlags) +{ + u32 priv:1; + u32 anon:1; + u32 noreserve:1; + u32 reserved:29; +}; + +fn u8* os_reserve(u64 base, u64 size, OSReserveProtectionFlags protection, OSReserveMapFlags map) { #if _WIN32 return (u8*)VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); #else - int protection_flags = PROT_NONE; - int map_flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; + int protection_flags = (protection.read * PROT_READ) | (protection.write * PROT_WRITE) | (protection.execute * PROT_EXEC); + int map_flags = (map.anon * MAP_ANONYMOUS) | (map.priv * MAP_PRIVATE) | (map.noreserve * MAP_NORESERVE); u8* result = (u8*)posix_mmap(0, size, protection_flags, map_flags, -1, 0); assert(result != MAP_FAILED); return result; @@ -1640,6 +1656,12 @@ fn u64 align_forward(u64 value, u64 alignment) return result; } +fn u64 align_backward(u64 value, u64 alignment) +{ + u64 result = value & ~(alignment - 1); + return result; +} + fn u32 format_hexadecimal(String buffer, u64 hexadecimal) { u64 value = hexadecimal; @@ -2791,7 +2813,13 @@ static_assert(sizeof(Arena) == 64); fn Arena* arena_init(u64 reserved_size, u64 granularity, u64 initial_size) { - Arena* arena = (Arena*)os_reserve(reserved_size); + Arena* arena = (Arena*)os_reserve(0, reserved_size, + (OSReserveProtectionFlags) {}, + (OSReserveMapFlags) { + .priv = 1, + .anon = 1, + .noreserve = 1, + }); commit(arena, initial_size); *arena = (Arena){ .reserved_size = reserved_size, @@ -2954,6 +2982,7 @@ decl_vb(u8); decl_vbp(u8); decl_vb(s32); decl_vb(u32); +decl_vb(String); fn void vb_generic_ensure_capacity(VirtualBuffer(u8)* vb, u32 item_size, u32 item_count) { @@ -2964,7 +2993,7 @@ fn void vb_generic_ensure_capacity(VirtualBuffer(u8)* vb, u32 item_size, u32 ite { if (old_capacity == 0) { - vb->pointer = os_reserve(item_size * UINT32_MAX); + vb->pointer = os_reserve(0, item_size * UINT32_MAX, (OSReserveProtectionFlags) {}, (OSReserveMapFlags) { .priv = 1, .anon = 1, .noreserve = 1 }); } u32 old_page_capacity = cast(u32, u64, align_forward(old_capacity * item_size, minimum_granularity)); diff --git a/bootstrap/main.c b/bootstrap/main.c index 732c82e..f76bf8d 100644 --- a/bootstrap/main.c +++ b/bootstrap/main.c @@ -35,26 +35,34 @@ fn String file_read(Arena* arena, String path) { String result = {}; int file_descriptor = syscall_open(string_to_c(path), 0, 0); - assert(file_descriptor != -1); + if (file_descriptor >= 0) + { + struct stat stat_buffer; + int stat_result = syscall_fstat(file_descriptor, &stat_buffer); + assert(stat_result == 0); - struct stat stat_buffer; - int stat_result = syscall_fstat(file_descriptor, &stat_buffer); - assert(stat_result == 0); + auto file_size = cast(u64, s64, stat_buffer.st_size); + if (file_size > 0) + { + result = (String){ + .pointer = arena_allocate_bytes(arena, file_size, 64), + .length = file_size, + }; - auto file_size = cast(u64, s64, stat_buffer.st_size); + // TODO: big files + ssize_t read_result = syscall_read(file_descriptor, result.pointer, result.length); + assert(read_result >= 0); + assert((u64)read_result == file_size); + } + else + { + result.pointer = (u8*)&result; + } - result = (String){ - .pointer = arena_allocate_bytes(arena, file_size, 64), - .length = file_size, - }; + auto close_result = syscall_close(file_descriptor); + assert(close_result == 0); + } - // TODO: big files - ssize_t read_result = syscall_read(file_descriptor, result.pointer, result.length); - assert(read_result >= 0); - assert((u64)read_result == file_size); - - auto close_result = syscall_close(file_descriptor); - assert(close_result == 0); return result; } @@ -428,6 +436,41 @@ typedef enum ELFSectionIndex : u16 COMMON = 0xfff2, } ELFSectionIndex; +STRUCT(ELFVersionRequirement) +{ + u16 version; + u16 count; + u32 name_offset; + u32 aux_offset; + u32 next; +}; + +STRUCT(ELFVersionRequirementEntry) +{ + u32 hash; + u16 flags; + u16 other; + u32 name_offset; + u32 next; +}; + +STRUCT(ELFVersionDefinition) +{ + u16 version; + u16 flags; + u16 index; + u16 count; + u32 hash; + u32 aux_offset; + u32 next; +}; +static_assert(sizeof(ELFVersionDefinition) == 20); +STRUCT(ELFVersionDefinitionEntry) +{ + u32 name_offset; + u32 next; +}; + STRUCT(ELFHeader) { u8 identifier[4]; @@ -6968,7 +7011,7 @@ fn void thread_init(Thread* thread) } // Actually make the syscall - auto* ptr = os_reserve(total_size); + auto* ptr = os_reserve(0, total_size, (OSReserveProtectionFlags) {}, (OSReserveMapFlags) { .priv = 1, .anon = 1, .noreserve = 1 }); assert(ptr); auto* buffer_it = (VirtualBuffer(u8)*)&thread->buffer; @@ -7555,17 +7598,6 @@ STRUCT(ELFNoteHeader) }; static_assert(sizeof(ELFNoteHeader) == 12); -STRUCT(ELFVersionDefinition) -{ - u16 version; - u16 flags; - u16 index; - u16 count; - u32 hash; - u32 aux; - u32 next; -}; -static_assert(sizeof(ELFVersionDefinition) == 20); #define elf_eh_frame_absptr 0x00 #define elf_eh_frame_udata4 0x03 @@ -8418,16 +8450,35 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr auto name = elf_get_section_name(builder, strlit(".gnu.version_r")); - // TODO: figure out - u8 blob[] = { - 0x01, 0x00, 0x02, 0x00, 0x22, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x75, 0x1A, 0x69, 0x09, 0x00, 0x00, 0x03, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0xB4, 0x91, 0x96, 0x06, 0x00, 0x00, 0x02, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ELFVersionRequirement first_requirement = { + .version = 1, + .count = 2, + .name_offset = libcso6, + .aux_offset = sizeof(ELFVersionRequirement), + .next = 0, + }; + *vb_add_struct(&builder->file, ELFVersionRequirement) = first_requirement; + + ELFVersionRequirementEntry entries[] = { + { + .hash = 0x9691a75, + .flags = 0, + .other = 3, + .name_offset = 0x2c, + .next = 0x10, + }, + { + .hash = 0x69691b4, + .flags = 0, + .other = 2, + .name_offset = 0x38, + .next = 0, + }, }; - auto size = sizeof(blob); + memcpy(vb_add(&builder->file, sizeof(entries)), entries, sizeof(entries)); - memcpy(vb_add(&builder->file, size), blob, size); + auto size = builder->file.length - offset; *section_header = (ELFSectionHeader) { .name_offset = name,