summaryrefslogtreecommitdiff
path: root/elf/segment.lua
blob: 19cb6d0f43e517a66b8433110b8af8ac7a0ac7c2 (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
local ec = require("elf.constants")
local fmt = require("elf.fmt")

---@class Segment
---@field type SegmentType
---@field flags? integer
---@field offset? integer
---@field vaddr? integer
---@field paddr? integer
---@field filesz? integer
---@field memsz? integer
---@field align? integer
---@field first_section? string
---@field last_section? string

---@class Segments
local M = {}


function M.normalize(phdrs)
    for _, phdr in ipairs(phdrs) do
        phdr.flags = phdr.flags or 0
        phdr.offset = phdr.offset or 0
        phdr.vaddr = phdr.vaddr or 0
        phdr.paddr = phdr.paddr or 0
        phdr.filesz = phdr.filesz or 0
        phdr.memsz = phdr.memsz or 0
        phdr.align = phdr.align or 1
    end
end

function M.validate(phdrs)
    for _, phdr in ipairs(phdrs) do
        if not phdr.type then error("type is required in segment", 3) end
        -- TODO additional validations
    end
end

---@param phdr Segment
---@param endian Endian
---@return string
---@nodiscard
local function pack32(phdr, endian)
    return string.pack(
        fmt.endian(endian) .. string.rep(fmt.word(ec.Class.bit32), 8),
        phdr.type,
        phdr.offset,
        phdr.vaddr,
        phdr.paddr,
        phdr.filesz,
        phdr.memsz,
        phdr.flags,
        phdr.align)
end

---@param phdr Segment
---@param endian Endian
---@return string
---@nodiscard
local function pack64(phdr, endian)
    return string.pack(
        fmt.endian(endian) .. "I4I4" .. string.rep(fmt.word(ec.Class.bit64), 6),
        phdr.type,
        phdr.flags,
        phdr.offset,
        phdr.vaddr,
        phdr.paddr,
        phdr.filesz,
        phdr.memsz,
        phdr.align)
end

---@param phdrs Segment[]
---@param endian Endian
---@param class Class
---@return string
---@nodiscard
function M.pack(phdrs, endian, class)
    local p = {}
    for i, phdr in ipairs(phdrs) do
        p[i] = (class == ec.Class.bit32) and
            pack32(phdr, endian) or
            pack64(phdr, endian)
    end
    return table.concat(p)
end

return M