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 <max_blocks>' to control the nr of block addresses printed.
+
* Massif:
- New monitor command 'all_snapshots <filename>' that dumps all snapshots
taken so far.
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
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
leak_check summary any
leak_check full kinds indirect,possible
leak_check full reachable any limited 100
- block_list <loss_record_nr>
+ block_list <loss_record_nr> [unlimited*|limited <max_blocks>]
after a leak search, shows the list of blocks of <loss_record_nr>
+ * = defaults
who_points_at <addr> [<len>]
shows places pointing inside <len> (default 1) bytes at <addr>
(with len 1, only shows "start pointers" pointing exactly to <addr>,
leak_check summary any
leak_check full kinds indirect,possible
leak_check full reachable any limited 100
- block_list <loss_record_nr>
+ block_list <loss_record_nr> [unlimited*|limited <max_blocks>]
after a leak search, shows the list of blocks of <loss_record_nr>
+ * = defaults
who_points_at <addr> [<len>]
shows places pointing inside <len> (default 1) bytes at <addr>
(with len 1, only shows "start pointers" pointing exactly to <addr>,
</listitem>
<listitem>
- <para><varname>block_list <loss_record_nr> </varname>
- shows the list of blocks belonging to <loss_record_nr>.
+ <para><varname>block_list <loss_record_nr>
+ [unlimited*|limited <max_blocks>]</varname>
+ shows the list of blocks belonging to <loss_record_nr>.
+ The nr of blocks to print can be controlled using the
+ <varname>limited</varname> argument followed by the maximum nr
+ of blocks to output.
</para>
<para> A leak search merges the allocated blocks in loss records :
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.
}
// 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) {
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");
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;
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.
// 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 {
" leak_check summary any\n"
" leak_check full kinds indirect,possible\n"
" leak_check full reachable any limited 100\n"
-" block_list <loss_record_nr>\n"
+" block_list <loss_record_nr> [unlimited*|limited <max_blocks>]\n"
" after a leak search, shows the list of blocks of <loss_record_nr>\n"
+" * = defaults\n"
" who_points_at <addr> [<len>]\n"
" shows places pointing inside <len> (default 1) bytes at <addr>\n"
" (with len 1, only shows \"start pointers\" pointing exactly to <addr>,\n"
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;