+2013-12-17 Pedro Alves <palves@redhat.com>
+
+ * frame.h (enum frame_id_stack_status): New enum.
+ (struct frame_id) <stack_addr>: Adjust comment.
+ <stack_addr_p>: Delete field, replaced with ...
+ <stack_status>: ... this new field.
+ (frame_id_build_unavailable_stack): Declare.
+ * frame.c (frame_addr_hash, fprint_field, outer_frame_id)
+ (frame_id_build_special): Adjust.
+ (frame_id_build_unavailable_stack): New function.
+ (frame_id_build, frame_id_build_wild): Adjust.
+ (frame_id_p, frame_id_eq, frame_id_inner): Adjust to take into
+ account frames with unavailable stack.
+
+ * amd64-tdep.c (amd64_frame_this_id)
+ (amd64_sigtramp_frame_this_id, amd64_epilogue_frame_this_id): Use
+ frame_id_build_unavailable_stack.
+ * dwarf2-frame.c (dwarf2_frame_this_id): Likewise.
+ * i386-tdep.c (i386_frame_this_id, i386_epilogue_frame_this_id)
+ (i386_sigtramp_frame_this_id): Likewise.
+
2013-12-17 Andrew Burgess <aburgess@broadcom.com>
* dwarf2loc.c (read_pieced_value): Mark bits, not bytes
amd64_frame_cache (this_frame, this_cache);
if (!cache->base_p)
- return;
-
- /* This marks the outermost frame. */
- if (cache->base == 0)
- return;
-
- (*this_id) = frame_id_build (cache->base + 16, cache->pc);
+ (*this_id) = frame_id_build_unavailable_stack (cache->pc);
+ else if (cache->base == 0)
+ {
+ /* This marks the outermost frame. */
+ return;
+ }
+ else
+ (*this_id) = frame_id_build (cache->base + 16, cache->pc);
}
static struct value *
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));
+ (*this_id) = frame_id_build_unavailable_stack (get_frame_pc (this_frame));
+ else if (cache->base == 0)
+ {
+ /* This marks the outermost frame. */
+ return;
+ }
+ else
+ (*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame));
}
static struct value *
this_cache);
if (!cache->base_p)
- return;
-
- (*this_id) = frame_id_build (cache->base + 8, cache->pc);
+ (*this_id) = frame_id_build_unavailable_stack (cache->pc);
+ else
+ (*this_id) = frame_id_build (cache->base + 8, cache->pc);
}
static const struct frame_unwind amd64_epilogue_frame_unwind =
dwarf2_frame_cache (this_frame, this_cache);
if (cache->unavailable_retaddr)
+ (*this_id) = frame_id_build_unavailable_stack (get_frame_func (this_frame));
+ else if (cache->undefined_retaddr)
return;
-
- if (cache->undefined_retaddr)
- return;
-
- (*this_id) = frame_id_build (cache->cfa, get_frame_func (this_frame));
+ else
+ (*this_id) = frame_id_build (cache->cfa, get_frame_func (this_frame));
}
static struct value *
const struct frame_id f_id = frame->this_id.value;
hashval_t hash = 0;
- gdb_assert (f_id.stack_addr_p || f_id.code_addr_p
+ gdb_assert (f_id.stack_status != FID_STACK_INVALID
+ || f_id.code_addr_p
|| f_id.special_addr_p);
- if (f_id.stack_addr_p)
+ if (f_id.stack_status == FID_STACK_VALID)
hash = iterative_hash (&f_id.stack_addr,
sizeof (f_id.stack_addr), hash);
if (f_id.code_addr_p)
fprint_frame_id (struct ui_file *file, struct frame_id id)
{
fprintf_unfiltered (file, "{");
- fprint_field (file, "stack", id.stack_addr_p, id.stack_addr);
+
+ if (id.stack_status == FID_STACK_INVALID)
+ fprintf_unfiltered (file, "!stack");
+ else if (id.stack_status == FID_STACK_UNAVAILABLE)
+ fprintf_unfiltered (file, "stack=<unavailable>");
+ else
+ fprintf_unfiltered (file, "stack=%s", hex_string (id.stack_addr));
fprintf_unfiltered (file, ",");
+
fprint_field (file, "code", id.code_addr_p, id.code_addr);
fprintf_unfiltered (file, ",");
+
fprint_field (file, "special", id.special_addr_p, id.special_addr);
+
if (id.artificial_depth)
fprintf_unfiltered (file, ",artificial=%d", id.artificial_depth);
+
fprintf_unfiltered (file, "}");
}
}
const struct frame_id null_frame_id; /* All zeros. */
-const struct frame_id outer_frame_id = { 0, 0, 0, 0, 0, 1, 0 };
+const struct frame_id outer_frame_id = { 0, 0, 0, FID_STACK_INVALID, 0, 1, 0 };
struct frame_id
frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr,
struct frame_id id = null_frame_id;
id.stack_addr = stack_addr;
- id.stack_addr_p = 1;
+ id.stack_status = FID_STACK_VALID;
id.code_addr = code_addr;
id.code_addr_p = 1;
id.special_addr = special_addr;
return id;
}
+/* See frame.h. */
+
+struct frame_id
+frame_id_build_unavailable_stack (CORE_ADDR code_addr)
+{
+ struct frame_id id = null_frame_id;
+
+ id.stack_status = FID_STACK_UNAVAILABLE;
+ id.code_addr = code_addr;
+ id.code_addr_p = 1;
+ return id;
+}
+
struct frame_id
frame_id_build (CORE_ADDR stack_addr, CORE_ADDR code_addr)
{
struct frame_id id = null_frame_id;
id.stack_addr = stack_addr;
- id.stack_addr_p = 1;
+ id.stack_status = FID_STACK_VALID;
id.code_addr = code_addr;
id.code_addr_p = 1;
return id;
struct frame_id id = null_frame_id;
id.stack_addr = stack_addr;
- id.stack_addr_p = 1;
+ id.stack_status = FID_STACK_VALID;
return id;
}
int p;
/* The frame is valid iff it has a valid stack address. */
- p = l.stack_addr_p;
+ p = l.stack_status != FID_STACK_INVALID;
/* outer_frame_id is also valid. */
if (!p && memcmp (&l, &outer_frame_id, sizeof (l)) == 0)
p = 1;
{
int eq;
- if (!l.stack_addr_p && l.special_addr_p
- && !r.stack_addr_p && r.special_addr_p)
+ if (l.stack_status == FID_STACK_INVALID && l.special_addr_p
+ && r.stack_status == FID_STACK_INVALID && r.special_addr_p)
/* The outermost frame marker is equal to itself. This is the
dodgy thing about outer_frame_id, since between execution steps
we might step into another function - from which we can't
unwind either. More thought required to get rid of
outer_frame_id. */
eq = 1;
- else if (!l.stack_addr_p || !r.stack_addr_p)
+ else if (l.stack_status == FID_STACK_INVALID
+ || l.stack_status == FID_STACK_INVALID)
/* Like a NaN, if either ID is invalid, the result is false.
Note that a frame ID is invalid iff it is the null frame ID. */
eq = 0;
- else if (l.stack_addr != r.stack_addr)
+ else if (l.stack_status != r.stack_status || l.stack_addr != r.stack_addr)
/* If .stack addresses are different, the frames are different. */
eq = 0;
else if (l.code_addr_p && r.code_addr_p && l.code_addr != r.code_addr)
{
int inner;
- if (!l.stack_addr_p || !r.stack_addr_p)
- /* Like NaN, any operation involving an invalid ID always fails. */
+ if (l.stack_status != FID_STACK_VALID || r.stack_status != FID_STACK_VALID)
+ /* Like NaN, any operation involving an invalid ID always fails.
+ Likewise if either ID has an unavailable stack address. */
inner = 0;
else if (l.artificial_depth > r.artificial_depth
&& l.stack_addr == r.stack_addr
struct gdbarch;
struct ui_file;
+/* Status of a given frame's stack. */
+
+enum frame_id_stack_status
+{
+ /* Stack address is invalid. E.g., this frame is the outermost
+ (i.e., _start), and the stack hasn't been setup yet. */
+ FID_STACK_INVALID = 0,
+
+ /* Stack address is valid, and is found in the stack_addr field. */
+ FID_STACK_VALID = 1,
+
+ /* Stack address is unavailable. I.e., there's a valid stack, but
+ we don't know where it is (because memory or registers we'd
+ compute it from were not collected). */
+ FID_STACK_UNAVAILABLE = -1
+};
+
/* The frame object. */
struct frame_info;
function pointer register or stack pointer register. They are
wrong.
- This field is valid only if stack_addr_p is true. Otherwise, this
- frame represents the null frame. */
+ This field is valid only if frame_id.stack_status is
+ FID_STACK_VALID. It will be 0 for other
+ FID_STACK_... statuses. */
CORE_ADDR stack_addr;
/* The frame's code address. This shall be constant through out the
CORE_ADDR special_addr;
/* Flags to indicate the above fields have valid contents. */
- unsigned int stack_addr_p : 1;
+ ENUM_BITFIELD(frame_id_stack_status) stack_status : 2;
unsigned int code_addr_p : 1;
unsigned int special_addr_p : 1;
CORE_ADDR code_addr,
CORE_ADDR special_addr);
+/* Construct a frame ID representing a frame where the stack address
+ exists, but is unavailable. CODE_ADDR is the frame's constant code
+ address (typically the entry point). The special identifier
+ address is set to indicate a wild card. */
+extern struct frame_id frame_id_build_unavailable_stack (CORE_ADDR code_addr);
+
/* Construct a wild card frame ID. The parameter is the frame's constant
stack address (typically the outer-bound). The code address as well
as the special identifier address are set to indicate wild cards. */
{
struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
- /* This marks the outermost frame. */
- if (cache->base == 0)
- return;
-
- /* See the end of i386_push_dummy_call. */
- (*this_id) = frame_id_build (cache->base + 8, cache->pc);
+ if (!cache->base_p)
+ (*this_id) = frame_id_build_unavailable_stack (cache->pc);
+ else if (cache->base == 0)
+ {
+ /* This marks the outermost frame. */
+ }
+ else
+ {
+ /* See the end of i386_push_dummy_call. */
+ (*this_id) = frame_id_build (cache->base + 8, cache->pc);
+ }
}
static enum unwind_stop_reason
i386_epilogue_frame_cache (this_frame, this_cache);
if (!cache->base_p)
- return;
-
- (*this_id) = frame_id_build (cache->base + 8, cache->pc);
+ (*this_id) = frame_id_build_unavailable_stack (cache->pc);
+ else
+ (*this_id) = frame_id_build (cache->base + 8, cache->pc);
}
static struct value *
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));
+ (*this_id) = frame_id_build_unavailable_stack (get_frame_pc (this_frame));
+ else
+ {
+ /* See the end of i386_push_dummy_call. */
+ (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
+ }
}
static struct value *
+2013-12-17 Pedro Alves <palves@redhat.com>
+
+ * gdb.trace/circ.exp: Expect frame info to be printed when
+ switching between frames with unavailable stack, but different
+ functions.
+
2013-12-17 Andrew Burgess <aburgess@broadcom.com>
* gdb.trace/unavailable-dwarf-piece.c: New file.
"first frame is at func0"
gdb_test "tfind pc func9" \
- ".*Found trace frame $decimal, tracepoint $decimal.*" \
+ ".*Found trace frame $decimal, tracepoint $decimal\r\n#0 func9 .*" \
"find frame for func9"
}
gdb_test \
"tfind pc func9" \
- ".*Found trace frame $decimal, tracepoint $decimal.*" \
+ ".*Found trace frame $decimal, tracepoint $decimal\r\n#0 func9 .*" \
"find frame for func9"
}