diff options
author | Reimer Behrends <behrends@gmail.com> | 2015-05-07 14:35:39 +0200 |
---|---|---|
committer | Reimer Behrends <behrends@gmail.com> | 2015-05-07 14:35:39 +0200 |
commit | 2a08bbdf31ce693ec0741ecbc9ae78a4d7b9a051 (patch) | |
tree | c37d85774e8f6f63a4aa45f9dfa0b7b3fc0f21c3 /lib | |
parent | b9e02b1efc14a309e613ec4d4cf8c793503bc797 (diff) | |
download | Nim-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.nim | 9 | ||||
-rw-r--r-- | lib/system/gc_ms.nim | 9 |
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]) |