summaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorMaxim Grigoriev <maxim2405@gmail.com>2011-03-09 03:28:36 +0000
committerMaxim Grigoriev <maxim2405@gmail.com>2011-03-09 03:28:36 +0000
commitf9bde0f4211bd630d4d0aa196b1cb7f59679e9c6 (patch)
treeeec2ca749ea2ac7346b8671a223fea2e3ba93c92 /gdb
parent21d4b6aaf60b144cccbd4be1d90f739f1e7c1491 (diff)
downloadgdb-f9bde0f4211bd630d4d0aa196b1cb7f59679e9c6.tar.gz
2011-03-08 Maxim Grigoriev <maxim2405@gmail.com>
* xtensa-tdep.c (call0_ret): New function. (xtensa_skip_prologue): Speed up analysis.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog5
-rw-r--r--gdb/xtensa-tdep.c86
2 files changed, 85 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3b7c7d30380..a0e3885da33 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
2011-03-08 Maxim Grigoriev <maxim2405@gmail.com>
+ * xtensa-tdep.c (call0_ret): New function.
+ (xtensa_skip_prologue): Speed up analysis.
+
+2011-03-08 Maxim Grigoriev <maxim2405@gmail.com>
+
* xtensa-tdep.c (xtensa_register_reggroup_p): Count in all registers
while executing MI command -data-list-changed-registers.
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index 7de03a5ce41..19a59b98f69 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -2000,6 +2000,75 @@ xtensa_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
/* Call0 ABI support routines. */
+/* Return true, if PC points to "ret" or "ret.n". */
+
+static int
+call0_ret (CORE_ADDR start_pc, CORE_ADDR finish_pc)
+{
+#define RETURN_RET goto done
+ xtensa_isa isa;
+ xtensa_insnbuf ins, slot;
+ char ibuf[XTENSA_ISA_BSZ];
+ CORE_ADDR ia, bt, ba;
+ xtensa_format ifmt;
+ int ilen, islots, is;
+ xtensa_opcode opc;
+ const char *opcname;
+ int found_ret = 0;
+
+ isa = xtensa_default_isa;
+ gdb_assert (XTENSA_ISA_BSZ >= xtensa_isa_maxlength (isa));
+ ins = xtensa_insnbuf_alloc (isa);
+ slot = xtensa_insnbuf_alloc (isa);
+ ba = 0;
+
+ for (ia = start_pc, bt = ia; ia < finish_pc ; ia += ilen)
+ {
+ if (ia + xtensa_isa_maxlength (isa) > bt)
+ {
+ ba = ia;
+ bt = (ba + XTENSA_ISA_BSZ) < finish_pc
+ ? ba + XTENSA_ISA_BSZ : finish_pc;
+ if (target_read_memory (ba, ibuf, bt - ba) != 0 )
+ RETURN_RET;
+ }
+
+ xtensa_insnbuf_from_chars (isa, ins, &ibuf[ia-ba], 0);
+ ifmt = xtensa_format_decode (isa, ins);
+ if (ifmt == XTENSA_UNDEFINED)
+ RETURN_RET;
+ ilen = xtensa_format_length (isa, ifmt);
+ if (ilen == XTENSA_UNDEFINED)
+ RETURN_RET;
+ islots = xtensa_format_num_slots (isa, ifmt);
+ if (islots == XTENSA_UNDEFINED)
+ RETURN_RET;
+
+ for (is = 0; is < islots; ++is)
+ {
+ if (xtensa_format_get_slot (isa, ifmt, is, ins, slot))
+ RETURN_RET;
+
+ opc = xtensa_opcode_decode (isa, ifmt, is, slot);
+ if (opc == XTENSA_UNDEFINED)
+ RETURN_RET;
+
+ opcname = xtensa_opcode_name (isa, opc);
+
+ if ((strcasecmp (opcname, "ret.n") == 0)
+ || (strcasecmp (opcname, "ret") == 0))
+ {
+ found_ret = 1;
+ RETURN_RET;
+ }
+ }
+ }
+ done:
+ xtensa_insnbuf_free(isa, slot);
+ xtensa_insnbuf_free(isa, ins);
+ return found_ret;
+}
+
/* Call0 opcode class. Opcodes are preclassified according to what they
mean for Call0 prologue analysis, and their number of significant operands.
The purpose of this is to simplify prologue analysis by separating
@@ -2873,15 +2942,20 @@ xtensa_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
prologue_sal = find_pc_line (start_pc, 0);
if (prologue_sal.line != 0) /* Found debug info. */
{
- /* In Call0, it is possible to have a function with only one instruction
- ('ret') resulting from a 1-line optimized function that does nothing.
- In that case, prologue_sal.end may actually point to the start of the
- next function in the text section, causing a breakpoint to be set at
- the wrong place. Check if the end address is in a different function,
- and if so return the start PC. We know we have symbol info. */
+ /* In Call0, it is possible to have a function with only one instruction
+ ('ret') resulting from a one-line optimized function that does nothing.
+ In that case, prologue_sal.end may actually point to the start of the
+ next function in the text section, causing a breakpoint to be set at
+ the wrong place. Check, if the end address is within a different
+ function, and if so return the start PC. We know we have symbol
+ information. */
CORE_ADDR end_func;
+ if ((gdbarch_tdep (gdbarch)->call_abi == CallAbiCall0Only)
+ && call0_ret (start_pc, prologue_sal.end))
+ return start_pc;
+
find_pc_partial_function (prologue_sal.end, NULL, &end_func, NULL);
if (end_func != start_pc)
return start_pc;