From 79f6b161f892f621a909ce1df99b3c680f3682a2 Mon Sep 17 00:00:00 2001 From: Sunil Nimmagadda Date: Fri, 23 Oct 2026 22:43:44 +0530 Subject: Refactor: Move to an elf module. While here, define a elf.d.lua to help author type check configuration file. --- elf/constants.lua | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ elf/fmt.lua | 17 +++++++++ elf/header.lua | 58 +++++++++++++++++++++++++++++++ elf/init.lua | 20 +++++++++++ elf/section.lua | 16 +++++++++ elf/segment.lua | 65 +++++++++++++++++++++++++++++++++++ 6 files changed, 277 insertions(+) create mode 100644 elf/constants.lua create mode 100644 elf/fmt.lua create mode 100644 elf/header.lua create mode 100644 elf/init.lua create mode 100644 elf/section.lua create mode 100644 elf/segment.lua (limited to 'elf') diff --git a/elf/constants.lua b/elf/constants.lua new file mode 100644 index 0000000..b06b275 --- /dev/null +++ b/elf/constants.lua @@ -0,0 +1,101 @@ +local M = {} + +M.VERSION = 1 + +---@enum Osabi +M.Osabi = { + sysv = 0x00, + hpux = 0x01, + netbsd = 0x02, + linux = 0x03, + hurd = 0x04, + solaris = 0x06, + aix = 0x07, + irix = 0x08, + freebsd = 0x09, + tru64 = 0x0a, + modesto = 0x0b, + openbsd = 0x0c, + openvms = 0x0d, + nsk = 0x0e, + aros = 0x0f, + fenixos = 0x10, + cloudabi = 0x11, + openvos = 0x12, +} + +---@enum Class +M.Class = { + bit32 = 0x1, + bit64 = 0x2, +} + +---@enum Endian +M.Endian = { + little = 0x1, + big = 0x2, +} + +---@enum Type +M.Type = { + none = 0x00, + rel = 0x01, + exec = 0x02, + dyn = 0x03, + core = 0x04, + loos = 0xfe00, + hios = 0xfeff, + loproc = 0xff00, + hiproc = 0xffff, +} + +---@enum Machine +M.Machine = { + none = 0x00, + m32 = 0x01, -- AT&T WE 32100 + sparc = 0x02, -- SPARC + i386 = 0x03, -- Intel 80386 + m68k = 0x04, -- Motorola 68000 (M68k) + m88k = 0x05, -- Motorola 88000 (M88k) + mcu = 0x06, -- Intel MCU + i860 = 0x07, -- Intel 80860 + mips = 0x08, -- MIPS + + s370 = 0x09, -- IBM System/370 + mipsrs3le = 0x0a, -- MIPS RS3000 Little Endian + parisc = 0x0f, -- Hewlett-Packard PA-RISC + vpp500 = 0x11, -- Fujitsu VPP500 + sparc32 = 0x12, -- Enhanced instruction set SPARC + i960 = 0x13, -- Intel 80960 + ppc = 0x14, -- PowerPC + ppc64 = 0x15, -- PowerPC (64-bit) + s390 = 0x16, -- IBM System/390 + spu = 0x17, -- IBM SPC/SPU + v800 = 0x24, -- NEC V800 + fr20 = 0x25, -- Fujitsu FR20 + -- todo +} + +---@enum SegmentType +M.SegmentType = { + null = 0x00000000, + load = 0x00000001, + dynamic = 0x00000002, + interp = 0x00000003, + note = 0x00000004, + shlib = 0x00000005, + phdr = 0x00000006, + tls = 0x00000007, + loos = 0x60000000, + hios = 0x6FFFFFFF, + loproc = 0x70000000, + hiproc = 0x7FFFFFFF, +} + +M.SegmentFlags = { + x = 0x1, + w = 0x2, + r = 0x4, +} + +return M diff --git a/elf/fmt.lua b/elf/fmt.lua new file mode 100644 index 0000000..44498d4 --- /dev/null +++ b/elf/fmt.lua @@ -0,0 +1,17 @@ +local constants = require("elf.constants") + +local M = {} + +---@param endian Endian +---@nodiscard +function M.endian(endian) + return (endian == constants.Endian.big) and ">" or "<" +end + +---@param class Class +---@nodiscard +function M.word(class) + return (class == constants.Class.bit64) and "I8" or "I4" +end + +return M diff --git a/elf/header.lua b/elf/header.lua new file mode 100644 index 0000000..2a9ec68 --- /dev/null +++ b/elf/header.lua @@ -0,0 +1,58 @@ +local fmt = require("elf.fmt") + +local M = {} + +---@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 + +---@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 diff --git a/elf/init.lua b/elf/init.lua new file mode 100644 index 0000000..6e6966a --- /dev/null +++ b/elf/init.lua @@ -0,0 +1,20 @@ +local constants = require("elf.constants") +local header = require("elf.header") +local segment = require("elf.segment") +local section = require("elf.section") + +local M = {} + +M.VERSION = constants.VERSION +M.Class = constants.Class +M.Endian = constants.Endian +M.Osabi = constants.Osabi +M.Type = constants.Type +M.Machine = constants.Machine +M.SegmentType = constants.SegmentType +M.SegmentFlags = constants.SegmentFlags +M.header = header +M.segment = segment +M.section = section + +return M diff --git a/elf/section.lua b/elf/section.lua new file mode 100644 index 0000000..64a91b2 --- /dev/null +++ b/elf/section.lua @@ -0,0 +1,16 @@ +local fmt = require("elf.fmt") + +local M = {} + +---@class Section + +---@param section Section +---@param endian Endian +---@return string +---@nodiscard +function M.pack(section, endian) + -- TODO + return string.pack("B", 0x1) +end + +return M diff --git a/elf/segment.lua b/elf/segment.lua new file mode 100644 index 0000000..da8e9c6 --- /dev/null +++ b/elf/segment.lua @@ -0,0 +1,65 @@ +local ec = require("elf.constants") +local fmt = require("elf.fmt") + +local M = {} + +---@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 + +---@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 -- cgit v1.3