local fmt = require("elf.fmt") local ec = require("elf.constants") ---@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 local M = {} function M.normalize(hdr) hdr.magic = hdr.magic or { 0x7f, 0x45, 0x4c, 0x46 } hdr.ident_version = hdr.ident_version or ec.VERSION hdr.osabi = hdr.osabi or ec.Osabi.sysv hdr.abiversion = hdr.abiversion or 0 hdr.version = hdr.version or ec.VERSION hdr.entry = hdr.entry or 0 hdr.phoff = hdr.phoff or 0 hdr.shoff = hdr.shoff or 0 hdr.flags = hdr.flags or 0 hdr.ehsize = hdr.ehsize or ((hdr.class == ec.Class.bit32) and 0x34 or 0x40) hdr.phentsize = hdr.phentsize or 0 hdr.phnum = hdr.phnum or 0 hdr.shentsize = hdr.shentsize or 0 hdr.shnum = hdr.shnum or 0 hdr.shstrndx = hdr.shstrndx or 0 end function M.validate(hdr) if not hdr.class then error("class is required in header", 3) end if not hdr.data then error("data is required in header", 3) end if not hdr.type then error("type is required in header", 3) end if not hdr.machine then error("machine is required in header", 3) end if hdr.class ~= ec.Class.bit32 and hdr.class ~= ec.Class.bit64 then error("class must be Class.bit32 or Class.bit64 in header", 3) end if hdr.data ~= ec.Endian.little and hdr.data ~= ec.Endian.big then error("data must be Endian.little or Endian.big in header", 3) end -- TODO additional validations end ---@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