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