package main import ( "encoding/binary" ) const ( EI_NIDENT = 16 ET_NONE = 0 ET_REL = 1 ET_EXEC = 2 ET_DYN = 3 ET_CORE = 4 MIPS = 0x08 EHSIZE = 52 PHENSIZE = 0x20 SHENTSIZE = 0x28 PT_NULL = 0 PT_LOAD = 1 PT_DYNAMIC = 2 PT_INTERP = 3 PT_NOTE = 4 PT_SHLIB = 5 PT_PHDR = 6 PT_TLS = 7 PF_READ = 4 PF_WRITE = 2 PF_EXEC = 1 ) type ElfHeader struct { e_ident [EI_NIDENT]byte e_type uint16 e_machine uint16 e_version uint32 e_entry uint32 e_phoff uint32 e_shoff uint32 e_flags uint32 e_ehsize uint16 e_phentsize uint16 e_phnum uint16 e_shentsize uint16 e_shnum uint16 e_shstrndx uint16 } type ProgramHeader struct { ptype uint32 offset uint32 vaddr uint32 paddr uint32 filesz uint32 memsz uint32 flags uint32 align uint32 } func EHInit(e_entry uint32, e_phnum uint16) ElfHeader { var e ElfHeader e.e_ident = [EI_NIDENT]byte{0x7f, 0x45, 0x4c, 0x46, // ELF magic number 0x01, // 32-bit format 0x00, // Endian 0x01, // ELF Version 0x00, // Target OS 0x00, // Target ABI 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // Padding if byteOrder == binary.BigEndian { e.e_ident[5] = 0x02 } else { e.e_ident[5] = 0x01 } e.e_type = ET_EXEC e.e_machine = MIPS e.e_version = 0x01 e.e_entry = e_entry e.e_phoff = EHSIZE // Program headers will be after ELF Header e.e_shoff = 0 e.e_ehsize = EHSIZE e.e_phentsize = PHENSIZE e.e_phnum = e_phnum e.e_shentsize = SHENTSIZE e.e_shnum = 0 e.e_shstrndx = 0 return e } /* NOTES: On the ToBytes methods * I understand that these two methods are not the prettiest, but I need * something to convert these structs to to byte arrays. From what I've read so * far there seems to be no way to do this. It appears that encoding/gob * ignores the size of data types, which is needed, and json serialization * would not produce the proper output. */ func (e *ElfHeader) ToBytes() []byte { bytes := make([]byte, EHSIZE) i := 0 for _, b := range e.e_ident { bytes[i] = b i++ } byteOrder.PutUint16(bytes[EI_NIDENT:], e.e_type) byteOrder.PutUint16(bytes[18:], e.e_machine) byteOrder.PutUint32(bytes[20:], e.e_version) byteOrder.PutUint32(bytes[24:], e.e_entry) byteOrder.PutUint32(bytes[28:], e.e_phoff) byteOrder.PutUint32(bytes[32:], e.e_shoff) byteOrder.PutUint32(bytes[36:], e.e_flags) byteOrder.PutUint16(bytes[40:], e.e_ehsize) byteOrder.PutUint16(bytes[42:], e.e_phentsize) byteOrder.PutUint16(bytes[44:], e.e_phnum) byteOrder.PutUint16(bytes[46:], e.e_shentsize) byteOrder.PutUint16(bytes[48:], e.e_shnum) byteOrder.PutUint16(bytes[50:], e.e_shstrndx) return bytes } func (p *ProgramHeader) ToBytes() []byte { bytes := make([]byte, PHENSIZE) byteOrder.PutUint32(bytes[0:], p.ptype) byteOrder.PutUint32(bytes[4:], p.offset) byteOrder.PutUint32(bytes[8:], p.vaddr) byteOrder.PutUint32(bytes[12:], p.paddr) byteOrder.PutUint32(bytes[16:], p.filesz) byteOrder.PutUint32(bytes[20:], p.memsz) byteOrder.PutUint32(bytes[24:], p.flags) byteOrder.PutUint32(bytes[28:], p.align) return bytes }