diff options
Diffstat (limited to 'hikari/loader/elf/types.zig')
| -rw-r--r-- | hikari/loader/elf/types.zig | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/hikari/loader/elf/types.zig b/hikari/loader/elf/types.zig new file mode 100644 index 0000000..1d4a3d4 --- /dev/null +++ b/hikari/loader/elf/types.zig @@ -0,0 +1,182 @@ +//! Hikari ELF Types + +const constants = @import("constants.zig"); + +pub const Elf64Header = extern struct { + magic: [4]u8, + class: u8, + data: u8, + version: u8, + osabi: u8, + abi_version: u8, + padding: [7]u8, + elf_type: u16 align(1), + machine: u16 align(1), + elf_version: u32 align(1), + entry: u64 align(1), + program_header_offset: u64 align(1), + section_header_offset: u64 align(1), + flags: u32 align(1), + header_size: u16 align(1), + program_header_entry_size: u16 align(1), + program_header_count: u16 align(1), + section_header_entry_size: u16 align(1), + section_header_count: u16 align(1), + section_identity_index: u16 align(1), + + pub fn is_valid(self: *const Elf64Header) bool { + if (self.magic[0] != constants.magic[0] or + self.magic[1] != constants.magic[1] or + self.magic[2] != constants.magic[2] or + self.magic[3] != constants.magic[3]) + { + return false; + } + if (self.class != constants.class_64) { + return false; + } + if (self.data != constants.data_little_endian) { + return false; + } + if (self.version != constants.version_current) { + return false; + } + return true; + } + + pub fn is_executable(self: *const Elf64Header) bool { + return self.elf_type == constants.type_executable; + } + + pub fn is_x86_64(self: *const Elf64Header) bool { + return self.machine == constants.machine_x86_64; + } + + pub fn get_program_headers(self: *const Elf64Header, base: [*]const u8) []const Elf64ProgramHeader { + const phdr_ptr: [*]const Elf64ProgramHeader = @ptrCast(@alignCast(base + self.program_header_offset)); + return phdr_ptr[0..self.program_header_count]; + } + + pub fn get_section_headers(self: *const Elf64Header, base: [*]const u8) []const Elf64SectionHeader { + const shdr_ptr: [*]const Elf64SectionHeader = @ptrCast(@alignCast(base + self.section_header_offset)); + return shdr_ptr[0..self.section_header_count]; + } +}; + +pub const Elf64ProgramHeader = extern struct { + segment_type: u32 align(1), + flags: u32 align(1), + offset: u64 align(1), + virtual_address: u64 align(1), + physical_address: u64 align(1), + unit_size: u64 align(1), + memory_size: u64 align(1), + alignment: u64 align(1), + + pub fn is_loadable(self: *const Elf64ProgramHeader) bool { + return self.segment_type == constants.segment_load; + } + + pub fn is_executable(self: *const Elf64ProgramHeader) bool { + return (self.flags & constants.segment_flag_execute) != 0; + } + + pub fn is_writable(self: *const Elf64ProgramHeader) bool { + return (self.flags & constants.segment_flag_write) != 0; + } + + pub fn is_readable(self: *const Elf64ProgramHeader) bool { + return (self.flags & constants.segment_flag_read) != 0; + } + + pub fn get_data(self: *const Elf64ProgramHeader, base: [*]const u8) []const u8 { + return (base + self.offset)[0..self.unit_size]; + } +}; + +pub const Elf64SectionHeader = extern struct { + identity_offset: u32 align(1), + section_type: u32 align(1), + flags: u64 align(1), + address: u64 align(1), + offset: u64 align(1), + size: u64 align(1), + link: u32 align(1), + info: u32 align(1), + address_alignment: u64 align(1), + entry_size: u64 align(1), + + pub fn is_allocatable(self: *const Elf64SectionHeader) bool { + return (self.flags & constants.section_flag_alloc) != 0; + } + + pub fn is_writable(self: *const Elf64SectionHeader) bool { + return (self.flags & constants.section_flag_write) != 0; + } + + pub fn is_executable(self: *const Elf64SectionHeader) bool { + return (self.flags & constants.section_flag_execinstr) != 0; + } + + pub fn is_nobits(self: *const Elf64SectionHeader) bool { + return self.section_type == constants.section_nobits; + } + + pub fn get_data(self: *const Elf64SectionHeader, base: [*]const u8) []const u8 { + return (base + self.offset)[0..self.size]; + } +}; + +pub const Elf64Symbol = extern struct { + identity_offset: u32 align(1), + info: u8, + other: u8, + section_index: u16 align(1), + value: u64 align(1), + size: u64 align(1), + + pub fn get_binding(self: *const Elf64Symbol) u8 { + return self.info >> 4; + } + + pub fn get_type(self: *const Elf64Symbol) u8 { + return self.info & 0x0F; + } + + pub fn get_visibility(self: *const Elf64Symbol) u8 { + return self.other & 0x03; + } +}; + +pub const Elf64Rela = extern struct { + offset: u64 align(1), + info: u64 align(1), + addend: i64 align(1), + + pub fn get_symbol(self: *const Elf64Rela) u32 { + return @truncate(self.info >> 32); + } + + pub fn get_type(self: *const Elf64Rela) u32 { + return @truncate(self.info & 0xFFFFFFFF); + } +}; + +pub const LoadedSegment = struct { + virtual_address: u64, + physical_address: u64, + memory_size: u64, + flags: u32, +}; + +pub const LoadedImage = struct { + entry_point: u64, + base_address: u64, + end_address: u64, + segments: [16]LoadedSegment, + segment_count: usize, + + pub fn total_size(self: *const LoadedImage) u64 { + return self.end_address - self.base_address; + } +}; |
