91 lines
2.6 KiB
Go
91 lines
2.6 KiB
Go
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)
|
|
}
|
|
}
|