From bc625510ddf3ee2ba14e41d37c73394028e2c62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Gallet?= Date: Tue, 16 Oct 2018 12:23:09 +0200 Subject: [PATCH] Save and restore the first stack frame of the alternate stack --- CHANGELOG.md | 1 + src/libTAS/checkpoint/AltStack.cpp | 17 +++++++++++++++++ src/libTAS/checkpoint/AltStack.h | 3 +++ src/libTAS/checkpoint/Checkpoint.cpp | 7 +++++++ 4 files changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3830efbc..38bcc742 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * Fix SDL1 keyboard layout * Wait for threads to register * Detect auto-repeat cases when detectable auto-repeat is not supported by the server +* Fix crash when loading a savestate on a non-draw frame ## [1.3.1] - 2018-08-30 ### Added diff --git a/src/libTAS/checkpoint/AltStack.cpp b/src/libTAS/checkpoint/AltStack.cpp index ae2f3ef4..12f021d4 100644 --- a/src/libTAS/checkpoint/AltStack.cpp +++ b/src/libTAS/checkpoint/AltStack.cpp @@ -34,6 +34,13 @@ namespace libtas { */ static stack_t oss; +/* We must save the last stack frame of the alternate stack in the savestate, so + * that we return at the correct location from the alternate stack. + */ +#define STACKFRAME_OFFSET 0x700 +#define STACKFRAME_SIZE 0x700 +static uint8_t stack_frame[STACKFRAME_SIZE]; + void AltStack::saveStack() { int ret; @@ -62,4 +69,14 @@ void AltStack::restoreStack() MYASSERT(ret == 0) } +void AltStack::saveStackFrame() +{ + memcpy(stack_frame, ReservedMemory::getAddr(ReservedMemory::STACK_ADDR + ReservedMemory::STACK_SIZE - STACKFRAME_OFFSET), STACKFRAME_SIZE); +} + +void AltStack::restoreStackFrame() +{ + memcpy(ReservedMemory::getAddr(ReservedMemory::STACK_ADDR + ReservedMemory::STACK_SIZE - STACKFRAME_OFFSET), stack_frame, STACKFRAME_SIZE); +} + } diff --git a/src/libTAS/checkpoint/AltStack.h b/src/libTAS/checkpoint/AltStack.h index f9446fc4..b0694401 100644 --- a/src/libTAS/checkpoint/AltStack.h +++ b/src/libTAS/checkpoint/AltStack.h @@ -28,6 +28,9 @@ namespace AltStack void saveStack(); void prepareStack(); void restoreStack(); + + void saveStackFrame(); + void restoreStackFrame(); }; } diff --git a/src/libTAS/checkpoint/Checkpoint.cpp b/src/libTAS/checkpoint/Checkpoint.cpp index 55c278d5..802c8026 100644 --- a/src/libTAS/checkpoint/Checkpoint.cpp +++ b/src/libTAS/checkpoint/Checkpoint.cpp @@ -21,6 +21,7 @@ #include "Checkpoint.h" #include "ThreadManager.h" +#include "AltStack.h" #include "../logging.h" #include "ProcMapsArea.h" #include "ProcSelfMaps.h" @@ -308,6 +309,9 @@ void Checkpoint::handler(int signum) /* Restore the entire xcb connection struct */ memcpy(cur_xcb_conn, &xcb_conn, sizeof(xcb_connection_t)); + + /* We must restore the current stack frame from the savestate */ + AltStack::restoreStackFrame(); } else { /* Check that base savestate exists, otherwise save it */ @@ -326,6 +330,9 @@ void Checkpoint::handler(int signum) } } + /* We must store the current stack frame in the savestate */ + AltStack::saveStackFrame(); + writeAllAreas(false); } debuglogstdio(LCF_CHECKPOINT, "End restore.");