Understand .gnu.version_r

This commit is contained in:
David Gonzalez Martin 2024-09-26 21:18:52 -06:00 committed by David
parent b0a6e65d42
commit da5d5d11c6
2 changed files with 120 additions and 40 deletions

View File

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

View File

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