diff options
author | jamesbowman <jamesb@excamera.com> | 2015-10-02 17:32:47 -0700 |
---|---|---|
committer | jamesbowman <jamesb@excamera.com> | 2015-10-02 17:32:47 -0700 |
commit | ae4e25019d53d38b2ad50475c80fa99ecab94c5c (patch) | |
tree | db590291fcd1df1983d071aa01988bd8844e24af | |
parent | 604763ceaa318df58f706c92eb563a7ba98ebe6e (diff) | |
download | gdb-ae4e25019d53d38b2ad50475c80fa99ecab94c5c.zip gdb-ae4e25019d53d38b2ad50475c80fa99ecab94c5c.tar.gz gdb-ae4e25019d53d38b2ad50475c80fa99ecab94c5c.tar.bz2 |
[FT32] gdb: Correctly interpret function prologs
The stack unwinder did not understand the function prologs
generated by gcc with -Os. Add code to recognize and interpret the
prolog calls.
[gdb]
2015-10-02 James Bowman <james.bowman@ftdichip.com>
* ft32-tdep.c (ft32_analyze_prologue): Add function prolog
subroutine handling.
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/ft32-tdep.c | 55 |
2 files changed, 54 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f9ef565..20d4a4b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2015-10-02 James Bowman <james.bowman@ftdichip.com> + + * ft32-tdep.c (ft32_analyze_prologue): Add function prolog + subroutine handling. + 2015-10-01 Simon Marchi <simon.marchi@ericsson.com> * common/vec.h (VEC_OP (T,cleanup)): Add pointer cast. diff --git a/gdb/ft32-tdep.c b/gdb/ft32-tdep.c index 00cf847..e9da23e 100644 --- a/gdb/ft32-tdep.c +++ b/gdb/ft32-tdep.c @@ -164,33 +164,76 @@ ft32_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr, CORE_ADDR next_addr; ULONGEST inst, inst2; LONGEST offset; - int regnum; + int regnum, pushreg; + struct bound_minimal_symbol msymbol; + const int first_saved_reg = 13; /* The first saved register. */ + /* PROLOGS are addresses of the subroutine prologs, PROLOGS[n] + is the address of __prolog_$rN. + __prolog_$rN pushes registers from 13 through n inclusive. + So for example CALL __prolog_$r15 is equivalent to: + PUSH $r13 + PUSH $r14 + PUSH $r15 + Note that PROLOGS[0] through PROLOGS[12] are unused. */ + CORE_ADDR prologs[32]; cache->saved_regs[FT32_PC_REGNUM] = 0; cache->framesize = 0; + for (regnum = first_saved_reg; regnum < 32; regnum++) + { + char prolog_symbol[32]; + + snprintf (prolog_symbol, sizeof (prolog_symbol), "__prolog_$r%02d", + regnum); + msymbol = lookup_minimal_symbol (prolog_symbol, NULL, NULL); + if (msymbol.minsym) + prologs[regnum] = BMSYMBOL_VALUE_ADDRESS (msymbol); + else + prologs[regnum] = 0; + } + if (start_addr >= end_addr) - return end_addr; + return end_addr; cache->established = 0; - for (next_addr = start_addr; next_addr < end_addr; ) + for (next_addr = start_addr; next_addr < end_addr;) { inst = read_memory_unsigned_integer (next_addr, 4, byte_order); if (FT32_IS_PUSH (inst)) { - regnum = FT32_R0_REGNUM + FT32_PUSH_REG (inst); + pushreg = FT32_PUSH_REG (inst); cache->framesize += 4; - cache->saved_regs[regnum] = cache->framesize; + cache->saved_regs[FT32_R0_REGNUM + pushreg] = cache->framesize; next_addr += 4; } + else if (FT32_IS_CALL (inst)) + { + for (regnum = first_saved_reg; regnum < 32; regnum++) + { + if ((4 * (inst & 0x3ffff)) == prologs[regnum]) + { + for (pushreg = first_saved_reg; pushreg <= regnum; + pushreg++) + { + cache->framesize += 4; + cache->saved_regs[FT32_R0_REGNUM + pushreg] = + cache->framesize; + } + next_addr += 4; + } + } + break; + } else break; } for (regnum = FT32_R0_REGNUM; regnum < FT32_PC_REGNUM; regnum++) { if (cache->saved_regs[regnum] != REG_UNAVAIL) - cache->saved_regs[regnum] = cache->framesize - cache->saved_regs[regnum]; + cache->saved_regs[regnum] = + cache->framesize - cache->saved_regs[regnum]; } cache->saved_regs[FT32_PC_REGNUM] = cache->framesize; |