Added Windows PE support
This commit is contained in:
parent
b90ee62b98
commit
7b1a293cd0
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
"git.akyoto.dev/cli/q/src/arch/x64"
|
"git.akyoto.dev/cli/q/src/arch/x64"
|
||||||
"git.akyoto.dev/cli/q/src/config"
|
"git.akyoto.dev/cli/q/src/config"
|
||||||
"git.akyoto.dev/cli/q/src/os/linux/elf"
|
"git.akyoto.dev/cli/q/src/os/common"
|
||||||
"git.akyoto.dev/cli/q/src/sizeof"
|
"git.akyoto.dev/cli/q/src/sizeof"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -338,7 +338,7 @@ restart:
|
|||||||
|
|
||||||
data, dataLabels = a.Data.Finalize()
|
data, dataLabels = a.Data.Finalize()
|
||||||
dataStart := config.BaseAddress + config.CodeOffset + Address(len(code))
|
dataStart := config.BaseAddress + config.CodeOffset + Address(len(code))
|
||||||
dataStart += int32(elf.Padding(int64(dataStart), config.Align))
|
dataStart += int32(common.Padding(int64(dataStart), config.Align))
|
||||||
|
|
||||||
for _, pointer := range dataPointers {
|
for _, pointer := range dataPointers {
|
||||||
address := dataStart + pointer.Resolve()
|
address := dataStart + pointer.Resolve()
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"git.akyoto.dev/cli/q/src/os/linux/elf"
|
"git.akyoto.dev/cli/q/src/os/linux/elf"
|
||||||
"git.akyoto.dev/cli/q/src/os/mac"
|
"git.akyoto.dev/cli/q/src/os/mac"
|
||||||
"git.akyoto.dev/cli/q/src/os/mac/macho"
|
"git.akyoto.dev/cli/q/src/os/mac/macho"
|
||||||
|
"git.akyoto.dev/cli/q/src/os/windows/pe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Result contains all the compiled functions in a build.
|
// Result contains all the compiled functions in a build.
|
||||||
@ -35,19 +36,21 @@ func (r *Result) finalize() ([]byte, []byte) {
|
|||||||
Data: make(map[string][]byte, r.DataCount),
|
Data: make(map[string][]byte, r.DataCount),
|
||||||
}
|
}
|
||||||
|
|
||||||
sysExit := 0
|
final.Call("main.main")
|
||||||
|
|
||||||
switch config.TargetOS {
|
switch config.TargetOS {
|
||||||
case "linux":
|
case "linux":
|
||||||
sysExit = linux.Exit
|
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], linux.Exit)
|
||||||
case "mac":
|
|
||||||
sysExit = mac.Exit
|
|
||||||
}
|
|
||||||
|
|
||||||
final.Call("main.main")
|
|
||||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], sysExit)
|
|
||||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 0)
|
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 0)
|
||||||
final.Syscall()
|
final.Syscall()
|
||||||
|
case "mac":
|
||||||
|
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], mac.Exit)
|
||||||
|
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 0)
|
||||||
|
final.Syscall()
|
||||||
|
case "windows":
|
||||||
|
final.RegisterNumber(asm.MOVE, x64.RAX, 0)
|
||||||
|
final.Return()
|
||||||
|
}
|
||||||
|
|
||||||
// This will place the main function immediately after the entry point
|
// This will place the main function immediately after the entry point
|
||||||
// and also add everything the main function calls recursively.
|
// and also add everything the main function calls recursively.
|
||||||
@ -56,9 +59,20 @@ func (r *Result) finalize() ([]byte, []byte) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
final.Label(asm.LABEL, "_crash")
|
final.Label(asm.LABEL, "_crash")
|
||||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], sysExit)
|
|
||||||
|
switch config.TargetOS {
|
||||||
|
case "linux":
|
||||||
|
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], linux.Exit)
|
||||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 1)
|
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 1)
|
||||||
final.Syscall()
|
final.Syscall()
|
||||||
|
case "mac":
|
||||||
|
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], mac.Exit)
|
||||||
|
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 1)
|
||||||
|
final.Syscall()
|
||||||
|
case "windows":
|
||||||
|
final.RegisterNumber(asm.MOVE, x64.RAX, 1)
|
||||||
|
final.Return()
|
||||||
|
}
|
||||||
|
|
||||||
code, data := final.Finalize()
|
code, data := final.Finalize()
|
||||||
return code, data
|
return code, data
|
||||||
@ -138,6 +152,9 @@ func write(writer io.Writer, code []byte, data []byte) error {
|
|||||||
case "mac":
|
case "mac":
|
||||||
exe := macho.New(code, data)
|
exe := macho.New(code, data)
|
||||||
exe.Write(buffer)
|
exe.Write(buffer)
|
||||||
|
case "windows":
|
||||||
|
exe := pe.New(code, data)
|
||||||
|
exe.Write(buffer)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported platform '%s'", config.TargetOS)
|
return fmt.Errorf("unsupported platform '%s'", config.TargetOS)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package elf
|
package common
|
||||||
|
|
||||||
// Padding calculates the padding needed to align `n` bytes with the specified alignment.
|
// Padding calculates the padding needed to align `n` bytes with the specified alignment.
|
||||||
func Padding[T int | int32 | int64 | uint | uint32 | uint64](n T, align T) T {
|
func Padding[T int64 | uint64 | int32 | uint32](n T, align T) T {
|
||||||
return align - (n % align)
|
return align - (n % align)
|
||||||
}
|
}
|
55
src/os/linux/elf/Constants.go
Normal file
55
src/os/linux/elf/Constants.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package elf
|
||||||
|
|
||||||
|
const (
|
||||||
|
LittleEndian = 1
|
||||||
|
TypeExecutable = 2
|
||||||
|
ArchitectureAMD64 = 0x3E
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProgramType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProgramTypeNULL ProgramType = 0
|
||||||
|
ProgramTypeLOAD ProgramType = 1
|
||||||
|
ProgramTypeDYNAMIC ProgramType = 2
|
||||||
|
ProgramTypeINTERP ProgramType = 3
|
||||||
|
ProgramTypeNOTE ProgramType = 4
|
||||||
|
ProgramTypeSHLIB ProgramType = 5
|
||||||
|
ProgramTypePHDR ProgramType = 6
|
||||||
|
ProgramTypeTLS ProgramType = 7
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProgramFlags int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProgramFlagsExecutable ProgramFlags = 0x1
|
||||||
|
ProgramFlagsWritable ProgramFlags = 0x2
|
||||||
|
ProgramFlagsReadable ProgramFlags = 0x4
|
||||||
|
)
|
||||||
|
|
||||||
|
type SectionType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
SectionTypeNULL SectionType = 0
|
||||||
|
SectionTypePROGBITS SectionType = 1
|
||||||
|
SectionTypeSYMTAB SectionType = 2
|
||||||
|
SectionTypeSTRTAB SectionType = 3
|
||||||
|
SectionTypeRELA SectionType = 4
|
||||||
|
SectionTypeHASH SectionType = 5
|
||||||
|
SectionTypeDYNAMIC SectionType = 6
|
||||||
|
SectionTypeNOTE SectionType = 7
|
||||||
|
SectionTypeNOBITS SectionType = 8
|
||||||
|
SectionTypeREL SectionType = 9
|
||||||
|
SectionTypeSHLIB SectionType = 10
|
||||||
|
SectionTypeDYNSYM SectionType = 11
|
||||||
|
)
|
||||||
|
|
||||||
|
type SectionFlags int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
SectionFlagsWritable SectionFlags = 1 << 0
|
||||||
|
SectionFlagsAllocate SectionFlags = 1 << 1
|
||||||
|
SectionFlagsExecutable SectionFlags = 1 << 2
|
||||||
|
SectionFlagsStrings SectionFlags = 1 << 5
|
||||||
|
SectionFlagsTLS SectionFlags = 1 << 10
|
||||||
|
)
|
@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.akyoto.dev/cli/q/src/config"
|
"git.akyoto.dev/cli/q/src/config"
|
||||||
|
"git.akyoto.dev/cli/q/src/os/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ELF represents an ELF file.
|
// ELF represents an ELF file.
|
||||||
@ -22,7 +23,7 @@ type ELF struct {
|
|||||||
// New creates a new ELF binary.
|
// New creates a new ELF binary.
|
||||||
func New(code []byte, data []byte) *ELF {
|
func New(code []byte, data []byte) *ELF {
|
||||||
dataOffset := config.CodeOffset + int64(len(code))
|
dataOffset := config.CodeOffset + int64(len(code))
|
||||||
dataPadding := Padding(dataOffset, config.Align)
|
dataPadding := common.Padding(dataOffset, config.Align)
|
||||||
dataOffset += dataPadding
|
dataOffset += dataPadding
|
||||||
|
|
||||||
return &ELF{
|
return &ELF{
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package elf
|
package elf
|
||||||
|
|
||||||
const (
|
// HeaderSize is equal to the size of a header in bytes.
|
||||||
LittleEndian = 1
|
const HeaderSize = 64
|
||||||
TypeExecutable = 2
|
|
||||||
ArchitectureAMD64 = 0x3E
|
|
||||||
HeaderSize = 64
|
|
||||||
)
|
|
||||||
|
|
||||||
// Header contains general information.
|
// Header contains general information.
|
||||||
type Header struct {
|
type Header struct {
|
||||||
|
@ -14,24 +14,3 @@ type ProgramHeader struct {
|
|||||||
SizeInMemory int64
|
SizeInMemory int64
|
||||||
Align int64
|
Align int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProgramType int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
ProgramTypeNULL ProgramType = 0
|
|
||||||
ProgramTypeLOAD ProgramType = 1
|
|
||||||
ProgramTypeDYNAMIC ProgramType = 2
|
|
||||||
ProgramTypeINTERP ProgramType = 3
|
|
||||||
ProgramTypeNOTE ProgramType = 4
|
|
||||||
ProgramTypeSHLIB ProgramType = 5
|
|
||||||
ProgramTypePHDR ProgramType = 6
|
|
||||||
ProgramTypeTLS ProgramType = 7
|
|
||||||
)
|
|
||||||
|
|
||||||
type ProgramFlags int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
ProgramFlagsExecutable ProgramFlags = 0x1
|
|
||||||
ProgramFlagsWritable ProgramFlags = 0x2
|
|
||||||
ProgramFlagsReadable ProgramFlags = 0x4
|
|
||||||
)
|
|
||||||
|
@ -16,30 +16,3 @@ type SectionHeader struct {
|
|||||||
Align int64
|
Align int64
|
||||||
EntrySize int64
|
EntrySize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type SectionType int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
SectionTypeNULL SectionType = 0
|
|
||||||
SectionTypePROGBITS SectionType = 1
|
|
||||||
SectionTypeSYMTAB SectionType = 2
|
|
||||||
SectionTypeSTRTAB SectionType = 3
|
|
||||||
SectionTypeRELA SectionType = 4
|
|
||||||
SectionTypeHASH SectionType = 5
|
|
||||||
SectionTypeDYNAMIC SectionType = 6
|
|
||||||
SectionTypeNOTE SectionType = 7
|
|
||||||
SectionTypeNOBITS SectionType = 8
|
|
||||||
SectionTypeREL SectionType = 9
|
|
||||||
SectionTypeSHLIB SectionType = 10
|
|
||||||
SectionTypeDYNSYM SectionType = 11
|
|
||||||
)
|
|
||||||
|
|
||||||
type SectionFlags int64
|
|
||||||
|
|
||||||
const (
|
|
||||||
SectionFlagsWritable SectionFlags = 1 << 0
|
|
||||||
SectionFlagsAllocate SectionFlags = 1 << 1
|
|
||||||
SectionFlagsExecutable SectionFlags = 1 << 2
|
|
||||||
SectionFlagsStrings SectionFlags = 1 << 5
|
|
||||||
SectionFlagsTLS SectionFlags = 1 << 10
|
|
||||||
)
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package macho
|
|
||||||
|
|
||||||
type CPU uint32
|
|
||||||
|
|
||||||
const (
|
|
||||||
CPU_X86 CPU = 7
|
|
||||||
CPU_X86_64 CPU = CPU_X86 | 0x01000000
|
|
||||||
CPU_ARM CPU = 12
|
|
||||||
CPU_ARM_64 CPU = CPU_ARM | 0x01000000
|
|
||||||
)
|
|
@ -1,5 +1,22 @@
|
|||||||
package macho
|
package macho
|
||||||
|
|
||||||
|
type CPU uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
CPU_X86 CPU = 7
|
||||||
|
CPU_X86_64 CPU = CPU_X86 | 0x01000000
|
||||||
|
CPU_ARM CPU = 12
|
||||||
|
CPU_ARM_64 CPU = CPU_ARM | 0x01000000
|
||||||
|
)
|
||||||
|
|
||||||
|
type Prot uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProtReadable Prot = 0x1
|
||||||
|
ProtWritable Prot = 0x2
|
||||||
|
ProtExecutable Prot = 0x4
|
||||||
|
)
|
||||||
|
|
||||||
type HeaderFlags uint32
|
type HeaderFlags uint32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -30,3 +47,14 @@ const (
|
|||||||
FlagNoHeapExecution HeaderFlags = 0x1000000
|
FlagNoHeapExecution HeaderFlags = 0x1000000
|
||||||
FlagAppExtensionSafe HeaderFlags = 0x2000000
|
FlagAppExtensionSafe HeaderFlags = 0x2000000
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type HeaderType uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
TypeObject HeaderType = 0x1
|
||||||
|
TypeExecute HeaderType = 0x2
|
||||||
|
TypeCore HeaderType = 0x4
|
||||||
|
TypeDylib HeaderType = 0x6
|
||||||
|
TypeBundle HeaderType = 0x8
|
||||||
|
TypeDsym HeaderType = 0xA
|
||||||
|
)
|
@ -1,12 +0,0 @@
|
|||||||
package macho
|
|
||||||
|
|
||||||
type HeaderType uint32
|
|
||||||
|
|
||||||
const (
|
|
||||||
TypeObject HeaderType = 0x1
|
|
||||||
TypeExecute HeaderType = 0x2
|
|
||||||
TypeCore HeaderType = 0x4
|
|
||||||
TypeDylib HeaderType = 0x6
|
|
||||||
TypeBundle HeaderType = 0x8
|
|
||||||
TypeDsym HeaderType = 0xA
|
|
||||||
)
|
|
@ -6,7 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.akyoto.dev/cli/q/src/config"
|
"git.akyoto.dev/cli/q/src/config"
|
||||||
"git.akyoto.dev/cli/q/src/os/linux/elf"
|
"git.akyoto.dev/cli/q/src/os/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MachO is the executable format used on MacOS.
|
// MachO is the executable format used on MacOS.
|
||||||
@ -55,7 +55,7 @@ func (m *MachO) Write(writer io.Writer) {
|
|||||||
codeStart := uint64(32 + m.Header.SizeCommands)
|
codeStart := uint64(32 + m.Header.SizeCommands)
|
||||||
codeLength := uint64(len(m.Code))
|
codeLength := uint64(len(m.Code))
|
||||||
codeEnd := codeStart + codeLength
|
codeEnd := codeStart + codeLength
|
||||||
dataPadding := elf.Padding(codeEnd, 4096)
|
dataPadding := common.Padding(codeEnd, config.Align)
|
||||||
dataStart := codeEnd + dataPadding
|
dataStart := codeEnd + dataPadding
|
||||||
|
|
||||||
binary.Write(writer, binary.LittleEndian, &Segment64{
|
binary.Write(writer, binary.LittleEndian, &Segment64{
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
package macho
|
|
||||||
|
|
||||||
type Prot uint32
|
|
||||||
|
|
||||||
const (
|
|
||||||
ProtReadable Prot = 0x1
|
|
||||||
ProtWritable Prot = 0x2
|
|
||||||
ProtExecutable Prot = 0x4
|
|
||||||
)
|
|
72
src/os/windows/pe/Constants.go
Normal file
72
src/os/windows/pe/Constants.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package pe
|
||||||
|
|
||||||
|
// CPU
|
||||||
|
const (
|
||||||
|
IMAGE_FILE_MACHINE_AMD64 = 0x8664
|
||||||
|
IMAGE_FILE_MACHINE_ARM64 = 0xAA64
|
||||||
|
IMAGE_FILE_MACHINE_RISCV64 = 0x5064
|
||||||
|
)
|
||||||
|
|
||||||
|
// Subsystems
|
||||||
|
const (
|
||||||
|
IMAGE_SUBSYSTEM_UNKNOWN = 0
|
||||||
|
IMAGE_SUBSYSTEM_NATIVE = 1
|
||||||
|
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
|
||||||
|
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
|
||||||
|
IMAGE_SUBSYSTEM_OS2_CUI = 5
|
||||||
|
IMAGE_SUBSYSTEM_POSIX_CUI = 7
|
||||||
|
IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8
|
||||||
|
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9
|
||||||
|
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10
|
||||||
|
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11
|
||||||
|
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12
|
||||||
|
IMAGE_SUBSYSTEM_EFI_ROM = 13
|
||||||
|
IMAGE_SUBSYSTEM_XBOX = 14
|
||||||
|
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
// Characteristics
|
||||||
|
const (
|
||||||
|
IMAGE_FILE_RELOCS_STRIPPED = 0x0001
|
||||||
|
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002
|
||||||
|
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004
|
||||||
|
IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008
|
||||||
|
IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010
|
||||||
|
IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020
|
||||||
|
IMAGE_FILE_BYTES_REVERSED_LO = 0x0080
|
||||||
|
IMAGE_FILE_32BIT_MACHINE = 0x0100
|
||||||
|
IMAGE_FILE_DEBUG_STRIPPED = 0x0200
|
||||||
|
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400
|
||||||
|
IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800
|
||||||
|
IMAGE_FILE_SYSTEM = 0x1000
|
||||||
|
IMAGE_FILE_DLL = 0x2000
|
||||||
|
IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000
|
||||||
|
IMAGE_FILE_BYTES_REVERSED_HI = 0x8000
|
||||||
|
)
|
||||||
|
|
||||||
|
// DLL characteristics
|
||||||
|
const (
|
||||||
|
IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020
|
||||||
|
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040
|
||||||
|
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080
|
||||||
|
IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100
|
||||||
|
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200
|
||||||
|
IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400
|
||||||
|
IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800
|
||||||
|
IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 0x1000
|
||||||
|
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000
|
||||||
|
IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000
|
||||||
|
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
|
||||||
|
)
|
||||||
|
|
||||||
|
// Section characteristics
|
||||||
|
const (
|
||||||
|
IMAGE_SCN_CNT_CODE = 0x00000020
|
||||||
|
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040
|
||||||
|
IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
|
||||||
|
IMAGE_SCN_LNK_COMDAT = 0x00001000
|
||||||
|
IMAGE_SCN_MEM_DISCARDABLE = 0x02000000
|
||||||
|
IMAGE_SCN_MEM_EXECUTE = 0x20000000
|
||||||
|
IMAGE_SCN_MEM_READ = 0x40000000
|
||||||
|
IMAGE_SCN_MEM_WRITE = 0x80000000
|
||||||
|
)
|
9
src/os/windows/pe/DOSHeader.go
Normal file
9
src/os/windows/pe/DOSHeader.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package pe
|
||||||
|
|
||||||
|
// DOSHeader is at the beginning of each EXE file and nowadays just points
|
||||||
|
// to the NTHeader using an absolute file offset.
|
||||||
|
type DOSHeader struct {
|
||||||
|
Magic [4]byte
|
||||||
|
_ [56]byte
|
||||||
|
NTHeaderOffset uint32
|
||||||
|
}
|
6
src/os/windows/pe/DataDirectory.go
Normal file
6
src/os/windows/pe/DataDirectory.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package pe
|
||||||
|
|
||||||
|
type DataDirectory struct {
|
||||||
|
VirtualAddress uint32
|
||||||
|
Size uint32
|
||||||
|
}
|
105
src/os/windows/pe/EXE.go
Normal file
105
src/os/windows/pe/EXE.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package pe
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"git.akyoto.dev/cli/q/src/config"
|
||||||
|
"git.akyoto.dev/cli/q/src/os/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EXE is the portable executable format used on Windows.
|
||||||
|
type EXE struct {
|
||||||
|
DOSHeader
|
||||||
|
NTHeader
|
||||||
|
OptionalHeader64
|
||||||
|
CodeHeader SectionHeader
|
||||||
|
Code []byte
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new EXE file.
|
||||||
|
func New(code []byte, data []byte) *EXE {
|
||||||
|
const codeStart = 0x170
|
||||||
|
const optHeaderSize = 0xF0
|
||||||
|
|
||||||
|
codeSize := uint32(len(code))
|
||||||
|
headerSize := uint32(codeStart)
|
||||||
|
sectionAlign := uint32(0x10)
|
||||||
|
fileAlign := uint32(0x10)
|
||||||
|
imageSize := uint32(codeStart + len(code))
|
||||||
|
imageSize += common.Padding(imageSize, sectionAlign)
|
||||||
|
|
||||||
|
return &EXE{
|
||||||
|
DOSHeader: DOSHeader{
|
||||||
|
Magic: [4]byte{'M', 'Z', 0, 0},
|
||||||
|
NTHeaderOffset: 0x40,
|
||||||
|
},
|
||||||
|
NTHeader: NTHeader{
|
||||||
|
Signature: [4]byte{'P', 'E', 0, 0},
|
||||||
|
Machine: IMAGE_FILE_MACHINE_AMD64,
|
||||||
|
NumberOfSections: 1,
|
||||||
|
SizeOfOptionalHeader: optHeaderSize,
|
||||||
|
Characteristics: IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE,
|
||||||
|
},
|
||||||
|
OptionalHeader64: OptionalHeader64{
|
||||||
|
Magic: 0x020B, // PE32+ executable
|
||||||
|
MajorLinkerVersion: 0x0E,
|
||||||
|
MinorLinkerVersion: 0x16,
|
||||||
|
SizeOfCode: codeSize,
|
||||||
|
AddressOfEntryPoint: codeStart,
|
||||||
|
ImageBase: config.BaseAddress,
|
||||||
|
SectionAlignment: sectionAlign, // power of 2, must be greater than or equal to FileAlignment
|
||||||
|
FileAlignment: fileAlign, // power of 2
|
||||||
|
MajorOperatingSystemVersion: 0x06,
|
||||||
|
MajorSubsystemVersion: 0x06,
|
||||||
|
SizeOfImage: imageSize,
|
||||||
|
SizeOfHeaders: headerSize,
|
||||||
|
Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI,
|
||||||
|
DllCharacteristics: IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE,
|
||||||
|
SizeOfStackReserve: 0x100000,
|
||||||
|
SizeOfStackCommit: 0x1000,
|
||||||
|
SizeOfHeapReserve: 0x100000,
|
||||||
|
SizeOfHeapCommit: 0x1000,
|
||||||
|
NumberOfRvaAndSizes: 16,
|
||||||
|
DataDirectory: [16]DataDirectory{
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
{VirtualAddress: 0, Size: 0},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CodeHeader: SectionHeader{
|
||||||
|
Name: [8]byte{'.', 't', 'e', 'x', 't'},
|
||||||
|
VirtualSize: uint32(len(code)),
|
||||||
|
VirtualAddress: codeStart,
|
||||||
|
RawSize: uint32(len(code)), // must be a multiple of FileAlignment
|
||||||
|
RawAddress: codeStart, // must be a multiple of FileAlignment
|
||||||
|
Characteristics: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ,
|
||||||
|
},
|
||||||
|
Code: code,
|
||||||
|
// Data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes the EXE file to the given writer.
|
||||||
|
func (pe *EXE) Write(writer io.Writer) {
|
||||||
|
binary.Write(writer, binary.LittleEndian, &pe.DOSHeader)
|
||||||
|
binary.Write(writer, binary.LittleEndian, &pe.NTHeader)
|
||||||
|
binary.Write(writer, binary.LittleEndian, &pe.OptionalHeader64)
|
||||||
|
binary.Write(writer, binary.LittleEndian, &pe.CodeHeader)
|
||||||
|
binary.Write(writer, binary.LittleEndian, &pe.Code)
|
||||||
|
// binary.Write(writer, binary.LittleEndian, &pe.Data)
|
||||||
|
}
|
12
src/os/windows/pe/NTHeader.go
Normal file
12
src/os/windows/pe/NTHeader.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package pe
|
||||||
|
|
||||||
|
type NTHeader struct {
|
||||||
|
Signature [4]byte
|
||||||
|
Machine uint16
|
||||||
|
NumberOfSections uint16
|
||||||
|
TimeDateStamp uint32
|
||||||
|
PointerToSymbolTable uint32
|
||||||
|
NumberOfSymbols uint32
|
||||||
|
SizeOfOptionalHeader uint16
|
||||||
|
Characteristics uint16
|
||||||
|
}
|
34
src/os/windows/pe/OptionalHeader64.go
Normal file
34
src/os/windows/pe/OptionalHeader64.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package pe
|
||||||
|
|
||||||
|
type OptionalHeader64 struct {
|
||||||
|
Magic uint16
|
||||||
|
MajorLinkerVersion uint8
|
||||||
|
MinorLinkerVersion uint8
|
||||||
|
SizeOfCode uint32
|
||||||
|
SizeOfInitializedData uint32
|
||||||
|
SizeOfUninitializedData uint32
|
||||||
|
AddressOfEntryPoint uint32
|
||||||
|
BaseOfCode uint32
|
||||||
|
ImageBase uint64
|
||||||
|
SectionAlignment uint32
|
||||||
|
FileAlignment uint32
|
||||||
|
MajorOperatingSystemVersion uint16
|
||||||
|
MinorOperatingSystemVersion uint16
|
||||||
|
MajorImageVersion uint16
|
||||||
|
MinorImageVersion uint16
|
||||||
|
MajorSubsystemVersion uint16
|
||||||
|
MinorSubsystemVersion uint16
|
||||||
|
Win32VersionValue uint32
|
||||||
|
SizeOfImage uint32
|
||||||
|
SizeOfHeaders uint32
|
||||||
|
CheckSum uint32
|
||||||
|
Subsystem uint16
|
||||||
|
DllCharacteristics uint16
|
||||||
|
SizeOfStackReserve uint64
|
||||||
|
SizeOfStackCommit uint64
|
||||||
|
SizeOfHeapReserve uint64
|
||||||
|
SizeOfHeapCommit uint64
|
||||||
|
LoaderFlags uint32
|
||||||
|
NumberOfRvaAndSizes uint32
|
||||||
|
DataDirectory [16]DataDirectory
|
||||||
|
}
|
14
src/os/windows/pe/SectionHeader.go
Normal file
14
src/os/windows/pe/SectionHeader.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package pe
|
||||||
|
|
||||||
|
type SectionHeader struct {
|
||||||
|
Name [8]byte
|
||||||
|
VirtualSize uint32
|
||||||
|
VirtualAddress uint32
|
||||||
|
RawSize uint32
|
||||||
|
RawAddress uint32
|
||||||
|
PointerToRelocations uint32
|
||||||
|
PointerToLineNumbers uint32
|
||||||
|
NumberOfRelocations uint16
|
||||||
|
NumberOfLineNumbers uint16
|
||||||
|
Characteristics uint32
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user