aboutsummaryrefslogtreecommitdiff
path: root/mirai.old/hikari/elf/parser.zig
diff options
context:
space:
mode:
Diffstat (limited to 'mirai.old/hikari/elf/parser.zig')
-rw-r--r--mirai.old/hikari/elf/parser.zig73
1 files changed, 73 insertions, 0 deletions
diff --git a/mirai.old/hikari/elf/parser.zig b/mirai.old/hikari/elf/parser.zig
new file mode 100644
index 0000000..1ce2f7b
--- /dev/null
+++ b/mirai.old/hikari/elf/parser.zig
@@ -0,0 +1,73 @@
+//! ELF parser
+
+const elf_const = @import("../../common/constants/elf.zig");
+const memory_limits = @import("../../common/limits/memory.zig");
+const types = @import("types.zig");
+
+pub fn parse(data: []const u8) !types.Info {
+ if (data.len < @sizeOf(types.Header)) {
+ return error.TooSmall;
+ }
+
+ const header = @as(*const types.Header, @ptrCast(@alignCast(data.ptr)));
+
+ if (header.magic[0] != elf_const.MAGIC[0] or
+ header.magic[1] != elf_const.MAGIC[1] or
+ header.magic[2] != elf_const.MAGIC[2] or
+ header.magic[3] != elf_const.MAGIC[3])
+ {
+ return error.InvalidMagic;
+ }
+
+ if (header.class != elf_const.CLASS_64) {
+ return error.Not64Bit;
+ }
+
+ if (header.data != elf_const.DATA_LSB) {
+ return error.NotLittleEndian;
+ }
+
+ if (header.type != elf_const.TYPE_EXEC and header.type != elf_const.TYPE_DYN) {
+ return error.NotExecutable;
+ }
+
+ if (!memory_limits.is_valid_kata_pointer(header.entry)) {
+ return error.InvalidEntryPoint;
+ }
+
+ if (header.phnum == 0) {
+ return error.NoProgramHeaders;
+ }
+
+ if (header.phentsize != @sizeOf(types.ProgramHeader)) {
+ return error.InvalidProgramHeaderSize;
+ }
+
+ const ph_table_size = @as(u64, header.phnum) * @as(u64, header.phentsize);
+ if (header.phoff + ph_table_size > data.len) {
+ return error.InvalidProgramHeaders;
+ }
+
+ const ph_start = data.ptr + header.phoff;
+ const ph_ptr: [*]const types.ProgramHeader = @ptrCast(@alignCast(ph_start));
+ const program_headers = ph_ptr[0..header.phnum];
+
+ for (program_headers) |phdr| {
+ if (phdr.type == elf_const.PT_LOAD) {
+ if (phdr.offset + phdr.filesz > data.len) {
+ return error.SegmentOutOfBounds;
+ }
+ if (phdr.filesz > phdr.memsz) {
+ return error.InvalidSegmentSize;
+ }
+ if (!memory_limits.is_kata_range(phdr.vaddr, phdr.memsz)) {
+ return error.SegmentAddressOutOfRange;
+ }
+ }
+ }
+
+ return types.Info{
+ .entry_point = header.entry,
+ .program_headers = program_headers,
+ };
+}