Skip to content

Commit 11af4ab

Browse files
committed
feat: implement findGlobals
1 parent 69f2ea2 commit 11af4ab

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

src/runtime/os_uefi.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,53 @@
22

33
package runtime
44

5+
import (
6+
"machine/uefi"
7+
"unsafe"
8+
)
9+
510
const baremetal = true
611

712
const GOOS = "uefi"
813

14+
// MS-DOS stub with PE header offset:
15+
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#ms-dos-stub-image-only
16+
type exeHeader struct {
17+
signature uint16
18+
_ [58]byte // skip DOS header
19+
peHeader uint32 // at offset 0x3C
20+
}
21+
22+
// COFF file header:
23+
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#file-headers
24+
type peHeader struct {
25+
magic uint32
26+
machine uint16
27+
numberOfSections uint16
28+
timeDateStamp uint32
29+
pointerToSymbolTable uint32
30+
numberOfSymbols uint32
31+
sizeOfOptionalHeader uint16
32+
characteristics uint16
33+
}
34+
35+
// COFF section header:
36+
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers
37+
type peSection struct {
38+
name [8]byte
39+
virtualSize uint32
40+
virtualAddress uint32
41+
sizeOfRawData uint32
42+
pointerToRawData uint32
43+
pointerToRelocations uint32
44+
pointerToLinenumbers uint32
45+
numberOfRelocations uint16
46+
numberOfLinenumbers uint16
47+
characteristics uint32
48+
}
49+
50+
var module *exeHeader
51+
952
// Mark global variables.
1053
// Unfortunately, the linker doesn't provide symbols for the start and end of
1154
// the data/bss sections. Therefore these addresses need to be determined at
@@ -14,5 +57,43 @@ const GOOS = "uefi"
1457
// Most of this function is based on the documentation in
1558
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format.
1659
func findGlobals(found func(start, end uintptr)) {
60+
// Constants used in this function.
61+
const (
62+
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa
63+
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 0x00000002
64+
65+
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
66+
IMAGE_SCN_MEM_WRITE = 0x80000000
67+
)
68+
69+
if module == nil {
70+
var loadedImage *uefi.EFI_LOADED_IMAGE_PROTOCOL
71+
72+
status := uefi.BS().HandleProtocol(uefi.GetImageHandle(), &uefi.EFI_LOADED_IMAGE_GUID, unsafe.Pointer(&loadedImage))
73+
if status != uefi.EFI_SUCCESS {
74+
uefi.DebugPrint("EFI_LOADED_IMAGE_GUID failed", uint64(status))
75+
return
76+
}
77+
78+
module = (*exeHeader)(unsafe.Pointer(loadedImage.ImageBase))
79+
}
80+
81+
// Find the PE header at offset 0x3C.
82+
pe := (*peHeader)(unsafe.Add(unsafe.Pointer(module), module.peHeader))
83+
if pe.magic != 0x00004550 { // 0x4550 is "PE"
84+
uefi.DebugPrint("cannot find PE header", uint64(pe.magic))
85+
return
86+
}
1787

88+
// Iterate through sections.
89+
section := (*peSection)(unsafe.Pointer(uintptr(unsafe.Pointer(pe)) + uintptr(pe.sizeOfOptionalHeader) + unsafe.Sizeof(peHeader{})))
90+
for i := 0; i < int(pe.numberOfSections); i++ {
91+
if section.characteristics&IMAGE_SCN_MEM_WRITE != 0 {
92+
// Found a writable section. Scan the entire section for roots.
93+
start := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress)
94+
end := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress) + uintptr(section.virtualSize)
95+
found(start, end)
96+
}
97+
section = (*peSection)(unsafe.Add(unsafe.Pointer(section), unsafe.Sizeof(peSection{})))
98+
}
1899
}

0 commit comments

Comments
 (0)