forked from Imagelibrary/rtems
cpukit/libdebugger: Prevent hang on memory access
When memory is accessed by the remote debugging client, the access is sandboxed with setjmp/longjmp and appropriate exception handlers to prevent the attempted access from causing a failure of the debugger or otherwise altering execution. The existing implementation works as expected when the context executing the memory access and the exception context resulting from a failed access do not share a stack. In the case of AArch64, a failed access when the debugger is already in exception context causes a re-entry into exception context where the machine state is pushed onto the same stack that was in use where the exception occurred. When setjmp is called inside a stack frame and the exception occurs outside that stack frame, the stack frame is unwound before the exception occurs and the exception entry overwrites the area previously occupied by the stack frame housing the setjmp and corrupting the link register that is stored there. After restoration of state using longjmp(), this corrupted link register information is loaded from the stack frame and undesired behavior occurs. In the instance of this bug that was encountered, the corrupted link register contained an unaligned pointer which caused an unending cascade of prefetch abort exceptions presenting as a hard hang. Closes #5273
This commit is contained in:
@@ -601,14 +601,6 @@ rtems_debugger_target_exception_thread_resume(rtems_debugger_thread* thread)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rtems_debugger_target_start_memory_access(void)
|
||||
{
|
||||
rtems_debugger_target* target = rtems_debugger->target;
|
||||
target->memory_access = true;
|
||||
return setjmp(target->access_return);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_debugger_target_end_memory_access(void)
|
||||
{
|
||||
|
||||
@@ -284,8 +284,20 @@ extern int rtems_debugger_target_cache_sync(rtems_debugger_target_swbreak* swbre
|
||||
/**
|
||||
* Start a target memory access. If 0 is return the access can proceed and if
|
||||
* -1 is return the access has failed.
|
||||
*
|
||||
* The call to setjmp() must not reside inside a stack frame relative to the
|
||||
* expected location of the possible failure. If the debugger is already
|
||||
* executing in exception context and setjmp is called with its own stack frame,
|
||||
* that stack frame will be released before the failure. The failure causes an
|
||||
* exception which will continue using the same stack and is highly likely to
|
||||
* overwrite stack information which is critical for the debugger to continue
|
||||
* execution.
|
||||
*/
|
||||
extern int rtems_debugger_target_start_memory_access(void);
|
||||
#define rtems_debugger_target_start_memory_access() \
|
||||
({ \
|
||||
rtems_debugger->target->memory_access = true, \
|
||||
setjmp(rtems_debugger->target->access_return); \
|
||||
})
|
||||
|
||||
/**
|
||||
* End a target memory access.
|
||||
|
||||
Reference in New Issue
Block a user