From c972a2b8b0ee667dc2a1289f46dfccdec5287cf3 Mon Sep 17 00:00:00 2001 From: Philippe Waroquiers Date: Sat, 21 Jan 2017 11:00:39 +0000 Subject: [PATCH] Allow memcheck to output the leak results as a callgrind xtree file. * New command line options --xtree-leak=no|yes and --xtree-leak-file= to produce the end of execution leak report in a xtree callgrind format file. * New option 'xtleak' in the memcheck leak_check monitor command, to produce the leak report in an xtree file. * File name template arguments (such as --log-file, --xtree-memory-file, ...) have a new %n format letter that is replaced by a sequence number. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16205 --- NEWS | 11 ++ coregrind/m_options.c | 13 ++ coregrind/m_xtmemory.c | 3 +- docs/xml/manual-core-adv.xml | 2 +- docs/xml/manual-core.xml | 10 +- gdbserver_tests/mchelp.stdoutB.exp | 10 +- memcheck/docs/mc-manual.xml | 61 ++++++++- memcheck/mc_include.h | 3 +- memcheck/mc_leakcheck.c | 211 ++++++++++++++++++++++++++++- memcheck/mc_main.c | 58 ++++++-- 10 files changed, 357 insertions(+), 25 deletions(-) diff --git a/NEWS b/NEWS index 1f51292446..609e4434f7 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,7 @@ X86/MacOSX 10.11/12, AMD64/MacOSX 10.11/12 and TILEGX/Linux. and 'massif format. The existing visualisers for these formats (e.g. callgrind_annotate, kcachegrind, ms_print) can be used to visualise and analyse these reports. + Memcheck can also produce leak reports in an xtree callgrind format. For more details, read the user manual. * ================== PLATFORM CHANGES ================= @@ -41,6 +42,13 @@ X86/MacOSX 10.11/12, AMD64/MacOSX 10.11/12 and TILEGX/Linux. - Support for --xtree-memory and 'xtmemory []>'. + - New command line options --xtree-leak=no|yes and --xtree-leak-file= + to produce the end of execution leak report in a xtree callgrind format + file. + + - New option 'xtleak' in the memcheck leak_check monitor command, to + produce the leak report in an xtree file. + * Massif: - Support for --xtree-memory and 'xtmemory []>'. @@ -68,6 +76,9 @@ X86/MacOSX 10.11/12, AMD64/MacOSX 10.11/12 and TILEGX/Linux. first line uniquely identifying the format ("# callgrind format"). Callgrind creates this line now (also the new xtree functionality). +* File name template arguments (such as --log-file, --xtree-memory-file, ...) + have a new %n format letter that is replaced by a sequence number. + * ==================== FIXED BUGS ==================== The following bugs have been fixed or resolved. Note that "n-i-bz" diff --git a/coregrind/m_options.c b/coregrind/m_options.c index 04808ce954..bf5472ba8c 100644 --- a/coregrind/m_options.c +++ b/coregrind/m_options.c @@ -226,6 +226,19 @@ HChar* VG_(expand_file_name)(const HChar* option_name, const HChar* format) j += VG_(sprintf)(&out[j], "%d", pid); i++; } + else if ('n' == format[i]) { + // Print a seq nr. + static Int last_pid; + static Int seq_nr; + Int pid = VG_(getpid)(); + if (last_pid != pid) + seq_nr = 0; + last_pid = pid; + seq_nr++; + ENSURE_THIS_MUCH_SPACE(10); + j += VG_(sprintf)(&out[j], "%d", seq_nr); + i++; + } else if ('q' == format[i]) { i++; if ('{' == format[i]) { diff --git a/coregrind/m_xtmemory.c b/coregrind/m_xtmemory.c index 5e92caddf3..20100ae20e 100644 --- a/coregrind/m_xtmemory.c +++ b/coregrind/m_xtmemory.c @@ -288,7 +288,8 @@ void VG_(XTMemory_report) = VG_(expand_file_name)("--xtree-memory-file", (filename == NULL) ? (fini ? - VG_(clo_xtree_memory_file) : "xtmemory.kcg") + VG_(clo_xtree_memory_file) + : "xtmemory.kcg.%p.%n") : filename); /* fini is False => even if user kept --xtree-memory=none, we diff --git a/docs/xml/manual-core-adv.xml b/docs/xml/manual-core-adv.xml index a5ac0cf264..27c871af9f 100644 --- a/docs/xml/manual-core-adv.xml +++ b/docs/xml/manual-core-adv.xml @@ -1397,7 +1397,7 @@ client request. - xtmemory [<filename> default xtmemory.kcg] + xtmemory [<filename> default xtmemory.kcg.%p.%n] requests the tool to produce an xtree heap memory report. See for a detailed explanation about execution trees. diff --git a/docs/xml/manual-core.xml b/docs/xml/manual-core.xml index e1a89823da..94885d0729 100644 --- a/docs/xml/manual-core.xml +++ b/docs/xml/manual-core.xml @@ -888,6 +888,12 @@ in most cases. We group the available options by rough categories. all those processes will go into one file, possibly jumbled up, and possibly incomplete. + is replaced with a file sequence number + unique for this process. + This is useful for processes that produces several files + from the same filename template. + + is replaced with the contents of the environment variable FOO. If the part is malformed, it causes an abort. This @@ -2747,7 +2753,9 @@ will create a core dump in the usual way. An execution tree (xtree) is made of a set of stack traces, each stack trace is associated with some resource consumptions or event counts. Depending on the xtree, different event counts/resource - consumptions can be recorded in the xtree. + consumptions can be recorded in the xtree. Multiple tools can + produce memory use xtree. Memcheck can output the leak search results + in an xtree. A typical usage for an xtree is to show a graphical or textual representation of the heap usage of a program. The below figure is diff --git a/gdbserver_tests/mchelp.stdoutB.exp b/gdbserver_tests/mchelp.stdoutB.exp index 742181f2c5..9fd12caef5 100644 --- a/gdbserver_tests/mchelp.stdoutB.exp +++ b/gdbserver_tests/mchelp.stdoutB.exp @@ -27,12 +27,13 @@ memcheck monitor commands: check_memory [addressable|defined] [] check that (or 1) bytes at have the given accessibility and outputs a description of - leak_check [full*|summary] + leak_check [full*|summary|xtleak] [kinds kind1,kind2,...|reachable|possibleleak*|definiteleak] [heuristics heur1,heur2,...] [increased*|changed|any] [unlimited*|limited ] * = defaults + xtleak produces an xtree full leak result in xtleak.kcg.%p.%n where kind is one of: definite indirect possible reachable all none where heur is one of: @@ -53,7 +54,7 @@ memcheck monitor commands: (with len 1, only shows "start pointers" pointing exactly to , with len > 1, will also show "interior pointers") xtmemory [] - dump xtree memory profile in (default xtmemory.kcg) + dump xtree memory profile in (default xtmemory.kcg.%p.%n) general valgrind monitor commands: help [debug] : monitor command help. With debug: + debugging commands v.wait [] : sleep (default 0) then continue @@ -98,12 +99,13 @@ memcheck monitor commands: check_memory [addressable|defined] [] check that (or 1) bytes at have the given accessibility and outputs a description of - leak_check [full*|summary] + leak_check [full*|summary|xtleak] [kinds kind1,kind2,...|reachable|possibleleak*|definiteleak] [heuristics heur1,heur2,...] [increased*|changed|any] [unlimited*|limited ] * = defaults + xtleak produces an xtree full leak result in xtleak.kcg.%p.%n where kind is one of: definite indirect possible reachable all none where heur is one of: @@ -124,5 +126,5 @@ memcheck monitor commands: (with len 1, only shows "start pointers" pointing exactly to , with len > 1, will also show "interior pointers") xtmemory [] - dump xtree memory profile in (default xtmemory.kcg) + dump xtree memory profile in (default xtmemory.kcg.%p.%n) monitor command request to kill this process diff --git a/memcheck/docs/mc-manual.xml b/memcheck/docs/mc-manual.xml index 084773a377..89f61d1a91 100644 --- a/memcheck/docs/mc-manual.xml +++ b/memcheck/docs/mc-manual.xml @@ -880,6 +880,56 @@ is Note that has no effect if is specified. + + + + + + + If set to yes, the results for the leak search done at exit will be + output in a 'Callgrind Format' execution tree file. The produced file + will contain the following events: + + : Reachable Bytes + : Possibly lost Bytes + : Indirectly lost Bytes + : Definitely lost Bytes (direct plus indirect) + : Definitely indirectly lost Bytes (subset of DB) + : reachable Blocks + : Possibly lost Blocks + : Indirectly lost Blocks + : Definitely lost Blocks + + + The increase or decrease for all events above will also be output in + the file to provide the delta (increase or decreaseà between 2 + successive leak searches. For example, is the + increase of the event, is the + decrease of event. The values for the increase and + decrease events will be zero for the first leak search done. + + See for a detailed explanation + about execution trees. + + + + + + + + + Specifies that Valgrind should produce the xtree leak + report in the specified file. Any , + or sequences appearing in + the filename are expanded + in exactly the same way as they are for . + See the description of + for details. + See + for a detailed explanation about execution trees formats. + + @@ -1834,7 +1884,7 @@ Address 0x8049E28 len 1 defined - leak_check [full*|summary] + leak_check [full*|summary|xtleak] [kinds <set>|reachable|possibleleak*|definiteleak] [heuristics heur1,heur2,...] [increased*|changed|any] @@ -1843,7 +1893,7 @@ Address 0x8049E28 len 1 defined performs a leak check. The * in the arguments indicates the default values. - If the [full*|summary] argument is + If the [full*|summary|xtleak] argument is summary, only a summary of the leak search is given; otherwise a full leak report is produced. A full leak report gives detailed information for each leak: the stack trace where the leaked blocks @@ -1857,6 +1907,13 @@ Address 0x8049E28 len 1 defined of leak records to output. If this maximum is reached, the leak search outputs the records with the biggest number of bytes. + The value xtleak also produces a full leak report, + but output it as an xtree in a file xtleak.kcg.%p.%n (see ). + See + for a detailed explanation about execution trees formats. + See for the description of the events + in a xtree leak file. + The kinds argument controls what kind of blocks are shown for a full leak search. The set of leak kinds diff --git a/memcheck/mc_include.h b/memcheck/mc_include.h index fc2d4b7823..fe06c3bac4 100644 --- a/memcheck/mc_include.h +++ b/memcheck/mc_include.h @@ -386,7 +386,7 @@ typedef // least one interior-pointer along the way. IndirectLeak =2, // Leaked, but reachable from another leaked block // (be it Unreached or IndirectLeak). - Unreached =3, // Not reached, ie. leaked. + Unreached =3 // Not reached, ie. leaked. // (At best, only reachable from itself via a cycle.) } Reachedness; @@ -461,6 +461,7 @@ typedef LeakCheckDeltaMode deltamode; UInt max_loss_records_output; // limit on the nr of loss records output. Bool requested_by_monitor_command; // True when requested by gdb/vgdb. + const HChar* xt_filename; // if != NULL, produce an xtree leak file. } LeakCheckParams; diff --git a/memcheck/mc_leakcheck.c b/memcheck/mc_leakcheck.c index f8ae72efef..5be97c2abc 100644 --- a/memcheck/mc_leakcheck.c +++ b/memcheck/mc_leakcheck.c @@ -46,6 +46,8 @@ #include "pub_tool_signals.h" // Needed for mc_include.h #include "pub_tool_libcsetjmp.h" // setjmp facilities #include "pub_tool_tooliface.h" // Needed for mc_include.h +#include "pub_tool_xarray.h" +#include "pub_tool_xtree.h" #include "mc_include.h" @@ -1301,6 +1303,189 @@ static void get_printing_rules(LeakCheckParams* lcp, && RiS(lr->key.state,lcp->errors_for_leak_kinds); } +// +// Types and functions for xtree leak report. +// + +static XTree* leak_xt; + +/* Sizes and delta sizes for a loss record output in an xtree. + As the output format can only show positive values, we need values for + the increase and decrease cases. */ +typedef + struct _XT_BIBK { + ULong szB; // Current values + ULong indirect_szB; + ULong num_blocks; + } XT_BIBK; // Bytes, Indirect bytes, BlocKs + +typedef + enum { + XT_Value =0, + XT_Increase =1, + XT_Decrease =2 + } + XT_VID; // Value or Increase or Decrease + +typedef + struct _XT_lr { + XT_BIBK vid[3]; // indexed by XT_VID + } XT_lr; + +typedef + struct _XT_Leak { + XT_lr xt_lr[4]; // indexed by Reachedness + } XT_Leak; + +static void MC_(XT_Leak_init)(void* xtl) +{ + VG_(memset) (xtl, 0, sizeof(XT_Leak)); +} +static void MC_(XT_Leak_add) (void* to, const void* xtleak) +{ + XT_Leak* xto = to; + const XT_Leak* xtl = xtleak; + + for (int r = Reachable; r <= Unreached; r++) + for (int d = 0; d < 3; d++) { + xto->xt_lr[r].vid[d].szB += xtl->xt_lr[r].vid[d].szB; + xto->xt_lr[r].vid[d].indirect_szB += xtl->xt_lr[r].vid[d].indirect_szB; + xto->xt_lr[r].vid[d].num_blocks += xtl->xt_lr[r].vid[d].num_blocks; + } +} +static void XT_insert_lr (LossRecord* lr) +{ + XT_Leak xtl; + Reachedness i = lr->key.state; + + MC_(XT_Leak_init)(&xtl); + + xtl.xt_lr[i].vid[XT_Value].szB = lr->szB; + xtl.xt_lr[i].vid[XT_Value].indirect_szB = lr->indirect_szB; + xtl.xt_lr[i].vid[XT_Value].num_blocks = lr->num_blocks; + + if (lr->szB > lr->old_szB) + xtl.xt_lr[i].vid[XT_Increase].szB = lr->szB - lr->old_szB; + else + xtl.xt_lr[i].vid[XT_Decrease].szB = lr->old_szB - lr->szB; + if (lr->indirect_szB > lr->old_indirect_szB) + xtl.xt_lr[i].vid[XT_Increase].indirect_szB + = lr->indirect_szB - lr->old_indirect_szB; + else + xtl.xt_lr[i].vid[XT_Decrease].indirect_szB + = lr->old_indirect_szB - lr->indirect_szB; + if (lr->num_blocks > lr->old_num_blocks) + xtl.xt_lr[i].vid[XT_Increase].num_blocks + = lr->num_blocks - lr->old_num_blocks; + else + xtl.xt_lr[i].vid[XT_Decrease].num_blocks + = lr->old_num_blocks - lr->num_blocks; + + VG_(XT_add_to_ec)(leak_xt, lr->key.allocated_at, &xtl); +} + +static void MC_(XT_Leak_sub) (void* from, const void* xtleak) +{ + tl_assert(0); // Should not be called. +} +static const HChar* MC_(XT_Leak_img) (const void* xtleak) +{ + static XT_Leak zero; + static HChar buf[600]; + UInt off = 0; + + const XT_Leak* xtl = xtleak; + + if (VG_(memcmp)(xtl, &zero, sizeof(XT_Leak)) != 0) { + for (UInt d = XT_Value; d <= XT_Decrease; d++) { + // print szB. We add indirect_szB to have the Unreachable showing + // the total bytes loss, including indirect loss. This is similar + // to the textual and xml reports. + for (UInt r = Reachable; r <= Unreached; r++) + off += VG_(sprintf) (buf + off, " %llu", + xtl->xt_lr[r].vid[d].szB + + xtl->xt_lr[r].vid[d].indirect_szB); + // print indirect_szB, only for reachedness having such values) + for (UInt r = Reachable; r <= Unreached; r++) + if (r == Unreached) + off += VG_(sprintf) (buf + off, " %llu", + xtl->xt_lr[r].vid[d].indirect_szB); + // print num_blocks + for (UInt r = Reachable; r <= Unreached; r++) + off += VG_(sprintf) (buf + off, " %llu", + xtl->xt_lr[r].vid[d].num_blocks); + } + return buf + 1; // + 1 to skip the useless first space + } else { + return NULL; + } +} + +/* The short event name is made of 2 or 3 or 4 letters: + an optional delta indication: i = increase d = decrease + a loss kind: R = Reachable P = Possibly I = Indirectly D = Definitely + an optional i to indicate this loss record has indirectly lost bytes + B = Bytes or Bk = Blocks. + Note that indirectly lost bytes/blocks can thus be counted in 2 + loss records: the loss records for their "own" allocation stack trace, + and the loss record of the 'main' Definitely or Possibly loss record + in the indirectly lost count for these loss records. */ +static const HChar* XT_Leak_events = + ////// XT_Value szB + "RB : Reachable Bytes" "," + "PB : Possibly lost Bytes" "," + "IB : Indirectly lost Bytes" "," + "DB : Definitely lost Bytes (direct plus indirect)" "," + + ////// XT_Value indirect_szB + // no RiB + // no PiB + // no IiB + "DiB : Definitely indirectly lost Bytes (subset of DB)" "," + + ////// XT_Value num_blocks + "RBk : reachable Blocks" "," + "PBk : Possibly lost Blocks" "," + "IBk : Indirectly lost Blocks" "," + "DBk : Definitely lost Blocks" "," + + ////// XT_Increase szB + "iRB : increase Reachable Bytes" "," + "iPB : increase Possibly lost Bytes" "," + "iIB : increase Indirectly lost Bytes" "," + "iDB : increase Definitely lost Bytes" "," + + ////// XT_Increase indirect_szB + // no iRiB + // no iPiB + // no iIiB + "iDiB : increase Definitely indirectly lost Bytes" "," + + ////// XT_Increase num_blocks + "iRBk : increase reachable Blocks" "," + "iPBk : increase Possibly lost Blocks" "," + "iIBk : increase Indirectly lost Blocks" "," + "iDBk : increase Definitely lost Blocks" "," + + + ////// XT_Decrease szB + "dRB : decrease Reachable Bytes" "," + "dPB : decrease Possibly lost Bytes" "," + "dIB : decrease Indirectly lost Bytes" "," + "dDB : decrease Definitely lost Bytes" "," + + ////// XT_Decrease indirect_szB + // no dRiB + // no dPiB + // no dIiB + "dDiB : decrease Definitely indirectly lost Bytes" "," + + ////// XT_Decrease num_blocks + "dRBk : decrease reachable Blocks" "," + "dPBk : decrease Possibly lost Blocks" "," + "dIBk : decrease Indirectly lost Blocks" "," + "dDBk : decrease Definitely lost Blocks"; + static void print_results(ThreadId tid, LeakCheckParams* lcp) { Int i, n_lossrecords, start_lr_output_scan; @@ -1452,14 +1637,28 @@ static void print_results(ThreadId tid, LeakCheckParams* lcp) } } + if (lcp->xt_filename != NULL) + leak_xt = VG_(XT_create) (VG_(malloc), + "mc_leakcheck.leak_xt", + VG_(free), + sizeof(XT_Leak), + MC_(XT_Leak_init), + MC_(XT_Leak_add), + MC_(XT_Leak_sub), + VG_(XT_filter_maybe_below_main)); + // Print the loss records (in size order) and collect summary stats. for (i = start_lr_output_scan; i < n_lossrecords; i++) { Bool count_as_error, print_record; lr = lr_array[i]; get_printing_rules(lcp, lr, &count_as_error, &print_record); is_suppressed = - MC_(record_leak_error) ( tid, i+1, n_lossrecords, lr, print_record, - count_as_error ); + MC_(record_leak_error) + ( tid, i+1, n_lossrecords, lr, + lcp->xt_filename == NULL ? print_record : False, + count_as_error ); + if (lcp->xt_filename != NULL && !is_suppressed && print_record) + XT_insert_lr (lr); if (is_suppressed) { MC_(blocks_suppressed) += lr->num_blocks; @@ -1486,6 +1685,14 @@ static void print_results(ThreadId tid, LeakCheckParams* lcp) } } + if (lcp->xt_filename != NULL) { + VG_(XT_callgrind_print)(leak_xt, + lcp->xt_filename, + XT_Leak_events, + MC_(XT_Leak_img)); + VG_(XT_delete)(leak_xt); + } + if (VG_(clo_verbosity) > 0 && !VG_(clo_xml)) { HChar d_bytes[31]; HChar d_blocks[31]; diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c index 1303b934b4..b461049079 100644 --- a/memcheck/mc_main.c +++ b/memcheck/mc_main.c @@ -6012,6 +6012,8 @@ UInt MC_(clo_leak_check_heuristics) = H2S(LchStdString) | H2S( LchLength64) | H2S( LchNewArray) | H2S( LchMultipleInheritance); +Bool MC_(clo_xtree_leak) = False; +const HChar* MC_(clo_xtree_leak_file) = "xtleak.kcg.%p"; Bool MC_(clo_workaround_gcc296_bugs) = False; Int MC_(clo_malloc_fill) = -1; Int MC_(clo_free_fill) = -1; @@ -6213,6 +6215,11 @@ static Bool mc_process_cmd_line_options(const HChar* arg) else if VG_BOOL_CLO(arg, "--expensive-definedness-checks", MC_(clo_expensive_definedness_checks)) {} + else if VG_BOOL_CLO(arg, "--xtree-leak", + MC_(clo_xtree_leak)) {} + else if VG_STR_CLO (arg, "--xtree-leak-file", + MC_(clo_xtree_leak_file)) {} + else return VG_(replacement_malloc_process_cmd_line_option)(arg); @@ -6244,6 +6251,8 @@ static void mc_print_usage(void) " same as --show-leak-kinds=definite,possible\n" " --show-reachable=no --show-possibly-lost=no\n" " same as --show-leak-kinds=definite\n" +" --xtree-leak=no|yes output leak result in xtree format? [no]\n" +" --xtree-leak-file= xtree leak report file [xtleak.kcg.%%p.%%n]\n" " --undef-value-errors=no|yes check for undefined value errors [yes]\n" " --track-origins=no|yes show origins of undefined values? [no]\n" " --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n" @@ -6378,12 +6387,13 @@ static void print_monitor_help ( void ) " check_memory [addressable|defined] []\n" " check that (or 1) bytes at have the given accessibility\n" " and outputs a description of \n" -" leak_check [full*|summary]\n" +" leak_check [full*|summary|xtleak]\n" " [kinds kind1,kind2,...|reachable|possibleleak*|definiteleak]\n" " [heuristics heur1,heur2,...]\n" " [increased*|changed|any]\n" " [unlimited*|limited ]\n" " * = defaults\n" +" xtleak produces an xtree full leak result in xtleak.kcg.%%p.%%n\n" " where kind is one of:\n" " definite indirect possible reachable all none\n" " where heur is one of:\n" @@ -6404,7 +6414,7 @@ static void print_monitor_help ( void ) " (with len 1, only shows \"start pointers\" pointing exactly to ,\n" " with len > 1, will also show \"interior pointers\")\n" " xtmemory []\n" -" dump xtree memory profile in (default xtmemory.kcg)\n" +" dump xtree memory profile in (default xtmemory.kcg.%%p.%%n)\n" "\n"); } @@ -6567,6 +6577,7 @@ static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) case 2: { /* leak_check */ Int err = 0; LeakCheckParams lcp; + HChar* xt_filename = NULL; HChar* kw; lcp.mode = LC_Full; @@ -6576,12 +6587,13 @@ static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) lcp.deltamode = LCD_Increased; lcp.max_loss_records_output = 999999999; lcp.requested_by_monitor_command = True; + lcp.xt_filename = NULL; for (kw = VG_(strtok_r) (NULL, " ", &ssaveptr); kw != NULL; kw = VG_(strtok_r) (NULL, " ", &ssaveptr)) { switch (VG_(keyword_id) - ("full summary " + ("full summary xtleak " "kinds reachable possibleleak definiteleak " "heuristics " "increased changed any " @@ -6593,7 +6605,14 @@ static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) lcp.mode = LC_Full; break; case 1: /* summary */ lcp.mode = LC_Summary; break; - case 2: { /* kinds */ + case 2: /* xtleak */ + lcp.mode = LC_Full; + xt_filename + = VG_(expand_file_name)("--xtleak-mc_main.c", + "xtleak.kcg.%p.%n"); + lcp.xt_filename = xt_filename; + break; + case 3: { /* kinds */ wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr); if (wcmd == NULL || !VG_(parse_enum_set)(MC_(parse_leak_kinds_tokens), @@ -6605,17 +6624,17 @@ static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) } break; } - case 3: /* reachable */ + case 4: /* reachable */ lcp.show_leak_kinds = MC_(all_Reachedness)(); break; - case 4: /* possibleleak */ + case 5: /* possibleleak */ lcp.show_leak_kinds = R2S(Possible) | R2S(IndirectLeak) | R2S(Unreached); break; - case 5: /* definiteleak */ + case 6: /* definiteleak */ lcp.show_leak_kinds = R2S(Unreached); break; - case 6: { /* heuristics */ + case 7: { /* heuristics */ wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr); if (wcmd == NULL || !VG_(parse_enum_set)(MC_(parse_leak_heuristics_tokens), @@ -6627,15 +6646,15 @@ static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) } break; } - case 7: /* increased */ + case 8: /* increased */ lcp.deltamode = LCD_Increased; break; - case 8: /* changed */ + case 9: /* changed */ lcp.deltamode = LCD_Changed; break; - case 9: /* any */ + case 10: /* any */ lcp.deltamode = LCD_Any; break; - case 10: /* unlimited */ + case 11: /* unlimited */ lcp.max_loss_records_output = 999999999; break; - case 11: { /* limited */ + case 12: { /* limited */ Int int_value; const HChar* endptr; @@ -6663,6 +6682,8 @@ static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) } if (!err) MC_(detect_memory_leaks)(tid, &lcp); + if (xt_filename != NULL) + VG_(free)(xt_filename); return True; } @@ -6990,6 +7011,7 @@ static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret ) } lcp.max_loss_records_output = 999999999; lcp.requested_by_monitor_command = False; + lcp.xt_filename = NULL; MC_(detect_memory_leaks)(tid, &lcp); *ret = 0; /* return value is meaningless */ @@ -8025,6 +8047,7 @@ static void mc_fini ( Int exitcode ) if (MC_(clo_leak_check) != LC_Off) { LeakCheckParams lcp; + HChar* xt_filename = NULL; lcp.mode = MC_(clo_leak_check); lcp.show_leak_kinds = MC_(clo_show_leak_kinds); lcp.heuristics = MC_(clo_leak_check_heuristics); @@ -8032,7 +8055,16 @@ static void mc_fini ( Int exitcode ) lcp.deltamode = LCD_Any; lcp.max_loss_records_output = 999999999; lcp.requested_by_monitor_command = False; + if (MC_(clo_xtree_leak)) { + xt_filename = VG_(expand_file_name)("--xtree-leak-file", + MC_(clo_xtree_leak_file)); + lcp.xt_filename = xt_filename; + } + else + lcp.xt_filename = NULL; MC_(detect_memory_leaks)(1/*bogus ThreadId*/, &lcp); + if (MC_(clo_xtree_leak)) + VG_(free)(xt_filename); } else { if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) { VG_(umsg)( -- 2.47.2