From 919d94e0f456e8ef3c196b0eb65ba3d39f4b2a9d Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Fri, 7 Mar 2025 16:55:30 +0100 Subject: [PATCH] Added optional section headers --- src/cli/Build.go | 11 +++++++---- src/cli/Help.go | 9 +++++---- src/cli/Main_test.go | 2 +- src/config/config.go | 2 ++ src/elf/AddSections.go | 35 +++++++++++++++++++++++++++++++++++ src/elf/ELF.go | 18 +++++++++++++----- 6 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 src/elf/AddSections.go diff --git a/src/cli/Build.go b/src/cli/Build.go index c9aa8ec..75f4377 100644 --- a/src/cli/Build.go +++ b/src/cli/Build.go @@ -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 diff --git a/src/cli/Help.go b/src/cli/Help.go index c96c6f0..eeba43e 100644 --- a/src/cli/Help.go +++ b/src/cli/Help.go @@ -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 diff --git a/src/cli/Main_test.go b/src/cli/Main_test.go index 236ef5a..b19cbfa 100644 --- a/src/cli/Main_test.go +++ b/src/cli/Main_test.go @@ -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}, } diff --git a/src/config/config.go b/src/config/config.go index 98bcdb4..b031375 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -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 { diff --git a/src/elf/AddSections.go b/src/elf/AddSections.go new file mode 100644 index 0000000..22d8e1f --- /dev/null +++ b/src/elf/AddSections.go @@ -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 +} diff --git a/src/elf/ELF.go b/src/elf/ELF.go index e914620..4a36abe 100644 --- a/src/elf/ELF.go +++ b/src/elf/ELF.go @@ -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) } }