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/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"
|
||||
)
|
||||
|
||||
@ -338,7 +338,7 @@ restart:
|
||||
|
||||
data, dataLabels = a.Data.Finalize()
|
||||
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 {
|
||||
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/mac"
|
||||
"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.
|
||||
@ -35,20 +36,22 @@ func (r *Result) finalize() ([]byte, []byte) {
|
||||
Data: make(map[string][]byte, r.DataCount),
|
||||
}
|
||||
|
||||
sysExit := 0
|
||||
final.Call("main.main")
|
||||
|
||||
switch config.TargetOS {
|
||||
case "linux":
|
||||
sysExit = linux.Exit
|
||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], linux.Exit)
|
||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 0)
|
||||
final.Syscall()
|
||||
case "mac":
|
||||
sysExit = mac.Exit
|
||||
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()
|
||||
}
|
||||
|
||||
final.Call("main.main")
|
||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], sysExit)
|
||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 0)
|
||||
final.Syscall()
|
||||
|
||||
// This will place the main function immediately after the entry point
|
||||
// and also add everything the main function calls recursively.
|
||||
r.eachFunction(r.Main, map[*core.Function]bool{}, func(f *core.Function) {
|
||||
@ -56,9 +59,20 @@ func (r *Result) finalize() ([]byte, []byte) {
|
||||
})
|
||||
|
||||
final.Label(asm.LABEL, "_crash")
|
||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], sysExit)
|
||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 1)
|
||||
final.Syscall()
|
||||
|
||||
switch config.TargetOS {
|
||||
case "linux":
|
||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[0], linux.Exit)
|
||||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 1)
|
||||
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()
|
||||
return code, data
|
||||
@ -138,6 +152,9 @@ func write(writer io.Writer, code []byte, data []byte) error {
|
||||
case "mac":
|
||||
exe := macho.New(code, data)
|
||||
exe.Write(buffer)
|
||||
case "windows":
|
||||
exe := pe.New(code, data)
|
||||
exe.Write(buffer)
|
||||
default:
|
||||
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.
|
||||
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)
|
||||
}
|
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"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/config"
|
||||
"git.akyoto.dev/cli/q/src/os/common"
|
||||
)
|
||||
|
||||
// ELF represents an ELF file.
|
||||
@ -22,7 +23,7 @@ type ELF struct {
|
||||
// New creates a new ELF binary.
|
||||
func New(code []byte, data []byte) *ELF {
|
||||
dataOffset := config.CodeOffset + int64(len(code))
|
||||
dataPadding := Padding(dataOffset, config.Align)
|
||||
dataPadding := common.Padding(dataOffset, config.Align)
|
||||
dataOffset += dataPadding
|
||||
|
||||
return &ELF{
|
||||
|
@ -1,11 +1,7 @@
|
||||
package elf
|
||||
|
||||
const (
|
||||
LittleEndian = 1
|
||||
TypeExecutable = 2
|
||||
ArchitectureAMD64 = 0x3E
|
||||
HeaderSize = 64
|
||||
)
|
||||
// HeaderSize is equal to the size of a header in bytes.
|
||||
const HeaderSize = 64
|
||||
|
||||
// Header contains general information.
|
||||
type Header struct {
|
||||
|
@ -14,24 +14,3 @@ type ProgramHeader struct {
|
||||
SizeInMemory 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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
const (
|
||||
@ -30,3 +47,14 @@ const (
|
||||
FlagNoHeapExecution HeaderFlags = 0x1000000
|
||||
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"
|
||||
|
||||
"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.
|
||||
@ -55,7 +55,7 @@ func (m *MachO) Write(writer io.Writer) {
|
||||
codeStart := uint64(32 + m.Header.SizeCommands)
|
||||
codeLength := uint64(len(m.Code))
|
||||
codeEnd := codeStart + codeLength
|
||||
dataPadding := elf.Padding(codeEnd, 4096)
|
||||
dataPadding := common.Padding(codeEnd, config.Align)
|
||||
dataStart := codeEnd + dataPadding
|
||||
|
||||
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