local ELFVERSION = 1 ---@enum Osabi local 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, opevos = 0x12, } ---@enum Class local Class = { bit32 = 0x1, bit64 = 0x2, } ---@enum Endian local Endian = { little = 0x1, big = 0x2, } ---@enum Type local Type = { none = 0x00, rel = 0x01, exec = 0x02, dyn = 0x03, core = 0x04, loos = 0xfe00, hios = 0xfeff, loproc = 0xfe00, hiproc = 0xfeff, } ---@enum Machine local 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 } ---@alias ElfMagic [integer, integer, integer, integer] ---@class ElfHeader ---@field magic ElfMagic ---@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 function efmt(endian) return (endian == Endian.big) and ">" or "<" end ---@param hdr ElfHeader ---@nodiscard local function ElfHeader_pack(hdr) local ident = string.pack("BBBBBBBBBxxxxxxx", hdr.magic[1], hdr.magic[2], hdr.magic[3], hdr.magic[4], hdr.class, hdr.data, hdr.ident_version, hdr.osabi, hdr.abiversion) local sz = (hdr.class == Class.bit64) and "I8" or "I4" local h = string.pack(efmt(hdr.data) .. "I2I2I4" .. sz .. sz .. sz .. "I4I2I2I2I2I2I2", 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) return ident .. h end ---@type ElfHeader local header = { magic = { 0x7f, 0x45, 0x4c, 0x46 }, class = Class.bit32, data = Endian.big, ident_version = ELFVERSION, osabi = Osabi.netbsd, abiversion = 0, type = Type.exec, machine = Machine.i386, version = ELFVERSION, entry = 0, phoff = 0x34, shoff = 0xff, flags = 0, ehsize = 52, phentsize = 0x20, phnum = 0, shentsize = 0x28, shnum = 0, shstrndx = 0, pack = ElfHeader_pack } local function main() local output = "a.out" for i in ipairs(arg) do if arg[i] ~= "-o" then goto continue end if not arg[i + 1] then error("mkelf: missing filename after -o") end output = arg[i + 1] ::continue:: end local f = assert(io.open(output, "w")) f:write(header:pack()) f:close() end main()