Improved mac support

This commit is contained in:
Eduard Urbach 2024-08-12 12:16:01 +02:00
parent af259b364c
commit f70a2e848d
Signed by: eduard
GPG key ID: 49226B848C78F6C8
25 changed files with 119 additions and 34 deletions

122
src/os/mac/macho/MachO.go Normal file
View file

@ -0,0 +1,122 @@
package macho
import (
"bytes"
"encoding/binary"
"io"
"git.akyoto.dev/cli/q/src/config"
"git.akyoto.dev/cli/q/src/os/linux/elf"
)
// MachO is the executable format used on MacOS.
type MachO struct {
Header
Code []byte
Data []byte
}
// New creates a new Mach-O binary.
func New(code []byte, data []byte) *MachO {
return &MachO{
Header: Header{
Magic: 0xFEEDFACF,
Architecture: CPU_X86_64,
MicroArchitecture: 3 | 0x80000000,
Type: TypeExecute,
NumCommands: 4,
SizeCommands: 0x48*3 + 184,
Flags: FlagNoUndefs,
Reserved: 0,
},
Code: code,
Data: data,
}
}
// Write writes the Mach-O format to the given writer.
func (m *MachO) Write(writer io.Writer) {
binary.Write(writer, binary.LittleEndian, &m.Header)
binary.Write(writer, binary.LittleEndian, &Segment64{
LoadCommand: LcSegment64,
Length: 0x48,
Name: [16]byte{'_', '_', 'P', 'A', 'G', 'E', 'Z', 'E', 'R', 'O'},
Address: 0,
SizeInMemory: config.BaseAddress,
Offset: 0,
SizeInFile: 0,
NumSections: 0,
Flag: 0,
MaxProt: 0,
InitProt: 0,
})
codeStart := 32 + m.Header.SizeCommands
codeEnd := uint64(codeStart) + uint64(len(m.Code))
dataPadding := elf.Padding(codeEnd, 4096)
dataStart := codeEnd + dataPadding
binary.Write(writer, binary.LittleEndian, &Segment64{
LoadCommand: LcSegment64,
Length: 0x48,
Name: [16]byte{'_', '_', 'T', 'E', 'X', 'T'},
Address: config.BaseAddress,
SizeInMemory: codeEnd,
Offset: 0,
SizeInFile: codeEnd,
NumSections: 0,
Flag: 0,
MaxProt: ProtReadable | ProtWritable | ProtExecutable,
InitProt: ProtReadable | ProtExecutable,
})
binary.Write(writer, binary.LittleEndian, &Segment64{
LoadCommand: LcSegment64,
Length: 0x48,
Name: [16]byte{'_', '_', 'D', 'A', 'T', 'A'},
Address: config.BaseAddress + dataStart,
SizeInMemory: uint64(len(m.Data)),
Offset: dataStart,
SizeInFile: uint64(len(m.Data)),
NumSections: 0,
Flag: 0,
MaxProt: ProtReadable,
InitProt: ProtReadable,
})
binary.Write(writer, binary.LittleEndian, &Thread{
LoadCommand: LcUnixthread,
Len: 184,
Type: 0x4,
})
binary.Write(writer, binary.LittleEndian, []uint32{
42,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
config.BaseAddress + uint32(codeStart), 0,
0, 0,
0, 0,
0, 0,
0, 0,
})
writer.Write(m.Code)
writer.Write(bytes.Repeat([]byte{0}, int(dataPadding)))
writer.Write(m.Data)
}