From: Antoine Tremblay <antoine.tremblay@ericsson.com>
To: <gdb-patches@sourceware.org>
Cc: Antoine Tremblay <antoine.tremblay@ericsson.com>
Subject: [PATCH V2 1/5] Teach arm unwinders to terminate gracefully
Date: Thu, 03 Nov 2016 14:33:00 -0000 [thread overview]
Message-ID: <20161103143300.24934-2-antoine.tremblay@ericsson.com> (raw)
In-Reply-To: <20161103143300.24934-1-antoine.tremblay@ericsson.com>
When examining a trace buffer we have the following issue:
~~~
tfind start
Register 13 is not available
Found trace frame 0, tracepoint 2
#-1 0x40123556 in pendfunc2
^^^
~~~
The reason for this is that the target's stack pointer is unavailable
when examining the trace buffer. What we are seeing is due to the
'tfind' command creating a sentinel frame and unwinding it. If an
exception is thrown, we are left with the sentinel frame being displayed
at level #-1. The exception is thrown when the prologue unwinder tries
to read the stack pointer to construct an ID for the frame.
This patch fixes this and similar issues by making all the arm unwinders
catch NOT_AVAILABLE_ERROR exceptions when either register or memory is
unreadable and report back to the frame core code with UNWIND_UNAVAILABLE.
Note this commit log adapted from 7dfa3edc033c443036d9f2a3e01120f7fb54f498
which fixed a similar issue for aarch64.
No regressions, tested on ubuntu 14.04 ARMv7 and x86.
With gdbserver-{native,extended} / { -marm -mthumb }
gdb/ChangeLog:
* arm-tdep.c (struct arm_prologue_cache) <available_p>: New field.
(arm_make_prologue_cache): Swallow NOT_AVAIABLE_ERROR or set
available_p.
(arm_prologue_unwind_stop_reason): Return UNWIND_UNAVAILABLE if
available_p is not set.
(arm_prologue_this_id): Call frame_id_build_unavailable_stack if
available_p is not set.
(arm_make_stub_cache): Swallow NOT_AVAIABLE_ERROR or set
available_p.
(arm_stub_this_id): Call frame_id_build_unavailable_stack if
available_p is not set.
(arm_m_exception_cache): Swallow NOT_AVAIABLE_ERROR or set
available_p.
(arm_m_exception_this_id): Call frame_id_build_unavailable_stack if
available_p is not set.
---
gdb/arm-tdep.c | 142 ++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 95 insertions(+), 47 deletions(-)
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 645825f..75343dd 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -258,6 +258,9 @@ struct arm_prologue_cache
to identify this frame. */
CORE_ADDR prev_sp;
+ /* Is the target available to read from ? */
+ int available_p;
+
/* The frame base for this frame is just prev_sp - frame size.
FRAMESIZE is the distance from the frame pointer to the
initial stack pointer. */
@@ -1847,19 +1850,29 @@ arm_make_prologue_cache (struct frame_info *this_frame)
cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- arm_scan_prologue (this_frame, cache);
+ TRY
+ {
+ arm_scan_prologue (this_frame, cache);
+ unwound_fp = get_frame_register_unsigned (this_frame, cache->framereg);
+ if (unwound_fp == 0)
+ return cache;
- unwound_fp = get_frame_register_unsigned (this_frame, cache->framereg);
- if (unwound_fp == 0)
- return cache;
+ cache->prev_sp = unwound_fp + cache->framesize;
- cache->prev_sp = unwound_fp + cache->framesize;
+ /* Calculate actual addresses of saved registers using offsets
+ determined by arm_scan_prologue. */
+ for (reg = 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); reg++)
+ if (trad_frame_addr_p (cache->saved_regs, reg))
+ cache->saved_regs[reg].addr += cache->prev_sp;
- /* Calculate actual addresses of saved registers using offsets
- determined by arm_scan_prologue. */
- for (reg = 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); reg++)
- if (trad_frame_addr_p (cache->saved_regs, reg))
- cache->saved_regs[reg].addr += cache->prev_sp;
+ cache->available_p = 1;
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+ }
+ END_CATCH
return cache;
}
@@ -1877,6 +1890,9 @@ arm_prologue_unwind_stop_reason (struct frame_info *this_frame,
*this_cache = arm_make_prologue_cache (this_frame);
cache = (struct arm_prologue_cache *) *this_cache;
+ if (!cache->available_p)
+ return UNWIND_UNAVAILABLE;
+
/* This is meant to halt the backtrace at "_start". */
pc = get_frame_pc (this_frame);
if (pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
@@ -1905,16 +1921,23 @@ arm_prologue_this_id (struct frame_info *this_frame,
*this_cache = arm_make_prologue_cache (this_frame);
cache = (struct arm_prologue_cache *) *this_cache;
- /* Use function start address as part of the frame ID. If we cannot
- identify the start address (due to missing symbol information),
- fall back to just using the current PC. */
- pc = get_frame_pc (this_frame);
- func = get_frame_func (this_frame);
- if (!func)
- func = pc;
+ if (!cache->available_p)
+ {
+ *this_id = frame_id_build_unavailable_stack (cache->prev_sp);
+ }
+ else
+ {
+ /* Use function start address as part of the frame ID. If we cannot
+ identify the start address (due to missing symbol information),
+ fall back to just using the current PC. */
+ pc = get_frame_pc (this_frame);
+ func = get_frame_func (this_frame);
+ if (!func)
+ func = pc;
- id = frame_id_build (cache->prev_sp, func);
- *this_id = id;
+ id = frame_id_build (cache->prev_sp, func);
+ *this_id = id;
+ }
}
static struct value *
@@ -2894,7 +2917,17 @@ arm_make_stub_cache (struct frame_info *this_frame)
cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- cache->prev_sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
+ TRY
+ {
+ cache->prev_sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
+ cache->available_p = 1;
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+ }
+ END_CATCH
return cache;
}
@@ -2912,7 +2945,10 @@ arm_stub_this_id (struct frame_info *this_frame,
*this_cache = arm_make_stub_cache (this_frame);
cache = (struct arm_prologue_cache *) *this_cache;
- *this_id = frame_id_build (cache->prev_sp, get_frame_pc (this_frame));
+ if (!cache->available_p)
+ *this_id = frame_id_build_unavailable_stack (cache->prev_sp);
+ else
+ *this_id = frame_id_build (cache->prev_sp, get_frame_pc (this_frame));
}
static int
@@ -2965,29 +3001,38 @@ arm_m_exception_cache (struct frame_info *this_frame)
cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- unwound_sp = get_frame_register_unsigned (this_frame,
- ARM_SP_REGNUM);
-
- /* The hardware saves eight 32-bit words, comprising xPSR,
- ReturnAddress, LR (R14), R12, R3, R2, R1, R0. See details in
- "B1.5.6 Exception entry behavior" in
- "ARMv7-M Architecture Reference Manual". */
- cache->saved_regs[0].addr = unwound_sp;
- cache->saved_regs[1].addr = unwound_sp + 4;
- cache->saved_regs[2].addr = unwound_sp + 8;
- cache->saved_regs[3].addr = unwound_sp + 12;
- cache->saved_regs[12].addr = unwound_sp + 16;
- cache->saved_regs[14].addr = unwound_sp + 20;
- cache->saved_regs[15].addr = unwound_sp + 24;
- cache->saved_regs[ARM_PS_REGNUM].addr = unwound_sp + 28;
-
- /* If bit 9 of the saved xPSR is set, then there is a four-byte
- aligner between the top of the 32-byte stack frame and the
- previous context's stack pointer. */
- cache->prev_sp = unwound_sp + 32;
- if (safe_read_memory_integer (unwound_sp + 28, 4, byte_order, &xpsr)
- && (xpsr & (1 << 9)) != 0)
- cache->prev_sp += 4;
+ TRY
+ {
+ unwound_sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
+ /* The hardware saves eight 32-bit words, comprising xPSR,
+ ReturnAddress, LR (R14), R12, R3, R2, R1, R0. See details in
+ "B1.5.6 Exception entry behavior" in
+ "ARMv7-M Architecture Reference Manual". */
+ cache->saved_regs[0].addr = unwound_sp;
+ cache->saved_regs[1].addr = unwound_sp + 4;
+ cache->saved_regs[2].addr = unwound_sp + 8;
+ cache->saved_regs[3].addr = unwound_sp + 12;
+ cache->saved_regs[12].addr = unwound_sp + 16;
+ cache->saved_regs[14].addr = unwound_sp + 20;
+ cache->saved_regs[15].addr = unwound_sp + 24;
+ cache->saved_regs[ARM_PS_REGNUM].addr = unwound_sp + 28;
+
+ /* If bit 9 of the saved xPSR is set, then there is a four-byte
+ aligner between the top of the 32-byte stack frame and the
+ previous context's stack pointer. */
+ cache->prev_sp = unwound_sp + 32;
+ if (safe_read_memory_integer (unwound_sp + 28, 4, byte_order, &xpsr)
+ && (xpsr & (1 << 9)) != 0)
+ cache->prev_sp += 4;
+
+ cache->available_p = 1;
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+ }
+ END_CATCH
return cache;
}
@@ -3006,9 +3051,12 @@ arm_m_exception_this_id (struct frame_info *this_frame,
*this_cache = arm_m_exception_cache (this_frame);
cache = (struct arm_prologue_cache *) *this_cache;
- /* Our frame ID for a stub frame is the current SP and LR. */
- *this_id = frame_id_build (cache->prev_sp,
- get_frame_pc (this_frame));
+ if (!cache->available_p)
+ *this_id = frame_id_build_unavailable_stack (cache->prev_sp);
+ else
+ /* Our frame ID for a stub frame is the current SP and LR. */
+ *this_id = frame_id_build (cache->prev_sp,
+ get_frame_pc (this_frame));
}
/* Implementation of function hook 'prev_register' in
--
2.9.2
next prev parent reply other threads:[~2016-11-03 14:33 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-03 14:33 [PATCH V2 0/5] Support tracepoints for ARM linux in GDBServer Antoine Tremblay
2016-11-03 14:33 ` [PATCH V2 4/5] Use FAST_TRACEPOINT_LABEL in range-stepping.exp Antoine Tremblay
2016-11-03 14:33 ` [PATCH V2 2/5] Enable tracing of pseudo-registers on ARM Antoine Tremblay
2016-11-03 14:33 ` [PATCH V2 5/5] Support tracepoints for ARM linux in GDBServer Antoine Tremblay
2016-11-03 17:51 ` Eli Zaretskii
2016-11-03 18:12 ` Antoine Tremblay
2016-11-10 14:01 ` Yao Qi
2016-11-15 14:42 ` Antoine Tremblay
2016-11-16 20:49 ` Yao Qi
2016-11-03 14:33 ` Antoine Tremblay [this message]
2016-11-03 14:33 ` [PATCH V2 3/5] Improve tests to allow for targets that support trace but not ftrace Antoine Tremblay
2016-11-07 9:25 ` [PATCH V2 0/5] Support tracepoints for ARM linux in GDBServer Yao Qi
[not found] ` <wwoka8dasqta.fsf@ericsson.com>
2016-11-08 15:34 ` Antoine Tremblay
2016-11-09 16:39 ` Yao Qi
2016-11-09 17:58 ` Antoine Tremblay
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20161103143300.24934-2-antoine.tremblay@ericsson.com \
--to=antoine.tremblay@ericsson.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox