Added sparse file support

This commit is contained in:
2025-05-23 19:35:52 +02:00
parent 9d6356e8a9
commit 60691d09ed
10 changed files with 32 additions and 37 deletions

View File

@ -1,7 +1,6 @@
package compiler
import (
"bufio"
"io"
"git.urbach.dev/cli/q/src/config"
@ -13,24 +12,20 @@ import (
)
// Write writes the executable to the given writer.
func (r *Result) Write(writer io.Writer) error {
return write(writer, r.Code, r.Data, r.DLLs)
func (r *Result) Write(writer io.WriteSeeker) {
write(writer, r.Code, r.Data, r.DLLs)
}
// write writes an executable file to the given writer.
func write(writer io.Writer, code []byte, data []byte, dlls dll.List) error {
buffer := bufio.NewWriter(writer)
func write(writer io.WriteSeeker, code []byte, data []byte, dlls dll.List) {
switch config.TargetOS {
case config.Linux:
elf.Write(buffer, code, data)
elf.Write(writer, code, data)
case config.Mac:
macho.Write(buffer, code, data)
macho.Write(writer, code, data)
case config.Web:
wasm.Write(buffer, code, data)
wasm.Write(writer, code, data)
case config.Windows:
pe.Write(buffer, code, data, dlls)
pe.Write(writer, code, data, dlls)
}
return buffer.Flush()
}

View File

@ -10,13 +10,7 @@ func (r *Result) WriteFile(path string) error {
return err
}
err = r.Write(file)
if err != nil {
file.Close()
return err
}
r.Write(file)
err = file.Close()
if err != nil {

View File

@ -1,7 +1,6 @@
package elf
import (
"bytes"
"encoding/binary"
"io"
@ -21,7 +20,7 @@ type ELF struct {
}
// Write writes the ELF64 format to the given writer.
func Write(writer io.Writer, codeBytes []byte, dataBytes []byte) {
func Write(writer io.WriteSeeker, codeBytes []byte, dataBytes []byte) {
sections := exe.MakeSections(HeaderEnd, codeBytes, dataBytes)
code := sections[0]
data := sections[1]
@ -76,9 +75,9 @@ func Write(writer io.Writer, codeBytes []byte, dataBytes []byte) {
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}, code.Padding))
writer.Seek(int64(code.Padding), io.SeekCurrent)
writer.Write(code.Bytes)
writer.Write(bytes.Repeat([]byte{0x00}, data.Padding))
writer.Seek(int64(data.Padding), io.SeekCurrent)
writer.Write(data.Bytes)
if config.Sections {

View File

@ -1,12 +1,12 @@
package elf_test
import (
"io"
"testing"
"git.urbach.dev/cli/q/src/elf"
"git.urbach.dev/cli/q/src/test"
)
func TestWrite(t *testing.T) {
elf.Write(io.Discard, nil, nil)
elf.Write(&test.Discard{}, nil, nil)
}

View File

@ -1,7 +1,6 @@
package macho
import (
"bytes"
"encoding/binary"
"io"
@ -24,7 +23,7 @@ type MachO struct {
}
// Write writes the Mach-O format to the given writer.
func Write(writer io.Writer, codeBytes []byte, dataBytes []byte) {
func Write(writer io.WriteSeeker, codeBytes []byte, dataBytes []byte) {
sections := exe.MakeSections(HeaderEnd, codeBytes, dataBytes)
code := sections[0]
data := sections[1]
@ -116,8 +115,8 @@ func Write(writer io.Writer, codeBytes []byte, dataBytes []byte) {
binary.Write(writer, binary.LittleEndian, &m.CodeHeader)
binary.Write(writer, binary.LittleEndian, &m.DataHeader)
binary.Write(writer, binary.LittleEndian, &m.UnixThread)
writer.Write(bytes.Repeat([]byte{0x00}, code.Padding))
writer.Seek(int64(code.Padding), io.SeekCurrent)
writer.Write(code.Bytes)
writer.Write(bytes.Repeat([]byte{0x00}, data.Padding))
writer.Seek(int64(data.Padding), io.SeekCurrent)
writer.Write(data.Bytes)
}

View File

@ -1,12 +1,12 @@
package macho_test
import (
"io"
"testing"
"git.urbach.dev/cli/q/src/macho"
"git.urbach.dev/cli/q/src/test"
)
func TestWrite(t *testing.T) {
macho.Write(io.Discard, nil, nil)
macho.Write(&test.Discard{}, nil, nil)
}

View File

@ -24,7 +24,7 @@ type EXE struct {
}
// Write writes the EXE file to the given writer.
func Write(writer io.Writer, codeBytes []byte, dataBytes []byte, dlls dll.List) {
func Write(writer io.WriteSeeker, codeBytes []byte, dataBytes []byte, dlls dll.List) {
var (
sections = exe.MakeSections(HeaderEnd, codeBytes, dataBytes, nil)
code = sections[0]
@ -144,10 +144,10 @@ func Write(writer io.Writer, codeBytes []byte, dataBytes []byte, dlls dll.List)
binary.Write(writer, binary.LittleEndian, &pe.NTHeader)
binary.Write(writer, binary.LittleEndian, &pe.OptionalHeader64)
binary.Write(writer, binary.LittleEndian, &pe.Sections)
writer.Write(bytes.Repeat([]byte{0x00}, code.Padding))
writer.Seek(int64(code.Padding), io.SeekCurrent)
writer.Write(code.Bytes)
writer.Write(bytes.Repeat([]byte{0x00}, data.Padding))
writer.Seek(int64(data.Padding), io.SeekCurrent)
writer.Write(data.Bytes)
writer.Write(bytes.Repeat([]byte{0x00}, imports.Padding))
writer.Seek(int64(imports.Padding), io.SeekCurrent)
writer.Write(imports.Bytes)
}

View File

@ -1,12 +1,12 @@
package pe_test
import (
"io"
"testing"
"git.urbach.dev/cli/q/src/pe"
"git.urbach.dev/cli/q/src/test"
)
func TestWrite(t *testing.T) {
pe.Write(io.Discard, nil, nil, nil)
pe.Write(&test.Discard{}, nil, nil, nil)
}

View File

@ -26,6 +26,7 @@
- [scope](scope) - Defines a `Scope` used for code blocks
- [set](set) - Generic set implementation
- [sizeof](sizeof) - Calculates the byte size of numbers
- [test](test) - Testing utilities
- [token](token) - Converts a file to tokens with the `Tokenize` function
- [types](types) - Type system
- [x86](x86) - x86-64 implementation

7
src/test/Discard.go Normal file
View File

@ -0,0 +1,7 @@
package test
// Discard implements a no-op WriteSeeker.
type Discard struct{}
func (w *Discard) Write(_ []byte) (int, error) { return 0, nil }
func (w *Discard) Seek(_ int64, _ int) (int64, error) { return 0, nil }