public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
From: Mark Wielaard <mark@klomp.org>
To: elfutils-devel@sourceware.org
Cc: Mark Wielaard <mark@klomp.org>
Subject: [PATCH] libdwfl: Handle unwind frame when the return address register isn't set.
Date: Tue, 10 Apr 2018 14:23:00 -0000	[thread overview]
Message-ID: <1523370202-534-1-git-send-email-mark@klomp.org> (raw)

When we have unwound the frame and then cannot set the return address
we wouldn't set any error. That meant that a dwfl_thread_getframes ()
call could end in an error, but without any dwfl_errno set, producing
the "no error" error message.

If we cannot set the return address at the end of unwinding the frame
that means that either the return address register is bogus (error),
or that the return address is undefined (end of the call stack).

This fixes the run-backtrace-native-biarch.sh testcase for me on an
i386 on x86_64 setup with gcc 7.2.1 and glibc 2.17.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libdwfl/ChangeLog      |  5 +++++
 libdwfl/frame_unwind.c | 46 ++++++++++++++++++++++++++++++----------------
 2 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 9776f1c..b6262c2 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2018-04-10  Mark Wielaard  <mark@klomp.org>
+
+	* frame_unwind.c (unwind): If __libdwfl_frame_reg_get fails for
+	the return address either set an error or mark the pc undefined.
+
 2018-03-17  Mark Wielaard  <mark@klomp.org>
 
 	* libdwflP.h (struct __libdwfl_remote_mem_cache): New.
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index eaea495..8da691e 100644
--- a/libdwfl/frame_unwind.c
+++ b/libdwfl/frame_unwind.c
@@ -632,24 +632,38 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
 	    ra_set = true;
 	}
     }
-  if (unwound->pc_state == DWFL_FRAME_STATE_ERROR
-      && __libdwfl_frame_reg_get (unwound,
-				  frame->fde->cie->return_address_register,
-				  &unwound->pc))
+  if (unwound->pc_state == DWFL_FRAME_STATE_ERROR)
     {
-      /* PPC32 __libc_start_main properly CFI-unwinds PC as zero.  Currently
-	 none of the archs supported for unwinding have zero as a valid PC.  */
-      if (unwound->pc == 0)
-	unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+      if (__libdwfl_frame_reg_get (unwound,
+				   frame->fde->cie->return_address_register,
+				   &unwound->pc))
+	{
+	  /* PPC32 __libc_start_main properly CFI-unwinds PC as zero.
+	     Currently none of the archs supported for unwinding have
+	     zero as a valid PC.  */
+	  if (unwound->pc == 0)
+	    unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+	  else
+	    {
+	      unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
+	      /* In SPARC the return address register actually contains
+		 the address of the call instruction instead of the return
+		 address.  Therefore we add here an offset defined by the
+		 backend.  Most likely 0.  */
+	      unwound->pc += ebl_ra_offset (ebl);
+	    }
+	}
       else
-        {
-          unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
-          /* In SPARC the return address register actually contains
-             the address of the call instruction instead of the return
-             address.  Therefore we add here an offset defined by the
-             backend.  Most likely 0.  */
-          unwound->pc += ebl_ra_offset (ebl);
-        }
+	{
+	  /* We couldn't set the return register, either it was bogus,
+	     or the return pc is undefined, maybe end of call stack.  */
+	  unsigned pcreg = frame->fde->cie->return_address_register;
+	  if (! ebl_dwarf_to_regno (ebl, &pcreg)
+	      || pcreg >= ebl_frame_nregs (ebl))
+	    __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+	  else
+	    unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+	}
     }
   free (frame);
 }
-- 
1.8.3.1

             reply	other threads:[~2018-04-10 14:23 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-10 14:23 Mark Wielaard [this message]
2018-04-13 11:43 ` Mark Wielaard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1523370202-534-1-git-send-email-mark@klomp.org \
    --to=mark@klomp.org \
    --cc=elfutils-devel@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).