diff --git a/src/runtime/gc_blocks.go b/src/runtime/gc_blocks.go index 01031ac8..02a82773 100644 --- a/src/runtime/gc_blocks.go +++ b/src/runtime/gc_blocks.go @@ -420,7 +420,7 @@ func runGC() (freeBytes uintptr) { // Mark phase: mark all reachable objects, recursively. markStack() - markGlobals() + findGlobals(markRoots) if baremetal && hasScheduler { // Channel operations in interrupts may move task pointers around while we are marking. diff --git a/src/runtime/gc_globals.go b/src/runtime/gc_globals.go index 9ae31778..f27911ec 100644 --- a/src/runtime/gc_globals.go +++ b/src/runtime/gc_globals.go @@ -2,13 +2,14 @@ package runtime -// This file implements markGlobals for all the files that don't have a more -// specific implementation. +// This file implements findGlobals for all systems where the start and end of +// the globals section can be found through linker-defined symbols. -// markGlobals marks all globals, which are reachable by definition. +// findGlobals finds all globals (which are reachable by definition) and calls +// the callback for them. // // This implementation marks all globals conservatively and assumes it can use // linker-defined symbols for the start and end of the .data section. -func markGlobals() { - markRoots(globalsStart, globalsEnd) +func findGlobals(found func(start, end uintptr)) { + found(globalsStart, globalsEnd) } diff --git a/src/runtime/gc_leaking.go b/src/runtime/gc_leaking.go index d99b8d12..26b012bd 100644 --- a/src/runtime/gc_leaking.go +++ b/src/runtime/gc_leaking.go @@ -100,7 +100,3 @@ func setHeapEnd(newHeapEnd uintptr) { // enough. heapEnd = newHeapEnd } - -func markRoots(start, end uintptr) { - // dummy, so that markGlobals will compile -} diff --git a/src/runtime/gc_none.go b/src/runtime/gc_none.go index 98636f5c..43d3c490 100644 --- a/src/runtime/gc_none.go +++ b/src/runtime/gc_none.go @@ -37,7 +37,3 @@ func initHeap() { func setHeapEnd(newHeapEnd uintptr) { // Nothing to do here, this function is never actually called. } - -func markRoots(start, end uintptr) { - // dummy, so that markGlobals will compile -} diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index 6584d6ca..6f751102 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -54,12 +54,12 @@ type segmentLoadCommand struct { //go:extern _mh_execute_header var libc_mh_execute_header machHeader -// Mark global variables. +// Find global variables in .data/.bss sections. // The MachO linker doesn't seem to provide symbols for the start and end of the // data section. There is get_etext, get_edata, and get_end, but these are // undocumented and don't work with ASLR (which is enabled by default). // Therefore, read the MachO header directly. -func markGlobals() { +func findGlobals(found func(start, end uintptr)) { // Here is a useful blog post to understand the MachO file format: // https://h3adsh0tzz.com/2020/01/macho-file-format/ @@ -103,7 +103,7 @@ func markGlobals() { // This could be improved by only reading the memory areas // covered by sections. That would reduce the amount of memory // scanned a little bit (up to a single VM page). - markRoots(offset+cmd.vmaddr, offset+cmd.vmaddr+cmd.vmsize) + found(offset+cmd.vmaddr, offset+cmd.vmaddr+cmd.vmsize) } } diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 0e6ad474..0b513dca 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -77,9 +77,9 @@ type elfProgramHeader32 struct { //go:extern __ehdr_start var ehdr_start elfHeader -// markGlobals marks all globals, which are reachable by definition. +// findGlobals finds globals in the .data/.bss sections. // It parses the ELF program header to find writable segments. -func markGlobals() { +func findGlobals(found func(start, end uintptr)) { // Relevant constants from the ELF specification. // See: https://refspecs.linuxfoundation.org/elf/elf.pdf const ( @@ -99,14 +99,14 @@ func markGlobals() { if header._type == PT_LOAD && header.flags&PF_W != 0 { start := header.vaddr end := start + header.memsz - markRoots(start, end) + found(start, end) } } else { header := (*elfProgramHeader32)(headerPtr) if header._type == PT_LOAD && header.flags&PF_W != 0 { start := header.vaddr end := start + header.memsz - markRoots(start, end) + found(start, end) } } headerPtr = unsafe.Add(headerPtr, ehdr_start.phentsize) diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 7e060497..3750d519 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -52,7 +52,7 @@ var module *exeHeader // around 160 bytes of amd64 instructions. // Most of this function is based on the documentation in // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format. -func markGlobals() { +func findGlobals(found func(start, end uintptr)) { // Constants used in this function. const ( // https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa @@ -85,7 +85,7 @@ func markGlobals() { // 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) - markRoots(start, end) + found(start, end) } section = (*peSection)(unsafe.Add(unsafe.Pointer(section), unsafe.Sizeof(peSection{}))) } diff --git a/src/runtime/runtime_nintendoswitch.go b/src/runtime/runtime_nintendoswitch.go index bcfa5151..059e449d 100644 --- a/src/runtime/runtime_nintendoswitch.go +++ b/src/runtime/runtime_nintendoswitch.go @@ -245,17 +245,17 @@ var bssStartSymbol [0]byte //go:extern __bss_end var bssEndSymbol [0]byte -// Mark global variables. +// Find global variables. // The linker script provides __*_start and __*_end symbols that can be used to // scan the given sections. They are already aligned so don't need to be // manually aligned here. -func markGlobals() { +func findGlobals(found func(start, end uintptr)) { dataStart := uintptr(unsafe.Pointer(&dataStartSymbol)) dataEnd := uintptr(unsafe.Pointer(&dataEndSymbol)) - markRoots(dataStart, dataEnd) + found(dataStart, dataEnd) bssStart := uintptr(unsafe.Pointer(&bssStartSymbol)) bssEnd := uintptr(unsafe.Pointer(&bssEndSymbol)) - markRoots(bssStart, bssEnd) + found(bssStart, bssEnd) } // getContextPtr returns the hblauncher context