/* * This file is part of mtrace-ng. * Copyright (C) 2018 Stefani Seibold * * This work was sponsored by Rohde & Schwarz GmbH & Co. KG, Munich/Germany. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "binfile.h" #include "client.h" #include "common.h" #include "dump.h" #include "ioevent.h" #include "job.h" #include "options.h" #include "process.h" #define PROGNAME "mtrace" struct cmd_opt { const char *name; unsigned int match_len; void *data; const char *info; const char *usage; struct cmd_opt *options; }; typedef int (*opt_call)(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[]); typedef int (*cmd_call)(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_dump(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_help(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_proclist(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_quit(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_reset(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_scan(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_set(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_show(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_status(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_start(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_stop(struct cmd_opt *cmd, int argc, const char *argv[]); static int do_set_searchpath(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[]); static int do_set_depth(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[]); static int do_show_info(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[]); static int do_show_searchpath(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[]); const char dump_str[] = "dump"; const char help_str[] = "help"; const char proclist_str[] = "proclist"; const char quit_str[] = "quit"; const char reset_str[] = "reset"; const char scan_str[] = "scan"; const char set_str[] = "set"; const char show_str[] = "show"; const char start_str[] = "start"; const char status_str[] = "status"; const char stop_str[] = "stop"; static const char *outfile; static int quit; static struct cmd_opt dump_opts[] = { { "allocations", 2, process_dump_sort_allocations, "sort by number of open allocations", NULL, NULL }, { "average", 2, process_dump_sort_average, "sort by average allocation of bytes (usage / allocations)", NULL, NULL }, { "badfree", 1, process_dump_sort_badfree, "sort by number of badfree releases", NULL, NULL }, { "bytes-leaked", 1, process_dump_sort_bytes_leaked, "sort by number of leaked bytes", NULL, NULL }, { "leaks", 1, process_dump_sort_leaks, "sort by number of detected leaks", NULL, NULL }, { "mismatched", 1, process_dump_sort_mismatched, "sort by number of mismatched releases", NULL, NULL }, { "stacks", 1, process_dump_stacks, "dump all stack sort by number of total allocations", NULL, NULL }, { "total", 2, process_dump_sort_total, "sort by number of total allocations", NULL, NULL }, { "tsc", 2, process_dump_sort_tsc, "sort by time stamp counter", NULL, NULL }, { "usage", 1, process_dump_sort_usage, "sort by number of bytes", NULL, NULL }, { NULL, 0, NULL, "\n use > to dump the output into a file", NULL, NULL }, }; static struct cmd_opt set_opts[] = { { "searchpath", 1, do_set_searchpath, "set searchpath for binaries and libraries", NULL, NULL }, { "depth", 1, do_set_depth, "set backtrace depth", NULL, NULL }, { }, }; static struct cmd_opt show_opts[] = { { "info", 1, do_show_info, "show client settings", NULL, NULL }, { "searchpath", 1, do_show_searchpath, "show searchpath for binaries and libraries", NULL, NULL }, { }, }; static struct cmd_opt scan_opts[] = { { "all", 1, (void *)SCAN_ALL, "scan all memory blocks", NULL, NULL }, { "leak", 1, (void *)SCAN_LEAK, "scan only leaked allocations", NULL, NULL }, { "new", 1, (void *)SCAN_NEW, "scan only allocations since last scan", NULL, NULL }, { }, }; static struct cmd_opt cmds[] = { { dump_str, 1, do_dump, "dump stack trees", "[sort-by] [-l] [] [>filename]", dump_opts }, { help_str, 1, do_help, "this help", "[]", cmds }, { proclist_str, 1, do_proclist, "list processes", "", NULL }, { quit_str, 1, do_quit, "exit the program", "", NULL }, { reset_str, 1, do_reset, "reset all current memory allocation", "[]", NULL }, { scan_str, 2, do_scan, "scan new memory leaks", "[mode] []", scan_opts }, { set_str, 2, do_set, "change settings", "