* graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
@ 2011-02-22 18:35 Pedro Alves
2011-02-28 15:42 ` Jan Kratochvil
` (4 more replies)
0 siblings, 5 replies; 15+ messages in thread
From: Pedro Alves @ 2011-02-22 18:35 UTC (permalink / raw)
To: gdb-patches
This patch applies on top of the "unavailable regs/locals"
series, starting at:
<http://sourceware.org/ml/gdb-patches/2011-02/msg00581.html>.
This teaches GDB about terminating unwinding gracefully if
unwind further we would need registers/memory that haven't
been collected.
Here's the result:
(gdb) bt
#0 begin (a=<unavailable>) at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:182
#1 0x00000000004008ad in main (argc=1, argv=0x7fff0e22cf28, envp=0x7fff0e22cf38)
at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:210
#2 <unavailable> in ?? ()
Backtrace stopped: Not enough registers or memory available to unwind further
I think I've implemented this differently in about 10
different ways. This is the design that I ended up with and
that I think is best.
- when we sniff unwinders trying to find a matching unwinder,
we catch NOT_AVAILABLE_ERRORS. If the PC is unavailable,
it is impossible to determine if a given non-prologue parser unwinder
would have been the best unwinder or not. By catching
NOT_AVAILABLE_ERRORS, we don't have too touch many sniffers.
When sniffing, they just read whatever minimum data they
require to determine they're the correct unwinder. If
any of that is unavailable, we'll hit an exception. So what
this means is that sniffer code does not try to check if a
given _required_ value is available --- it just goes ahead and
reads it.
- adds a new frame_unwind method, to make it possible for an unwinder
to tell the core frame code that it can't unwind further. The
concept here, is that if we are able to tell a given unwinder
would be the best unwinder, select it, even if actually trying to
unwind from it wouldn't work due to unavailable data. E.g., if
all we have available is the PC, we'll be able to tell that we
have dwarf unwind info for that frame. But if we then find out
that we don't have enough registers/memory to compute the CFA, we know
we aren't going to be able to unwind. We _don't_ fallback to
prologue parsing in such cases, since if we couldn't unwind with
the precise unwind info missing, prologue parsing is surely not
going to be able to unwind correctly.
- this new method incidently allows cleanly reporting to the core
frame machinery when a frame is the outermost, without resorting
to hacks in the frame_id, which opens the door to fixing a
corner case with stepping through the outermost frame when there's
no debug info. I won't be implementing that, it just paves the way.
- the prologue parsers then need to be made aware that they may trip
on necessary registers (e.g., PC / SP / FP) unavailable to unwine,
and that they should return that they can't unwind further in
the new frame_unwind method in that case. I've taught the x86
and x64_64 unwinders, but not all others. I did do the mechanical
work of adjusting all of them to the new interface, so that
--enable-targets=all still builds, and so that they continue working
as today. Theaching other prologue unwinders how to terminate
gracefully with UNWIND_UNAVAILABLE is only interesting when a
corresponding target supports tracepoints on that architecture, so
it can be enabled on a case by case basis.
--
Pedro Alves
2012-02-22 Pedro Alves <pedro@codesourcery.com>
gdb/
* frame.c (frame_unwind_register): Throw an error if unwinding the
register failed.
* get_prev_frame_1 (get_prev_frame_1): Ask the unwinder if there's
an unwind stop reason.
(frame_stop_reason_string): Handle UNWIND_UNAVAILABLE.
* frame.h (enum unwind_stop_reason) <UNWIND_OUTERMOST,
UNWIND_UNAVAILABLE>: New.
* inline-frame.c (inline_frame_unwind): Install
default_frame_unwind_stop_reason.
* frame-unwind.c: Include "exceptions.h".
(frame_unwind_find_by_frame): Swallow NOT_AVAILABLE_ERROR errors.
(default_frame_unwind_stop_reason): New.
* frame-unwind.h (frame_unwind_stop_reason_ftype): New typedef.
(default_frame_unwind_stop_reason): Declare.
(struct frame_unwind) <stop_reason>: New function pointer.
* dummy-frame.c: Install default_frame_unwind_stop_reason.
* dwarf2-frame.c: Include exceptions.h.
(struct dwarf2_frame_cache) <unavailable_retaddr>: New field.
(dwarf2_frame_cache): Swallow NOT_AVAILABLE_ERROR errors when
computing the CFA. If such an error was thrown, set
unavailable_retaddr.
(dwarf2_frame_unwind_stop_reason): New.
(dwarf2_frame_this_id): Don't build a frame id if the CFA was
unavailable.
(dwarf2_frame_unwind): Install dwarf2_frame_unwind_stop_reason.
(dwarf2_signal_frame_unwind): Ditto.
* amd64-tdep.c: Include "exceptions.h".
(struct amd64_frame_cache): New field "base_p".
(amd64_init_frame_cache): Clear it.
(amd64_frame_cache_1): New, factored out from amd64_frame_cache.
Avoid reading registers with functions that throw if the register
is not necessary to compute the frame base.
(amd64_frame_cache): Reimplement wrapping amd64_frame_cache_1, and
swallowing NOT_AVAILABLE_ERROR.
(amd64_frame_unwind_stop_reason): New.
(amd64_frame_this_id): Don't build a frame id if the frame base
was unavailable.
(amd64_frame_unwind): Install amd64_frame_unwind_stop_reason.
(amd64_sigtramp_frame_cache): Swallow NOT_AVAILABLE_ERROR, and set
base_p if the frame base was computable.
(amd64_sigtramp_frame_unwind_stop_reason): New.
(amd64_sigtramp_frame_this_id): Don't build a frame id if the
frame base was unavailable.
(amd64_sigtramp_frame_unwind): Install
amd64_sigtramp_frame_unwind_stop_reason.
(amd64_epilogue_frame_cache): Swallow NOT_AVAILABLE_ERROR, and set
base_p if the frame base was computable.
(amd64_epilogue_frame_unwind_stop_reason): New.
(amd64_epilogue_frame_this_id): Don't build a frame id if the
frame base was unavailable.
(amd64_epilogue_frame_unwind): Install
amd64_epilogue_frame_unwind_stop_reason.
* i386-tdep.c: Include "exceptions.h".
(struct i386_frame_cache): New field "base_p".
(i386_init_frame_cache): Clear it.
(i386_frame_cache_1): New, factored out from amd64_frame_cache.
Avoid reading registers with functions that throw if the register
is not necessary to compute the frame base.
(i386_frame_cache): Reimplement wrapping amd64_frame_cache_1, and
swallowing NOT_AVAILABLE_ERROR.
(i386_frame_unwind_stop_reason): New.
(i386_frame_this_id): Don't build a frame id if the frame base was
unavailable.
(i386_frame_prev_register): Handle unavailable SP.
(i386_frame_unwind): Install i386_frame_unwind_stop_reason.
(i386_epilogue_frame_cache): Swallow NOT_AVAILABLE_ERROR, and set
base_p if the frame base was computable.
(i386_epilogue_frame_unwind_stop_reason): New.
(i386_epilogue_frame_this_id): Don't build a frame id if the frame
base was unavailable.
(i386_epilogue_frame_unwind): Install
i386_epilogue_frame_unwind_stop_reason.
(i386_sigtramp_frame_cache): Swallow NOT_AVAILABLE_ERROR, and set
base_p if the frame base was computable.
(i386_sigtramp_frame_unwind_stop_reason): New.
(i386_sigtramp_frame_this_id): Don't build a frame id if the frame
base was unavailable.
(i386_sigtramp_frame_unwind): Install
i386_sigtramp_frame_unwind_stop_reason.
* sentinel-frame.c (sentinel_frame_prev_register): Use the value
type's size, not the register's.
(sentinel_frame_unwind): Install default_frame_unwind_stop_reason.
* alpha-mdebug-tdep.c (alpha_mdebug_frame_unwind): Install
default_frame_unwind_stop_reason.
* alpha-tdep.c (alpha_sigtramp_frame_unwind)
(alpha_heuristic_frame_unwind): Ditto.
* amd64obsd-tdep.c (amd64obsd_trapframe_unwind): Ditto.
* arm-tdep.c (arm_prologue_unwind, arm_stub_unwind): Ditto.
* avr-tdep.c (avr_frame_unwind): Ditto.
* cris-tdep.c (cris_sigtramp_frame_unwind, cris_frame_unwind):
Ditto.
* frv-linux-tdep.c (frv_linux_sigtramp_frame_unwind): Ditto.
* frv-tdep.c (frv_frame_unwind): Ditto.
* h8300-tdep.c (h8300_frame_unwind): Ditto.
* hppa-hpux-tdep.c (hppa_hpux_sigtramp_frame_unwind): Ditto.
* hppa-linux-tdep.c (hppa_linux_sigtramp_frame_unwind): Ditto.
* hppa-tdep.c (hppa_frame_unwind, hppa_fallback_frame_unwind)
(hppa_stub_frame_unwind): Ditto.
* i386obsd-tdep.c (i386obsd_trapframe_unwind): Ditto.
* ia64-tdep.c (ia64_frame_unwind, ia64_sigtramp_frame_unwind)
(ia64_libunwind_frame_unwind)
(ia64_libunwind_sigtramp_frame_unwind): Ditto.
* iq2000-tdep.c (iq2000_frame_unwind): Ditto.
* lm32-tdep.c (lm32_frame_unwind): Ditto.
* m32c-tdep.c (m32c_unwind): Ditto.
* m32r-linux-tdep.c (m32r_linux_sigtramp_frame_unwind): Ditto.
* m32r-tdep.c (m32r_frame_unwind): Ditto.
* m68hc11-tdep.c (m68hc11_frame_unwind): Ditto.
* m68k-tdep.c (m68k_frame_unwind): Ditto.
* m68klinux-tdep.c (m68k_linux_sigtramp_frame_unwind): Ditto.
* m88k-tdep.c (m88k_frame_unwind): Ditto.
* mep-tdep.c (mep_frame_unwind): Ditto.
* microblaze-tdep.c (microblaze_frame_unwind): Ditto.
* mips-tdep.c (mips_insn16_frame_unwind, mips_insn32_frame_unwind)
(mips_stub_frame_unwind): Ditto.
* mn10300-tdep.c (mn10300_frame_unwind): Ditto.
* moxie-tdep.c (moxie_frame_unwind): Ditto.
* mt-tdep.c (mt_frame_unwind): Ditto.
* ppc-linux-tdep.c (ppu2spu_unwind): Ditto.
* ppcobsd-tdep.c (ppcobsd_sigtramp_frame_unwind): Ditto.
* rs6000-tdep.c (rs6000_frame_unwind): Ditto.
* s390-tdep.c (s390_frame_unwind, s390_stub_frame_unwind)
(s390_sigtramp_frame_unwind): Ditto.
* score-tdep.c (score_prologue_unwind): Ditto.
* sh-tdep.c (sh_frame_unwind): Ditto.
* sh64-tdep.c (sh64_frame_unwind): Ditto.
* sparc-sol2-tdep.c (sparc32_sol2_sigtramp_frame_unwind): Ditto.
* sparc-tdep.c (sparc32_frame_unwind): Ditto.
* sparc64-sol2-tdep.c (sparc64_sol2_sigtramp_frame_unwind): Ditto.
* sparc64-tdep.c (sparc64_frame_unwind): Ditto.
* sparc64fbsd-tdep.c (sparc64fbsd_sigtramp_frame_unwind): Ditto.
* sparc64nbsd-tdep.c (sparc64nbsd_sigcontext_frame_unwind): Ditto.
* sparc64obsd-tdep.c (sparc64obsd_frame_unwind)
(sparc64obsd_trapframe_unwind): Ditto.
* sparcnbsd-tdep.c (sparc32nbsd_sigcontext_frame_unwind): Ditto.
* sparcobsd-tdep.c (sparc32obsd_sigtramp_frame_unwind): Ditto.
* spu-tdep.c (spu_frame_unwind, spu2ppu_unwind): Ditto.
* v850-tdep.c (v850_frame_unwind): Ditto.
* vax-tdep.c (vax_frame_unwind): Ditto.
* vaxobsd-tdep.c (vaxobsd_sigtramp_frame_unwind): Ditto.
* xstormy16-tdep.c (frame_unwind xstormy16_frame_unwind): Ditto.
* xtensa-tdep.c (xtensa_unwind): Ditto.
---
gdb/alpha-mdebug-tdep.c | 1
gdb/alpha-tdep.c | 2
gdb/amd64-tdep.c | 156 ++++++++++++++++++++++++++++++--------
gdb/amd64obsd-tdep.c | 1
gdb/arm-tdep.c | 3
gdb/avr-tdep.c | 1
gdb/bfin-tdep.c | 1
gdb/cris-tdep.c | 2
gdb/dummy-frame.c | 1
gdb/dwarf2-frame.c | 79 ++++++++++++++-----
gdb/frame-unwind.c | 37 +++++++--
gdb/frame-unwind.h | 11 ++
gdb/frame.c | 18 ++++
gdb/frame.h | 7 +
gdb/frv-linux-tdep.c | 1
gdb/frv-tdep.c | 1
gdb/h8300-tdep.c | 1
gdb/hppa-hpux-tdep.c | 1
gdb/hppa-linux-tdep.c | 1
gdb/hppa-tdep.c | 3
gdb/i386-tdep.c | 193 ++++++++++++++++++++++++++++++++++++------------
gdb/i386obsd-tdep.c | 1
gdb/ia64-tdep.c | 4
gdb/inline-frame.c | 1
gdb/iq2000-tdep.c | 1
gdb/lm32-tdep.c | 1
gdb/m32c-tdep.c | 1
gdb/m32r-linux-tdep.c | 1
gdb/m32r-tdep.c | 1
gdb/m68hc11-tdep.c | 1
gdb/m68k-tdep.c | 1
gdb/m68klinux-tdep.c | 1
gdb/m88k-tdep.c | 1
gdb/mep-tdep.c | 1
gdb/microblaze-tdep.c | 1
gdb/mips-tdep.c | 3
gdb/mn10300-tdep.c | 1
gdb/moxie-tdep.c | 1
gdb/mt-tdep.c | 1
gdb/ppc-linux-tdep.c | 1
gdb/ppcobsd-tdep.c | 1
gdb/rs6000-tdep.c | 1
gdb/s390-tdep.c | 3
gdb/score-tdep.c | 1
gdb/sentinel-frame.c | 6 -
gdb/sh-tdep.c | 1
gdb/sh64-tdep.c | 1
gdb/sparc-sol2-tdep.c | 1
gdb/sparc-tdep.c | 1
gdb/sparc64-sol2-tdep.c | 1
gdb/sparc64-tdep.c | 1
gdb/sparc64fbsd-tdep.c | 1
gdb/sparc64nbsd-tdep.c | 1
gdb/sparc64obsd-tdep.c | 2
gdb/sparcnbsd-tdep.c | 1
gdb/sparcobsd-tdep.c | 1
gdb/spu-tdep.c | 2
gdb/v850-tdep.c | 1
gdb/vax-tdep.c | 1
gdb/vaxobsd-tdep.c | 1
gdb/xstormy16-tdep.c | 1
gdb/xtensa-tdep.c | 1
62 files changed, 468 insertions(+), 108 deletions(-)
Index: src/gdb/frame.c
===================================================================
--- src.orig/gdb/frame.c 2011-02-22 17:57:50.000000000 +0000
+++ src/gdb/frame.c 2011-02-22 17:58:04.244708001 +0000
@@ -912,6 +912,12 @@ frame_unwind_register (struct frame_info
frame_register_unwind (frame, regnum, &optimized, &unavailable,
&lval, &addr, &realnum, buf);
+
+ if (optimized)
+ error (_("Register %d was optimized out"), regnum);
+ if (unavailable)
+ throw_error (NOT_AVAILABLE_ERROR,
+ _("Register %d is not available"), regnum);
}
void
@@ -1599,6 +1605,15 @@ get_prev_frame_1 (struct frame_info *thi
if (get_frame_type (this_frame) == INLINE_FRAME)
return get_prev_frame_raw (this_frame);
+ /* Check that this frame is unwindable. If it isn't, don't try to
+ unwind to the prev frame. */
+ this_frame->stop_reason
+ = this_frame->unwind->stop_reason (this_frame,
+ &this_frame->prologue_cache);
+
+ if (this_frame->stop_reason != UNWIND_NO_REASON)
+ return NULL;
+
/* Check that this frame's ID was valid. If it wasn't, don't try to
unwind to the prev frame. Be careful to not apply this test to
the sentinel frame. */
@@ -2323,6 +2338,9 @@ frame_stop_reason_string (enum unwind_st
case UNWIND_NULL_ID:
return _("unwinder did not report frame ID");
+ case UNWIND_UNAVAILABLE:
+ return _("Not enough registers or memory available to unwind further");
+
case UNWIND_INNER_ID:
return _("previous frame inner to this frame (corrupt stack?)");
Index: src/gdb/frame.h
===================================================================
--- src.orig/gdb/frame.h 2011-02-22 17:57:50.000000000 +0000
+++ src/gdb/frame.h 2011-02-22 17:58:04.244708001 +0000
@@ -454,12 +454,19 @@ enum unwind_stop_reason
error. But that's a project for another day. */
UNWIND_NULL_ID,
+ /* This frame is the outermost. */
+ UNWIND_OUTERMOST,
+
/* All the conditions after this point are considered errors;
abnormal stack termination. If a backtrace stops for one
of these reasons, we'll let the user know. This marker
is not a valid stop reason. */
UNWIND_FIRST_ERROR,
+ /* Can't unwind further, because that would require knowing the
+ values of registers or memory that haven't been collected. */
+ UNWIND_UNAVAILABLE,
+
/* This frame ID looks like it ought to belong to a NEXT frame,
but we got it for a PREV frame. Normally, this is a sign of
unwinder failure. It could also indicate stack corruption. */
Index: src/gdb/inline-frame.c
===================================================================
--- src.orig/gdb/inline-frame.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/inline-frame.c 2011-02-22 17:58:04.244708001 +0000
@@ -260,6 +260,7 @@ inline_frame_sniffer (const struct frame
const struct frame_unwind inline_frame_unwind = {
INLINE_FRAME,
+ default_frame_unwind_stop_reason,
inline_frame_this_id,
inline_frame_prev_register,
NULL,
Index: src/gdb/frame-unwind.c
===================================================================
--- src.orig/gdb/frame-unwind.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/frame-unwind.c 2011-02-22 17:58:04.244708001 +0000
@@ -25,7 +25,7 @@
#include "inline-frame.h"
#include "value.h"
#include "regcache.h"
-
+#include "exceptions.h"
#include "gdb_assert.h"
#include "gdb_obstack.h"
@@ -103,14 +103,31 @@ frame_unwind_find_by_frame (struct frame
for (entry = table->list; entry != NULL; entry = entry->next)
{
struct cleanup *old_cleanup;
+ volatile struct gdb_exception ex;
+ int res = 0;
old_cleanup = frame_prepare_for_sniffer (this_frame, entry->unwinder);
- if (entry->unwinder->sniffer (entry->unwinder, this_frame,
- this_cache))
+
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
{
- discard_cleanups (old_cleanup);
- return;
+ res = entry->unwinder->sniffer (entry->unwinder, this_frame,
+ this_cache);
}
+ if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+ {
+ /* This usually means that not even the PC is available,
+ thus most unwinders aren't able to determine if they're
+ the best fit. Keep trying. Fallback prologue unwinders
+ should always accept the frame. */
+ }
+ else if (ex.reason < 0)
+ throw_exception (ex);
+ else if (res)
+ {
+ discard_cleanups (old_cleanup);
+ return;
+ }
+
do_cleanups (old_cleanup);
}
internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed"));
@@ -127,6 +144,16 @@ default_frame_sniffer (const struct fram
return 1;
}
+/* A default frame unwinder stop_reason callback that always claims
+ the frame is unwindable. */
+
+enum unwind_stop_reason
+default_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ return UNWIND_NO_REASON;
+}
+
/* Helper functions for value-based register unwinding. These return
a (possibly lazy) value of the appropriate type. */
Index: src/gdb/dwarf2-frame.c
===================================================================
--- src.orig/gdb/dwarf2-frame.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/dwarf2-frame.c 2011-02-22 17:58:04.254708002 +0000
@@ -40,6 +40,7 @@
#include "dwarf2-frame.h"
#include "ax.h"
#include "dwarf2loc.h"
+#include "exceptions.h"
struct comp_unit;
@@ -986,6 +987,10 @@ struct dwarf2_frame_cache
/* DWARF Call Frame Address. */
CORE_ADDR cfa;
+ /* Set if the return address column was marked as unavailable
+ (required non-collected memory or registers to compute). */
+ int unavailable_retaddr;
+
/* Set if the return address column was marked as undefined. */
int undefined_retaddr;
@@ -1013,6 +1018,7 @@ dwarf2_frame_cache (struct frame_info *t
struct dwarf2_frame_cache *cache;
struct dwarf2_frame_state *fs;
struct dwarf2_fde *fde;
+ volatile struct gdb_exception ex;
if (*this_cache)
return *this_cache;
@@ -1020,10 +1026,10 @@ dwarf2_frame_cache (struct frame_info *t
/* Allocate a new cache. */
cache = FRAME_OBSTACK_ZALLOC (struct dwarf2_frame_cache);
cache->reg = FRAME_OBSTACK_CALLOC (num_regs, struct dwarf2_frame_state_reg);
+ *this_cache = cache;
/* Allocate and initialize the frame state. */
- fs = XMALLOC (struct dwarf2_frame_state);
- memset (fs, 0, sizeof (struct dwarf2_frame_state));
+ fs = XZALLOC (struct dwarf2_frame_state);
old_chain = make_cleanup (dwarf2_frame_state_free, fs);
/* Unwind the PC.
@@ -1068,26 +1074,39 @@ dwarf2_frame_cache (struct frame_info *t
execute_cfa_program (fde, fde->instructions, fde->end, gdbarch,
get_frame_pc (this_frame), fs);
- /* Calculate the CFA. */
- switch (fs->regs.cfa_how)
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
{
- case CFA_REG_OFFSET:
- cache->cfa = read_reg (this_frame, fs->regs.cfa_reg);
- if (fs->armcc_cfa_offsets_reversed)
- cache->cfa -= fs->regs.cfa_offset;
- else
- cache->cfa += fs->regs.cfa_offset;
- break;
+ /* Calculate the CFA. */
+ switch (fs->regs.cfa_how)
+ {
+ case CFA_REG_OFFSET:
+ cache->cfa = read_reg (this_frame, fs->regs.cfa_reg);
+ if (fs->armcc_cfa_offsets_reversed)
+ cache->cfa -= fs->regs.cfa_offset;
+ else
+ cache->cfa += fs->regs.cfa_offset;
+ break;
+
+ case CFA_EXP:
+ cache->cfa =
+ execute_stack_op (fs->regs.cfa_exp, fs->regs.cfa_exp_len,
+ cache->addr_size, cache->text_offset,
+ this_frame, 0, 0);
+ break;
- case CFA_EXP:
- cache->cfa =
- execute_stack_op (fs->regs.cfa_exp, fs->regs.cfa_exp_len,
- cache->addr_size, cache->text_offset,
- this_frame, 0, 0);
- break;
+ default:
+ internal_error (__FILE__, __LINE__, _("Unknown CFA rule."));
+ }
+ }
+ if (ex.reason < 0)
+ {
+ if (ex.error == NOT_AVAILABLE_ERROR)
+ {
+ cache->unavailable_retaddr = 1;
+ return cache;
+ }
- default:
- internal_error (__FILE__, __LINE__, _("Unknown CFA rule."));
+ throw_exception (ex);
}
/* Initialize the register state. */
@@ -1193,10 +1212,25 @@ incomplete CFI data; unspecified registe
do_cleanups (old_chain);
- *this_cache = cache;
return cache;
}
+static enum unwind_stop_reason
+dwarf2_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct dwarf2_frame_cache *cache
+ = dwarf2_frame_cache (this_frame, this_cache);
+
+ if (cache->unavailable_retaddr)
+ return UNWIND_UNAVAILABLE;
+
+ if (cache->undefined_retaddr)
+ return UNWIND_OUTERMOST;
+
+ return UNWIND_NO_REASON;
+}
+
static void
dwarf2_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct frame_id *this_id)
@@ -1204,6 +1238,9 @@ dwarf2_frame_this_id (struct frame_info
struct dwarf2_frame_cache *cache =
dwarf2_frame_cache (this_frame, this_cache);
+ if (cache->unavailable_retaddr)
+ return;
+
if (cache->undefined_retaddr)
return;
@@ -1321,6 +1358,7 @@ dwarf2_frame_sniffer (const struct frame
static const struct frame_unwind dwarf2_frame_unwind =
{
NORMAL_FRAME,
+ dwarf2_frame_unwind_stop_reason,
dwarf2_frame_this_id,
dwarf2_frame_prev_register,
NULL,
@@ -1330,6 +1368,7 @@ static const struct frame_unwind dwarf2_
static const struct frame_unwind dwarf2_signal_frame_unwind =
{
SIGTRAMP_FRAME,
+ dwarf2_frame_unwind_stop_reason,
dwarf2_frame_this_id,
dwarf2_frame_prev_register,
NULL,
Index: src/gdb/amd64-tdep.c
===================================================================
--- src.orig/gdb/amd64-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/amd64-tdep.c 2011-02-22 17:58:04.254708002 +0000
@@ -38,7 +38,7 @@
#include "symfile.h"
#include "disasm.h"
#include "gdb_assert.h"
-
+#include "exceptions.h"
#include "amd64-tdep.h"
#include "i387-tdep.h"
@@ -1628,6 +1628,7 @@ struct amd64_frame_cache
{
/* Base address. */
CORE_ADDR base;
+ int base_p;
CORE_ADDR sp_offset;
CORE_ADDR pc;
@@ -1649,6 +1650,7 @@ amd64_init_frame_cache (struct amd64_fra
/* Base address. */
cache->base = 0;
+ cache->base_p = 0;
cache->sp_offset = -8;
cache->pc = 0;
@@ -1906,33 +1908,20 @@ amd64_skip_prologue (struct gdbarch *gdb
/* Normal frames. */
-static struct amd64_frame_cache *
-amd64_frame_cache (struct frame_info *this_frame, void **this_cache)
+static void
+amd64_frame_cache_1 (struct frame_info *this_frame,
+ struct amd64_frame_cache *cache)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct amd64_frame_cache *cache;
gdb_byte buf[8];
int i;
- if (*this_cache)
- return *this_cache;
-
- cache = amd64_alloc_frame_cache ();
- *this_cache = cache;
-
cache->pc = get_frame_func (this_frame);
if (cache->pc != 0)
amd64_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame),
cache);
- if (cache->saved_sp_reg != -1)
- {
- /* Stack pointer has been saved. */
- get_frame_register (this_frame, cache->saved_sp_reg, buf);
- cache->saved_sp = extract_unsigned_integer(buf, 8, byte_order);
- }
-
if (cache->frameless_p)
{
/* We didn't find a valid frame. If we're at the start of a
@@ -1944,6 +1933,10 @@ amd64_frame_cache (struct frame_info *th
if (cache->saved_sp_reg != -1)
{
+ /* Stack pointer has been saved. */
+ get_frame_register (this_frame, cache->saved_sp_reg, buf);
+ cache->saved_sp = extract_unsigned_integer (buf, 8, byte_order);
+
/* We're halfway aligning the stack. */
cache->base = ((cache->saved_sp - 8) & 0xfffffffffffffff0LL) - 8;
cache->saved_regs[AMD64_RIP_REGNUM] = cache->saved_sp - 8;
@@ -1981,9 +1974,48 @@ amd64_frame_cache (struct frame_info *th
if (cache->saved_regs[i] != -1)
cache->saved_regs[i] += cache->base;
+ cache->base_p = 1;
+}
+
+static struct amd64_frame_cache *
+amd64_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+ volatile struct gdb_exception ex;
+ struct amd64_frame_cache *cache;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = amd64_alloc_frame_cache ();
+ *this_cache = cache;
+
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ amd64_frame_cache_1 (this_frame, cache);
+ }
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+
return cache;
}
+static enum unwind_stop_reason
+amd64_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct amd64_frame_cache *cache =
+ amd64_frame_cache (this_frame, this_cache);
+
+ if (!cache->base_p)
+ return UNWIND_UNAVAILABLE;
+
+ /* This marks the outermost frame. */
+ if (cache->base == 0)
+ return UNWIND_OUTERMOST;
+
+ return UNWIND_NO_REASON;
+}
+
static void
amd64_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct frame_id *this_id)
@@ -1991,6 +2023,9 @@ amd64_frame_this_id (struct frame_info *
struct amd64_frame_cache *cache =
amd64_frame_cache (this_frame, this_cache);
+ if (!cache->base_p)
+ return;
+
/* This marks the outermost frame. */
if (cache->base == 0)
return;
@@ -2021,6 +2056,7 @@ amd64_frame_prev_register (struct frame_
static const struct frame_unwind amd64_frame_unwind =
{
NORMAL_FRAME,
+ amd64_frame_unwind_stop_reason,
amd64_frame_this_id,
amd64_frame_prev_register,
NULL,
@@ -2040,6 +2076,7 @@ amd64_sigtramp_frame_cache (struct frame
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ volatile struct gdb_exception ex;
struct amd64_frame_cache *cache;
CORE_ADDR addr;
gdb_byte buf[8];
@@ -2050,20 +2087,40 @@ amd64_sigtramp_frame_cache (struct frame
cache = amd64_alloc_frame_cache ();
- get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
- cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8;
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8;
+
+ addr = tdep->sigcontext_addr (this_frame);
+ gdb_assert (tdep->sc_reg_offset);
+ gdb_assert (tdep->sc_num_regs <= AMD64_NUM_SAVED_REGS);
+ for (i = 0; i < tdep->sc_num_regs; i++)
+ if (tdep->sc_reg_offset[i] != -1)
+ cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
- addr = tdep->sigcontext_addr (this_frame);
- gdb_assert (tdep->sc_reg_offset);
- gdb_assert (tdep->sc_num_regs <= AMD64_NUM_SAVED_REGS);
- for (i = 0; i < tdep->sc_num_regs; i++)
- if (tdep->sc_reg_offset[i] != -1)
- cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
+ cache->base_p = 1;
+ }
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
*this_cache = cache;
return cache;
}
+static enum unwind_stop_reason
+amd64_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct amd64_frame_cache *cache =
+ amd64_sigtramp_frame_cache (this_frame, this_cache);
+
+ if (!cache->base_p)
+ return UNWIND_UNAVAILABLE;
+
+ return UNWIND_NO_REASON;
+}
+
static void
amd64_sigtramp_frame_this_id (struct frame_info *this_frame,
void **this_cache, struct frame_id *this_id)
@@ -2071,6 +2128,9 @@ amd64_sigtramp_frame_this_id (struct fra
struct amd64_frame_cache *cache =
amd64_sigtramp_frame_cache (this_frame, this_cache);
+ if (!cache->base_p)
+ return;
+
(*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame));
}
@@ -2117,6 +2177,7 @@ amd64_sigtramp_frame_sniffer (const stru
static const struct frame_unwind amd64_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ amd64_sigtramp_frame_unwind_stop_reason,
amd64_sigtramp_frame_this_id,
amd64_sigtramp_frame_prev_register,
NULL,
@@ -2178,6 +2239,7 @@ amd64_epilogue_frame_cache (struct frame
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ volatile struct gdb_exception ex;
struct amd64_frame_cache *cache;
gdb_byte buf[8];
@@ -2187,23 +2249,43 @@ amd64_epilogue_frame_cache (struct frame
cache = amd64_alloc_frame_cache ();
*this_cache = cache;
- /* Cache base will be %esp plus cache->sp_offset (-8). */
- get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
- cache->base = extract_unsigned_integer (buf, 8,
- byte_order) + cache->sp_offset;
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ /* Cache base will be %esp plus cache->sp_offset (-8). */
+ get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 8,
+ byte_order) + cache->sp_offset;
+
+ /* Cache pc will be the frame func. */
+ cache->pc = get_frame_pc (this_frame);
- /* Cache pc will be the frame func. */
- cache->pc = get_frame_pc (this_frame);
+ /* The saved %esp will be at cache->base plus 16. */
+ cache->saved_sp = cache->base + 16;
- /* The saved %esp will be at cache->base plus 16. */
- cache->saved_sp = cache->base + 16;
+ /* The saved %eip will be at cache->base plus 8. */
+ cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8;
- /* The saved %eip will be at cache->base plus 8. */
- cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8;
+ cache->base_p = 1;
+ }
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
return cache;
}
+static enum unwind_stop_reason
+amd64_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct amd64_frame_cache *cache
+ = amd64_epilogue_frame_cache (this_frame, this_cache);
+
+ if (!cache->base_p)
+ return UNWIND_UNAVAILABLE;
+
+ return UNWIND_NO_REASON;
+}
+
static void
amd64_epilogue_frame_this_id (struct frame_info *this_frame,
void **this_cache,
@@ -2212,12 +2294,16 @@ amd64_epilogue_frame_this_id (struct fra
struct amd64_frame_cache *cache = amd64_epilogue_frame_cache (this_frame,
this_cache);
+ if (!cache->base_p)
+ return;
+
(*this_id) = frame_id_build (cache->base + 8, cache->pc);
}
static const struct frame_unwind amd64_epilogue_frame_unwind =
{
NORMAL_FRAME,
+ amd64_epilogue_frame_unwind_stop_reason,
amd64_epilogue_frame_this_id,
amd64_frame_prev_register,
NULL,
Index: src/gdb/dummy-frame.c
===================================================================
--- src.orig/gdb/dummy-frame.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/dummy-frame.c 2011-02-22 17:58:04.254708002 +0000
@@ -278,6 +278,7 @@ dummy_frame_this_id (struct frame_info *
const struct frame_unwind dummy_frame_unwind =
{
DUMMY_FRAME,
+ default_frame_unwind_stop_reason,
dummy_frame_this_id,
dummy_frame_prev_register,
NULL,
Index: src/gdb/frame-unwind.h
===================================================================
--- src.orig/gdb/frame-unwind.h 2011-02-22 17:45:30.000000000 +0000
+++ src/gdb/frame-unwind.h 2011-02-22 17:58:04.254708002 +0000
@@ -51,6 +51,9 @@ typedef int (frame_sniffer_ftype) (const
struct frame_info *this_frame,
void **this_prologue_cache);
+typedef enum unwind_stop_reason (frame_unwind_stop_reason_ftype)
+ (struct frame_info *this_frame, void **this_prologue_cache);
+
/* A default frame sniffer which always accepts the frame. Used by
fallback prologue unwinders. */
@@ -58,6 +61,13 @@ int default_frame_sniffer (const struct
struct frame_info *this_frame,
void **this_prologue_cache);
+/* A default stop_reason callback which always claims the frame is
+ unwindable. */
+
+enum unwind_stop_reason
+ default_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache);
+
/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
use THIS frame, and through it the NEXT frame's register unwind
method, to determine the frame ID of THIS frame.
@@ -136,6 +146,7 @@ struct frame_unwind
enum frame_type type;
/* Should an attribute indicating the frame's address-in-block go
here? */
+ frame_unwind_stop_reason_ftype *stop_reason;
frame_this_id_ftype *this_id;
frame_prev_register_ftype *prev_register;
const struct frame_data *unwind_data;
Index: src/gdb/i386-tdep.c
===================================================================
--- src.orig/gdb/i386-tdep.c 2011-02-22 17:57:49.000000000 +0000
+++ src/gdb/i386-tdep.c 2011-02-22 17:58:04.254708002 +0000
@@ -45,7 +45,7 @@
#include "dis-asm.h"
#include "disasm.h"
#include "remote.h"
-
+#include "exceptions.h"
#include "gdb_assert.h"
#include "gdb_string.h"
@@ -797,6 +797,7 @@ struct i386_frame_cache
{
/* Base address. */
CORE_ADDR base;
+ int base_p;
LONGEST sp_offset;
CORE_ADDR pc;
@@ -821,6 +822,7 @@ i386_alloc_frame_cache (void)
cache = FRAME_OBSTACK_ZALLOC (struct i386_frame_cache);
/* Base address. */
+ cache->base_p = 0;
cache->base = 0;
cache->sp_offset = -4;
cache->pc = 0;
@@ -1577,20 +1579,16 @@ i386_unwind_pc (struct gdbarch *gdbarch,
/* Normal frames. */
-static struct i386_frame_cache *
-i386_frame_cache (struct frame_info *this_frame, void **this_cache)
+static void
+i386_frame_cache_1 (struct frame_info *this_frame,
+ struct i386_frame_cache *cache)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct i386_frame_cache *cache;
gdb_byte buf[4];
int i;
- if (*this_cache)
- return *this_cache;
-
- cache = i386_alloc_frame_cache ();
- *this_cache = cache;
+ cache->pc = get_frame_func (this_frame);
/* In principle, for normal frames, %ebp holds the frame pointer,
which holds the base address for the current stack frame.
@@ -1604,23 +1602,15 @@ i386_frame_cache (struct frame_info *thi
get_frame_register (this_frame, I386_EBP_REGNUM, buf);
cache->base = extract_unsigned_integer (buf, 4, byte_order);
if (cache->base == 0)
- return cache;
+ return;
/* For normal frames, %eip is stored at 4(%ebp). */
cache->saved_regs[I386_EIP_REGNUM] = 4;
- cache->pc = get_frame_func (this_frame);
if (cache->pc != 0)
i386_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame),
cache);
- if (cache->saved_sp_reg != -1)
- {
- /* Saved stack pointer has been saved. */
- get_frame_register (this_frame, cache->saved_sp_reg, buf);
- cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order);
- }
-
if (cache->locals < 0)
{
/* We didn't find a valid frame, which means that CACHE->base
@@ -1633,6 +1623,10 @@ i386_frame_cache (struct frame_info *thi
if (cache->saved_sp_reg != -1)
{
+ /* Saved stack pointer has been saved. */
+ get_frame_register (this_frame, cache->saved_sp_reg, buf);
+ cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order);
+
/* We're halfway aligning the stack. */
cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4;
cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4;
@@ -1660,9 +1654,17 @@ i386_frame_cache (struct frame_info *thi
cache->saved_regs[I386_EBP_REGNUM] = 0;
}
+ if (cache->saved_sp_reg != -1)
+ {
+ /* Saved stack pointer has been saved (but the SAVED_SP_REG
+ register may be unavailable). */
+ if (cache->saved_sp == 0
+ && frame_register_read (this_frame, cache->saved_sp_reg, buf))
+ cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order);
+ }
/* Now that we have the base address for the stack frame we can
calculate the value of %esp in the calling frame. */
- if (cache->saved_sp == 0)
+ else if (cache->saved_sp == 0)
cache->saved_sp = cache->base + 8;
/* Adjust all the saved registers such that they contain addresses
@@ -1671,6 +1673,28 @@ i386_frame_cache (struct frame_info *thi
if (cache->saved_regs[i] != -1)
cache->saved_regs[i] += cache->base;
+ cache->base_p = 1;
+}
+
+static struct i386_frame_cache *
+i386_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+ volatile struct gdb_exception ex;
+ struct i386_frame_cache *cache;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = i386_alloc_frame_cache ();
+ *this_cache = cache;
+
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ i386_frame_cache_1 (this_frame, cache);
+ }
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+
return cache;
}
@@ -1688,6 +1712,22 @@ i386_frame_this_id (struct frame_info *t
(*this_id) = frame_id_build (cache->base + 8, cache->pc);
}
+static enum unwind_stop_reason
+i386_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
+
+ if (!cache->base_p)
+ return UNWIND_UNAVAILABLE;
+
+ /* This marks the outermost frame. */
+ if (cache->base == 0)
+ return UNWIND_OUTERMOST;
+
+ return UNWIND_NO_REASON;
+}
+
static struct value *
i386_frame_prev_register (struct frame_info *this_frame, void **this_cache,
int regnum)
@@ -1727,8 +1767,18 @@ i386_frame_prev_register (struct frame_i
if (regnum == I386_EIP_REGNUM && cache->pc_in_eax)
return frame_unwind_got_register (this_frame, regnum, I386_EAX_REGNUM);
- if (regnum == I386_ESP_REGNUM && cache->saved_sp)
- return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
+ if (regnum == I386_ESP_REGNUM)
+ {
+ /* If the SP has been saved, but we don't know where, then this
+ means that SAVED_SP_REG register was found unavailable back
+ when we built the cache. */
+ if (cache->saved_sp == 0 && cache->saved_sp_reg != -1)
+ return frame_unwind_got_register (this_frame, regnum,
+ cache->saved_sp_reg);
+ else
+ return frame_unwind_got_constant (this_frame, regnum,
+ cache->saved_sp);
+ }
if (regnum < I386_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1)
return frame_unwind_got_memory (this_frame, regnum,
@@ -1740,6 +1790,7 @@ i386_frame_prev_register (struct frame_i
static const struct frame_unwind i386_frame_unwind =
{
NORMAL_FRAME,
+ i386_frame_unwind_stop_reason,
i386_frame_this_id,
i386_frame_prev_register,
NULL,
@@ -1783,6 +1834,7 @@ i386_epilogue_frame_cache (struct frame_
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ volatile struct gdb_exception ex;
struct i386_frame_cache *cache;
gdb_byte buf[4];
@@ -1792,23 +1844,43 @@ i386_epilogue_frame_cache (struct frame_
cache = i386_alloc_frame_cache ();
*this_cache = cache;
- /* Cache base will be %esp plus cache->sp_offset (-4). */
- get_frame_register (this_frame, I386_ESP_REGNUM, buf);
- cache->base = extract_unsigned_integer (buf, 4,
- byte_order) + cache->sp_offset;
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ /* Cache base will be %esp plus cache->sp_offset (-4). */
+ get_frame_register (this_frame, I386_ESP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 4,
+ byte_order) + cache->sp_offset;
+
+ /* Cache pc will be the frame func. */
+ cache->pc = get_frame_pc (this_frame);
- /* Cache pc will be the frame func. */
- cache->pc = get_frame_pc (this_frame);
+ /* The saved %esp will be at cache->base plus 8. */
+ cache->saved_sp = cache->base + 8;
- /* The saved %esp will be at cache->base plus 8. */
- cache->saved_sp = cache->base + 8;
+ /* The saved %eip will be at cache->base plus 4. */
+ cache->saved_regs[I386_EIP_REGNUM] = cache->base + 4;
- /* The saved %eip will be at cache->base plus 4. */
- cache->saved_regs[I386_EIP_REGNUM] = cache->base + 4;
+ cache->base_p = 1;
+ }
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
return cache;
}
+static enum unwind_stop_reason
+i386_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct i386_frame_cache *cache
+ = i386_epilogue_frame_cache (this_frame, this_cache);
+
+ if (!cache->base_p)
+ return UNWIND_UNAVAILABLE;
+
+ return UNWIND_NO_REASON;
+}
+
static void
i386_epilogue_frame_this_id (struct frame_info *this_frame,
void **this_cache,
@@ -1817,12 +1889,16 @@ i386_epilogue_frame_this_id (struct fram
struct i386_frame_cache *cache = i386_epilogue_frame_cache (this_frame,
this_cache);
+ if (!cache->base_p)
+ return;
+
(*this_id) = frame_id_build (cache->base + 8, cache->pc);
}
static const struct frame_unwind i386_epilogue_frame_unwind =
{
NORMAL_FRAME,
+ i386_epilogue_frame_unwind_stop_reason,
i386_epilogue_frame_this_id,
i386_frame_prev_register,
NULL,
@@ -1838,6 +1914,7 @@ i386_sigtramp_frame_cache (struct frame_
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ volatile struct gdb_exception ex;
struct i386_frame_cache *cache;
CORE_ADDR addr;
gdb_byte buf[4];
@@ -1847,30 +1924,50 @@ i386_sigtramp_frame_cache (struct frame_
cache = i386_alloc_frame_cache ();
- get_frame_register (this_frame, I386_ESP_REGNUM, buf);
- cache->base = extract_unsigned_integer (buf, 4, byte_order) - 4;
-
- addr = tdep->sigcontext_addr (this_frame);
- if (tdep->sc_reg_offset)
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
{
- int i;
+ get_frame_register (this_frame, I386_ESP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 4, byte_order) - 4;
- gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS);
+ addr = tdep->sigcontext_addr (this_frame);
+ if (tdep->sc_reg_offset)
+ {
+ int i;
- for (i = 0; i < tdep->sc_num_regs; i++)
- if (tdep->sc_reg_offset[i] != -1)
- cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
- }
- else
- {
- cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset;
- cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset;
+ gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS);
+
+ for (i = 0; i < tdep->sc_num_regs; i++)
+ if (tdep->sc_reg_offset[i] != -1)
+ cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
+ }
+ else
+ {
+ cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset;
+ cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset;
+ }
+
+ cache->base_p = 1;
}
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
*this_cache = cache;
return cache;
}
+static enum unwind_stop_reason
+i386_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct i386_frame_cache *cache =
+ i386_sigtramp_frame_cache (this_frame, this_cache);
+
+ if (!cache->base_p)
+ return UNWIND_UNAVAILABLE;
+
+ return UNWIND_NO_REASON;
+}
+
static void
i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct frame_id *this_id)
@@ -1878,6 +1975,9 @@ i386_sigtramp_frame_this_id (struct fram
struct i386_frame_cache *cache =
i386_sigtramp_frame_cache (this_frame, this_cache);
+ if (!cache->base_p)
+ return;
+
/* See the end of i386_push_dummy_call. */
(*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
}
@@ -1925,6 +2025,7 @@ i386_sigtramp_frame_sniffer (const struc
static const struct frame_unwind i386_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ i386_sigtramp_frame_unwind_stop_reason,
i386_sigtramp_frame_this_id,
i386_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/sentinel-frame.c
===================================================================
--- src.orig/gdb/sentinel-frame.c 2011-02-22 17:57:48.000000000 +0000
+++ src/gdb/sentinel-frame.c 2011-02-22 17:58:04.264708003 +0000
@@ -51,9 +51,10 @@ sentinel_frame_prev_register (struct fra
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct frame_unwind_cache *cache = *this_prologue_cache;
struct value *value;
+ struct type *regtype = register_type (gdbarch, regnum);
/* Return the actual value. */
- value = allocate_value (register_type (gdbarch, regnum));
+ value = allocate_value (regtype);
VALUE_LVAL (value) = lval_register;
VALUE_REGNUM (value) = regnum;
VALUE_FRAME_ID (value) = get_frame_id (this_frame);
@@ -64,7 +65,7 @@ sentinel_frame_prev_register (struct fra
if (regcache_cooked_read (cache->regcache,
regnum,
value_contents_raw (value)) == REG_UNAVAILABLE)
- mark_value_bytes_unavailable (value, 0, register_size (gdbarch, regnum));
+ mark_value_bytes_unavailable (value, 0, TYPE_LENGTH (regtype));
return value;
}
@@ -92,6 +93,7 @@ sentinel_frame_prev_arch (struct frame_i
const struct frame_unwind sentinel_frame_unwind =
{
SENTINEL_FRAME,
+ default_frame_unwind_stop_reason,
sentinel_frame_this_id,
sentinel_frame_prev_register,
NULL,
Index: src/gdb/alpha-mdebug-tdep.c
===================================================================
--- src.orig/gdb/alpha-mdebug-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/alpha-mdebug-tdep.c 2011-02-22 17:58:04.264708003 +0000
@@ -336,6 +336,7 @@ alpha_mdebug_frame_sniffer (const struct
static const struct frame_unwind alpha_mdebug_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
alpha_mdebug_frame_this_id,
alpha_mdebug_frame_prev_register,
NULL,
Index: src/gdb/alpha-tdep.c
===================================================================
--- src.orig/gdb/alpha-tdep.c 2011-02-22 17:57:49.000000000 +0000
+++ src/gdb/alpha-tdep.c 2011-02-22 17:58:04.264708003 +0000
@@ -936,6 +936,7 @@ alpha_sigtramp_frame_sniffer (const stru
static const struct frame_unwind alpha_sigtramp_frame_unwind = {
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
alpha_sigtramp_frame_this_id,
alpha_sigtramp_frame_prev_register,
NULL,
@@ -1351,6 +1352,7 @@ alpha_heuristic_frame_prev_register (str
static const struct frame_unwind alpha_heuristic_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
alpha_heuristic_frame_this_id,
alpha_heuristic_frame_prev_register,
NULL,
Index: src/gdb/amd64obsd-tdep.c
===================================================================
--- src.orig/gdb/amd64obsd-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/amd64obsd-tdep.c 2011-02-22 17:58:04.264708003 +0000
@@ -437,6 +437,7 @@ static const struct frame_unwind amd64ob
frame, but SIGTRAMP_FRAME would print <signal handler called>,
which really is not what we want here. */
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
amd64obsd_trapframe_this_id,
amd64obsd_trapframe_prev_register,
NULL,
Index: src/gdb/arm-tdep.c
===================================================================
--- src.orig/gdb/arm-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/arm-tdep.c 2011-02-22 17:58:04.264708003 +0000
@@ -2146,6 +2146,7 @@ arm_prologue_prev_register (struct frame
struct frame_unwind arm_prologue_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
arm_prologue_this_id,
arm_prologue_prev_register,
NULL,
@@ -2884,6 +2885,7 @@ arm_exidx_unwind_sniffer (const struct f
struct frame_unwind arm_exidx_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
arm_prologue_this_id,
arm_prologue_prev_register,
NULL,
@@ -2939,6 +2941,7 @@ arm_stub_unwind_sniffer (const struct fr
struct frame_unwind arm_stub_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
arm_stub_this_id,
arm_prologue_prev_register,
NULL,
Index: src/gdb/avr-tdep.c
===================================================================
--- src.orig/gdb/avr-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/avr-tdep.c 2011-02-22 17:58:04.264708003 +0000
@@ -1131,6 +1131,7 @@ avr_frame_prev_register (struct frame_in
static const struct frame_unwind avr_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
avr_frame_this_id,
avr_frame_prev_register,
NULL,
Index: src/gdb/cris-tdep.c
===================================================================
--- src.orig/gdb/cris-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/cris-tdep.c 2011-02-22 17:58:04.274708004 +0000
@@ -448,6 +448,7 @@ cris_sigtramp_frame_sniffer (const struc
static const struct frame_unwind cris_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
cris_sigtramp_frame_this_id,
cris_sigtramp_frame_prev_register,
NULL,
@@ -985,6 +986,7 @@ cris_push_dummy_call (struct gdbarch *gd
static const struct frame_unwind cris_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
cris_frame_this_id,
cris_frame_prev_register,
NULL,
Index: src/gdb/frv-linux-tdep.c
===================================================================
--- src.orig/gdb/frv-linux-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/frv-linux-tdep.c 2011-02-22 17:58:04.274708004 +0000
@@ -336,6 +336,7 @@ frv_linux_sigtramp_frame_sniffer (const
static const struct frame_unwind frv_linux_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
frv_linux_sigtramp_frame_this_id,
frv_linux_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/frv-tdep.c
===================================================================
--- src.orig/gdb/frv-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/frv-tdep.c 2011-02-22 17:58:04.274708004 +0000
@@ -1494,6 +1494,7 @@ frv_frame_prev_register (struct frame_in
static const struct frame_unwind frv_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
frv_frame_this_id,
frv_frame_prev_register,
NULL,
Index: src/gdb/h8300-tdep.c
===================================================================
--- src.orig/gdb/h8300-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/h8300-tdep.c 2011-02-22 17:58:04.274708004 +0000
@@ -526,6 +526,7 @@ h8300_frame_prev_register (struct frame_
static const struct frame_unwind h8300_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
h8300_frame_this_id,
h8300_frame_prev_register,
NULL,
Index: src/gdb/hppa-hpux-tdep.c
===================================================================
--- src.orig/gdb/hppa-hpux-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/hppa-hpux-tdep.c 2011-02-22 17:58:04.274708004 +0000
@@ -753,6 +753,7 @@ hppa_hpux_sigtramp_unwind_sniffer (const
static const struct frame_unwind hppa_hpux_sigtramp_frame_unwind = {
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
hppa_hpux_sigtramp_frame_this_id,
hppa_hpux_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/hppa-linux-tdep.c
===================================================================
--- src.orig/gdb/hppa-linux-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/hppa-linux-tdep.c 2011-02-22 17:58:04.274708004 +0000
@@ -314,6 +314,7 @@ hppa_linux_sigtramp_frame_sniffer (const
static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = {
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
hppa_linux_sigtramp_frame_this_id,
hppa_linux_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/hppa-tdep.c
===================================================================
--- src.orig/gdb/hppa-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/hppa-tdep.c 2011-02-22 17:58:04.274708004 +0000
@@ -2225,6 +2225,7 @@ hppa_frame_unwind_sniffer (const struct
static const struct frame_unwind hppa_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
hppa_frame_this_id,
hppa_frame_prev_register,
NULL,
@@ -2335,6 +2336,7 @@ hppa_fallback_frame_prev_register (struc
static const struct frame_unwind hppa_fallback_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
hppa_fallback_frame_this_id,
hppa_fallback_frame_prev_register,
NULL,
@@ -2431,6 +2433,7 @@ hppa_stub_unwind_sniffer (const struct f
static const struct frame_unwind hppa_stub_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
hppa_stub_frame_this_id,
hppa_stub_frame_prev_register,
NULL,
Index: src/gdb/i386obsd-tdep.c
===================================================================
--- src.orig/gdb/i386obsd-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/i386obsd-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -434,6 +434,7 @@ static const struct frame_unwind i386obs
frame, but SIGTRAMP_FRAME would print <signal handler called>,
which really is not what we want here. */
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
i386obsd_trapframe_this_id,
i386obsd_trapframe_prev_register,
NULL,
Index: src/gdb/ia64-tdep.c
===================================================================
--- src.orig/gdb/ia64-tdep.c 2011-02-22 17:57:49.000000000 +0000
+++ src/gdb/ia64-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -2175,6 +2175,7 @@ ia64_frame_prev_register (struct frame_i
static const struct frame_unwind ia64_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
&ia64_frame_this_id,
&ia64_frame_prev_register,
NULL,
@@ -2366,6 +2367,7 @@ ia64_sigtramp_frame_sniffer (const struc
static const struct frame_unwind ia64_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
ia64_sigtramp_frame_this_id,
ia64_sigtramp_frame_prev_register,
NULL,
@@ -3051,6 +3053,7 @@ ia64_libunwind_frame_sniffer (const stru
static const struct frame_unwind ia64_libunwind_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
ia64_libunwind_frame_this_id,
ia64_libunwind_frame_prev_register,
NULL,
@@ -3139,6 +3142,7 @@ ia64_libunwind_sigtramp_frame_sniffer (c
static const struct frame_unwind ia64_libunwind_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
ia64_libunwind_sigtramp_frame_this_id,
ia64_libunwind_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/iq2000-tdep.c
===================================================================
--- src.orig/gdb/iq2000-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/iq2000-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -436,6 +436,7 @@ iq2000_frame_this_id (struct frame_info
static const struct frame_unwind iq2000_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
iq2000_frame_this_id,
iq2000_frame_prev_register,
NULL,
Index: src/gdb/lm32-tdep.c
===================================================================
--- src.orig/gdb/lm32-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/lm32-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -496,6 +496,7 @@ lm32_frame_prev_register (struct frame_i
static const struct frame_unwind lm32_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
lm32_frame_this_id,
lm32_frame_prev_register,
NULL,
Index: src/gdb/m32c-tdep.c
===================================================================
--- src.orig/gdb/m32c-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/m32c-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -1960,6 +1960,7 @@ m32c_prev_register (struct frame_info *t
static const struct frame_unwind m32c_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
m32c_this_id,
m32c_prev_register,
NULL,
Index: src/gdb/m32r-linux-tdep.c
===================================================================
--- src.orig/gdb/m32r-linux-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/m32r-linux-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -305,6 +305,7 @@ m32r_linux_sigtramp_frame_sniffer (const
static const struct frame_unwind m32r_linux_sigtramp_frame_unwind = {
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
m32r_linux_sigtramp_frame_this_id,
m32r_linux_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/m32r-tdep.c
===================================================================
--- src.orig/gdb/m32r-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/m32r-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -876,6 +876,7 @@ m32r_frame_prev_register (struct frame_i
static const struct frame_unwind m32r_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
m32r_frame_this_id,
m32r_frame_prev_register,
NULL,
Index: src/gdb/m68hc11-tdep.c
===================================================================
--- src.orig/gdb/m68hc11-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/m68hc11-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -949,6 +949,7 @@ m68hc11_frame_prev_register (struct fram
static const struct frame_unwind m68hc11_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
m68hc11_frame_this_id,
m68hc11_frame_prev_register,
NULL,
Index: src/gdb/m68k-tdep.c
===================================================================
--- src.orig/gdb/m68k-tdep.c 2011-02-22 17:57:49.000000000 +0000
+++ src/gdb/m68k-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -976,6 +976,7 @@ m68k_frame_prev_register (struct frame_i
static const struct frame_unwind m68k_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
m68k_frame_this_id,
m68k_frame_prev_register,
NULL,
Index: src/gdb/m68klinux-tdep.c
===================================================================
--- src.orig/gdb/m68klinux-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/m68klinux-tdep.c 2011-02-22 17:58:04.284708000 +0000
@@ -328,6 +328,7 @@ m68k_linux_sigtramp_frame_sniffer (const
static const struct frame_unwind m68k_linux_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
m68k_linux_sigtramp_frame_this_id,
m68k_linux_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/m88k-tdep.c
===================================================================
--- src.orig/gdb/m88k-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/m88k-tdep.c 2011-02-22 17:58:04.294708001 +0000
@@ -749,6 +749,7 @@ m88k_frame_prev_register (struct frame_i
static const struct frame_unwind m88k_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
m88k_frame_this_id,
m88k_frame_prev_register,
NULL,
Index: src/gdb/mep-tdep.c
===================================================================
--- src.orig/gdb/mep-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/mep-tdep.c 2011-02-22 17:58:04.294708001 +0000
@@ -2094,6 +2094,7 @@ mep_frame_prev_register (struct frame_in
static const struct frame_unwind mep_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
mep_frame_this_id,
mep_frame_prev_register,
NULL,
Index: src/gdb/microblaze-tdep.c
===================================================================
--- src.orig/gdb/microblaze-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/microblaze-tdep.c 2011-02-22 17:58:04.294708001 +0000
@@ -521,6 +521,7 @@ microblaze_frame_prev_register (struct f
static const struct frame_unwind microblaze_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
microblaze_frame_this_id,
microblaze_frame_prev_register,
NULL,
Index: src/gdb/mips-tdep.c
===================================================================
--- src.orig/gdb/mips-tdep.c 2011-02-22 17:57:49.000000000 +0000
+++ src/gdb/mips-tdep.c 2011-02-22 17:58:04.294708001 +0000
@@ -2028,6 +2028,7 @@ mips_insn16_frame_sniffer (const struct
static const struct frame_unwind mips_insn16_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
mips_insn16_frame_this_id,
mips_insn16_frame_prev_register,
NULL,
@@ -2381,6 +2382,7 @@ mips_insn32_frame_sniffer (const struct
static const struct frame_unwind mips_insn32_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
mips_insn32_frame_this_id,
mips_insn32_frame_prev_register,
NULL,
@@ -2505,6 +2507,7 @@ mips_stub_frame_sniffer (const struct fr
static const struct frame_unwind mips_stub_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
mips_stub_frame_this_id,
mips_stub_frame_prev_register,
NULL,
Index: src/gdb/mn10300-tdep.c
===================================================================
--- src.orig/gdb/mn10300-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/mn10300-tdep.c 2011-02-22 17:58:04.294708001 +0000
@@ -1174,6 +1174,7 @@ mn10300_frame_prev_register (struct fram
static const struct frame_unwind mn10300_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
mn10300_frame_this_id,
mn10300_frame_prev_register,
NULL,
Index: src/gdb/moxie-tdep.c
===================================================================
--- src.orig/gdb/moxie-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/moxie-tdep.c 2011-02-22 17:58:04.294708001 +0000
@@ -461,6 +461,7 @@ moxie_frame_prev_register (struct frame_
static const struct frame_unwind moxie_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
moxie_frame_this_id,
moxie_frame_prev_register,
NULL,
Index: src/gdb/mt-tdep.c
===================================================================
--- src.orig/gdb/mt-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/mt-tdep.c 2011-02-22 17:58:04.294708001 +0000
@@ -1115,6 +1115,7 @@ mt_frame_base_address (struct frame_info
static const struct frame_unwind mt_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
mt_frame_this_id,
mt_frame_prev_register,
NULL,
Index: src/gdb/ppc-linux-tdep.c
===================================================================
--- src.orig/gdb/ppc-linux-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/ppc-linux-tdep.c 2011-02-22 17:58:04.304708002 +0000
@@ -1472,6 +1472,7 @@ ppu2spu_dealloc_cache (struct frame_info
static const struct frame_unwind ppu2spu_unwind = {
ARCH_FRAME,
+ default_frame_unwind_stop_reason,
ppu2spu_this_id,
ppu2spu_prev_register,
NULL,
Index: src/gdb/ppcobsd-tdep.c
===================================================================
--- src.orig/gdb/ppcobsd-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/ppcobsd-tdep.c 2011-02-22 17:58:04.304708002 +0000
@@ -239,6 +239,7 @@ ppcobsd_sigtramp_frame_prev_register (st
static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = {
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
ppcobsd_sigtramp_frame_this_id,
ppcobsd_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/rs6000-tdep.c
===================================================================
--- src.orig/gdb/rs6000-tdep.c 2011-02-22 17:57:49.000000000 +0000
+++ src/gdb/rs6000-tdep.c 2011-02-22 17:58:04.304708002 +0000
@@ -3319,6 +3319,7 @@ rs6000_frame_prev_register (struct frame
static const struct frame_unwind rs6000_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
rs6000_frame_this_id,
rs6000_frame_prev_register,
NULL,
Index: src/gdb/s390-tdep.c
===================================================================
--- src.orig/gdb/s390-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/s390-tdep.c 2011-02-22 17:58:04.304708002 +0000
@@ -1758,6 +1758,7 @@ s390_frame_prev_register (struct frame_i
static const struct frame_unwind s390_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
s390_frame_this_id,
s390_frame_prev_register,
NULL,
@@ -1841,6 +1842,7 @@ s390_stub_frame_sniffer (const struct fr
static const struct frame_unwind s390_stub_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
s390_stub_frame_this_id,
s390_stub_frame_prev_register,
NULL,
@@ -2032,6 +2034,7 @@ s390_sigtramp_frame_sniffer (const struc
static const struct frame_unwind s390_sigtramp_frame_unwind = {
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
s390_sigtramp_frame_this_id,
s390_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/score-tdep.c
===================================================================
--- src.orig/gdb/score-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/score-tdep.c 2011-02-22 17:58:04.304708002 +0000
@@ -1369,6 +1369,7 @@ score_prologue_prev_register (struct fra
static const struct frame_unwind score_prologue_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
score_prologue_this_id,
score_prologue_prev_register,
NULL,
Index: src/gdb/sh-tdep.c
===================================================================
--- src.orig/gdb/sh-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/sh-tdep.c 2011-02-22 17:58:04.304708002 +0000
@@ -2635,6 +2635,7 @@ sh_frame_this_id (struct frame_info *thi
static const struct frame_unwind sh_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
sh_frame_this_id,
sh_frame_prev_register,
NULL,
Index: src/gdb/sh64-tdep.c
===================================================================
--- src.orig/gdb/sh64-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/sh64-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -2437,6 +2437,7 @@ sh64_frame_this_id (struct frame_info *t
static const struct frame_unwind sh64_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
sh64_frame_this_id,
sh64_frame_prev_register,
NULL,
Index: src/gdb/sparc-sol2-tdep.c
===================================================================
--- src.orig/gdb/sparc-sol2-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/sparc-sol2-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -164,6 +164,7 @@ sparc32_sol2_sigtramp_frame_sniffer (con
static const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
sparc32_sol2_sigtramp_frame_this_id,
sparc32_sol2_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/sparc-tdep.c
===================================================================
--- src.orig/gdb/sparc-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/sparc-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -1031,6 +1031,7 @@ sparc32_frame_prev_register (struct fram
static const struct frame_unwind sparc32_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
sparc32_frame_this_id,
sparc32_frame_prev_register,
NULL,
Index: src/gdb/sparc64-sol2-tdep.c
===================================================================
--- src.orig/gdb/sparc64-sol2-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/sparc64-sol2-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -141,6 +141,7 @@ sparc64_sol2_sigtramp_frame_sniffer (con
static const struct frame_unwind sparc64_sol2_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
sparc64_sol2_sigtramp_frame_this_id,
sparc64_sol2_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/sparc64-tdep.c
===================================================================
--- src.orig/gdb/sparc64-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/sparc64-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -562,6 +562,7 @@ sparc64_frame_prev_register (struct fram
static const struct frame_unwind sparc64_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
sparc64_frame_this_id,
sparc64_frame_prev_register,
NULL,
Index: src/gdb/sparc64fbsd-tdep.c
===================================================================
--- src.orig/gdb/sparc64fbsd-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/sparc64fbsd-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -202,6 +202,7 @@ sparc64fbsd_sigtramp_frame_sniffer (cons
static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
sparc64fbsd_sigtramp_frame_this_id,
sparc64fbsd_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/sparc64nbsd-tdep.c
===================================================================
--- src.orig/gdb/sparc64nbsd-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/sparc64nbsd-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -230,6 +230,7 @@ sparc64nbsd_sigtramp_frame_sniffer (cons
static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
sparc64nbsd_sigcontext_frame_this_id,
sparc64nbsd_sigcontext_frame_prev_register,
NULL,
Index: src/gdb/sparc64obsd-tdep.c
===================================================================
--- src.orig/gdb/sparc64obsd-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/sparc64obsd-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -195,6 +195,7 @@ sparc64obsd_sigtramp_frame_sniffer (cons
static const struct frame_unwind sparc64obsd_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
sparc64obsd_frame_this_id,
sparc64obsd_frame_prev_register,
NULL,
@@ -277,6 +278,7 @@ sparc64obsd_trapframe_sniffer (const str
static const struct frame_unwind sparc64obsd_trapframe_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
sparc64obsd_trapframe_this_id,
sparc64obsd_trapframe_prev_register,
NULL,
Index: src/gdb/sparcnbsd-tdep.c
===================================================================
--- src.orig/gdb/sparcnbsd-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/sparcnbsd-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -254,6 +254,7 @@ sparc32nbsd_sigcontext_frame_sniffer (co
static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
sparc32nbsd_sigcontext_frame_this_id,
sparc32nbsd_sigcontext_frame_prev_register,
NULL,
Index: src/gdb/sparcobsd-tdep.c
===================================================================
--- src.orig/gdb/sparcobsd-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/sparcobsd-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -139,6 +139,7 @@ sparc32obsd_sigtramp_frame_sniffer (cons
static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
sparc32obsd_sigtramp_frame_this_id,
sparc32obsd_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/spu-tdep.c
===================================================================
--- src.orig/gdb/spu-tdep.c 2011-02-22 17:57:49.000000000 +0000
+++ src/gdb/spu-tdep.c 2011-02-22 17:58:04.314708003 +0000
@@ -1082,6 +1082,7 @@ spu_frame_prev_register (struct frame_in
static const struct frame_unwind spu_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
spu_frame_this_id,
spu_frame_prev_register,
NULL,
@@ -1236,6 +1237,7 @@ spu2ppu_dealloc_cache (struct frame_info
static const struct frame_unwind spu2ppu_unwind = {
ARCH_FRAME,
+ default_frame_unwind_stop_reason,
spu2ppu_this_id,
spu2ppu_prev_register,
NULL,
Index: src/gdb/v850-tdep.c
===================================================================
--- src.orig/gdb/v850-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/v850-tdep.c 2011-02-22 17:58:04.324708004 +0000
@@ -935,6 +935,7 @@ v850_frame_this_id (struct frame_info *t
static const struct frame_unwind v850_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
v850_frame_this_id,
v850_frame_prev_register,
NULL,
Index: src/gdb/vax-tdep.c
===================================================================
--- src.orig/gdb/vax-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/vax-tdep.c 2011-02-22 17:58:04.324708004 +0000
@@ -402,6 +402,7 @@ vax_frame_prev_register (struct frame_in
static const struct frame_unwind vax_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
vax_frame_this_id,
vax_frame_prev_register,
NULL,
Index: src/gdb/vaxobsd-tdep.c
===================================================================
--- src.orig/gdb/vaxobsd-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/vaxobsd-tdep.c 2011-02-22 17:58:04.324708004 +0000
@@ -135,6 +135,7 @@ vaxobsd_sigtramp_frame_prev_register (st
static const struct frame_unwind vaxobsd_sigtramp_frame_unwind = {
SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
vaxobsd_sigtramp_frame_this_id,
vaxobsd_sigtramp_frame_prev_register,
NULL,
Index: src/gdb/xstormy16-tdep.c
===================================================================
--- src.orig/gdb/xstormy16-tdep.c 2011-02-22 17:11:07.000000000 +0000
+++ src/gdb/xstormy16-tdep.c 2011-02-22 17:58:04.324708004 +0000
@@ -742,6 +742,7 @@ xstormy16_frame_base_address (struct fra
static const struct frame_unwind xstormy16_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
xstormy16_frame_this_id,
xstormy16_frame_prev_register,
NULL,
Index: src/gdb/xtensa-tdep.c
===================================================================
--- src.orig/gdb/xtensa-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/xtensa-tdep.c 2011-02-22 17:58:04.324708004 +0000
@@ -1438,6 +1438,7 @@ static const struct frame_unwind
xtensa_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
xtensa_frame_this_id,
xtensa_frame_prev_register,
NULL,
Index: src/gdb/bfin-tdep.c
===================================================================
--- src.orig/gdb/bfin-tdep.c 2011-02-22 17:57:47.000000000 +0000
+++ src/gdb/bfin-tdep.c 2011-02-22 17:58:04.324708004 +0000
@@ -374,6 +374,7 @@ bfin_frame_prev_register (struct frame_i
static const struct frame_unwind bfin_frame_unwind =
{
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
bfin_frame_this_id,
bfin_frame_prev_register,
NULL,
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
2011-02-22 18:35 graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further Pedro Alves
@ 2011-02-28 15:42 ` Jan Kratochvil
2011-02-28 15:56 ` Pedro Alves
2011-03-18 20:21 ` Pedro Alves
` (3 subsequent siblings)
4 siblings, 1 reply; 15+ messages in thread
From: Jan Kratochvil @ 2011-02-28 15:42 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
On Tue, 22 Feb 2011 19:34:42 +0100, Pedro Alves wrote:
> This teaches GDB about terminating unwinding gracefully if
> unwind further we would need registers/memory that haven't
> been collected.
>
> Here's the result:
>
> (gdb) bt
> #0 begin (a=<unavailable>) at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:182
> #1 0x00000000004008ad in main (argc=1, argv=0x7fff0e22cf28, envp=0x7fff0e22cf38)
> at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:210
> #2 <unavailable> in ?? ()
> Backtrace stopped: Not enough registers or memory available to unwind further
In my case:
(gdb) tfind 0
Found trace frame 0, tracepoint 2
#0 f () at 1.c:11
11 v++;
(gdb) bt
#0 f () at 1.c:11
Backtrace stopped: Not enough registers or memory available to unwind further
(gdb)
That is without that <unavailable>. I think it is a bug.
Thanks,
Jan
$ ./gdb -nx -x ~/.gdbinit -ex 'target remote localhost:1234' ./gdbserver/1 -ex 'tb main' -ex c
GNU gdb (GDB) 7.2.50.20110228-cvs
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/jkratoch/redhat/gdb-clean/gdb/gdbserver/1...done.
Remote debugging using localhost:1234
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib64/ld-2.13.90.so.debug...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007fcc89596600 in _start () from /lib64/ld-linux-x86-64.so.2
Temporary breakpoint 1 at 0x4004aa: file 1.c, line 18.
Continuing.
Temporary breakpoint 1, main () at 1.c:18
18 f ();
(gdb) trace 11
Tracepoint 2 at 0x400480: file 1.c, line 11.
(gdb) actions
Enter actions for tracepoint 2, one per line.
End with a line saying just "end".
>collect v
>end
(gdb) tstart
(gdb) b b
Breakpoint 3 at 0x400478: file 1.c, line 6.
(gdb) c
Continuing.
Breakpoint 3, b () at 1.c:6
6 }
(gdb) tstop
(gdb) tstatus
Trace stopped by a tstop command.
Collected 9 trace frames.
Trace buffer has 5242691 bytes of 5242880 bytes free (0% full).
Trace will stop if GDB disconnects.
Not looking at any trace frame.
(gdb) tfind 0
Found trace frame 0, tracepoint 2
#0 f () at 1.c:11
11 v++;
(gdb) bt
#0 f () at 1.c:11
Backtrace stopped: Not enough registers or memory available to unwind further
(gdb)
$ ./gdbserver :1234 ./1
Process ./1 created; pid = 20703
Listening on port 1234
Remote debugging from host 127.0.0.1
1:int v = 1;
2:int q = 1;
3:void
4:b (void)
5:{
6:}
7:int
8:f (void)
9:{
10: while (v < 10)
11: v++;
12: b ();
13: return 5;
14:}
15:int
16:main (void)
17:{
18: f ();
19: return 0;
20:}
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
2011-02-28 15:42 ` Jan Kratochvil
@ 2011-02-28 15:56 ` Pedro Alves
2011-02-28 18:50 ` Jan Kratochvil
0 siblings, 1 reply; 15+ messages in thread
From: Pedro Alves @ 2011-02-28 15:56 UTC (permalink / raw)
To: gdb-patches; +Cc: Jan Kratochvil
On Monday 28 February 2011 15:41:32, Jan Kratochvil wrote:
> In my case:
>
> (gdb) tfind 0
> Found trace frame 0, tracepoint 2
> #0 f () at 1.c:11
> 11 v++;
> (gdb) bt
> #0 f () at 1.c:11
> Backtrace stopped: Not enough registers or memory available to unwind further
> (gdb)
>
> That is without that <unavailable>. I think it is a bug.
That's expected. In my example, the _PC_ was not
unwoundable in the outermost unwindable frame, but other
registers were. In your example, it was, and I'm going
to guess that since you haven't collected any registers,
you're seeing the dwarf unwinder not being able to compute
the CFA.
In my example, notice info registers in the outermost
frame:
(gdb) bt
#0 begin () at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:180
#1 0x0000000000400b69 in main (argc=1, argv=0x7fffa180ace8, envp=0x7fffa180acf8) at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:329
#2 <unavailable> in ?? ()
Backtrace stopped: Not enough registers or memory available to unwind further
(gdb) up
#1 0x0000000000400b69 in main (argc=1, argv=0x7fffa180ace8, envp=0x7fffa180acf8) at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:329
329 begin ();
(gdb)
#2 <unavailable> in ?? ()
(gdb) info registers
rax 0x7fa45460eec8 140343767002824
rbx 0x0 0
rcx 0x5 5
rdx 0x7fffa180acf8 140735902952696
rsi 0x7fffa180ace8 140735902952680
rdi 0x1 1
rbp *value not available*
rsp 0x7fffa180ac10 0x7fffa180ac10
r8 0x7fa45460d300 140343766995712
r9 0x7fa454dc05c0 140343775069632
r10 0x7fffa180a8f0 140735902951664
r11 0x7fa4542c8770 140343763568496
r12 0x4006b0 4196016
r13 0x7fffa180ace0 140735902952672
r14 0x0 0
r15 0x0 0
rip *value not available*
eflags 0x203 [ CF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
--
Pedro Alves
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
2011-02-28 15:56 ` Pedro Alves
@ 2011-02-28 18:50 ` Jan Kratochvil
0 siblings, 0 replies; 15+ messages in thread
From: Jan Kratochvil @ 2011-02-28 18:50 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
On Mon, 28 Feb 2011 16:55:56 +0100, Pedro Alves wrote:
> That's expected. In my example, the _PC_ was not
> unwoundable in the outermost unwindable frame, but other
> registers were. In your example, it was, and I'm going
> to guess that since you haven't collected any registers,
> you're seeing the dwarf unwinder not being able to compute
> the CFA.
OK, I see now that explains it.
Thanks,
Jan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
2011-02-22 18:35 graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further Pedro Alves
2011-02-28 15:42 ` Jan Kratochvil
@ 2011-03-18 20:21 ` Pedro Alves
2011-03-21 10:09 ` Regression: " Jan Kratochvil
` (2 subsequent siblings)
4 siblings, 0 replies; 15+ messages in thread
From: Pedro Alves @ 2011-03-18 20:21 UTC (permalink / raw)
To: gdb-patches
I've checked this one in as well.
On Tuesday 22 February 2011 18:34:42, Pedro Alves wrote:
> This patch applies on top of the "unavailable regs/locals"
> series, starting at:
> <http://sourceware.org/ml/gdb-patches/2011-02/msg00581.html>.
>
> This teaches GDB about terminating unwinding gracefully if
> unwind further we would need registers/memory that haven't
> been collected.
>
> Here's the result:
>
> (gdb) bt
> #0 begin (a=<unavailable>) at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:182
> #1 0x00000000004008ad in main (argc=1, argv=0x7fff0e22cf28, envp=0x7fff0e22cf38)
> at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:210
> #2 <unavailable> in ?? ()
> Backtrace stopped: Not enough registers or memory available to unwind further
>
> I think I've implemented this differently in about 10
> different ways. This is the design that I ended up with and
> that I think is best.
>
> - when we sniff unwinders trying to find a matching unwinder,
> we catch NOT_AVAILABLE_ERRORS. If the PC is unavailable,
> it is impossible to determine if a given non-prologue parser unwinder
> would have been the best unwinder or not. By catching
> NOT_AVAILABLE_ERRORS, we don't have too touch many sniffers.
> When sniffing, they just read whatever minimum data they
> require to determine they're the correct unwinder. If
> any of that is unavailable, we'll hit an exception. So what
> this means is that sniffer code does not try to check if a
> given _required_ value is available --- it just goes ahead and
> reads it.
>
> - adds a new frame_unwind method, to make it possible for an unwinder
> to tell the core frame code that it can't unwind further. The
> concept here, is that if we are able to tell a given unwinder
> would be the best unwinder, select it, even if actually trying to
> unwind from it wouldn't work due to unavailable data. E.g., if
> all we have available is the PC, we'll be able to tell that we
> have dwarf unwind info for that frame. But if we then find out
> that we don't have enough registers/memory to compute the CFA, we know
> we aren't going to be able to unwind. We _don't_ fallback to
> prologue parsing in such cases, since if we couldn't unwind with
> the precise unwind info missing, prologue parsing is surely not
> going to be able to unwind correctly.
>
> - this new method incidently allows cleanly reporting to the core
> frame machinery when a frame is the outermost, without resorting
> to hacks in the frame_id, which opens the door to fixing a
> corner case with stepping through the outermost frame when there's
> no debug info. I won't be implementing that, it just paves the way.
>
> - the prologue parsers then need to be made aware that they may trip
> on necessary registers (e.g., PC / SP / FP) unavailable to unwine,
> and that they should return that they can't unwind further in
> the new frame_unwind method in that case. I've taught the x86
> and x64_64 unwinders, but not all others. I did do the mechanical
> work of adjusting all of them to the new interface, so that
> --enable-targets=all still builds, and so that they continue working
> as today. Theaching other prologue unwinders how to terminate
> gracefully with UNWIND_UNAVAILABLE is only interesting when a
> corresponding target supports tracepoints on that architecture, so
> it can be enabled on a case by case basis.
--
Pedro Alves
^ permalink raw reply [flat|nested] 15+ messages in thread
* Regression: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
2011-02-22 18:35 graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further Pedro Alves
2011-02-28 15:42 ` Jan Kratochvil
2011-03-18 20:21 ` Pedro Alves
@ 2011-03-21 10:09 ` Jan Kratochvil
2011-03-21 20:46 ` Pedro Alves
2011-03-22 14:40 ` Pedro Alves
2011-03-21 17:46 ` [commit] Fix tramp-frame.c crash (Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further) Ulrich Weigand
2011-03-31 14:43 ` [rfc] Fix broken i386 signal unwinding " Ulrich Weigand
4 siblings, 2 replies; 15+ messages in thread
From: Jan Kratochvil @ 2011-03-21 10:09 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Hi Pedro,
on a testfile from the Fedora patchset there is a regression, IMO a valid one:
e67dca4a095f4db1022fd0753ef0bda3873dc1bc is the first bad commit
commit e67dca4a095f4db1022fd0753ef0bda3873dc1bc
Author: Pedro Alves <pedro@codesourcery.com>
Date: Fri Mar 18 18:52:28 2011 +0000
gdb/
* frame.c (frame_unwind_register): Throw an error if unwinding the
register failed.
[...]
:040000 040000 6bdd3071cc91073d64ffd2a1030c44ce2b1956b9 a4487e736a1087aee5d5b5207cee5a56ae936f42 M gdb
bisect run success
http://pkgs.fedoraproject.org/gitweb/?p=gdb.git;a=blob_plain;f=gdb-6.8-bz457187-largefile-test.patch;hb=f15/master
= This file is included in this mail.
(gdb) x/i 0x400078
0x400078: hlt
PASS: gdb.arch/i386-biarch-core.exp: .text is readable
->
(gdb) x/i 0x400078
PC not available
FAIL: gdb.arch/i386-biarch-core.exp: .text is readable
The core file does not have accessible registers. It was not a goal of the
testcase, it tests something else. But it has found this unrelated
regression. I believe one should be able to evaluate PC-indepenent
expressions even if PC is not available.
Even the first part is regressing (although it stays PASS->PASS):
(gdb) core-file gdb.arch/i386-biarch-core.core
[New LWP 6901]
warning: Couldn't recognize general-purpose registers in core file.
Core was generated by `./bad'.
Program terminated with signal 11, Segmentation fault.
warning: Couldn't recognize general-purpose registers in core file.
#0 0x00000000 in ?? ()
->
(gdb) core-file gdb.arch/i386-biarch-core.core
[New LWP 6901]
warning: Couldn't recognize general-purpose registers in core file.
PC register is not available
The core file reason is not displayed while it could be, I have tried the
following patch does not help in this case:
[patch 3/3] Display core reasons even during thread error
http://sourceware.org/ml/gdb-patches/2011-02/msg00675.html
Thanks,
Jan
--- /dev/null 2009-04-19 14:49:00.974648389 +0200
+++ gdb-6.8/gdb/testsuite/gdb.arch/i386-biarch-core.exp 2009-04-19 16:30:12.000000000 +0200
@@ -0,0 +1,61 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Test ability to load an elf64-i386 core file. The provided core file was
+# elf64-x8664 one but it got binary patched to i386:
+# Elf32_Ehdr.e_machine @0x12..0x13
+# Elf64_Ehdr.e_machine @0x12..0x13
+# #define EM_386 3 /* Intel 80386 */
+# #define EM_X86_64 62 /* AMD x86-64 architecture */
+# patch @0x12: 0x3E -> 0x03
+
+if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } then {
+ verbose "Skipping i386-biarch-core test."
+ return
+}
+
+set testfile "i386-biarch-core"
+set corebz2uufile ${srcdir}/${subdir}/${testfile}.core.bz2.uu
+set corefile ${objdir}/${subdir}/${testfile}.core
+# Entry point of the original executable.
+set address 0x400078
+
+if {[catch "system \"uudecode -o - ${corebz2uufile} | bzip2 -dc >${corefile}\""] != 0} {
+ untested "failed uudecode or bzip2"
+ return -1
+}
+file stat ${corefile} corestat
+if {$corestat(size) != 102400} {
+ untested "uudecode or bzip2 produce invalid result"
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+# Wrongly built GDB complains by:
+# "..." is not a core dump: File format not recognized
+# As the provided test core has 64bit PRSTATUS i386 built GDB cannot parse it.
+# This is just a problem of the test care, real-world elf64-i386 file will have
+# 32bit PRSTATUS. One cannot prepare elf64-i386 core file from elf32-i386 by
+# objcopy as it corrupts the core file beyond all recognition.
+# "\r\nCore was generated by `\[^\r\n\]*'\\.\r\nProgram terminated with signal 11, Segmentation fault\\.\r\n.*"
+gdb_test "core-file ${corefile}"
+
+gdb_test "x/i $address" "\r\n\[ \t\]*$address:\[ \t\]*hlt\[ \t\]*" ".text is readable"
--- /dev/null 2009-04-19 14:49:00.974648389 +0200
+++ gdb-6.8/gdb/testsuite/gdb.arch/i386-biarch-core.S 2009-04-19 14:52:28.000000000 +0200
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2009 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+ .globl _start
+_start:
+ hlt
--- /dev/null 2009-04-19 14:49:00.974648389 +0200
+++ gdb-6.8/gdb/testsuite/gdb.arch/i386-biarch-core.core.bz2.uu 2009-04-19 15:02:12.000000000 +0200
@@ -0,0 +1,13 @@
+begin 600 i386-biarch-core.core.bz2
+M0EIH.3%!629361`P1\P`!)?_____\9'@"8Q)6P380'9@'&#`0D@``"``%(``
+M@`#`"!<(L`%F"(:$GH13::F-)M&D&U,AD:`--#)M0&FT0XR9--,)D9`P(Q-&
+M",(-&F``02)%38HT]0T`&AH```'H@``T^>9T*(,("&)SE`>`9@+GP=[,N)KB
+M'I8BL(L]N5TCY\%V]/?DB.BN*UZ'U@]TN7-]UJ5\_%0QTT<*086#%MHT7XVJ
+M9D"+C!"2*L:8D1XPD!`--M@*XT1H5RFYN&)(!0P0#:`I:;2;$5M&\*9"0@%:
+MK@X[T()M)9N7`D$VA!^63)%,;@8LT`(7\K&[7G;U:"B6'!GG+46ALOZF.2F-
+M!@>C*%86X$-]C2`KE;HG)UL(913VR2G]0BD:J=Z_`G@S,`W%.8RMS-#5P:J0
+MAJ2\8&X?@DE;UF68QHM<,D`('::J65/S:PAG*R-09["8DBI)'V]Y.[(/AM*L
+M"X_O^V;%FY.S6Q]FM=D37>5F,%4-F1ZF#,CFJVU;H*^IT<(%<V`.32$`JU["
+/G`68?\7<D4X4)`0,$?,`
+`
+end
^ permalink raw reply [flat|nested] 15+ messages in thread
* [commit] Fix tramp-frame.c crash (Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further)
2011-02-22 18:35 graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further Pedro Alves
` (2 preceding siblings ...)
2011-03-21 10:09 ` Regression: " Jan Kratochvil
@ 2011-03-21 17:46 ` Ulrich Weigand
2011-03-21 20:52 ` Pedro Alves
2011-03-31 14:43 ` [rfc] Fix broken i386 signal unwinding " Ulrich Weigand
4 siblings, 1 reply; 15+ messages in thread
From: Ulrich Weigand @ 2011-03-21 17:46 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Pedro Alves wrote:
> (struct frame_unwind) <stop_reason>: New function pointer.
It seems you initialized this field in all statically allocated frame_unwind
structures, but not in those dynamically allocated and returned from the
tramp_frame_prepend_unwinder routine. This causes crashes on all platforms
that use the tramp-frame.c framework ...
Fixed by the following patch.
Tested on powerpc64-linux, committed to mainline.
Bye,
Ulrich
ChangeLog:
* tramp-frame.c (tramp_frame_prepend_unwinder): Set stop_reason
field in returned unwinder.
Index: gdb/tramp-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/tramp-frame.c,v
retrieving revision 1.21
diff -u -p -r1.21 tramp-frame.c
--- gdb/tramp-frame.c 1 Jan 2011 15:33:18 -0000 1.21
+++ gdb/tramp-frame.c 21 Mar 2011 17:14:17 -0000
@@ -163,6 +163,7 @@ tramp_frame_prepend_unwinder (struct gdb
unwinder->type = tramp_frame->frame_type;
unwinder->unwind_data = data;
unwinder->sniffer = tramp_frame_sniffer;
+ unwinder->stop_reason = default_frame_unwind_stop_reason;
unwinder->this_id = tramp_frame_this_id;
unwinder->prev_register = tramp_frame_prev_register;
frame_unwind_prepend_unwinder (gdbarch, unwinder);
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Regression: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
2011-03-21 10:09 ` Regression: " Jan Kratochvil
@ 2011-03-21 20:46 ` Pedro Alves
2011-03-22 14:40 ` Pedro Alves
1 sibling, 0 replies; 15+ messages in thread
From: Pedro Alves @ 2011-03-21 20:46 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches
Thanks Jan. I'll take a look as soon as possible.
--
Pedro Alves
On Sunday 20 March 2011 18:48:45, Jan Kratochvil wrote:
> Hi Pedro,
>
> on a testfile from the Fedora patchset there is a regression, IMO a valid one:
>
> e67dca4a095f4db1022fd0753ef0bda3873dc1bc is the first bad commit
> commit e67dca4a095f4db1022fd0753ef0bda3873dc1bc
> Author: Pedro Alves <pedro@codesourcery.com>
> Date: Fri Mar 18 18:52:28 2011 +0000
>
> gdb/
> * frame.c (frame_unwind_register): Throw an error if unwinding the
> register failed.
> [...]
> :040000 040000 6bdd3071cc91073d64ffd2a1030c44ce2b1956b9 a4487e736a1087aee5d5b5207cee5a56ae936f42 M gdb
> bisect run success
>
> http://pkgs.fedoraproject.org/gitweb/?p=gdb.git;a=blob_plain;f=gdb-6.8-bz457187-largefile-test.patch;hb=f15/master
> = This file is included in this mail.
>
> (gdb) x/i 0x400078
> 0x400078: hlt
> PASS: gdb.arch/i386-biarch-core.exp: .text is readable
> ->
> (gdb) x/i 0x400078
> PC not available
> FAIL: gdb.arch/i386-biarch-core.exp: .text is readable
>
> The core file does not have accessible registers. It was not a goal of the
> testcase, it tests something else. But it has found this unrelated
> regression. I believe one should be able to evaluate PC-indepenent
> expressions even if PC is not available.
>
>
> Even the first part is regressing (although it stays PASS->PASS):
> (gdb) core-file gdb.arch/i386-biarch-core.core
> [New LWP 6901]
> warning: Couldn't recognize general-purpose registers in core file.
> Core was generated by `./bad'.
> Program terminated with signal 11, Segmentation fault.
> warning: Couldn't recognize general-purpose registers in core file.
> #0 0x00000000 in ?? ()
> ->
> (gdb) core-file gdb.arch/i386-biarch-core.core
> [New LWP 6901]
> warning: Couldn't recognize general-purpose registers in core file.
> PC register is not available
>
> The core file reason is not displayed while it could be, I have tried the
> following patch does not help in this case:
> [patch 3/3] Display core reasons even during thread error
> http://sourceware.org/ml/gdb-patches/2011-02/msg00675.html
>
>
> Thanks,
> Jan
>
>
> --- /dev/null 2009-04-19 14:49:00.974648389 +0200
> +++ gdb-6.8/gdb/testsuite/gdb.arch/i386-biarch-core.exp 2009-04-19 16:30:12.000000000 +0200
> @@ -0,0 +1,61 @@
> +# This testcase is part of GDB, the GNU debugger.
> +
> +# Copyright 2009 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> +
> +# Test ability to load an elf64-i386 core file. The provided core file was
> +# elf64-x8664 one but it got binary patched to i386:
> +# Elf32_Ehdr.e_machine @0x12..0x13
> +# Elf64_Ehdr.e_machine @0x12..0x13
> +# #define EM_386 3 /* Intel 80386 */
> +# #define EM_X86_64 62 /* AMD x86-64 architecture */
> +# patch @0x12: 0x3E -> 0x03
> +
> +if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } then {
> + verbose "Skipping i386-biarch-core test."
> + return
> +}
> +
> +set testfile "i386-biarch-core"
> +set corebz2uufile ${srcdir}/${subdir}/${testfile}.core.bz2.uu
> +set corefile ${objdir}/${subdir}/${testfile}.core
> +# Entry point of the original executable.
> +set address 0x400078
> +
> +if {[catch "system \"uudecode -o - ${corebz2uufile} | bzip2 -dc >${corefile}\""] != 0} {
> + untested "failed uudecode or bzip2"
> + return -1
> +}
> +file stat ${corefile} corestat
> +if {$corestat(size) != 102400} {
> + untested "uudecode or bzip2 produce invalid result"
> + return -1
> +}
> +
> +gdb_exit
> +gdb_start
> +gdb_reinitialize_dir $srcdir/$subdir
> +
> +# Wrongly built GDB complains by:
> +# "..." is not a core dump: File format not recognized
> +# As the provided test core has 64bit PRSTATUS i386 built GDB cannot parse it.
> +# This is just a problem of the test care, real-world elf64-i386 file will have
> +# 32bit PRSTATUS. One cannot prepare elf64-i386 core file from elf32-i386 by
> +# objcopy as it corrupts the core file beyond all recognition.
> +# "\r\nCore was generated by `\[^\r\n\]*'\\.\r\nProgram terminated with signal 11, Segmentation fault\\.\r\n.*"
> +gdb_test "core-file ${corefile}"
> +
> +gdb_test "x/i $address" "\r\n\[ \t\]*$address:\[ \t\]*hlt\[ \t\]*" ".text is readable"
> --- /dev/null 2009-04-19 14:49:00.974648389 +0200
> +++ gdb-6.8/gdb/testsuite/gdb.arch/i386-biarch-core.S 2009-04-19 14:52:28.000000000 +0200
> @@ -0,0 +1,22 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> + Copyright 2009 Free Software Foundation, Inc.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 2 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program; if not, write to the Free Software
> + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> + .globl _start
> +_start:
> + hlt
> --- /dev/null 2009-04-19 14:49:00.974648389 +0200
> +++ gdb-6.8/gdb/testsuite/gdb.arch/i386-biarch-core.core.bz2.uu 2009-04-19 15:02:12.000000000 +0200
> @@ -0,0 +1,13 @@
> +begin 600 i386-biarch-core.core.bz2
> +M0EIH.3%!629361`P1\P`!)?_____\9'@"8Q)6P380'9@'&#`0D@``"``%(``
> +M@`#`"!<(L`%F"(:$GH13::F-)M&D&U,AD:`--#)M0&FT0XR9--,)D9`P(Q-&
> +M",(-&F``02)%38HT]0T`&AH```'H@``T^>9T*(,("&)SE`>`9@+GP=[,N)KB
> +M'I8BL(L]N5TCY\%V]/?DB.BN*UZ'U@]TN7-]UJ5\_%0QTT<*086#%MHT7XVJ
> +M9D"+C!"2*L:8D1XPD!`--M@*XT1H5RFYN&)(!0P0#:`I:;2;$5M&\*9"0@%:
> +MK@X[T()M)9N7`D$VA!^63)%,;@8LT`(7\K&[7G;U:"B6'!GG+46ALOZF.2F-
> +M!@>C*%86X$-]C2`KE;HG)UL(913VR2G]0BD:J=Z_`G@S,`W%.8RMS-#5P:J0
> +MAJ2\8&X?@DE;UF68QHM<,D`('::J65/S:PAG*R-09["8DBI)'V]Y.[(/AM*L
> +M"X_O^V;%FY.S6Q]FM=D37>5F,%4-F1ZF#,CFJVU;H*^IT<(%<V`.32$`JU["
> +/G`68?\7<D4X4)`0,$?,`
> +`
> +end
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [commit] Fix tramp-frame.c crash (Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further)
2011-03-21 17:46 ` [commit] Fix tramp-frame.c crash (Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further) Ulrich Weigand
@ 2011-03-21 20:52 ` Pedro Alves
0 siblings, 0 replies; 15+ messages in thread
From: Pedro Alves @ 2011-03-21 20:52 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: gdb-patches
On Monday 21 March 2011 17:24:45, Ulrich Weigand wrote:
> Pedro Alves wrote:
>
> > (struct frame_unwind) <stop_reason>: New function pointer.
>
> It seems you initialized this field in all statically allocated frame_unwind
> structures, but not in those dynamically allocated and returned from the
> tramp_frame_prepend_unwinder routine. This causes crashes on all platforms
> that use the tramp-frame.c framework ...
Whoops, sorry about that.
> Fixed by the following patch.
Thanks!
--
Pedro Alves
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Regression: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
2011-03-21 10:09 ` Regression: " Jan Kratochvil
2011-03-21 20:46 ` Pedro Alves
@ 2011-03-22 14:40 ` Pedro Alves
2011-03-22 15:36 ` Jan Kratochvil
1 sibling, 1 reply; 15+ messages in thread
From: Pedro Alves @ 2011-03-22 14:40 UTC (permalink / raw)
To: gdb-patches; +Cc: Jan Kratochvil
On Sunday 20 March 2011 18:48:45, Jan Kratochvil wrote:
> Hi Pedro,
>
> on a testfile from the Fedora patchset there is a regression, IMO a valid one:
Agreed.
> http://pkgs.fedoraproject.org/gitweb/?p=gdb.git;a=blob_plain;f=gdb-6.8-bz457187-largefile-test.patch;hb=f15/master
> = This file is included in this mail.
Thanks!
> The core file does not have accessible registers. It was not a goal of the
> testcase, it tests something else. But it has found this unrelated
> regression.
Yeah, nice test.
> (gdb) x/i 0x400078
> 0x400078: hlt
> PASS: gdb.arch/i386-biarch-core.exp: .text is readable
> ->
> (gdb) x/i 0x400078
> PC not available
> FAIL: gdb.arch/i386-biarch-core.exp: .text is readable
> I believe one should be able to evaluate PC-indepenent
> expressions even if PC is not available.
Yep, and you can. The quirk is x/i / disassemble specific. The
error is thrown while trying to decide whether to print the "==>" that
indicates the current PC.
> Even the first part is regressing (although it stays PASS->PASS):
> (gdb) core-file gdb.arch/i386-biarch-core.core
> [New LWP 6901]
> warning: Couldn't recognize general-purpose registers in core file.
> Core was generated by `./bad'.
> Program terminated with signal 11, Segmentation fault.
> warning: Couldn't recognize general-purpose registers in core file.
> #0 0x00000000 in ?? ()
> ->
> (gdb) core-file gdb.arch/i386-biarch-core.core
> [New LWP 6901]
> warning: Couldn't recognize general-purpose registers in core file.
> PC register is not available
Fixed as well. After the patch:
(...)
warning: Couldn't recognize general-purpose registers in core file.
Core was generated by `./bad'.
Program terminated with signal 11, Segmentation fault.
warning: Couldn't recognize general-purpose registers in core file.
#0 <unavailable> in ?? ()
(gdb)
and:
(gdb) x/i 0x400078
0x400078: hlt
Below's the patch. Doesn't cause regressions for me.
Did you see any other regression?
Thanks,
Pedro Alves
2011-03-27 Pedro Alves <pedro@codesourcery.com>
* infcmd.c (post_create_inferior): Ignore NOT_AVAILABLE_ERROR
errors when reading the `stop_pc'.
* printcmd.c (pc_prefix): Use get_frame_pc_if_available instead of
get_frame_pc.
---
gdb/infcmd.c | 14 ++++++++++++--
gdb/printcmd.c | 4 +---
2 files changed, 13 insertions(+), 5 deletions(-)
Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c 2011-03-15 20:15:05.000000000 +0000
+++ src/gdb/infcmd.c 2011-03-22 10:22:17.729088002 +0000
@@ -395,6 +395,8 @@ strip_bg_char (char **args)
void
post_create_inferior (struct target_ops *target, int from_tty)
{
+ volatile struct gdb_exception ex;
+
/* Be sure we own the terminal in case write operations are performed. */
target_terminal_ours ();
@@ -404,8 +406,16 @@ post_create_inferior (struct target_ops
don't need to. */
target_find_description ();
- /* Now that we know the register layout, retrieve current PC. */
- stop_pc = regcache_read_pc (get_current_regcache ());
+ /* Now that we know the register layout, retrieve current PC. But
+ if the PC is unavailable (e.g., we're opening a core file with
+ missing registers info), ignore it. */
+ stop_pc = 0;
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ stop_pc = regcache_read_pc (get_current_regcache ());
+ }
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
if (exec_bfd)
{
Index: src/gdb/printcmd.c
===================================================================
--- src.orig/gdb/printcmd.c 2011-03-15 20:15:34.000000000 +0000
+++ src/gdb/printcmd.c 2011-03-22 10:21:41.829088002 +0000
@@ -759,9 +759,7 @@ pc_prefix (CORE_ADDR addr)
CORE_ADDR pc;
frame = get_selected_frame (NULL);
- pc = get_frame_pc (frame);
-
- if (pc == addr)
+ if (get_frame_pc_if_available (frame, &pc) && pc == addr)
return "=> ";
}
return " ";
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Regression: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
2011-03-22 14:40 ` Pedro Alves
@ 2011-03-22 15:36 ` Jan Kratochvil
2011-03-22 16:19 ` Pedro Alves
0 siblings, 1 reply; 15+ messages in thread
From: Jan Kratochvil @ 2011-03-22 15:36 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
On Tue, 22 Mar 2011 12:13:16 +0100, Pedro Alves wrote:
> Yep, and you can. The quirk is x/i / disassemble specific. The
> error is thrown while trying to decide whether to print the "==>" that
> indicates the current PC.
Aha.
> Below's the patch. Doesn't cause regressions for me.
I can confirm it works here as proclaimed. Please check it in.
> Did you see any other regression?
No.
Thanks,
Jan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Regression: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
2011-03-22 15:36 ` Jan Kratochvil
@ 2011-03-22 16:19 ` Pedro Alves
0 siblings, 0 replies; 15+ messages in thread
From: Pedro Alves @ 2011-03-22 16:19 UTC (permalink / raw)
To: gdb-patches; +Cc: Jan Kratochvil
On Tuesday 22 March 2011 13:21:59, Jan Kratochvil wrote:
> On Tue, 22 Mar 2011 12:13:16 +0100, Pedro Alves wrote:
> > Below's the patch. Doesn't cause regressions for me.
>
> I can confirm it works here as proclaimed. Please check it in.
Great, done.
Thanks.
--
Pedro Alves
^ permalink raw reply [flat|nested] 15+ messages in thread
* [rfc] Fix broken i386 signal unwinding (Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further)
2011-02-22 18:35 graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further Pedro Alves
` (3 preceding siblings ...)
2011-03-21 17:46 ` [commit] Fix tramp-frame.c crash (Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further) Ulrich Weigand
@ 2011-03-31 14:43 ` Ulrich Weigand
2011-03-31 16:20 ` Pedro Alves
4 siblings, 1 reply; 15+ messages in thread
From: Ulrich Weigand @ 2011-03-31 14:43 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Pedro Alves wrote:
> (i386_frame_prev_register): Handle unavailable SP.
> - if (regnum == I386_ESP_REGNUM && cache->saved_sp)
> - return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
> + if (regnum == I386_ESP_REGNUM)
> + {
> + /* If the SP has been saved, but we don't know where, then this
> + means that SAVED_SP_REG register was found unavailable back
> + when we built the cache. */
> + if (cache->saved_sp == 0 && cache->saved_sp_reg != -1)
> + return frame_unwind_got_register (this_frame, regnum,
> + cache->saved_sp_reg);
> + else
> + return frame_unwind_got_constant (this_frame, regnum,
> + cache->saved_sp);
> + }
>
> if (regnum < I386_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1)
> return frame_unwind_got_memory (this_frame, regnum,
It seems this change broke unwinding out of signal trampoline
frames on i386 for me. In this case, neither SAVED_SP nor
SAVED_SP_REG is set; instead, SP is supposed to be unwound
from memory (the trampoline stack frame) via SAVED_REGS.
However, after your change, we now fall into the _got_constant
case and SP is always unwound as 0.
The following patch fixes this for me, and gets about 50 test
cases back to PASS.
Does this look right to you?
Tested on i386-linux (Ubuntu Lucid).
Bye,
Ulrich
ChangeLog:
* i386-tdep.c (i386_frame_prev_register): Unwind SP from memory
if neither saved value nor register available (e.g. signal frame).
Index: gdb/i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.330
diff -u -p -r1.330 i386-tdep.c
--- gdb/i386-tdep.c 18 Mar 2011 18:52:30 -0000 1.330
+++ gdb/i386-tdep.c 31 Mar 2011 13:50:07 -0000
@@ -1798,12 +1798,13 @@ i386_frame_prev_register (struct frame_i
if (regnum == I386_EIP_REGNUM && cache->pc_in_eax)
return frame_unwind_got_register (this_frame, regnum, I386_EAX_REGNUM);
- if (regnum == I386_ESP_REGNUM)
+ if (regnum == I386_ESP_REGNUM
+ && (cache->saved_sp != 0 || cache->saved_sp_reg != -1))
{
/* If the SP has been saved, but we don't know where, then this
means that SAVED_SP_REG register was found unavailable back
when we built the cache. */
- if (cache->saved_sp == 0 && cache->saved_sp_reg != -1)
+ if (cache->saved_sp == 0)
return frame_unwind_got_register (this_frame, regnum,
cache->saved_sp_reg);
else
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [rfc] Fix broken i386 signal unwinding (Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further)
2011-03-31 14:43 ` [rfc] Fix broken i386 signal unwinding " Ulrich Weigand
@ 2011-03-31 16:20 ` Pedro Alves
2011-03-31 16:23 ` [rfc] Fix broken i386 signal unwinding (Re: graceful unwind termination when we'd need unavailable/uncollect memory or regis Ulrich Weigand
0 siblings, 1 reply; 15+ messages in thread
From: Pedro Alves @ 2011-03-31 16:20 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: gdb-patches
On Thursday 31 March 2011 14:57:51, Ulrich Weigand wrote:
> It seems this change broke unwinding out of signal trampoline
> frames on i386 for me. In this case, neither SAVED_SP nor
> SAVED_SP_REG is set; instead, SP is supposed to be unwound
> from memory (the trampoline stack frame) via SAVED_REGS.
>
> However, after your change, we now fall into the _got_constant
> case and SP is always unwound as 0.
>
> The following patch fixes this for me, and gets about 50 test
> cases back to PASS.
>
> Does this look right to you?
Yes it does. Thanks much for tracking and fixing it.
--
Pedro Alves
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [rfc] Fix broken i386 signal unwinding (Re: graceful unwind termination when we'd need unavailable/uncollect memory or regis
2011-03-31 16:20 ` Pedro Alves
@ 2011-03-31 16:23 ` Ulrich Weigand
0 siblings, 0 replies; 15+ messages in thread
From: Ulrich Weigand @ 2011-03-31 16:23 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, patches
Pedro Alves wrote:
> On Thursday 31 March 2011 14:57:51, Ulrich Weigand wrote:
> > It seems this change broke unwinding out of signal trampoline
> > frames on i386 for me. In this case, neither SAVED_SP nor
> > SAVED_SP_REG is set; instead, SP is supposed to be unwound
> > from memory (the trampoline stack frame) via SAVED_REGS.
> >
> > However, after your change, we now fall into the _got_constant
> > case and SP is always unwound as 0.
> >
> > The following patch fixes this for me, and gets about 50 test
> > cases back to PASS.
> >
> > Does this look right to you?
>
> Yes it does. Thanks much for tracking and fixing it.
OK, I've checked this in now.
Thanks,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2011-03-31 16:19 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-22 18:35 graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further Pedro Alves
2011-02-28 15:42 ` Jan Kratochvil
2011-02-28 15:56 ` Pedro Alves
2011-02-28 18:50 ` Jan Kratochvil
2011-03-18 20:21 ` Pedro Alves
2011-03-21 10:09 ` Regression: " Jan Kratochvil
2011-03-21 20:46 ` Pedro Alves
2011-03-22 14:40 ` Pedro Alves
2011-03-22 15:36 ` Jan Kratochvil
2011-03-22 16:19 ` Pedro Alves
2011-03-21 17:46 ` [commit] Fix tramp-frame.c crash (Re: graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further) Ulrich Weigand
2011-03-21 20:52 ` Pedro Alves
2011-03-31 14:43 ` [rfc] Fix broken i386 signal unwinding " Ulrich Weigand
2011-03-31 16:20 ` Pedro Alves
2011-03-31 16:23 ` [rfc] Fix broken i386 signal unwinding (Re: graceful unwind termination when we'd need unavailable/uncollect memory or regis Ulrich Weigand
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).