https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79341

--- Comment #64 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Perhaps the easiest hack would be for
sanitizer_common/sanitizer_unwind_linux_libcdep.cc (Unwind_GetIP) call
_Unwind_GetIPInfo instead of _Unwind_GetIP (perhaps just on SANITIZER_LINUX or
wherever it is available), and return for the signal frames the pc + 1 so that
the later - 1 subtraction undoes that.

So like (completely untested, but I also can't reproduce the nullptr-1.c
failure myself):

--- libsanitizer/sanitizer_common/sanitizer_unwind_linux_libcdep.cc.jj 
2016-11-09 15:22:41.000000000 +0100
+++ libsanitizer/sanitizer_common/sanitizer_unwind_linux_libcdep.cc    
2017-02-15 15:26:31.658948328 +0100
@@ -92,6 +92,17 @@ uptr Unwind_GetIP(struct _Unwind_Context
   CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
   // Clear the Thumb bit.
   return val & ~(uptr)1;
+#elif SANITIZER_LINUX && !defined(__arm__)
+  int pc_before_insn = 0;
+  uptr pc = _Unwind_GetIPInfo (context, &pc_before_insn);
+  /* If context is for a signal frame, the returned PC is
+     the right one to use, but StackTrace::GetPreviousInstructionPc
+     will be applied to it later unconditionally.  So adjust PC now
+     so that GetPreviousInstructionPc will return what _Unwind_GetIPInfo
+     returned.  */
+  if (pc_before_insn)
+    pc += pc - StackTrace::GetPreviousInstructionPc (pc);
+  return pc;
 #else
   return _Unwind_GetIP(ctx);
 #endif

Reply via email to