UEFI Target groundwork: runtime: extract Windows PE globals scan helper (#5361)

* runtime: extract Windows PE globals scan helper
* Update src/runtime/os_windows_pe.go
* run goimports
This commit is contained in:
Matthew Hiles
2026-06-07 02:45:16 -04:00
committed by GitHub
parent 7b3dc19445
commit e6e7250a47
2 changed files with 64 additions and 58 deletions
+1 -58
View File
@@ -7,44 +7,6 @@ const GOOS = "windows"
//export GetModuleHandleExA
func _GetModuleHandleExA(dwFlags uint32, lpModuleName unsafe.Pointer, phModule **exeHeader) bool
// MS-DOS stub with PE header offset:
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#ms-dos-stub-image-only
type exeHeader struct {
signature uint16
_ [58]byte // skip DOS header
peHeader uint32 // at offset 0x3C
}
// COFF file header:
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#file-headers
type peHeader struct {
magic uint32
machine uint16
numberOfSections uint16
timeDateStamp uint32
pointerToSymbolTable uint32
numberOfSymbols uint32
sizeOfOptionalHeader uint16
characteristics uint16
}
// COFF section header:
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers
type peSection struct {
name [8]byte
virtualSize uint32
virtualAddress uint32
sizeOfRawData uint32
pointerToRawData uint32
pointerToRelocations uint32
pointerToLinenumbers uint32
numberOfRelocations uint16
numberOfLinenumbers uint16
characteristics uint32
}
var module *exeHeader
// Mark global variables.
// Unfortunately, the linker doesn't provide symbols for the start and end of
// the data/bss sections. Therefore these addresses need to be determined at
@@ -57,9 +19,6 @@ func findGlobals(found func(start, end uintptr)) {
const (
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 0x00000002
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
IMAGE_SCN_MEM_WRITE = 0x80000000
)
if module == nil {
@@ -72,23 +31,7 @@ func findGlobals(found func(start, end uintptr)) {
}
}
// Find the PE header at offset 0x3C.
pe := (*peHeader)(unsafe.Add(unsafe.Pointer(module), module.peHeader))
if gcAsserts && pe.magic != 0x00004550 { // 0x4550 is "PE"
runtimePanic("cannot find PE header")
}
// Iterate through sections.
section := (*peSection)(unsafe.Pointer(uintptr(unsafe.Pointer(pe)) + uintptr(pe.sizeOfOptionalHeader) + unsafe.Sizeof(peHeader{})))
for i := 0; i < int(pe.numberOfSections); i++ {
if section.characteristics&IMAGE_SCN_MEM_WRITE != 0 {
// Found a writable section. Scan the entire section for roots.
start := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress)
end := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress) + uintptr(section.virtualSize)
found(start, end)
}
section = (*peSection)(unsafe.Add(unsafe.Pointer(section), unsafe.Sizeof(peSection{})))
}
findGlobalsForPE(found)
}
type systeminfo struct {
+63
View File
@@ -0,0 +1,63 @@
//go:build windows
package runtime
import "unsafe"
// MS-DOS stub with PE header offset:
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#ms-dos-stub-image-only
type exeHeader struct {
signature uint16
_ [58]byte // skip DOS header
peHeader uint32 // at offset 0x3C
}
// COFF file header:
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#file-headers
type peHeader struct {
magic uint32
machine uint16
numberOfSections uint16
timeDateStamp uint32
pointerToSymbolTable uint32
numberOfSymbols uint32
sizeOfOptionalHeader uint16
characteristics uint16
}
// COFF section header:
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers
type peSection struct {
name [8]byte
virtualSize uint32
virtualAddress uint32
sizeOfRawData uint32
pointerToRawData uint32
pointerToRelocations uint32
pointerToLinenumbers uint32
numberOfRelocations uint16
numberOfLinenumbers uint16
characteristics uint32
}
var module *exeHeader
func findGlobalsForPE(found func(start, end uintptr)) {
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
const imageSCNMemWrite = 0x80000000
pe := (*peHeader)(unsafe.Add(unsafe.Pointer(module), module.peHeader))
if gcAsserts && pe.magic != 0x00004550 { // 0x4550 is "PE"
runtimePanic("cannot find PE header")
}
section := (*peSection)(unsafe.Pointer(uintptr(unsafe.Pointer(pe)) + uintptr(pe.sizeOfOptionalHeader) + unsafe.Sizeof(peHeader{})))
for i := 0; i < int(pe.numberOfSections); i++ {
if section.characteristics&imageSCNMemWrite != 0 {
start := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress)
end := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress) + uintptr(section.virtualSize)
found(start, end)
}
section = (*peSection)(unsafe.Add(unsafe.Pointer(section), unsafe.Sizeof(peSection{})))
}
}