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
|
local elf = require("elf")
local ec = require("elf.constants")
local function die(fmt, ...)
io.stderr:write("mkelf: ", string.format(fmt, ...), "\n")
os.exit(1, true)
end
local function usage()
die("[-o output] input")
end
---@param fn string|nil
---@return Header, Segments, Sections
local function loadconfig(fn)
local header, segments, sections = {}, {}, {}
local header_mt = { __index = elf.header }
local segments_mt = { __index = elf.segment }
local sections_mt = { __index = elf.section }
local env = {
-- Keep in sync with types/elf.d.lua
Class = elf.Class,
Endian = elf.Endian,
Osabi = elf.Osabi,
Type = elf.Type,
Machine = elf.Machine,
SegmentType = elf.SegmentType,
SegmentFlags = elf.SegmentFlags,
ELFVERSION = elf.VERSION,
header = function(t) header = setmetatable(t, header_mt) end,
segments = function(t) segments = setmetatable(t, segments_mt) end,
sections = function(t) sections = setmetatable(t, sections_mt) end,
}
-- TODO error check for multiple headers
local chunk, err = loadfile(fn, "t", env)
if not chunk then die("%s", err) end
local ok, perr = pcall(chunk)
if not ok then die("%s", perr) end
return header, segments, sections
end
local function main()
local outfn, infn = "a.out", nil
local i = 1
while arg[i] do
if arg[i] == "-o" then
i = i + 1
outfn = arg[i] or die("missing filename after -o")
elseif infn then
usage()
else
infn = arg[i]
end
i = i + 1
end
local header, segments, sections = loadconfig(infn)
header.phnum = #segments
header.phentsize = (header.class == ec.Class.bit64) and 0x38 or 0x20
-- TODO write to a temp file and atomic rename to outfn.
local out <close> = assert(io.open(outfn, "wb"))
out:write(header:pack())
out:write(segments:pack(header.data, header.class))
-- TODO finish section.pack
out:write(sections:pack(header.data))
end
main()
|