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
|
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/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 h1:mMAoMIwLBPNy7ocRSxdsCFs7onPC3GfDEiJErCneqRE=
|
||||||
git.akyoto.dev/go/color v0.1.1/go.mod h1:ywOjoD0O0sk6bIn92uAJf7mErlEFCuQInL84y4Lqi3Q=
|
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.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
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/config"
|
||||||
"git.akyoto.dev/cli/q/src/dll"
|
"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/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/sizeof"
|
||||||
"git.akyoto.dev/cli/q/src/x64"
|
"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()
|
data, dataLabels = a.Data.Finalize()
|
||||||
dataStart := config.BaseAddress + config.CodeOffset + len(code)
|
|
||||||
dataStart, _ = fs.Align(dataStart, config.Align)
|
|
||||||
|
|
||||||
for _, pointer := range dataPointers {
|
for _, pointer := range dataPointers {
|
||||||
address := Address(dataStart) + pointer.Resolve()
|
address := config.BaseAddress + Address(dataStart) + pointer.Resolve()
|
||||||
slice := code[pointer.Position : pointer.Position+4]
|
slice := code[pointer.Position : pointer.Position+4]
|
||||||
binary.LittleEndian.PutUint32(slice, uint32(address))
|
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 {
|
for _, pointer := range dllPointers {
|
||||||
destination := Address(0x3000) + pointer.Resolve()
|
destination := Address(importsStart) + pointer.Resolve()
|
||||||
address := destination - Address(config.CodeOffset+pointer.Position+Address(pointer.Size))
|
delta := destination - Address(codeStart+pointer.Position+Address(pointer.Size))
|
||||||
slice := code[pointer.Position : pointer.Position+4]
|
slice := code[pointer.Position : pointer.Position+4]
|
||||||
binary.LittleEndian.PutUint32(slice, uint32(address))
|
binary.LittleEndian.PutUint32(slice, uint32(delta))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return code, data
|
return code, data
|
||||||
|
@ -9,11 +9,8 @@ const (
|
|||||||
// The base address is the virtual address for our ELF file.
|
// The base address is the virtual address for our ELF file.
|
||||||
BaseAddress = 0x40 * MinAddress
|
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
|
Align = 0x1000
|
||||||
|
|
||||||
// The code offset is the offset of the executable machine code within the file.
|
|
||||||
CodeOffset = Align
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -9,6 +9,8 @@ import (
|
|||||||
"git.akyoto.dev/cli/q/src/fs"
|
"git.akyoto.dev/cli/q/src/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const HeaderEnd = HeaderSize + ProgramHeaderSize*2
|
||||||
|
|
||||||
// ELF represents an ELF file.
|
// ELF represents an ELF file.
|
||||||
type ELF struct {
|
type ELF struct {
|
||||||
Header
|
Header
|
||||||
@ -18,8 +20,6 @@ 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, code []byte, data []byte) {
|
func Write(writer io.Writer, code []byte, data []byte) {
|
||||||
const HeaderEnd = HeaderSize + ProgramHeaderSize*2
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
codeStart, codePadding = fs.Align(HeaderEnd, config.Align)
|
codeStart, codePadding = fs.Align(HeaderEnd, config.Align)
|
||||||
dataStart, dataPadding = fs.Align(codeStart+len(code), 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,
|
Type: TypeExecutable,
|
||||||
Architecture: ArchitectureAMD64,
|
Architecture: ArchitectureAMD64,
|
||||||
FileVersion: 1,
|
FileVersion: 1,
|
||||||
EntryPointInMemory: config.BaseAddress + config.CodeOffset,
|
EntryPointInMemory: int64(config.BaseAddress + codeStart),
|
||||||
ProgramHeaderOffset: HeaderSize,
|
ProgramHeaderOffset: HeaderSize,
|
||||||
SectionHeaderOffset: 0,
|
SectionHeaderOffset: 0,
|
||||||
Flags: 0,
|
Flags: 0,
|
||||||
@ -50,9 +50,9 @@ func Write(writer io.Writer, code []byte, data []byte) {
|
|||||||
CodeHeader: ProgramHeader{
|
CodeHeader: ProgramHeader{
|
||||||
Type: ProgramTypeLOAD,
|
Type: ProgramTypeLOAD,
|
||||||
Flags: ProgramFlagsExecutable | ProgramFlagsReadable,
|
Flags: ProgramFlagsExecutable | ProgramFlagsReadable,
|
||||||
Offset: config.CodeOffset,
|
Offset: int64(codeStart),
|
||||||
VirtualAddress: config.BaseAddress + config.CodeOffset,
|
VirtualAddress: int64(config.BaseAddress + codeStart),
|
||||||
PhysicalAddress: config.BaseAddress + config.CodeOffset,
|
PhysicalAddress: int64(config.BaseAddress + codeStart),
|
||||||
SizeInFile: int64(len(code)),
|
SizeInFile: int64(len(code)),
|
||||||
SizeInMemory: int64(len(code)),
|
SizeInMemory: int64(len(code)),
|
||||||
Align: config.Align,
|
Align: config.Align,
|
||||||
|
@ -9,6 +9,11 @@ import (
|
|||||||
"git.akyoto.dev/cli/q/src/fs"
|
"git.akyoto.dev/cli/q/src/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SizeCommands = Segment64Size*3 + ThreadSize
|
||||||
|
HeaderEnd = HeaderSize + SizeCommands
|
||||||
|
)
|
||||||
|
|
||||||
// MachO is the executable format used on MacOS.
|
// MachO is the executable format used on MacOS.
|
||||||
type MachO struct {
|
type MachO struct {
|
||||||
Header
|
Header
|
||||||
@ -20,11 +25,6 @@ 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, code []byte, data []byte) {
|
func Write(writer io.Writer, code []byte, data []byte) {
|
||||||
const (
|
|
||||||
SizeCommands = Segment64Size*3 + ThreadSize
|
|
||||||
HeaderEnd = HeaderSize + SizeCommands
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
codeStart, codePadding = fs.Align(HeaderEnd, config.Align)
|
codeStart, codePadding = fs.Align(HeaderEnd, config.Align)
|
||||||
dataStart, dataPadding = fs.Align(codeStart+len(code), 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,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
config.BaseAddress + config.CodeOffset, 0,
|
uint32(config.BaseAddress + codeStart), 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
|
@ -10,6 +10,11 @@ import (
|
|||||||
"git.akyoto.dev/cli/q/src/fs"
|
"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.
|
// EXE is the portable executable format used on Windows.
|
||||||
type EXE struct {
|
type EXE struct {
|
||||||
DOSHeader
|
DOSHeader
|
||||||
@ -20,12 +25,6 @@ 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, code []byte, data []byte, dlls dll.List) {
|
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)
|
codeStart, codePadding := fs.Align(HeaderEnd, config.Align)
|
||||||
dataStart, dataPadding := fs.Align(codeStart+len(code), config.Align)
|
dataStart, dataPadding := fs.Align(codeStart+len(code), config.Align)
|
||||||
importsStart, importsPadding := fs.Align(dataStart+len(data), 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)),
|
SizeOfCode: uint32(len(code)),
|
||||||
SizeOfInitializedData: 0,
|
SizeOfInitializedData: 0,
|
||||||
SizeOfUninitializedData: 0,
|
SizeOfUninitializedData: 0,
|
||||||
AddressOfEntryPoint: config.CodeOffset,
|
AddressOfEntryPoint: uint32(codeStart),
|
||||||
BaseOfCode: config.CodeOffset,
|
BaseOfCode: uint32(codeStart),
|
||||||
ImageBase: config.BaseAddress,
|
ImageBase: config.BaseAddress,
|
||||||
SectionAlignment: config.Align, // power of 2, must be greater than or equal to FileAlignment
|
SectionAlignment: config.Align, // power of 2, must be greater than or equal to FileAlignment
|
||||||
FileAlignment: config.Align, // power of 2
|
FileAlignment: config.Align, // power of 2
|
||||||
@ -128,7 +127,7 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
|||||||
MinorSubsystemVersion: 0,
|
MinorSubsystemVersion: 0,
|
||||||
Win32VersionValue: 0,
|
Win32VersionValue: 0,
|
||||||
SizeOfImage: uint32(imageSize),
|
SizeOfImage: uint32(imageSize),
|
||||||
SizeOfHeaders: config.CodeOffset, // section bodies begin here
|
SizeOfHeaders: uint32(codeStart), // section bodies begin here
|
||||||
CheckSum: 0,
|
CheckSum: 0,
|
||||||
Subsystem: uint16(subSystem),
|
Subsystem: uint16(subSystem),
|
||||||
DllCharacteristics: IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, // IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
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'},
|
Name: [8]byte{'.', 't', 'e', 'x', 't'},
|
||||||
VirtualSize: uint32(len(code)),
|
VirtualSize: uint32(len(code)),
|
||||||
VirtualAddress: config.CodeOffset,
|
VirtualAddress: uint32(codeStart),
|
||||||
RawSize: uint32(len(code)), // must be a multiple of FileAlignment
|
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,
|
Characteristics: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user