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
|