summaryrefslogtreecommitdiff
path: root/elf/header.lua
blob: b289f13e78c42bef2cb200e009a3af8c1efac5ca (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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
local fmt = require("elf.fmt")
local ec = require("elf.constants")

---@alias Magic [integer, integer, integer, integer]

---@class Header
---@field magic? Magic
---@field class Class
---@field data Endian
---@field ident_version? integer
---@field osabi? Osabi
---@field abiversion? integer
---@field type Type
---@field machine Machine
---@field version? integer
---@field entry? integer
---@field phoff? integer
---@field shoff? integer
---@field flags? integer
---@field ehsize? integer
---@field phentsize? integer
---@field phnum? integer
---@field shentsize? integer
---@field shnum? integer
---@field shstrndx? integer
local M = {}

function M.normalize(hdr)
    hdr.magic = hdr.magic or { 0x7f, 0x45, 0x4c, 0x46 }
    hdr.ident_version = hdr.ident_version or ec.VERSION
    hdr.osabi = hdr.osabi or ec.Osabi.sysv
    hdr.abiversion = hdr.abiversion or 0
    hdr.version = hdr.version or ec.VERSION
    hdr.entry = hdr.entry or 0
    hdr.phoff = hdr.phoff or 0
    hdr.shoff = hdr.shoff or 0
    hdr.flags = hdr.flags or 0
    hdr.ehsize = hdr.ehsize or 0
    hdr.phentsize = hdr.phentsize or 0
    hdr.phnum = hdr.phnum or 0
    hdr.shentsize = hdr.shentsize or 0
    hdr.shnum = hdr.shnum or 0
    hdr.shstrndx = hdr.shstrndx or 0
end

function M.validate(hdr)
    if not hdr.class then error("class is required in header", 3) end
    if not hdr.data then error("data is required in header", 3) end
    if not hdr.type then error("type is required in header", 3) end
    if not hdr.machine then error("machine is required in header", 3) end

    if hdr.class ~= ec.Class.bit32 and hdr.class ~= ec.Class.bit64 then
        error("class must be Class.bit32 or Class.bit64 in header", 3)
    end
    if hdr.data ~= ec.Endian.little and hdr.data ~= ec.Endian.big then
        error("data must be Endian.little or Endian.big in header", 3)
    end
    -- TODO additional validations
end

---@param hdr Header
---@return string
---@nodiscard
function M.pack(hdr)
    return string.pack("BBBBBBBBBxxxxxxx" ..
        fmt.endian(hdr.data) ..
        "I2I2I4" ..
        string.rep(fmt.word(hdr.class), 3) ..
        "I4I2I2I2I2I2I2",
        hdr.magic[1], hdr.magic[2], hdr.magic[3], hdr.magic[4],
        hdr.class,
        hdr.data,
        hdr.ident_version,
        hdr.osabi,
        hdr.abiversion,
        hdr.type,
        hdr.machine,
        hdr.version,
        hdr.entry,
        hdr.phoff,
        hdr.shoff,
        hdr.flags,
        hdr.ehsize,
        hdr.phentsize,
        hdr.phnum,
        hdr.shentsize,
        hdr.shnum,
        hdr.shstrndx)
end

return M