aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/elf.lua102
1 files changed, 88 insertions, 14 deletions
diff --git a/plugins/elf.lua b/plugins/elf.lua
index f891af7..a9a0d81 100644
--- a/plugins/elf.lua
+++ b/plugins/elf.lua
@@ -16,6 +16,8 @@
-- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--
+-- See man 5 elf, /usr/include/elf.h and /usr/include/llvm/Support/ELF.h
+
local detect = function (c)
return c:read (4) == "\x7FELF"
end
@@ -33,11 +35,11 @@ local ph_type_table = {
local xform_ph_flags = function (u32)
local info = {}
- if u32 & 4 ~= 0 then table.insert (info, "read") end
- if u32 & 2 ~= 0 then table.insert (info, "write") end
- if u32 & 1 ~= 0 then table.insert (info, "execute") end
+ if u32 & 0x4 ~= 0 then table.insert (info, "read") end
+ if u32 & 0x2 ~= 0 then table.insert (info, "write") end
+ if u32 & 0x1 ~= 0 then table.insert (info, "execute") end
- local junk = u32 & ~7
+ local junk = u32 & ~0x7
if junk ~= 0 then
table.insert (info, ("unknown: %#x"):format (junk))
end
@@ -65,10 +67,67 @@ local decode_ph = function (elf, c)
ph.memsz = elf.uwide (c, "sise in memory: %d")
if elf.class == 1 then ph.flags = c:u32 ("flags: %s", xform_ph_flags) end
ph.align = elf.uwide (c, "alignment: %d")
+ return ph
+end
+
+local sh_type_table = {
+ [0] = "null entry",
+ [1] = "program-defined contents",
+ [2] = "symbol table",
+ [3] = "string table",
+ [4] = "relocation entries",
+ [5] = "symbol hash table",
+ [6] = "dynamic linking information",
+ [7] = "information about the file",
+ [8] = "data occupies no space in file",
+ [9] = "relocation entries",
+ [10] = "reserved",
+ [11] = "symbol table",
+ [14] = "pointers to initialization functions",
+ [15] = "pointers to terminnation functions",
+ [16] = "pointers to pre-init functions",
+ [17] = "section group",
+ [18] = "indices for SHN_XINDEX entries"
+}
+
+local xform_sh_flags = function (u)
+ -- TODO: there are more known weird values and ranges
+ local info = {}
+ if u & 0x1 ~= 0 then table.insert (info, "write") end
+ if u & 0x2 ~= 0 then table.insert (info, "alloc") end
+ if u & 0x4 ~= 0 then table.insert (info, "execinstr") end
+
+ local junk = u & ~0x7
+ if junk ~= 0 then
+ table.insert (info, ("unknown: %#x"):format (junk))
+ end
+
+ if #info == 0 then return 0 end
+
+ local result = info[1]
+ for i = 2, #info do result = result .. ", " .. info[i] end
+ return result
end
local decode_sh = function (elf, c)
- -- TODO
+ local sh = {}
+ -- TODO: decode the values, give the fields meaning
+ sh.name = c:u32 ("name index: %d")
+ sh.type = c:u32 ("type: %s", function (u32)
+ -- TODO: there are more known weird values and ranges
+ name = sh_type_table[u32]
+ if name then return name end
+ return "unknown: %#x", u32
+ end)
+ sh.flags = elf.uwide (c, "flags: %s", xform_sh_flags)
+ sh.addr = elf.uwide (c, "load address: %#x")
+ sh.offset = elf.uwide (c, "offset in file: %#x")
+ sh.size = elf.uwide (c, "size: %d")
+ sh.link = c:u32 ("header table index link: %d")
+ sh.info = c:u32 ("extra information: %d")
+ sh.addralign = elf.uwide (c, "address alignment: %d")
+ sh.entsize = elf.uwide (c, "size of records: %d")
+ return sh
end
local abi_table = {
@@ -353,21 +412,36 @@ local decode = function (c)
elf.sh_number = c:u16 ("section header count: %d")
elf.sh_string_index = c:u16 ("section header index for strings: %d")
- -- TODO: decode all headers as well, see man 5 elf,
- -- /usr/include/elf.h and /usr/include/llvm/Support/ELF.h
for i = 1, elf.ph_number do
local start = elf.ph_offset + (i - 1) * elf.ph_entry_size
- local ph = c (1 + start, start + elf.ph_entry_size)
- ph:mark ("ELF program header %d", i - 1)
- decode_ph (elf, ph)
+ local pchunk = c (1 + start, start + elf.ph_entry_size)
+ pchunk:mark ("ELF program header %d", i - 1)
+ decode_ph (elf, pchunk)
end
- -- TODO: we will need to decode "sh_string_index" first to get names
+ -- Only mark section headers after we've decoded them all,
+ -- so that we can name them using the section containing section names
+ local shs = {}
for i = 1, elf.sh_number do
local start = elf.sh_offset + (i - 1) * elf.sh_entry_size
- local sh = c (1 + start, start + elf.sh_entry_size)
- sh:mark ("ELF section header %d", i - 1)
- decode_sh (elf, sh)
+ local schunk = c (1 + start, start + elf.sh_entry_size)
+ sh = decode_sh (elf, schunk)
+ shs[i], shs[sh] = sh, schunk
+ end
+
+ local strings
+ if elf.sh_string_index ~= 0 and elf.sh_string_index < elf.sh_number then
+ local sh = shs[elf.sh_string_index + 1]
+ strings = c (sh.offset + 1, sh.offset + sh.size)
+ end
+ for i, sh in ipairs (shs) do
+ local schunk = shs[sh]
+ if strings and sh.name < #strings then
+ sh.name_string = strings (sh.name + 1):cstring ()
+ schunk:mark ("ELF section header %d (%s)", i - 1, sh.name_string)
+ else
+ schunk:mark ("ELF section header %d", i - 1)
+ end
end
end