Improved section offset calculation
This commit is contained in:
parent
e2a6a31d8e
commit
4b7c9f387d
2
go.mod
2
go.mod
@ -7,4 +7,4 @@ require (
|
||||
git.akyoto.dev/go/color v0.1.1
|
||||
)
|
||||
|
||||
require golang.org/x/sys v0.24.0 // indirect
|
||||
require golang.org/x/sys v0.29.0 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -2,5 +2,5 @@ git.akyoto.dev/go/assert v0.1.3 h1:QwCUbmG4aZYsNk/OuRBz1zWVKmGlDUHhOnnDBfn8Qw8=
|
||||
git.akyoto.dev/go/assert v0.1.3/go.mod h1:0GzMaM0eURuDwtGkJJkCsI7r2aUKr+5GmWNTFPgDocM=
|
||||
git.akyoto.dev/go/color v0.1.1 h1:mMAoMIwLBPNy7ocRSxdsCFs7onPC3GfDEiJErCneqRE=
|
||||
git.akyoto.dev/go/color v0.1.1/go.mod h1:ywOjoD0O0sk6bIn92uAJf7mErlEFCuQInL84y4Lqi3Q=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
|
@ -8,7 +8,10 @@ import (
|
||||
|
||||
"git.akyoto.dev/cli/q/src/config"
|
||||
"git.akyoto.dev/cli/q/src/dll"
|
||||
"git.akyoto.dev/cli/q/src/elf"
|
||||
"git.akyoto.dev/cli/q/src/fs"
|
||||
"git.akyoto.dev/cli/q/src/macho"
|
||||
"git.akyoto.dev/cli/q/src/pe"
|
||||
"git.akyoto.dev/cli/q/src/sizeof"
|
||||
"git.akyoto.dev/cli/q/src/x64"
|
||||
)
|
||||
@ -370,21 +373,40 @@ restart:
|
||||
}
|
||||
}
|
||||
|
||||
headerEnd := Address(0)
|
||||
|
||||
switch config.TargetOS {
|
||||
case "linux":
|
||||
headerEnd = elf.HeaderEnd
|
||||
case "macos":
|
||||
headerEnd = macho.HeaderEnd
|
||||
case "windows":
|
||||
headerEnd = pe.HeaderEnd
|
||||
}
|
||||
|
||||
codeStart, _ := fs.Align(headerEnd, config.Align)
|
||||
dataStart, _ := fs.Align(codeStart+Address(len(code)), config.Align)
|
||||
data, dataLabels = a.Data.Finalize()
|
||||
dataStart := config.BaseAddress + config.CodeOffset + len(code)
|
||||
dataStart, _ = fs.Align(dataStart, config.Align)
|
||||
|
||||
for _, pointer := range dataPointers {
|
||||
address := Address(dataStart) + pointer.Resolve()
|
||||
address := config.BaseAddress + Address(dataStart) + pointer.Resolve()
|
||||
slice := code[pointer.Position : pointer.Position+4]
|
||||
binary.LittleEndian.PutUint32(slice, uint32(address))
|
||||
}
|
||||
|
||||
for _, pointer := range dllPointers {
|
||||
destination := Address(0x3000) + pointer.Resolve()
|
||||
address := destination - Address(config.CodeOffset+pointer.Position+Address(pointer.Size))
|
||||
slice := code[pointer.Position : pointer.Position+4]
|
||||
binary.LittleEndian.PutUint32(slice, uint32(address))
|
||||
if config.TargetOS == "windows" {
|
||||
if len(data) == 0 {
|
||||
data = []byte{0}
|
||||
}
|
||||
|
||||
importsStart, _ := fs.Align(dataStart+Address(len(data)), config.Align)
|
||||
|
||||
for _, pointer := range dllPointers {
|
||||
destination := Address(importsStart) + pointer.Resolve()
|
||||
delta := destination - Address(codeStart+pointer.Position+Address(pointer.Size))
|
||||
slice := code[pointer.Position : pointer.Position+4]
|
||||
binary.LittleEndian.PutUint32(slice, uint32(delta))
|
||||
}
|
||||
}
|
||||
|
||||
return code, data
|
||||
|
@ -9,11 +9,8 @@ const (
|
||||
// The base address is the virtual address for our ELF file.
|
||||
BaseAddress = 0x40 * MinAddress
|
||||
|
||||
// Align decides the alignment of the sections and it must be a multiple of the page size.
|
||||
// Align is the alignment of the sections and it must be a multiple of the page size.
|
||||
Align = 0x1000
|
||||
|
||||
// The code offset is the offset of the executable machine code within the file.
|
||||
CodeOffset = Align
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -9,6 +9,8 @@ import (
|
||||
"git.akyoto.dev/cli/q/src/fs"
|
||||
)
|
||||
|
||||
const HeaderEnd = HeaderSize + ProgramHeaderSize*2
|
||||
|
||||
// ELF represents an ELF file.
|
||||
type ELF struct {
|
||||
Header
|
||||
@ -18,8 +20,6 @@ type ELF struct {
|
||||
|
||||
// Write writes the ELF64 format to the given writer.
|
||||
func Write(writer io.Writer, code []byte, data []byte) {
|
||||
const HeaderEnd = HeaderSize + ProgramHeaderSize*2
|
||||
|
||||
var (
|
||||
codeStart, codePadding = fs.Align(HeaderEnd, config.Align)
|
||||
dataStart, dataPadding = fs.Align(codeStart+len(code), config.Align)
|
||||
@ -36,7 +36,7 @@ func Write(writer io.Writer, code []byte, data []byte) {
|
||||
Type: TypeExecutable,
|
||||
Architecture: ArchitectureAMD64,
|
||||
FileVersion: 1,
|
||||
EntryPointInMemory: config.BaseAddress + config.CodeOffset,
|
||||
EntryPointInMemory: int64(config.BaseAddress + codeStart),
|
||||
ProgramHeaderOffset: HeaderSize,
|
||||
SectionHeaderOffset: 0,
|
||||
Flags: 0,
|
||||
@ -50,9 +50,9 @@ func Write(writer io.Writer, code []byte, data []byte) {
|
||||
CodeHeader: ProgramHeader{
|
||||
Type: ProgramTypeLOAD,
|
||||
Flags: ProgramFlagsExecutable | ProgramFlagsReadable,
|
||||
Offset: config.CodeOffset,
|
||||
VirtualAddress: config.BaseAddress + config.CodeOffset,
|
||||
PhysicalAddress: config.BaseAddress + config.CodeOffset,
|
||||
Offset: int64(codeStart),
|
||||
VirtualAddress: int64(config.BaseAddress + codeStart),
|
||||
PhysicalAddress: int64(config.BaseAddress + codeStart),
|
||||
SizeInFile: int64(len(code)),
|
||||
SizeInMemory: int64(len(code)),
|
||||
Align: config.Align,
|
||||
|
@ -9,6 +9,11 @@ import (
|
||||
"git.akyoto.dev/cli/q/src/fs"
|
||||
)
|
||||
|
||||
const (
|
||||
SizeCommands = Segment64Size*3 + ThreadSize
|
||||
HeaderEnd = HeaderSize + SizeCommands
|
||||
)
|
||||
|
||||
// MachO is the executable format used on MacOS.
|
||||
type MachO struct {
|
||||
Header
|
||||
@ -20,11 +25,6 @@ type MachO struct {
|
||||
|
||||
// Write writes the Mach-O format to the given writer.
|
||||
func Write(writer io.Writer, code []byte, data []byte) {
|
||||
const (
|
||||
SizeCommands = Segment64Size*3 + ThreadSize
|
||||
HeaderEnd = HeaderSize + SizeCommands
|
||||
)
|
||||
|
||||
var (
|
||||
codeStart, codePadding = fs.Align(HeaderEnd, config.Align)
|
||||
dataStart, dataPadding = fs.Align(codeStart+len(code), config.Align)
|
||||
@ -102,7 +102,7 @@ func Write(writer io.Writer, code []byte, data []byte) {
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
config.BaseAddress + config.CodeOffset, 0,
|
||||
uint32(config.BaseAddress + codeStart), 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
|
@ -10,6 +10,11 @@ import (
|
||||
"git.akyoto.dev/cli/q/src/fs"
|
||||
)
|
||||
|
||||
const (
|
||||
NumSections = 3
|
||||
HeaderEnd = DOSHeaderSize + NTHeaderSize + OptionalHeader64Size + SectionHeaderSize*NumSections
|
||||
)
|
||||
|
||||
// EXE is the portable executable format used on Windows.
|
||||
type EXE struct {
|
||||
DOSHeader
|
||||
@ -20,12 +25,6 @@ type EXE struct {
|
||||
|
||||
// Write writes the EXE file to the given writer.
|
||||
func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
if len(data) == 0 {
|
||||
data = []byte{0}
|
||||
}
|
||||
|
||||
NumSections := 3
|
||||
HeaderEnd := DOSHeaderSize + NTHeaderSize + OptionalHeader64Size + SectionHeaderSize*NumSections
|
||||
codeStart, codePadding := fs.Align(HeaderEnd, config.Align)
|
||||
dataStart, dataPadding := fs.Align(codeStart+len(code), config.Align)
|
||||
importsStart, importsPadding := fs.Align(dataStart+len(data), config.Align)
|
||||
@ -115,8 +114,8 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
SizeOfCode: uint32(len(code)),
|
||||
SizeOfInitializedData: 0,
|
||||
SizeOfUninitializedData: 0,
|
||||
AddressOfEntryPoint: config.CodeOffset,
|
||||
BaseOfCode: config.CodeOffset,
|
||||
AddressOfEntryPoint: uint32(codeStart),
|
||||
BaseOfCode: uint32(codeStart),
|
||||
ImageBase: config.BaseAddress,
|
||||
SectionAlignment: config.Align, // power of 2, must be greater than or equal to FileAlignment
|
||||
FileAlignment: config.Align, // power of 2
|
||||
@ -128,7 +127,7 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
MinorSubsystemVersion: 0,
|
||||
Win32VersionValue: 0,
|
||||
SizeOfImage: uint32(imageSize),
|
||||
SizeOfHeaders: config.CodeOffset, // section bodies begin here
|
||||
SizeOfHeaders: uint32(codeStart), // section bodies begin here
|
||||
CheckSum: 0,
|
||||
Subsystem: uint16(subSystem),
|
||||
DllCharacteristics: IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, // IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
||||
@ -161,9 +160,9 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
{
|
||||
Name: [8]byte{'.', 't', 'e', 'x', 't'},
|
||||
VirtualSize: uint32(len(code)),
|
||||
VirtualAddress: config.CodeOffset,
|
||||
VirtualAddress: uint32(codeStart),
|
||||
RawSize: uint32(len(code)), // must be a multiple of FileAlignment
|
||||
RawAddress: config.CodeOffset, // must be a multiple of FileAlignment
|
||||
RawAddress: uint32(codeStart), // must be a multiple of FileAlignment
|
||||
Characteristics: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ,
|
||||
},
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user