From: Philippe Waroquiers Date: Thu, 13 Aug 2015 22:49:32 +0000 (+0000) Subject: Fix 350202 - Add limited param to 'monitor block_list' X-Git-Tag: svn/VALGRIND_3_11_0~117 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b6876b9917bd79137b642b3a5938e6b6ac7b3f6a;p=thirdparty%2Fvalgrind.git Fix 350202 - Add limited param to 'monitor block_list' git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15540 --- diff --git a/NEWS b/NEWS index b37e87b1f7..3057e15982 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,9 @@ Release 3.11.0 is under development, not yet released. get_vbits (in particular on little endian computers) when you need to associate byte data value with their corresponding validity bits. + - The 'block_list' monitor command now accepts an optional argument + 'limited ' to control the nr of block addresses printed. + * Massif: - New monitor command 'all_snapshots ' that dumps all snapshots taken so far. @@ -282,6 +285,7 @@ where XXXXXX is the bug number as listed below. 349874 Fix typos in source code 349828 memcpy intercepts memmove causing src/dst overlap error (ppc64 ld.so) 349941 di_notify_mmap might create wrong start/size DebugInfoMapping +350202 Add limited param to 'monitor block_list' 350809 Fix none/tests/async-sigs for Solaris 350811 Remove reference to --db-attach which has been removed. 350813 Use handwritten memcheck assembly helpers on x86/Solaris in addition to {arm,x86}-linux diff --git a/docs/internals/3_10_BUGSTATUS.txt b/docs/internals/3_10_BUGSTATUS.txt index caf111c9e4..0a7708c94f 100644 --- a/docs/internals/3_10_BUGSTATUS.txt +++ b/docs/internals/3_10_BUGSTATUS.txt @@ -364,8 +364,6 @@ go in here. 348358 describe should show info about main stack guard page -350202 Add limited param to 'monitor block_list' - === Output ============================================================= 339405 Adds ability to invoke a script in order to determine a diff --git a/gdbserver_tests/mchelp.stdoutB.exp b/gdbserver_tests/mchelp.stdoutB.exp index 4e057ad031..77d1eb182a 100644 --- a/gdbserver_tests/mchelp.stdoutB.exp +++ b/gdbserver_tests/mchelp.stdoutB.exp @@ -41,8 +41,9 @@ memcheck monitor commands: leak_check summary any leak_check full kinds indirect,possible leak_check full reachable any limited 100 - block_list + block_list [unlimited*|limited ] after a leak search, shows the list of blocks of + * = defaults who_points_at [] shows places pointing inside (default 1) bytes at (with len 1, only shows "start pointers" pointing exactly to , @@ -105,8 +106,9 @@ memcheck monitor commands: leak_check summary any leak_check full kinds indirect,possible leak_check full reachable any limited 100 - block_list + block_list [unlimited*|limited ] after a leak search, shows the list of blocks of + * = defaults who_points_at [] shows places pointing inside (default 1) bytes at (with len 1, only shows "start pointers" pointing exactly to , diff --git a/memcheck/docs/mc-manual.xml b/memcheck/docs/mc-manual.xml index d384770194..330355440f 100644 --- a/memcheck/docs/mc-manual.xml +++ b/memcheck/docs/mc-manual.xml @@ -1886,8 +1886,12 @@ Address 0x8049E28 len 1 defined - block_list <loss_record_nr> - shows the list of blocks belonging to <loss_record_nr>. + block_list <loss_record_nr> + [unlimited*|limited <max_blocks>] + shows the list of blocks belonging to <loss_record_nr>. + The nr of blocks to print can be controlled using the + limited argument followed by the maximum nr + of blocks to output. A leak search merges the allocated blocks in loss records : diff --git a/memcheck/mc_include.h b/memcheck/mc_include.h index 3493fb5bcd..991c5b94cc 100644 --- a/memcheck/mc_include.h +++ b/memcheck/mc_include.h @@ -461,9 +461,10 @@ extern UInt MC_(leak_search_gen); extern LeakCheckDeltaMode MC_(detect_memory_leaks_last_delta_mode); // prints the list of blocks corresponding to the given loss_record_nr. +// (up to maximum max_blocks) // Returns True if loss_record_nr identifies a correct loss record from last // leak search, returns False otherwise. -Bool MC_(print_block_list) ( UInt loss_record_nr); +Bool MC_(print_block_list) ( UInt loss_record_nr, UInt max_blocks); // Prints the addresses/registers/... at which a pointer to // the given range [address, address+szB[ is found. diff --git a/memcheck/mc_leakcheck.c b/memcheck/mc_leakcheck.c index 84d4688684..db317f75f7 100644 --- a/memcheck/mc_leakcheck.c +++ b/memcheck/mc_leakcheck.c @@ -1507,14 +1507,15 @@ static void print_results(ThreadId tid, LeakCheckParams* lcp) } // print recursively all indirectly leaked blocks collected in clique. -static void print_clique (Int clique, UInt level) +// Printing stops when *remaining reaches 0. +static void print_clique (Int clique, UInt level, UInt *remaining) { Int ind; UInt i, n_lossrecords; n_lossrecords = VG_(OSetGen_Size)(lr_table); - for (ind = 0; ind < lc_n_chunks; ind++) { + for (ind = 0; ind < lc_n_chunks && *remaining > 0; ind++) { LC_Extra* ind_ex = &(lc_extras)[ind]; if (ind_ex->state == IndirectLeak && ind_ex->IorC.clique == (SizeT) clique) { @@ -1533,19 +1534,21 @@ static void print_clique (Int clique, UInt level) VG_(umsg)("%p[%lu] indirect loss record %u\n", (void *)ind_ch->data, (SizeT)ind_ch->szB, lr_i+1); // lr_i+1 for user numbering. + (*remaining)--; if (lr_i >= n_lossrecords) VG_(umsg) ("error: no indirect loss record found for %p[%lu]?????\n", (void *)ind_ch->data, (SizeT)ind_ch->szB); - print_clique(ind, level+1); + print_clique(ind, level+1, remaining); } } } -Bool MC_(print_block_list) ( UInt loss_record_nr) +Bool MC_(print_block_list) ( UInt loss_record_nr, UInt max_blocks) { UInt i, n_lossrecords; LossRecord* lr; + UInt remaining = max_blocks; if (lr_table == NULL || lc_chunks == NULL || lc_extras == NULL) { VG_(umsg)("Can't print block list : no valid leak search result\n"); @@ -1569,7 +1572,7 @@ Bool MC_(print_block_list) ( UInt loss_record_nr) MC_(pp_LossRecord)(loss_record_nr+1, n_lossrecords, lr); // Match the chunks with loss records. - for (i = 0; i < lc_n_chunks; i++) { + for (i = 0; i < lc_n_chunks && remaining > 0; i++) { MC_Chunk* ch = lc_chunks[i]; LC_Extra* ex = &(lc_extras)[i]; LossRecord* old_lr; @@ -1584,6 +1587,7 @@ Bool MC_(print_block_list) ( UInt loss_record_nr) if (old_lr == lr_array[loss_record_nr]) { VG_(umsg)("%p[%lu]\n", (void *)ch->data, (SizeT)ch->szB); + remaining--; if (ex->state != Reachable) { // We can print the clique in all states, except Reachable. // In Unreached state, lc_chunk[i] is the clique leader. @@ -1591,7 +1595,7 @@ Bool MC_(print_block_list) ( UInt loss_record_nr) // which was later collected in another clique. // For Possible, lc_chunk[i] might be the top of a clique // or an intermediate clique. - print_clique(i, 1); + print_clique(i, 1, &remaining); } } } else { diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c index 14a1d6ade0..c0d3417e3c 100644 --- a/memcheck/mc_main.c +++ b/memcheck/mc_main.c @@ -6038,8 +6038,9 @@ static void print_monitor_help ( void ) " leak_check summary any\n" " leak_check full kinds indirect,possible\n" " leak_check full reachable any limited 100\n" -" block_list \n" +" block_list [unlimited*|limited ]\n" " after a leak search, shows the list of blocks of \n" +" * = defaults\n" " who_points_at []\n" " shows places pointing inside (default 1) bytes at \n" " (with len 1, only shows \"start pointers\" pointing exactly to ,\n" @@ -6322,16 +6323,53 @@ static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) case 5: { /* block_list */ HChar* wl; HChar *endptr; + HChar *the_end; UInt lr_nr = 0; + wl = VG_(strtok_r) (NULL, " ", &ssaveptr); if (wl != NULL) lr_nr = VG_(strtoull10) (wl, &endptr); if (wl == NULL || *endptr != '\0') { VG_(gdb_printf) ("malformed or missing integer\n"); } else { + UInt limit_blocks; + Int int_value; + + wl = VG_(strtok_r) (NULL, " ", &ssaveptr); + if (wl != NULL) { + switch (VG_(keyword_id) ("unlimited limited ", + wl, kwd_report_all)) { + case -2: return True; + case -1: return True; + case 0: /* unlimited */ + limit_blocks = 999999999; break; + case 1: /* limited */ + wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr); + if (wcmd == NULL) { + VG_(gdb_printf) ("missing integer value\n"); + return True; + } + int_value = VG_(strtoll10) (wcmd, &the_end); + if (*the_end != '\0') { + VG_(gdb_printf) ("malformed integer value\n"); + return True; + } + if (int_value <= 0) { + VG_(gdb_printf) ("max_blocks must be >= 1," + " got %d\n", int_value); + return True; + } + limit_blocks = (UInt) int_value; + break; + default: + tl_assert (0); + } + } else { + limit_blocks = 999999999; + } /* lr_nr-1 as what is shown to the user is 1 more than the index in lr_array. */ - if (lr_nr == 0 || ! MC_(print_block_list) (lr_nr-1)) + if (lr_nr == 0 || ! MC_(print_block_list) (lr_nr-1, limit_blocks)) VG_(gdb_printf) ("invalid loss record nr\n"); } return True;