Added sparse file support
This commit is contained in:
parent
2e00b28016
commit
dc315b8076
10 changed files with 32 additions and 37 deletions
|
@ -1,7 +1,6 @@
|
||||||
package compiler
|
package compiler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/config"
|
"git.urbach.dev/cli/q/src/config"
|
||||||
|
@ -13,24 +12,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Write writes the executable to the given writer.
|
// Write writes the executable to the given writer.
|
||||||
func (r *Result) Write(writer io.Writer) error {
|
func (r *Result) Write(writer io.WriteSeeker) {
|
||||||
return write(writer, r.Code, r.Data, r.DLLs)
|
write(writer, r.Code, r.Data, r.DLLs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// write writes an executable file to the given writer.
|
// write writes an executable file to the given writer.
|
||||||
func write(writer io.Writer, code []byte, data []byte, dlls dll.List) error {
|
func write(writer io.WriteSeeker, code []byte, data []byte, dlls dll.List) {
|
||||||
buffer := bufio.NewWriter(writer)
|
|
||||||
|
|
||||||
switch config.TargetOS {
|
switch config.TargetOS {
|
||||||
case config.Linux:
|
case config.Linux:
|
||||||
elf.Write(buffer, code, data)
|
elf.Write(writer, code, data)
|
||||||
case config.Mac:
|
case config.Mac:
|
||||||
macho.Write(buffer, code, data)
|
macho.Write(writer, code, data)
|
||||||
case config.Web:
|
case config.Web:
|
||||||
wasm.Write(buffer, code, data)
|
wasm.Write(writer, code, data)
|
||||||
case config.Windows:
|
case config.Windows:
|
||||||
pe.Write(buffer, code, data, dlls)
|
pe.Write(writer, code, data, dlls)
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.Flush()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,7 @@ func (r *Result) WriteFile(path string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = r.Write(file)
|
r.Write(file)
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
file.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = file.Close()
|
err = file.Close()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package elf
|
package elf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
@ -21,7 +20,7 @@ type ELF struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes the ELF64 format to the given writer.
|
// 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)
|
sections := exe.MakeSections(HeaderEnd, codeBytes, dataBytes)
|
||||||
code := sections[0]
|
code := sections[0]
|
||||||
data := sections[1]
|
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.Header)
|
||||||
binary.Write(writer, binary.LittleEndian, &elf.CodeHeader)
|
binary.Write(writer, binary.LittleEndian, &elf.CodeHeader)
|
||||||
binary.Write(writer, binary.LittleEndian, &elf.DataHeader)
|
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(code.Bytes)
|
||||||
writer.Write(bytes.Repeat([]byte{0x00}, data.Padding))
|
writer.Seek(int64(data.Padding), io.SeekCurrent)
|
||||||
writer.Write(data.Bytes)
|
writer.Write(data.Bytes)
|
||||||
|
|
||||||
if config.Sections {
|
if config.Sections {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package elf_test
|
package elf_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/elf"
|
"git.urbach.dev/cli/q/src/elf"
|
||||||
|
"git.urbach.dev/cli/q/src/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWrite(t *testing.T) {
|
func TestWrite(t *testing.T) {
|
||||||
elf.Write(io.Discard, nil, nil)
|
elf.Write(&test.Discard{}, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package macho
|
package macho
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
@ -24,7 +23,7 @@ type MachO struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes the Mach-O format to the given writer.
|
// 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)
|
sections := exe.MakeSections(HeaderEnd, codeBytes, dataBytes)
|
||||||
code := sections[0]
|
code := sections[0]
|
||||||
data := sections[1]
|
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.CodeHeader)
|
||||||
binary.Write(writer, binary.LittleEndian, &m.DataHeader)
|
binary.Write(writer, binary.LittleEndian, &m.DataHeader)
|
||||||
binary.Write(writer, binary.LittleEndian, &m.UnixThread)
|
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(code.Bytes)
|
||||||
writer.Write(bytes.Repeat([]byte{0x00}, data.Padding))
|
writer.Seek(int64(data.Padding), io.SeekCurrent)
|
||||||
writer.Write(data.Bytes)
|
writer.Write(data.Bytes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package macho_test
|
package macho_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/macho"
|
"git.urbach.dev/cli/q/src/macho"
|
||||||
|
"git.urbach.dev/cli/q/src/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWrite(t *testing.T) {
|
func TestWrite(t *testing.T) {
|
||||||
macho.Write(io.Discard, nil, nil)
|
macho.Write(&test.Discard{}, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ type EXE struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes the EXE file to the given writer.
|
// 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 (
|
var (
|
||||||
sections = exe.MakeSections(HeaderEnd, codeBytes, dataBytes, nil)
|
sections = exe.MakeSections(HeaderEnd, codeBytes, dataBytes, nil)
|
||||||
code = sections[0]
|
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.NTHeader)
|
||||||
binary.Write(writer, binary.LittleEndian, &pe.OptionalHeader64)
|
binary.Write(writer, binary.LittleEndian, &pe.OptionalHeader64)
|
||||||
binary.Write(writer, binary.LittleEndian, &pe.Sections)
|
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(code.Bytes)
|
||||||
writer.Write(bytes.Repeat([]byte{0x00}, data.Padding))
|
writer.Seek(int64(data.Padding), io.SeekCurrent)
|
||||||
writer.Write(data.Bytes)
|
writer.Write(data.Bytes)
|
||||||
writer.Write(bytes.Repeat([]byte{0x00}, imports.Padding))
|
writer.Seek(int64(imports.Padding), io.SeekCurrent)
|
||||||
writer.Write(imports.Bytes)
|
writer.Write(imports.Bytes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package pe_test
|
package pe_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/pe"
|
"git.urbach.dev/cli/q/src/pe"
|
||||||
|
"git.urbach.dev/cli/q/src/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWrite(t *testing.T) {
|
func TestWrite(t *testing.T) {
|
||||||
pe.Write(io.Discard, nil, nil, nil)
|
pe.Write(&test.Discard{}, nil, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
- [scope](scope) - Defines a `Scope` used for code blocks
|
- [scope](scope) - Defines a `Scope` used for code blocks
|
||||||
- [set](set) - Generic set implementation
|
- [set](set) - Generic set implementation
|
||||||
- [sizeof](sizeof) - Calculates the byte size of numbers
|
- [sizeof](sizeof) - Calculates the byte size of numbers
|
||||||
|
- [test](test) - Testing utilities
|
||||||
- [token](token) - Converts a file to tokens with the `Tokenize` function
|
- [token](token) - Converts a file to tokens with the `Tokenize` function
|
||||||
- [types](types) - Type system
|
- [types](types) - Type system
|
||||||
- [x86](x86) - x86-64 implementation
|
- [x86](x86) - x86-64 implementation
|
||||||
|
|
7
src/test/Discard.go
Normal file
7
src/test/Discard.go
Normal 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 }
|
Loading…
Add table
Add a link
Reference in a new issue