diff --git a/src/build/asm/Assembler.go b/src/build/asm/Assembler.go index 08efb10..6ad35c8 100644 --- a/src/build/asm/Assembler.go +++ b/src/build/asm/Assembler.go @@ -4,12 +4,12 @@ import "maps" // Assembler contains a list of instructions. type Assembler struct { - Instructions []Instruction Data map[string][]byte + Instructions []Instruction } // Merge combines the contents of this assembler with another one. func (a *Assembler) Merge(b Assembler) { - a.Instructions = append(a.Instructions, b.Instructions...) maps.Copy(a.Data, b.Data) + a.Instructions = append(a.Instructions, b.Instructions...) } diff --git a/src/build/asm/RegisterLabel.go b/src/build/asm/RegisterLabel.go index 4eb23a3..f51bf77 100644 --- a/src/build/asm/RegisterLabel.go +++ b/src/build/asm/RegisterLabel.go @@ -8,8 +8,8 @@ import ( // RegisterLabel operates with a register and a label. type RegisterLabel struct { - Register cpu.Register Label string + Register cpu.Register } // String returns a human readable version. diff --git a/src/build/config/config.go b/src/build/config/config.go index 4f97a22..0697fa1 100644 --- a/src/build/config/config.go +++ b/src/build/config/config.go @@ -1,10 +1,17 @@ package config const ( - MinAddress = 0x10000 + // This is the absolute virtual minimum address we can load a program at, see `sysctl vm.mmap_min_addr`. + MinAddress = 0x10000 + + // The base address is the virtual address for our ELF file. BaseAddress = 0x40 * MinAddress - CodeOffset = 0x80 - Align = 0x10 + + // The code offset is the offset of the executable machine code within the file. + CodeOffset = 64 + 56 + 56 + + // Align decides the alignment of the sections and it must be a multiple of the page size. + Align = 0x1000 ) var ( diff --git a/src/build/elf/ELF.go b/src/build/elf/ELF.go index b6c3e34..a2b1e4a 100644 --- a/src/build/elf/ELF.go +++ b/src/build/elf/ELF.go @@ -11,11 +11,12 @@ import ( // ELF represents an ELF file. type ELF struct { Header - CodeHeader ProgramHeader - PadCode []byte - Code []byte - PadData []byte - Data []byte + CodeHeader ProgramHeader + DataHeader ProgramHeader + CodePadding []byte + Code []byte + DataPadding []byte + Data []byte } // New creates a new ELF binary. @@ -24,7 +25,7 @@ func New(code []byte, data []byte) *ELF { dataPadding := Padding(dataOffset, config.Align) dataOffset += dataPadding - elf := &ELF{ + return &ELF{ Header: Header{ Magic: [4]byte{0x7F, 'E', 'L', 'F'}, Class: 2, @@ -41,7 +42,7 @@ func New(code []byte, data []byte) *ELF { Flags: 0, Size: HeaderSize, ProgramHeaderEntrySize: ProgramHeaderSize, - ProgramHeaderEntryCount: 1, + ProgramHeaderEntryCount: 2, SectionHeaderEntrySize: SectionHeaderSize, SectionHeaderEntryCount: 0, SectionNameStringTableIndex: 0, @@ -56,25 +57,30 @@ func New(code []byte, data []byte) *ELF { SizeInMemory: int64(len(code)), Align: config.Align, }, - PadCode: bytes.Repeat([]byte{0}, 8), - Code: code, - PadData: bytes.Repeat([]byte{0}, int(dataPadding)), - Data: data, + 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: config.Align, + }, + CodePadding: nil, + Code: code, + DataPadding: bytes.Repeat([]byte{0}, int(dataPadding)), + Data: data, } - - return elf -} - -func Padding(n int64, align int64) int64 { - return align - (n % align) } // 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) - writer.Write(elf.PadCode) + binary.Write(writer, binary.LittleEndian, &elf.DataHeader) + writer.Write(elf.CodePadding) writer.Write(elf.Code) - writer.Write(elf.PadData) + writer.Write(elf.DataPadding) writer.Write(elf.Data) } diff --git a/src/build/elf/Padding.go b/src/build/elf/Padding.go new file mode 100644 index 0000000..5cca58e --- /dev/null +++ b/src/build/elf/Padding.go @@ -0,0 +1,6 @@ +package elf + +// Padding calculates the padding needed to align `n` bytes with the specified alignment. +func Padding(n int64, align int64) int64 { + return align - (n % align) +} diff --git a/src/build/elf/elf.md b/src/build/elf/elf.md index 83df35c..c40f005 100644 --- a/src/build/elf/elf.md +++ b/src/build/elf/elf.md @@ -23,4 +23,8 @@ Usually, this value is 65536 (0x1000). ## Initialization in Linux -See `/lib/modules/$(uname -r)/build/arch/x86/include/asm/elf.h`. +ELF loader: +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/binfmt_elf.c + +ELF register definitions: +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/include/asm/elf.h