From e6e7250a476c3e8ce252420aa675ef7006fc7954 Mon Sep 17 00:00:00 2001 From: Matthew Hiles <15929821+sparques@users.noreply.github.com> Date: Sun, 7 Jun 2026 02:45:16 -0400 Subject: [PATCH] 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 --- src/runtime/os_windows.go | 59 +-------------------------------- src/runtime/os_windows_pe.go | 63 ++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 58 deletions(-) create mode 100644 src/runtime/os_windows_pe.go diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index a124e7ab1..4003a2ab3 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -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 { diff --git a/src/runtime/os_windows_pe.go b/src/runtime/os_windows_pe.go new file mode 100644 index 000000000..febe0b210 --- /dev/null +++ b/src/runtime/os_windows_pe.go @@ -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{}))) + } +}