This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] libebl: Add ebl_unwind_ret_mask.


Another ARM oddity. A return value address in an unwind will contain an
extra bit to indicate whether to return to a regular ARM or THUMB function.
Add a new ebl function to return a mask to use to get the actual return
address during an unwind ebl_unwind_ret_mask.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 backends/ChangeLog     | 4 ++++
 backends/arm_init.c    | 3 +++
 libdwfl/ChangeLog      | 4 ++++
 libdwfl/frame_unwind.c | 6 +++++-
 libebl/ChangeLog       | 6 ++++++
 libebl/eblinitreg.c    | 9 ++++++++-
 libebl/libebl.h        | 4 ++++
 libebl/libeblP.h       | 8 +++++++-
 8 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/backends/ChangeLog b/backends/ChangeLog
index 64b669e..11538b0 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-15  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_init.c (arm_init): Set unwind_ret_mask.
+
 2014-06-14  Mark Wielaard  <mjw@redhat.com>
 
 	* arm_init.c (arm_init): Hook sym_func_value.
diff --git a/backends/arm_init.c b/backends/arm_init.c
index e2e20e4..f95949d 100644
--- a/backends/arm_init.c
+++ b/backends/arm_init.c
@@ -70,5 +70,8 @@ arm_init (elf, machine, eh, ehlen)
   eh->frame_nregs = 16;
   HOOK (eh, set_initial_registers_tid);
 
+  /* Bit zero encodes whether to return to a THUMB or ARM function. */
+  eh->unwind_ret_mask = ~(GElf_Addr)1;
+
   return MODVERSION;
 }
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 888b400..195f5a0 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-15  Mark Wielaard  <mjw@redhat.com>
+
+	* frame_unwind.c (handle_cfi): Use ebl_unwind_ret_mask.
+
 2014-06-14  Mark Wielaard  <mjw@redhat.com>
 
 	* dwfl_module_getsym.c (__libdwfl_getsym): Call ebl_sym_func_value.
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index 18c808b..f93348f 100644
--- a/libdwfl/frame_unwind.c
+++ b/libdwfl/frame_unwind.c
@@ -1,5 +1,5 @@
 /* Get previous frame state for an existing frame state.
-   Copyright (C) 2013 Red Hat, Inc.
+   Copyright (C) 2013, 2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -582,6 +582,10 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
 	  continue;
 	}
 
+      /* Some architectures encode some extra info in the return address.  */
+      if (regno == frame->fde->cie->return_address_register)
+	regval &= ebl_unwind_ret_mask (ebl);
+
       /* This is another strange PPC[64] case.  There are two
 	 registers numbers that can represent the same DWARF return
 	 register number.  We only want one to actually set the return
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 1c7a2ba..d5fac1d 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,9 @@
+2014-06-15  Mark Wielaard  <mjw@redhat.com>
+
+	* eblinitreg.c (ebl_unwind_ret_mask): New function.
+	* libebl.h (ebl_unwind_ret_mask): Define.
+	* libeblP.h (struct ebl): Add unwind_ret_mask.
+
 2014-06-14  Mark Wielaard  <mjw@redhat.com>
 
 	* Makefile.am (gen_SOURCES): Add eblsymfuncval.c.
diff --git a/libebl/eblinitreg.c b/libebl/eblinitreg.c
index 8909c50..a6bb00c 100644
--- a/libebl/eblinitreg.c
+++ b/libebl/eblinitreg.c
@@ -1,5 +1,5 @@
 /* Fetch live process Dwfl_Frame from PID.
-   Copyright (C) 2013 Red Hat, Inc.
+   Copyright (C) 2013, 2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -49,3 +49,10 @@ ebl_frame_nregs (Ebl *ebl)
 {
   return ebl == NULL ? 0 : ebl->frame_nregs;
 }
+
+GElf_Addr
+ebl_unwind_ret_mask (Ebl *ebl)
+{
+  return ((ebl == NULL || ebl->unwind_ret_mask == 0)
+	  ? ~(GElf_Addr)0 : ebl->unwind_ret_mask);
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index bc1f491..768dab4 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -409,6 +409,10 @@ extern bool ebl_set_initial_registers_tid (Ebl *ebl,
 extern size_t ebl_frame_nregs (Ebl *ebl)
   __nonnull_attribute__ (1);
 
+/* Mask to use for unwind return address in case the architecture adds
+   some extra non-address bits to it.  */
+extern GElf_Addr ebl_unwind_ret_mask (Ebl *ebl);
+
 /* Convert *REGNO as is in DWARF to a lower range suitable for
    Dwarf_Frame->REGS indexing.  */
 extern bool ebl_dwarf_to_regno (Ebl *ebl, unsigned *regno)
diff --git a/libebl/libeblP.h b/libebl/libeblP.h
index f91c2a0..ac38258 100644
--- a/libebl/libeblP.h
+++ b/libebl/libeblP.h
@@ -1,5 +1,5 @@
 /* Internal definitions for interface for libebl.
-   Copyright (C) 2000-2009, 2013 Red Hat, Inc.
+   Copyright (C) 2000-2009, 2013, 2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -64,6 +64,12 @@ struct ebl
      Ebl architecture can unwind iff FRAME_NREGS > 0.  */
   size_t frame_nregs;
 
+  /* Mask to use to get the return address from an unwind in case the
+     architecture adds some extra non-address bits to it.  When not
+     initialized (0) then ebl_unwind_ret_mask will return ~0, otherwise
+     it should be the actual mask to use.  */
+  GElf_Addr unwind_ret_mask;
+
   /* Function descriptor load address and table as used by
      ebl_resolve_sym_value if available for this arch.  */
   GElf_Addr fd_addr;
-- 
1.9.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]