Skip to content

Commit e6e7250

Browse files
authored
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
1 parent 7b3dc19 commit e6e7250

2 files changed

Lines changed: 64 additions & 58 deletions

File tree

src/runtime/os_windows.go

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,6 @@ const GOOS = "windows"
77
//export GetModuleHandleExA
88
func _GetModuleHandleExA(dwFlags uint32, lpModuleName unsafe.Pointer, phModule **exeHeader) bool
99

10-
// MS-DOS stub with PE header offset:
11-
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#ms-dos-stub-image-only
12-
type exeHeader struct {
13-
signature uint16
14-
_ [58]byte // skip DOS header
15-
peHeader uint32 // at offset 0x3C
16-
}
17-
18-
// COFF file header:
19-
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#file-headers
20-
type peHeader struct {
21-
magic uint32
22-
machine uint16
23-
numberOfSections uint16
24-
timeDateStamp uint32
25-
pointerToSymbolTable uint32
26-
numberOfSymbols uint32
27-
sizeOfOptionalHeader uint16
28-
characteristics uint16
29-
}
30-
31-
// COFF section header:
32-
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers
33-
type peSection struct {
34-
name [8]byte
35-
virtualSize uint32
36-
virtualAddress uint32
37-
sizeOfRawData uint32
38-
pointerToRawData uint32
39-
pointerToRelocations uint32
40-
pointerToLinenumbers uint32
41-
numberOfRelocations uint16
42-
numberOfLinenumbers uint16
43-
characteristics uint32
44-
}
45-
46-
var module *exeHeader
47-
4810
// Mark global variables.
4911
// Unfortunately, the linker doesn't provide symbols for the start and end of
5012
// the data/bss sections. Therefore these addresses need to be determined at
@@ -57,9 +19,6 @@ func findGlobals(found func(start, end uintptr)) {
5719
const (
5820
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa
5921
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 0x00000002
60-
61-
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
62-
IMAGE_SCN_MEM_WRITE = 0x80000000
6322
)
6423

6524
if module == nil {
@@ -72,23 +31,7 @@ func findGlobals(found func(start, end uintptr)) {
7231
}
7332
}
7433

75-
// Find the PE header at offset 0x3C.
76-
pe := (*peHeader)(unsafe.Add(unsafe.Pointer(module), module.peHeader))
77-
if gcAsserts && pe.magic != 0x00004550 { // 0x4550 is "PE"
78-
runtimePanic("cannot find PE header")
79-
}
80-
81-
// Iterate through sections.
82-
section := (*peSection)(unsafe.Pointer(uintptr(unsafe.Pointer(pe)) + uintptr(pe.sizeOfOptionalHeader) + unsafe.Sizeof(peHeader{})))
83-
for i := 0; i < int(pe.numberOfSections); i++ {
84-
if section.characteristics&IMAGE_SCN_MEM_WRITE != 0 {
85-
// Found a writable section. Scan the entire section for roots.
86-
start := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress)
87-
end := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress) + uintptr(section.virtualSize)
88-
found(start, end)
89-
}
90-
section = (*peSection)(unsafe.Add(unsafe.Pointer(section), unsafe.Sizeof(peSection{})))
91-
}
34+
findGlobalsForPE(found)
9235
}
9336

9437
type systeminfo struct {

src/runtime/os_windows_pe.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//go:build windows
2+
3+
package runtime
4+
5+
import "unsafe"
6+
7+
// MS-DOS stub with PE header offset:
8+
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#ms-dos-stub-image-only
9+
type exeHeader struct {
10+
signature uint16
11+
_ [58]byte // skip DOS header
12+
peHeader uint32 // at offset 0x3C
13+
}
14+
15+
// COFF file header:
16+
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#file-headers
17+
type peHeader struct {
18+
magic uint32
19+
machine uint16
20+
numberOfSections uint16
21+
timeDateStamp uint32
22+
pointerToSymbolTable uint32
23+
numberOfSymbols uint32
24+
sizeOfOptionalHeader uint16
25+
characteristics uint16
26+
}
27+
28+
// COFF section header:
29+
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers
30+
type peSection struct {
31+
name [8]byte
32+
virtualSize uint32
33+
virtualAddress uint32
34+
sizeOfRawData uint32
35+
pointerToRawData uint32
36+
pointerToRelocations uint32
37+
pointerToLinenumbers uint32
38+
numberOfRelocations uint16
39+
numberOfLinenumbers uint16
40+
characteristics uint32
41+
}
42+
43+
var module *exeHeader
44+
45+
func findGlobalsForPE(found func(start, end uintptr)) {
46+
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
47+
const imageSCNMemWrite = 0x80000000
48+
49+
pe := (*peHeader)(unsafe.Add(unsafe.Pointer(module), module.peHeader))
50+
if gcAsserts && pe.magic != 0x00004550 { // 0x4550 is "PE"
51+
runtimePanic("cannot find PE header")
52+
}
53+
54+
section := (*peSection)(unsafe.Pointer(uintptr(unsafe.Pointer(pe)) + uintptr(pe.sizeOfOptionalHeader) + unsafe.Sizeof(peHeader{})))
55+
for i := 0; i < int(pe.numberOfSections); i++ {
56+
if section.characteristics&imageSCNMemWrite != 0 {
57+
start := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress)
58+
end := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress) + uintptr(section.virtualSize)
59+
found(start, end)
60+
}
61+
section = (*peSection)(unsafe.Add(unsafe.Pointer(section), unsafe.Sizeof(peSection{})))
62+
}
63+
}

0 commit comments

Comments
 (0)