runtime (gc): correct scan bounds

This fixes 2 bugs in the GC scan bounds:
1. On AVR, the GC could sometimes read one byte past the end of a block due to the difference between pointer size and alignment.
2. On WASM, the linker does not properly align the marker for the end of the globals section. A manual alignment operation has been added to markGlobals to work around this.
Этот коммит содержится в:
Nia Waldvogel 2021-12-15 17:17:18 -05:00 коммит произвёл Ayke
родитель 62bda8e129
коммит e6fbad13c6
2 изменённых файлов: 23 добавлений и 1 удалений

Просмотреть файл

@ -430,7 +430,17 @@ func markRoots(start, end uintptr) {
if start >= end { if start >= end {
runtimePanic("gc: unexpected range to mark") runtimePanic("gc: unexpected range to mark")
} }
if start%unsafe.Alignof(start) != 0 {
runtimePanic("gc: unaligned start pointer")
} }
if end%unsafe.Alignof(end) != 0 {
runtimePanic("gc: unaligned end pointer")
}
}
// Reduce the end bound to avoid reading too far on platforms where pointer alignment is smaller than pointer size.
// If the size of the range is 0, then end will be slightly below start after this.
end -= unsafe.Sizeof(end) - unsafe.Alignof(end)
for addr := start; addr < end; addr += unsafe.Alignof(addr) { for addr := start; addr < end; addr += unsafe.Alignof(addr) {
root := *(*uintptr)(unsafe.Pointer(addr)) root := *(*uintptr)(unsafe.Pointer(addr))

Просмотреть файл

@ -1,12 +1,24 @@
//go:build (gc.conservative || gc.extalloc) && (baremetal || tinygo.wasm)
// +build gc.conservative gc.extalloc // +build gc.conservative gc.extalloc
// +build baremetal tinygo.wasm // +build baremetal tinygo.wasm
package runtime package runtime
import "unsafe"
// markGlobals marks all globals, which are reachable by definition. // markGlobals marks all globals, which are reachable by definition.
// //
// This implementation marks all globals conservatively and assumes it can use // This implementation marks all globals conservatively and assumes it can use
// linker-defined symbols for the start and end of the .data section. // linker-defined symbols for the start and end of the .data section.
func markGlobals() { func markGlobals() {
markRoots(globalsStart, globalsEnd) end := globalsEnd
if GOARCH == "wasm" {
// This is a workaround for a bug in wasm-ld: wasm-ld doesn't always
// align __heap_base and when this memory is shared through an API, it
// might result in unaligned memory. For details, see:
// https://reviews.llvm.org/D106499
// It should be removed once we switch to LLVM 13, where this is fixed.
end = end &^ (unsafe.Alignof(end) - 1)
}
markRoots(globalsStart, end)
} }