summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorReimer Behrends <behrends@gmail.com>2015-05-07 14:35:39 +0200
committerReimer Behrends <behrends@gmail.com>2015-05-07 14:35:39 +0200
commit2a08bbdf31ce693ec0741ecbc9ae78a4d7b9a051 (patch)
treec37d85774e8f6f63a4aa45f9dfa0b7b3fc0f21c3 /lib
parentb9e02b1efc14a309e613ec4d4cf8c793503bc797 (diff)
downloadNim-2a08bbdf31ce693ec0741ecbc9ae78a4d7b9a051.tar.gz
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/system/gc.nim9
-rw-r--r--lib/system/gc_ms.nim9
2 files changed, 18 insertions, 0 deletions
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index c4374d00c..e0d1006d9 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 e287bf5d9..a0699f46a 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])