[Ltrace-devel] [PATCH] [MIPS] Detect return from rt_sigreturn syscalls

Faraz Shahbazker faraz.shahbazker at imgtec.com
Thu Feb 19 18:13:11 UTC 2015


On MIPS, sigreturn/rt_sigreturn does not return control to the instruction
after the syscall instruction. Instead, it transfers control directly to
the point where the signal occurred. If this transfer is not correctly
marked as a SYSRET event, it gets mis-categorized as a breakpoint event
and generates "unexpected breakpoint" messages. The sigreturn
frame remains on the callstack until the next sigreturn, which is then
misinterpreted as as a return from the previous 'unfinished' syscall.

If the top of the callstack is a sigreturn or rt_sigreturn syscall, we
must force the current event to be treated as a SYSRET without checking
for a preceding SYSCALL instruction.

Verify by invoking:
$ ltrace [-S] openssl speed
---
 sysdeps/linux-gnu/mips/trace.c |   20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/sysdeps/linux-gnu/mips/trace.c b/sysdeps/linux-gnu/mips/trace.c
index 88e13ac..f3198c6 100644
--- a/sysdeps/linux-gnu/mips/trace.c
+++ b/sysdeps/linux-gnu/mips/trace.c
@@ -30,6 +30,7 @@
 #include <sys/ptrace.h>
 #include <asm/ptrace.h>
 #include <assert.h>
+#include <asm/unistd.h>
 
 #include "backend.h"
 #include "common.h"
@@ -103,7 +104,24 @@ syscall_p(struct process *proc, int status, int *sysnum)
 		   0000000c    syscall
 		 */
 		if(insn!=0x0000000c){
-			return 0;
+			/* sigreturn returns control to the point
+			   where the signal was received; skip check 
+			   for preceeding syscall instruction */
+			int depth = proc->callstack_depth;
+			struct callstack_element *top = NULL;
+			if (depth > 0)
+				top = &proc->callstack[depth - 1];
+
+			if (top != NULL &&  top->is_syscall &&
+			    (top->c_un.syscall == (__NR_rt_sigreturn -
+						   __NR_Linux) ||
+			     top->c_un.syscall == (__NR_sigreturn -
+						   __NR_Linux))) {
+				*sysnum = top->c_un.syscall;
+				return 2;
+			}
+			else
+				return 0;
 		}
 
 		*sysnum = (num & 0xFFFF) - 4000;
-- 
1.7.9.5



More information about the Ltrace-devel mailing list