Understand .gnu.version_r
This commit is contained in:
parent
b0a6e65d42
commit
da5d5d11c6
@ -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));
|
||||
|
121
bootstrap/main.c
121
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user