Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: refactor markGlobals to findGlobals #3885

Merged
merged 1 commit into from
Sep 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/runtime/gc_blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 6 additions & 5 deletions src/runtime/gc_globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
4 changes: 0 additions & 4 deletions src/runtime/gc_leaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,3 @@ func setHeapEnd(newHeapEnd uintptr) {
// enough.
heapEnd = newHeapEnd
}

func markRoots(start, end uintptr) {
// dummy, so that markGlobals will compile
}
4 changes: 0 additions & 4 deletions src/runtime/gc_none.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
6 changes: 3 additions & 3 deletions src/runtime/os_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/

Expand Down Expand Up @@ -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)
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/runtime/os_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/os_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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{})))
}
Expand Down
8 changes: 4 additions & 4 deletions src/runtime/runtime_nintendoswitch.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down