Added optional section headers

This commit is contained in:
2025-03-07 16:55:30 +01:00
parent 0bf299d007
commit 919d94e0f4
6 changed files with 63 additions and 14 deletions

View File

@ -28,16 +28,19 @@ func buildExecutable(args []string) (*build.Build, error) {
for i := 0; i < len(args); i++ {
switch args[i] {
case "-a", "--assembly":
case "--assembly", "-a":
config.ShowAssembly = true
case "-d", "--dry":
case "--dry":
config.Dry = true
case "-s", "--statistics":
case "--sections":
config.Sections = true
case "--statistics":
config.ShowStatistics = true
case "-v", "--verbose":
case "--verbose", "-v":
config.ShowAssembly = true
config.ShowStatistics = true

View File

@ -14,11 +14,12 @@ func Help(w io.Writer, code int) int {
Commands:
build [directory | file] build an executable from a file or directory
--arch [arch] cross-compile for another CPU architecture [x86|arm]
--arch [arch] cross-compile for CPU: [x86|arm]
--assembly, -a show assembly instructions
--dry, -d skip writing the executable to disk
--os [os] cross-compile for another OS [linux|mac|windows]
--statistics, -s show statistics
--dry skip writing the executable to disk
--os [os] cross-compile for OS: [linux|mac|windows]
--sections add sections to the executable
--statistics show statistics
--verbose, -v show everything
run [directory | file] build and run the executable

View File

@ -28,7 +28,7 @@ func TestCLI(t *testing.T) {
{[]string{"build", "../../examples/hello", "--dry", "--os", "mac"}, 0},
{[]string{"build", "../../examples/hello", "--dry", "--os", "windows"}, 0},
{[]string{"build", "../../examples/hello/hello.q", "--dry"}, 0},
{[]string{"build", "../../examples/hello"}, 0},
{[]string{"build", "../../examples/hello", "--sections"}, 0},
{[]string{"run", "../../examples/hello", "--invalid"}, 2},
{[]string{"run", "../../examples/hello"}, 0},
}

View File

@ -7,6 +7,7 @@ var (
Dry bool // Skips writing the executable to disk.
ShowAssembly bool // Shows assembly instructions at the end.
ShowStatistics bool // Shows statistics at the end.
Sections bool // Adds section headers to the executable.
TargetArch Arch // Target architecture.
TargetOS OS // Target platform.
)
@ -15,6 +16,7 @@ var (
func Reset() {
ShowAssembly = false
ShowStatistics = false
Sections = false
Dry = false
switch runtime.GOARCH {

35
src/elf/AddSections.go Normal file
View File

@ -0,0 +1,35 @@
package elf
// AddSections adds section headers to the ELF file.
func (elf *ELF) AddSections() {
elf.StringTable = []byte("\000.text\000.shstrtab\000")
stringTableStart := elf.DataHeader.Offset + elf.DataHeader.SizeInFile
sectionHeaderStart := stringTableStart + int64(len(elf.StringTable))
elf.SectionHeaders = []SectionHeader{
{
Type: SectionTypeNULL,
},
{
NameIndex: 1,
Type: SectionTypePROGBITS,
Flags: SectionFlagsAllocate | SectionFlagsExecutable,
VirtualAddress: elf.CodeHeader.VirtualAddress,
Offset: elf.CodeHeader.Offset,
SizeInFile: elf.CodeHeader.SizeInFile,
Align: elf.CodeHeader.Align,
},
{
NameIndex: 7,
Type: SectionTypeSTRTAB,
Offset: int64(stringTableStart),
SizeInFile: int64(len(elf.StringTable)),
Align: 1,
},
}
elf.SectionHeaderEntrySize = SectionHeaderSize
elf.SectionHeaderEntryCount = int16(len(elf.SectionHeaders))
elf.SectionHeaderOffset = int64(sectionHeaderStart)
elf.SectionNameStringTableIndex = 2
}

View File

@ -14,8 +14,10 @@ const HeaderEnd = HeaderSize + ProgramHeaderSize*2
// ELF represents an ELF file.
type ELF struct {
Header
CodeHeader ProgramHeader
DataHeader ProgramHeader
CodeHeader ProgramHeader
DataHeader ProgramHeader
SectionHeaders []SectionHeader
StringTable []byte
}
// Write writes the ELF64 format to the given writer.
@ -77,14 +79,20 @@ func Write(writer io.Writer, code []byte, data []byte) {
},
}
if config.Sections {
elf.AddSections()
}
binary.Write(writer, binary.LittleEndian, &elf.Header)
binary.Write(writer, binary.LittleEndian, &elf.CodeHeader)
binary.Write(writer, binary.LittleEndian, &elf.DataHeader)
writer.Write(bytes.Repeat([]byte{0x00}, codePadding))
writer.Write(code)
writer.Write(bytes.Repeat([]byte{0x00}, dataPadding))
writer.Write(data)
if len(data) > 0 {
writer.Write(bytes.Repeat([]byte{0x00}, dataPadding))
writer.Write(data)
if config.Sections {
writer.Write(elf.StringTable)
binary.Write(writer, binary.LittleEndian, &elf.SectionHeaders)
}
}