aboutsummaryrefslogtreecommitdiff
path: root/mirai.old/hikari/format/parser.zig
blob: 6274b3b1d0bba91347f8f6a069491ccbc0f1623c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//! Akiba format parser

const akiba_const = @import("../../common/constants/akiba.zig");
const types = @import("types.zig");

pub fn parse(data: []const u8) !types.Executable {
    if (data.len < @sizeOf(types.Header)) {
        return error.TooSmall;
    }

    const header = @as(*const types.Header, @ptrCast(@alignCast(data.ptr)));

    for (akiba_const.MAGIC, 0..) |byte, i| {
        if (header.magic[i] != byte) {
            return error.InvalidMagic;
        }
    }

    if (header.version == 0 or header.version > akiba_const.VERSION) {
        return error.UnsupportedVersion;
    }

    if (header.exec_type > akiba_const.TYPE_LIBRARY) {
        return error.InvalidExecutableType;
    }

    if (header.elf_size == 0) {
        return error.EmptyELF;
    }

    if (header.elf_offset < @sizeOf(types.Header)) {
        return error.InvalidELFOffset;
    }

    if (header.elf_offset + header.elf_size > data.len) {
        return error.InvalidELFBounds;
    }

    const elf_data = data[header.elf_offset .. header.elf_offset + header.elf_size];

    var metadata: ?types.Metadata = null;
    if (header.metadata_offset > 0 and header.metadata_size > 0) {
        if (header.metadata_offset + header.metadata_size <= data.len) {
            const meta_ptr = data.ptr + header.metadata_offset;
            metadata = @as(*const types.Metadata, @ptrCast(@alignCast(meta_ptr))).*;
        }
    }

    return types.Executable{
        .header = header.*,
        .elf_data = elf_data,
        .metadata = metadata,
    };
}

pub fn validate_magic(data: []const u8) bool {
    if (data.len < 8) return false;

    for (akiba_const.MAGIC, 0..) |byte, i| {
        if (data[i] != byte) return false;
    }

    return true;
}