package elf import ( "bytes" "encoding/binary" "io" "git.akyoto.dev/cli/q/src/config" "git.akyoto.dev/cli/q/src/os/common" ) // ELF represents an ELF file. type ELF struct { Header CodeHeader ProgramHeader DataHeader ProgramHeader CodePadding []byte Code []byte DataPadding []byte Data []byte } // New creates a new ELF binary. func New(code []byte, data []byte) *ELF { dataOffset := CodeOffset + int64(len(code)) dataPadding := common.Padding(dataOffset, Align) dataOffset += dataPadding return &ELF{ Header: Header{ Magic: [4]byte{0x7F, 'E', 'L', 'F'}, Class: 2, Endianness: LittleEndian, Version: 1, OSABI: 0, ABIVersion: 0, Type: TypeExecutable, Architecture: ArchitectureAMD64, FileVersion: 1, EntryPointInMemory: config.BaseAddress + CodeOffset, ProgramHeaderOffset: HeaderSize, SectionHeaderOffset: 0, Flags: 0, Size: HeaderSize, ProgramHeaderEntrySize: ProgramHeaderSize, ProgramHeaderEntryCount: 2, SectionHeaderEntrySize: SectionHeaderSize, SectionHeaderEntryCount: 0, SectionNameStringTableIndex: 0, }, CodeHeader: ProgramHeader{ Type: ProgramTypeLOAD, Flags: ProgramFlagsExecutable | ProgramFlagsReadable, Offset: CodeOffset, VirtualAddress: config.BaseAddress + CodeOffset, PhysicalAddress: config.BaseAddress + CodeOffset, SizeInFile: int64(len(code)), SizeInMemory: int64(len(code)), Align: Align, }, DataHeader: ProgramHeader{ Type: ProgramTypeLOAD, Flags: ProgramFlagsReadable, Offset: dataOffset, VirtualAddress: config.BaseAddress + dataOffset, PhysicalAddress: config.BaseAddress + dataOffset, SizeInFile: int64(len(data)), SizeInMemory: int64(len(data)), Align: Align, }, CodePadding: nil, Code: code, DataPadding: bytes.Repeat([]byte{0}, int(dataPadding)), Data: data, } } // Write writes the ELF64 format to the given writer. func (elf *ELF) Write(writer io.Writer) { binary.Write(writer, binary.LittleEndian, &elf.Header) binary.Write(writer, binary.LittleEndian, &elf.CodeHeader) binary.Write(writer, binary.LittleEndian, &elf.DataHeader) writer.Write(elf.CodePadding) writer.Write(elf.Code) if len(elf.Data) > 0 { writer.Write(elf.DataPadding) writer.Write(elf.Data) } }