From 2a08bbdf31ce693ec0741ecbc9ae78a4d7b9a051 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Thu, 7 May 2015 14:35:39 +0200 Subject: [PATCH] Fix GC scanning of registers on x86_64 architectures. It is possible for jmp_buf to not be word-aligned or addresses in the register dump to not be word-aligned. This can result in either addresses in registers being missed or even addresses on the stack past the register area not being scanned properly. --- lib/system/gc.nim | 9 +++++++++ lib/system/gc_ms.nim | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/lib/system/gc.nim b/lib/system/gc.nim index c4374d00c6..e0d1006d95 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -922,6 +922,15 @@ else: if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. var max = cast[ByteAddress](gch.stackBottom) var sp = cast[ByteAddress](addr(registers)) + when defined(amd64): + # words within the jmp_buf structure may not be properly aligned. + let regEnd = sp +% sizeof(registers) + while sp <% regEnd: + gcMark(gch, cast[PPointer](sp)[]) + gcMark(gch, cast[PPointer](sp +% sizeof(pointer) div 2)[]) + sp = sp +% sizeof(pointer) + # Make sure sp is word-aligned + sp = sp and not (sizeof(pointer) - 1) # loop unrolled: while sp <% max - 8*sizeof(pointer): gcMark(gch, cast[PStackSlice](sp)[0]) diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index e287bf5d90..a0699f46a8 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -514,6 +514,15 @@ else: if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. var max = cast[ByteAddress](gch.stackBottom) var sp = cast[ByteAddress](addr(registers)) + when defined(amd64): + # words within the jmp_buf structure may not be properly aligned. + let regEnd = sp +% sizeof(registers) + while sp <% regEnd: + gcMark(gch, cast[PPointer](sp)[]) + gcMark(gch, cast[PPointer](sp +% sizeof(pointer) div 2)[]) + sp = sp +% sizeof(pointer) + # Make sure sp is word-aligned + sp = sp and not (sizeof(pointer) - 1) # loop unrolled: while sp <% max - 8*sizeof(pointer): gcMark(gch, cast[PStackSlice](sp)[0])