From: Philippe Waroquiers Date: Tue, 2 Jun 2015 22:09:42 +0000 (+0000) Subject: Add a gdbxrv monitor command to print the CFI unwind info for an address+len X-Git-Tag: svn/VALGRIND_3_11_0~326 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a833d76cd9d03efe0d972926c27e02860f819a1e;p=thirdparty%2Fvalgrind.git Add a gdbxrv monitor command to print the CFI unwind info for an address+len git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15306 --- diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index 15f1603505..0dc78a3420 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -2828,6 +2828,37 @@ Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp, # endif } +void VG_(ppUnwindInfo) (Addr from, Addr to) +{ + DebugInfo* di; + CFSI_m_CacheEnt* ce; + Addr ce_from; + CFSI_m_CacheEnt* next_ce; + + + ce = cfsi_m_cache__find(from); + ce_from = from; + while (from <= to) { + from++; + next_ce = cfsi_m_cache__find(from); + if ((ce == NULL && next_ce != NULL) + || (ce != NULL && next_ce == NULL) + || (ce != NULL && next_ce != NULL && ce->cfsi_m != next_ce->cfsi_m) + || from > to) { + if (ce == NULL) { + VG_(printf)("[%#lx .. %#lx]: no CFI info\n", ce_from, from-1); + } else { + di = ce->di; + ML_(ppDiCfSI)(di->cfsi_exprs, + ce_from, from - ce_from, + ce->cfsi_m); + } + ce = next_ce; + ce_from = from; + } + } +} + /* The main function for DWARF2/3 CFI-based stack unwinding. Given a set of registers in UREGS, modify it to hold the register values diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c index 926a13f717..89afca60d5 100644 --- a/coregrind/m_debuginfo/storage.c +++ b/coregrind/m_debuginfo/storage.c @@ -142,8 +142,12 @@ void ML_(ppDiCfSI) ( const XArray* /* of CfiExpr */ exprs, } \ } while (0) - VG_(printf)("[%#lx .. %#lx]: ", base, - base + (UWord)len - 1); + if (base != 0 || len != 0) + VG_(printf)("[%#lx .. %#lx]: ", base, + base + (UWord)len - 1); + else + VG_(printf)("[]: "); + switch (si_m->cfa_how) { case CFIC_IA_SPREL: VG_(printf)("let cfa=oldSP+%d", si_m->cfa_off); diff --git a/coregrind/m_gdbserver/server.c b/coregrind/m_gdbserver/server.c index 6361c5acac..7a67fd029d 100644 --- a/coregrind/m_gdbserver/server.c +++ b/coregrind/m_gdbserver/server.c @@ -248,6 +248,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return) " v.info exectxt : show stacktraces and stats of all execontexts\n" " v.info scheduler : show valgrind thread state and stacktrace\n" " v.info stats : show various valgrind and tool stats\n" +" v.info unwind [] : show unwind debug info for .. \n" " v.set debuglog : set valgrind debug log level to \n" " v.set hostvisibility [yes*|no] : (en/dis)ables access by gdb/gdbserver to\n" " Valgrind internal host status/memory\n" @@ -364,7 +365,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return) wcmd = strtok_r (NULL, " ", &ssaveptr); switch (kwdid = VG_(keyword_id) ("all_errors n_errs_found last_error gdbserver_status memory" - " scheduler stats open_fds exectxt location", + " scheduler stats open_fds exectxt location unwind", wcmd, kwd_report_all)) { case -2: case -1: @@ -456,6 +457,17 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return) ret = 1; break; } + case 10: { /* unwind */ + Addr address; + SizeT sz = 0; + if (VG_(strtok_get_address_and_size) (&address, + &sz, &ssaveptr)) { + VG_(ppUnwindInfo) (address, address + sz - 1); + } + ret = 1; + break; + } + default: vg_assert(0); } diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h index 98029ab79e..bb57b33007 100644 --- a/coregrind/pub_core_debuginfo.h +++ b/coregrind/pub_core_debuginfo.h @@ -165,6 +165,10 @@ extern Bool VG_(use_FPO_info) ( /*MOD*/Addr* ipP, Addr min_accessible, Addr max_accessible ); +/* Print the unwind info (if there is some) for the given address + range [from,to]. */ +extern void VG_(ppUnwindInfo) (Addr from, Addr to); + /* AVMAs for a symbol. Usually only the lowest address of the entity. On ppc64 platforms, also contains tocptr and local_ep. These fields should only be accessed using the macros diff --git a/docs/xml/manual-core-adv.xml b/docs/xml/manual-core-adv.xml index 409cddf692..b767825c5b 100644 --- a/docs/xml/manual-core-adv.xml +++ b/docs/xml/manual-core-adv.xml @@ -1478,6 +1478,14 @@ problems or bugs. + + v.info unwind <addr> [<len>] shows + the CFI unwind debug info for the address range [addr, addr+len-1]. + The default value of <len> is 1, giving the unwind information + for the instruction at <addr>. + + + v.set debuglog <intvalue> sets the Valgrind debug log level to <intvalue>. This allows to diff --git a/gdbserver_tests/mchelp.stdoutB.exp b/gdbserver_tests/mchelp.stdoutB.exp index d3c61a1c86..c2d2c8d07d 100644 --- a/gdbserver_tests/mchelp.stdoutB.exp +++ b/gdbserver_tests/mchelp.stdoutB.exp @@ -65,6 +65,7 @@ debugging valgrind internals monitor commands: v.info exectxt : show stacktraces and stats of all execontexts v.info scheduler : show valgrind thread state and stacktrace v.info stats : show various valgrind and tool stats + v.info unwind [] : show unwind debug info for .. v.set debuglog : set valgrind debug log level to v.set hostvisibility [yes*|no] : (en/dis)ables access by gdb/gdbserver to Valgrind internal host status/memory