|
|
2c2fa1 |
NOTE: The testcase part of this patch has been removed.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
commit 5ce0145de764dc9c6e92daf2f843fa6e496c49d0
|
|
|
2c2fa1 |
Author: Pedro Alves <palves@redhat.com>
|
|
|
2c2fa1 |
Date: Tue Dec 17 20:47:36 2013 +0000
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
"tfind" across unavailable-stack frames.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
Like when stepping, the current stack frame location is expected to be
|
|
|
2c2fa1 |
printed as result of tfind command, if that results in moving to a
|
|
|
2c2fa1 |
different function. In tfind_1 we see:
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
if (from_tty
|
|
|
2c2fa1 |
&& (has_stack_frames () || traceframe_number >= 0))
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
enum print_what print_what;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
/* NOTE: in imitation of the step command, try to determine
|
|
|
2c2fa1 |
whether we have made a transition from one function to
|
|
|
2c2fa1 |
another. If so, we'll print the "stack frame" (ie. the new
|
|
|
2c2fa1 |
function and it's arguments) -- otherwise we'll just show the
|
|
|
2c2fa1 |
new source line. */
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
if (frame_id_eq (old_frame_id,
|
|
|
2c2fa1 |
get_frame_id (get_current_frame ())))
|
|
|
2c2fa1 |
print_what = SRC_LINE;
|
|
|
2c2fa1 |
else
|
|
|
2c2fa1 |
print_what = SRC_AND_LOC;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
print_stack_frame (get_selected_frame (NULL), 1, print_what, 1);
|
|
|
2c2fa1 |
do_displays ();
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
However, when we haven't collected any registers in the tracepoint
|
|
|
2c2fa1 |
(collect $regs), that doesn't actually work:
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
(gdb) tstart
|
|
|
2c2fa1 |
(gdb) info tracepoints
|
|
|
2c2fa1 |
Num Type Disp Enb Address What
|
|
|
2c2fa1 |
1 tracepoint keep y 0x080483b7 in func0
|
|
|
2c2fa1 |
at ../.././../git/gdb/testsuite/gdb.trace/circ.c:28
|
|
|
2c2fa1 |
collect testload
|
|
|
2c2fa1 |
installed on target
|
|
|
2c2fa1 |
2 tracepoint keep y 0x080483bc in func1
|
|
|
2c2fa1 |
at ../.././../git/gdb/testsuite/gdb.trace/circ.c:32
|
|
|
2c2fa1 |
collect testload
|
|
|
2c2fa1 |
installed on target
|
|
|
2c2fa1 |
(gdb) c
|
|
|
2c2fa1 |
Continuing.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
Breakpoint 3, end () at ../.././../git/gdb/testsuite/gdb.trace/circ.c:72
|
|
|
2c2fa1 |
72 }
|
|
|
2c2fa1 |
(gdb) tstop
|
|
|
2c2fa1 |
(gdb) tfind start
|
|
|
2c2fa1 |
Found trace frame 0, tracepoint 1
|
|
|
2c2fa1 |
#0 func0 () at ../.././../git/gdb/testsuite/gdb.trace/circ.c:28
|
|
|
2c2fa1 |
28 }
|
|
|
2c2fa1 |
(gdb) tfind
|
|
|
2c2fa1 |
Found trace frame 1, tracepoint 2
|
|
|
2c2fa1 |
32 }
|
|
|
2c2fa1 |
(gdb)
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
When we don't have info about the stack available
|
|
|
2c2fa1 |
(UNWIND_UNAVAILABLE), frames end up with outer_frame_id as frame ID.
|
|
|
2c2fa1 |
And in the scenario above, the issue is that both frames before and
|
|
|
2c2fa1 |
after the second tfind (the frames for func0 an func1) have the same
|
|
|
2c2fa1 |
id (outer_frame_id), so the frame_id_eq check returns false, even
|
|
|
2c2fa1 |
though the frames were of different functions. GDB knows that,
|
|
|
2c2fa1 |
because the PC is inferred from the tracepoint's address, even if no
|
|
|
2c2fa1 |
registers were collected.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
To fix this, this patch adds support for frame ids with a valid code
|
|
|
2c2fa1 |
address, but <unavailable> stack address, and then makes the unwinders
|
|
|
2c2fa1 |
use that instead of the catch-all outer_frame_id for such frames. The
|
|
|
2c2fa1 |
frame_id_eq check in tfind_1 then automatically does the right thing
|
|
|
2c2fa1 |
as expected.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
I tested with --directory=gdb.trace/ , before/after the patch, and
|
|
|
2c2fa1 |
compared the resulting gdb.logs, then adjusted the tests to expect the
|
|
|
2c2fa1 |
extra output that came out. Turns out that was only circ.exp, the
|
|
|
2c2fa1 |
original test that actually brought this issue to light.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
Tested on x86_64 Fedora 17, native and gdbserver.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
gdb/
|
|
|
2c2fa1 |
2013-12-17 Pedro Alves <palves@redhat.com>
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
* frame.h (enum frame_id_stack_status): New enum.
|
|
|
2c2fa1 |
(struct frame_id) <stack_addr>: Adjust comment.
|
|
|
2c2fa1 |
<stack_addr_p>: Delete field, replaced with ...
|
|
|
2c2fa1 |
<stack_status>: ... this new field.
|
|
|
2c2fa1 |
(frame_id_build_unavailable_stack): Declare.
|
|
|
2c2fa1 |
* frame.c (frame_addr_hash, fprint_field, outer_frame_id)
|
|
|
2c2fa1 |
(frame_id_build_special): Adjust.
|
|
|
2c2fa1 |
(frame_id_build_unavailable_stack): New function.
|
|
|
2c2fa1 |
(frame_id_build, frame_id_build_wild): Adjust.
|
|
|
2c2fa1 |
(frame_id_p, frame_id_eq, frame_id_inner): Adjust to take into
|
|
|
2c2fa1 |
account frames with unavailable stack.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
* amd64-tdep.c (amd64_frame_this_id)
|
|
|
2c2fa1 |
(amd64_sigtramp_frame_this_id, amd64_epilogue_frame_this_id): Use
|
|
|
2c2fa1 |
frame_id_build_unavailable_stack.
|
|
|
2c2fa1 |
* dwarf2-frame.c (dwarf2_frame_this_id): Likewise.
|
|
|
2c2fa1 |
* i386-tdep.c (i386_frame_this_id, i386_epilogue_frame_this_id)
|
|
|
2c2fa1 |
(i386_sigtramp_frame_this_id): Likewise.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
gdb/testsuite/
|
|
|
2c2fa1 |
2013-12-17 Pedro Alves <palves@redhat.com>
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
* gdb.trace/circ.exp: Expect frame info to be printed when
|
|
|
2c2fa1 |
switching between frames with unavailable stack, but different
|
|
|
2c2fa1 |
functions.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/amd64-tdep.c
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/amd64-tdep.c
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/amd64-tdep.c
|
|
|
2c2fa1 |
@@ -2403,15 +2403,16 @@ amd64_frame_this_id (struct frame_info *
|
|
|
2c2fa1 |
struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
if (!cache->base_p)
|
|
|
2c2fa1 |
- return;
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- /* This marks the outermost frame. */
|
|
|
2c2fa1 |
- if (cache->base == 0)
|
|
|
2c2fa1 |
- return;
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- /* Detect OS dependent outermost frames; such as `clone'. */
|
|
|
2c2fa1 |
- if (tdep->outermost_frame_p && tdep->outermost_frame_p (this_frame))
|
|
|
2c2fa1 |
- return;
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build_unavailable_stack (cache->pc);
|
|
|
2c2fa1 |
+ else if (cache->base == 0)
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ /* This marks the outermost frame. */
|
|
|
2c2fa1 |
+ return;
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
+ else
|
|
|
2c2fa1 |
+ /* Detect OS dependent outermost frames; such as `clone'. */
|
|
|
2c2fa1 |
+ if (tdep->outermost_frame_p && tdep->outermost_frame_p (this_frame))
|
|
|
2c2fa1 |
+ return;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
(*this_id) = frame_id_build (cache->base + 16, cache->pc);
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
@@ -2528,9 +2529,14 @@ amd64_sigtramp_frame_this_id (struct fra
|
|
|
2c2fa1 |
amd64_sigtramp_frame_cache (this_frame, this_cache);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
if (!cache->base_p)
|
|
|
2c2fa1 |
- return;
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- (*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame));
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build_unavailable_stack (get_frame_pc (this_frame));
|
|
|
2c2fa1 |
+ else if (cache->base == 0)
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ /* This marks the outermost frame. */
|
|
|
2c2fa1 |
+ return;
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
+ else
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame));
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
static struct value *
|
|
|
2c2fa1 |
@@ -2699,9 +2705,9 @@ amd64_epilogue_frame_this_id (struct fra
|
|
|
2c2fa1 |
this_cache);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
if (!cache->base_p)
|
|
|
2c2fa1 |
- return;
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- (*this_id) = frame_id_build (cache->base + 8, cache->pc);
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build_unavailable_stack (cache->pc);
|
|
|
2c2fa1 |
+ else
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build (cache->base + 8, cache->pc);
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
static const struct frame_unwind amd64_epilogue_frame_unwind =
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/dwarf2-frame.c
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/dwarf2-frame.c
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/dwarf2-frame.c
|
|
|
2c2fa1 |
@@ -1265,12 +1265,11 @@ dwarf2_frame_this_id (struct frame_info
|
|
|
2c2fa1 |
dwarf2_frame_cache (this_frame, this_cache);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
if (cache->unavailable_retaddr)
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build_unavailable_stack (get_frame_func (this_frame));
|
|
|
2c2fa1 |
+ else if (cache->undefined_retaddr)
|
|
|
2c2fa1 |
return;
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- if (cache->undefined_retaddr)
|
|
|
2c2fa1 |
- return;
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- (*this_id) = frame_id_build (cache->cfa, get_frame_func (this_frame));
|
|
|
2c2fa1 |
+ else
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build (cache->cfa, get_frame_func (this_frame));
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
static struct value *
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/frame.c
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/frame.c
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/frame.c
|
|
|
2c2fa1 |
@@ -147,10 +147,11 @@ frame_addr_hash (const void *ap)
|
|
|
2c2fa1 |
const struct frame_id f_id = frame->this_id.value;
|
|
|
2c2fa1 |
hashval_t hash = 0;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
- gdb_assert (f_id.stack_addr_p || f_id.code_addr_p
|
|
|
2c2fa1 |
+ gdb_assert (f_id.stack_status != FID_STACK_INVALID
|
|
|
2c2fa1 |
+ || f_id.code_addr_p
|
|
|
2c2fa1 |
|| f_id.special_addr_p);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
- if (f_id.stack_addr_p)
|
|
|
2c2fa1 |
+ if (f_id.stack_status == FID_STACK_VALID)
|
|
|
2c2fa1 |
hash = iterative_hash (&f_id.stack_addr,
|
|
|
2c2fa1 |
sizeof (f_id.stack_addr), hash);
|
|
|
2c2fa1 |
if (f_id.code_addr_p)
|
|
|
2c2fa1 |
@@ -290,13 +291,23 @@ void
|
|
|
2c2fa1 |
fprint_frame_id (struct ui_file *file, struct frame_id id)
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
fprintf_unfiltered (file, "{");
|
|
|
2c2fa1 |
- fprint_field (file, "stack", id.stack_addr_p, id.stack_addr);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ if (id.stack_status == FID_STACK_INVALID)
|
|
|
2c2fa1 |
+ fprintf_unfiltered (file, "!stack");
|
|
|
2c2fa1 |
+ else if (id.stack_status == FID_STACK_UNAVAILABLE)
|
|
|
2c2fa1 |
+ fprintf_unfiltered (file, "stack=<unavailable>");
|
|
|
2c2fa1 |
+ else
|
|
|
2c2fa1 |
+ fprintf_unfiltered (file, "stack=%s", hex_string (id.stack_addr));
|
|
|
2c2fa1 |
fprintf_unfiltered (file, ",");
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
fprint_field (file, "code", id.code_addr_p, id.code_addr);
|
|
|
2c2fa1 |
fprintf_unfiltered (file, ",");
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
fprint_field (file, "special", id.special_addr_p, id.special_addr);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
if (id.artificial_depth)
|
|
|
2c2fa1 |
fprintf_unfiltered (file, ",artificial=%d", id.artificial_depth);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
fprintf_unfiltered (file, "}");
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
@@ -446,7 +457,7 @@ frame_unwind_caller_id (struct frame_inf
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
const struct frame_id null_frame_id; /* All zeros. */
|
|
|
2c2fa1 |
-const struct frame_id outer_frame_id = { 0, 0, 0, 0, 0, 1, 0 };
|
|
|
2c2fa1 |
+const struct frame_id outer_frame_id = { 0, 0, 0, FID_STACK_INVALID, 0, 1, 0 };
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
struct frame_id
|
|
|
2c2fa1 |
frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr,
|
|
|
2c2fa1 |
@@ -455,7 +466,7 @@ frame_id_build_special (CORE_ADDR stack_
|
|
|
2c2fa1 |
struct frame_id id = null_frame_id;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
id.stack_addr = stack_addr;
|
|
|
2c2fa1 |
- id.stack_addr_p = 1;
|
|
|
2c2fa1 |
+ id.stack_status = FID_STACK_VALID;
|
|
|
2c2fa1 |
id.code_addr = code_addr;
|
|
|
2c2fa1 |
id.code_addr_p = 1;
|
|
|
2c2fa1 |
id.special_addr = special_addr;
|
|
|
2c2fa1 |
@@ -463,13 +474,26 @@ frame_id_build_special (CORE_ADDR stack_
|
|
|
2c2fa1 |
return id;
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
+/* See frame.h. */
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+struct frame_id
|
|
|
2c2fa1 |
+frame_id_build_unavailable_stack (CORE_ADDR code_addr)
|
|
|
2c2fa1 |
+{
|
|
|
2c2fa1 |
+ struct frame_id id = null_frame_id;
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ id.stack_status = FID_STACK_UNAVAILABLE;
|
|
|
2c2fa1 |
+ id.code_addr = code_addr;
|
|
|
2c2fa1 |
+ id.code_addr_p = 1;
|
|
|
2c2fa1 |
+ return id;
|
|
|
2c2fa1 |
+}
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
struct frame_id
|
|
|
2c2fa1 |
frame_id_build (CORE_ADDR stack_addr, CORE_ADDR code_addr)
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
struct frame_id id = null_frame_id;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
id.stack_addr = stack_addr;
|
|
|
2c2fa1 |
- id.stack_addr_p = 1;
|
|
|
2c2fa1 |
+ id.stack_status = FID_STACK_VALID;
|
|
|
2c2fa1 |
id.code_addr = code_addr;
|
|
|
2c2fa1 |
id.code_addr_p = 1;
|
|
|
2c2fa1 |
return id;
|
|
|
2c2fa1 |
@@ -481,7 +505,7 @@ frame_id_build_wild (CORE_ADDR stack_add
|
|
|
2c2fa1 |
struct frame_id id = null_frame_id;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
id.stack_addr = stack_addr;
|
|
|
2c2fa1 |
- id.stack_addr_p = 1;
|
|
|
2c2fa1 |
+ id.stack_status = FID_STACK_VALID;
|
|
|
2c2fa1 |
return id;
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
@@ -491,7 +515,7 @@ frame_id_p (struct frame_id l)
|
|
|
2c2fa1 |
int p;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
/* The frame is valid iff it has a valid stack address. */
|
|
|
2c2fa1 |
- p = l.stack_addr_p;
|
|
|
2c2fa1 |
+ p = l.stack_status != FID_STACK_INVALID;
|
|
|
2c2fa1 |
/* outer_frame_id is also valid. */
|
|
|
2c2fa1 |
if (!p && memcmp (&l, &outer_frame_id, sizeof (l)) == 0)
|
|
|
2c2fa1 |
p = 1;
|
|
|
2c2fa1 |
@@ -518,19 +542,20 @@ frame_id_eq (struct frame_id l, struct f
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
int eq;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
- if (!l.stack_addr_p && l.special_addr_p
|
|
|
2c2fa1 |
- && !r.stack_addr_p && r.special_addr_p)
|
|
|
2c2fa1 |
+ if (l.stack_status == FID_STACK_INVALID && l.special_addr_p
|
|
|
2c2fa1 |
+ && r.stack_status == FID_STACK_INVALID && r.special_addr_p)
|
|
|
2c2fa1 |
/* The outermost frame marker is equal to itself. This is the
|
|
|
2c2fa1 |
dodgy thing about outer_frame_id, since between execution steps
|
|
|
2c2fa1 |
we might step into another function - from which we can't
|
|
|
2c2fa1 |
unwind either. More thought required to get rid of
|
|
|
2c2fa1 |
outer_frame_id. */
|
|
|
2c2fa1 |
eq = 1;
|
|
|
2c2fa1 |
- else if (!l.stack_addr_p || !r.stack_addr_p)
|
|
|
2c2fa1 |
+ else if (l.stack_status == FID_STACK_INVALID
|
|
|
2c2fa1 |
+ || r.stack_status == FID_STACK_INVALID)
|
|
|
2c2fa1 |
/* Like a NaN, if either ID is invalid, the result is false.
|
|
|
2c2fa1 |
Note that a frame ID is invalid iff it is the null frame ID. */
|
|
|
2c2fa1 |
eq = 0;
|
|
|
2c2fa1 |
- else if (l.stack_addr != r.stack_addr)
|
|
|
2c2fa1 |
+ else if (l.stack_status != r.stack_status || l.stack_addr != r.stack_addr)
|
|
|
2c2fa1 |
/* If .stack addresses are different, the frames are different. */
|
|
|
2c2fa1 |
eq = 0;
|
|
|
2c2fa1 |
else if (l.code_addr_p && r.code_addr_p && l.code_addr != r.code_addr)
|
|
|
2c2fa1 |
@@ -597,8 +622,9 @@ frame_id_inner (struct gdbarch *gdbarch,
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
int inner;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
- if (!l.stack_addr_p || !r.stack_addr_p)
|
|
|
2c2fa1 |
- /* Like NaN, any operation involving an invalid ID always fails. */
|
|
|
2c2fa1 |
+ if (l.stack_status != FID_STACK_VALID || r.stack_status != FID_STACK_VALID)
|
|
|
2c2fa1 |
+ /* Like NaN, any operation involving an invalid ID always fails.
|
|
|
2c2fa1 |
+ Likewise if either ID has an unavailable stack address. */
|
|
|
2c2fa1 |
inner = 0;
|
|
|
2c2fa1 |
else if (l.artificial_depth > r.artificial_depth
|
|
|
2c2fa1 |
&& l.stack_addr == r.stack_addr
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/frame.h
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/frame.h
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/frame.h
|
|
|
2c2fa1 |
@@ -76,6 +76,23 @@ struct block;
|
|
|
2c2fa1 |
struct gdbarch;
|
|
|
2c2fa1 |
struct ui_file;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
+/* Status of a given frame's stack. */
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+enum frame_id_stack_status
|
|
|
2c2fa1 |
+{
|
|
|
2c2fa1 |
+ /* Stack address is invalid. E.g., this frame is the outermost
|
|
|
2c2fa1 |
+ (i.e., _start), and the stack hasn't been setup yet. */
|
|
|
2c2fa1 |
+ FID_STACK_INVALID = 0,
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ /* Stack address is valid, and is found in the stack_addr field. */
|
|
|
2c2fa1 |
+ FID_STACK_VALID = 1,
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ /* Stack address is unavailable. I.e., there's a valid stack, but
|
|
|
2c2fa1 |
+ we don't know where it is (because memory or registers we'd
|
|
|
2c2fa1 |
+ compute it from were not collected). */
|
|
|
2c2fa1 |
+ FID_STACK_UNAVAILABLE = -1
|
|
|
2c2fa1 |
+};
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
/* The frame object. */
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
struct frame_info;
|
|
|
2c2fa1 |
@@ -97,8 +114,9 @@ struct frame_id
|
|
|
2c2fa1 |
function pointer register or stack pointer register. They are
|
|
|
2c2fa1 |
wrong.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
- This field is valid only if stack_addr_p is true. Otherwise, this
|
|
|
2c2fa1 |
- frame represents the null frame. */
|
|
|
2c2fa1 |
+ This field is valid only if frame_id.stack_status is
|
|
|
2c2fa1 |
+ FID_STACK_VALID. It will be 0 for other
|
|
|
2c2fa1 |
+ FID_STACK_... statuses. */
|
|
|
2c2fa1 |
CORE_ADDR stack_addr;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
/* The frame's code address. This shall be constant through out the
|
|
|
2c2fa1 |
@@ -129,7 +147,7 @@ struct frame_id
|
|
|
2c2fa1 |
CORE_ADDR special_addr;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
/* Flags to indicate the above fields have valid contents. */
|
|
|
2c2fa1 |
- unsigned int stack_addr_p : 1;
|
|
|
2c2fa1 |
+ ENUM_BITFIELD(frame_id_stack_status) stack_status : 2;
|
|
|
2c2fa1 |
unsigned int code_addr_p : 1;
|
|
|
2c2fa1 |
unsigned int special_addr_p : 1;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
@@ -169,6 +187,12 @@ extern struct frame_id frame_id_build_sp
|
|
|
2c2fa1 |
CORE_ADDR code_addr,
|
|
|
2c2fa1 |
CORE_ADDR special_addr);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
+/* Construct a frame ID representing a frame where the stack address
|
|
|
2c2fa1 |
+ exists, but is unavailable. CODE_ADDR is the frame's constant code
|
|
|
2c2fa1 |
+ address (typically the entry point). The special identifier
|
|
|
2c2fa1 |
+ address is set to indicate a wild card. */
|
|
|
2c2fa1 |
+extern struct frame_id frame_id_build_unavailable_stack (CORE_ADDR code_addr);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
/* Construct a wild card frame ID. The parameter is the frame's constant
|
|
|
2c2fa1 |
stack address (typically the outer-bound). The code address as well
|
|
|
2c2fa1 |
as the special identifier address are set to indicate wild cards. */
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/i386-tdep.c
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/i386-tdep.c
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/i386-tdep.c
|
|
|
2c2fa1 |
@@ -1846,12 +1846,17 @@ i386_frame_this_id (struct frame_info *t
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
- /* This marks the outermost frame. */
|
|
|
2c2fa1 |
- if (cache->base == 0)
|
|
|
2c2fa1 |
- return;
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- /* See the end of i386_push_dummy_call. */
|
|
|
2c2fa1 |
- (*this_id) = frame_id_build (cache->base + 8, cache->pc);
|
|
|
2c2fa1 |
+ if (!cache->base_p)
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build_unavailable_stack (cache->pc);
|
|
|
2c2fa1 |
+ else if (cache->base == 0)
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ /* This marks the outermost frame. */
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
+ else
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ /* See the end of i386_push_dummy_call. */
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build (cache->base + 8, cache->pc);
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
static enum unwind_stop_reason
|
|
|
2c2fa1 |
@@ -2032,9 +2037,9 @@ i386_epilogue_frame_this_id (struct fram
|
|
|
2c2fa1 |
i386_epilogue_frame_cache (this_frame, this_cache);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
if (!cache->base_p)
|
|
|
2c2fa1 |
- return;
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- (*this_id) = frame_id_build (cache->base + 8, cache->pc);
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build_unavailable_stack (cache->pc);
|
|
|
2c2fa1 |
+ else
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build (cache->base + 8, cache->pc);
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
static struct value *
|
|
|
2c2fa1 |
@@ -2226,10 +2231,12 @@ i386_sigtramp_frame_this_id (struct fram
|
|
|
2c2fa1 |
i386_sigtramp_frame_cache (this_frame, this_cache);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
if (!cache->base_p)
|
|
|
2c2fa1 |
- return;
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- /* See the end of i386_push_dummy_call. */
|
|
|
2c2fa1 |
- (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build_unavailable_stack (get_frame_pc (this_frame));
|
|
|
2c2fa1 |
+ else
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ /* See the end of i386_push_dummy_call. */
|
|
|
2c2fa1 |
+ (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
static struct value *
|