mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-07 17:26:44 +08:00
misc fixes
fix sortby function removed not longer needed sigchld handler fix interactive mode add verbose level 2 for library trace output
This commit is contained in:
parent
04aa768634
commit
046b2003dc
@ -42,6 +42,7 @@
|
||||
#include "client.h"
|
||||
#include "dump.h"
|
||||
#include "ioevent.h"
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
#include "process.h"
|
||||
#include "readline.h"
|
||||
@ -592,7 +593,8 @@ static int signal_func(void)
|
||||
{
|
||||
fprintf(stderr, "terminating...\n");
|
||||
client_iterate_processes(scan_process);
|
||||
exit(0);
|
||||
client_close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int client_start(void)
|
||||
@ -624,10 +626,15 @@ int client_start(void)
|
||||
ioevent_add_input(client_fd, client_func);
|
||||
|
||||
if (options.interactive) {
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
|
||||
readline_init();
|
||||
|
||||
while(ioevent_watch(-1) != -1)
|
||||
;
|
||||
|
||||
readline_exit();
|
||||
}
|
||||
else {
|
||||
if (pipe(pipefd) == -1) {
|
||||
@ -651,8 +658,22 @@ int client_start(void)
|
||||
|
||||
void *client_thread(void *unused)
|
||||
{
|
||||
while(client_fd != -1)
|
||||
client_func();
|
||||
if (options.interactive) {
|
||||
ioevent_add_input(client_fd, client_func);
|
||||
|
||||
readline_init();
|
||||
|
||||
while(ioevent_watch(-1) != -1)
|
||||
;
|
||||
|
||||
readline_exit();
|
||||
|
||||
mtrace_request_exit();
|
||||
}
|
||||
else {
|
||||
while(client_fd != -1)
|
||||
client_func();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -617,7 +617,7 @@ static int process_rb_insert_block(struct process *process, unsigned long addr,
|
||||
parent = *new;
|
||||
|
||||
if (addr <= this->addr && addr + n > this->addr) {
|
||||
if (options.kill || options.verbose > 1) {
|
||||
if (options.kill || options.verbose > 2) {
|
||||
process_dump_collision(process, this, addr, size, operation);
|
||||
|
||||
if (options.kill)
|
||||
@ -1128,7 +1128,7 @@ void process_munmap(struct process *process, struct mt_msg *mt_msg, void *payloa
|
||||
break;
|
||||
|
||||
if (!is_mmap(block->stack_node->stack->operation)) {
|
||||
if (options.kill || options.verbose > 1) {
|
||||
if (options.kill || options.verbose > 2) {
|
||||
fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr);
|
||||
|
||||
if (options.kill)
|
||||
@ -1213,7 +1213,7 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||
block = process_rb_search(&process->block_table, ptr);
|
||||
if (block) {
|
||||
if (is_mmap(block->stack_node->stack->operation)) {
|
||||
if (options.kill || options.verbose > 1) {
|
||||
if (options.kill || options.verbose > 2) {
|
||||
fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr);
|
||||
|
||||
if (options.kill)
|
||||
@ -1224,7 +1224,7 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||
}
|
||||
else {
|
||||
if (!process->attached) {
|
||||
if (options.kill || options.verbose > 1) {
|
||||
if (options.kill || options.verbose > 2) {
|
||||
fprintf(stderr, ">>> block %#lx not found pid:%d tid:%d\n", ptr, process->pid, mt_msg->tid);
|
||||
|
||||
if (options.kill)
|
||||
@ -1271,7 +1271,7 @@ void process_alloc(struct process *process, struct mt_msg *mt_msg, void *payload
|
||||
|
||||
block = process_rb_search_range(&process->block_table, ptr, size);
|
||||
if (block) {
|
||||
if (options.kill || options.verbose > 1) {
|
||||
if (options.kill || options.verbose > 2) {
|
||||
process_dump_collision(process, block, ptr, size, mt_msg->operation);
|
||||
|
||||
if (options.kill)
|
||||
@ -1321,6 +1321,12 @@ void process_dump_sortby(struct process *process)
|
||||
case OPT_SORT_AVERAGE:
|
||||
_process_dump(process, sort_average, skip_zero_allocations, options.output);
|
||||
break;
|
||||
case OPT_SORT_BYTES_LEAKED:
|
||||
_process_dump(process, sort_bytes_leaked, skip_zero_leaks, options.output);
|
||||
break;
|
||||
case OPT_SORT_LEAKS:
|
||||
_process_dump(process, sort_leaks, skip_zero_leaks, options.output);
|
||||
break;
|
||||
case OPT_SORT_STACKS:
|
||||
_process_dump(process, sort_allocations, skip_none, options.output);
|
||||
break;
|
||||
|
||||
@ -86,6 +86,7 @@ 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" },
|
||||
@ -203,12 +204,6 @@ static struct cmd_opt cmds[] = {
|
||||
{ },
|
||||
};
|
||||
|
||||
static void _quit(void)
|
||||
{
|
||||
rl_callback_handler_remove();
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
static inline char *skip_spaces(const char *s)
|
||||
{
|
||||
while(isspace(*s))
|
||||
@ -663,7 +658,7 @@ 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[])
|
||||
{
|
||||
_quit();
|
||||
quit = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -826,6 +821,10 @@ static int do_stop(struct cmd_opt *cmd, int argc, const char *argv[])
|
||||
static int readline_func(void)
|
||||
{
|
||||
rl_callback_read_char();
|
||||
|
||||
if (quit)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -857,3 +856,8 @@ void readline_init(void)
|
||||
ioevent_add_input(0, readline_func);
|
||||
}
|
||||
|
||||
void readline_exit(void)
|
||||
{
|
||||
rl_callback_handler_remove();
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#define _INC_CLIENT_READLINE_H
|
||||
|
||||
void readline_init(void);
|
||||
void readline_exit(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "debug.h"
|
||||
#include "dict.h"
|
||||
#include "library.h"
|
||||
#include "options.h"
|
||||
#include "report.h"
|
||||
#include "server.h"
|
||||
#include "task.h"
|
||||
@ -202,6 +203,9 @@ void library_delete_list(struct task *leader, struct list_head *list)
|
||||
|
||||
debug(DEBUG_FUNCTION, "%s@%#lx", lib->filename, lib->base);
|
||||
|
||||
if (options.verbose > 1)
|
||||
fprintf(stderr, "+++ library del pid=%d %s@%#lx %#lx-%#lx +++\n", leader->pid, lib->filename, lib->base, lib->load_addr, lib->load_addr + lib->load_size);
|
||||
|
||||
library_destroy(leader, lib);
|
||||
}
|
||||
}
|
||||
@ -220,7 +224,7 @@ static void cb_breakpoint_for_symbol(struct library_symbol *libsym, void *data)
|
||||
}
|
||||
bp = breakpoint_new(task, addr, libsym, libsym->func->hw_bp_min <= HW_BREAKPOINTS ? HW_BP : SW_BP);
|
||||
if (!bp)
|
||||
fprintf(stderr, "Couldn't insert breakpoint for %s to %d: %s.", libsym->func->name, task->pid, strerror(errno));
|
||||
fprintf(stderr, "Couldn't insert breakpoint for %s to %d: %s", libsym->func->name, task->pid, strerror(errno));
|
||||
|
||||
if (server_connected())
|
||||
breakpoint_enable(task, bp);
|
||||
@ -232,6 +236,9 @@ void library_add(struct task *leader, struct library *lib)
|
||||
|
||||
debug(DEBUG_PROCESS, "%s@%#lx to pid=%d", lib->filename, lib->base, leader->pid);
|
||||
|
||||
if (options.verbose > 1)
|
||||
fprintf(stderr, "+++ library add pid=%d %s@%#lx %#lx-%#lx +++\n", leader->pid, lib->filename, lib->base, lib->load_addr, lib->load_addr + lib->load_size);
|
||||
|
||||
/* Insert breakpoints for all active symbols. */
|
||||
library_each_symbol(lib, cb_breakpoint_for_symbol, leader);
|
||||
|
||||
|
||||
12
main.c
12
main.c
@ -86,12 +86,14 @@ static void dump_process(struct task *leader)
|
||||
|
||||
static void mtrace_exit(void)
|
||||
{
|
||||
each_process(stop_threads);
|
||||
if (!options.interactive) {
|
||||
each_process(stop_threads);
|
||||
|
||||
while(server_connected()) {
|
||||
if (task_list_empty())
|
||||
break;
|
||||
dump_process(get_first_process());
|
||||
while(server_connected()) {
|
||||
if (task_list_empty())
|
||||
break;
|
||||
dump_process(get_first_process());
|
||||
}
|
||||
}
|
||||
|
||||
each_process(remove_proc);
|
||||
|
||||
24
mtelf.c
24
mtelf.c
@ -75,8 +75,10 @@ static int open_elf(struct mt_elf *mte, struct task *task, const char *filename)
|
||||
mte->fd = open(filename, O_RDONLY);
|
||||
}
|
||||
|
||||
if (mte->fd == -1)
|
||||
return 1;
|
||||
if (mte->fd == -1) {
|
||||
fprintf(stderr, "could not open %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
elf_version(EV_CURRENT);
|
||||
|
||||
@ -88,17 +90,17 @@ static int open_elf(struct mt_elf *mte, struct task *task, const char *filename)
|
||||
|
||||
if (mte->elf == NULL || elf_kind(mte->elf) != ELF_K_ELF) {
|
||||
fprintf(stderr, "\"%s\" is not an ELF file\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gelf_getehdr(mte->elf, &mte->ehdr) == NULL) {
|
||||
fprintf(stderr, "can't read ELF header of \"%s\": %s\n", filename, elf_errmsg(-1));
|
||||
exit(EXIT_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mte->ehdr.e_type != ET_EXEC && mte->ehdr.e_type != ET_DYN) {
|
||||
fprintf(stderr, "\"%s\" is neither an ELF executable" " nor a shared library\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (1
|
||||
@ -113,7 +115,7 @@ static int open_elf(struct mt_elf *mte, struct task *task, const char *filename)
|
||||
#endif
|
||||
) {
|
||||
fprintf(stderr, "\"%s\" is ELF from incompatible architecture\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -320,13 +322,13 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
||||
scn = elf_getscn(mte->elf, i);
|
||||
if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
|
||||
fprintf(stderr, "Couldn't get section #%d from" " \"%s\": %s\n", i, filename, elf_errmsg(-1));
|
||||
exit(EXIT_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
name = elf_strptr(mte->elf, mte->ehdr.e_shstrndx, shdr.sh_name);
|
||||
if (name == NULL) {
|
||||
fprintf(stderr, "Couldn't get name of section #%d from \"%s\": %s\n", i, filename, elf_errmsg(-1));
|
||||
exit(EXIT_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (shdr.sh_type == SHT_SYMTAB) {
|
||||
@ -341,7 +343,7 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
||||
data = elf_getdata(scn, NULL);
|
||||
if (data == NULL) {
|
||||
fprintf(stderr, "Couldn't get .dynamic data from \"%s\": %s\n", filename, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(idx = 0; gelf_getdyn(data, idx, &dyn); ++idx) {
|
||||
@ -357,12 +359,12 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
||||
|
||||
if (!mte->dyn_addr) {
|
||||
fprintf(stderr, "Couldn't find .dynamic section \"%s\"\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mte->dynsym || !mte->dynstr) {
|
||||
fprintf(stderr, "Couldn't find .dynsym or .dynstr in \"%s\"\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -148,10 +148,6 @@ static void signal_exit(int sig)
|
||||
mtrace_request_exit();
|
||||
}
|
||||
|
||||
static void sigchld_handler(int signum)
|
||||
{
|
||||
}
|
||||
|
||||
static int open_mem(pid_t pid)
|
||||
{
|
||||
int h;
|
||||
@ -389,11 +385,9 @@ ssize_t sock_fd_write(int sock, void *buf, ssize_t buflen, int fd)
|
||||
|
||||
int os_init(void)
|
||||
{
|
||||
sigset_t block_sigset;
|
||||
struct sigaction act;
|
||||
const int siglist[] = { SIGSEGV, SIGABRT, SIGTRAP, SIGILL, SIGFPE };
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(siglist); i++) {
|
||||
act.sa_flags = SA_ONESHOT | SA_SIGINFO;
|
||||
@ -402,26 +396,14 @@ int os_init(void)
|
||||
sigaction(siglist[i], &act, NULL);
|
||||
}
|
||||
|
||||
signal(SIGINT, signal_exit); /* Detach task_es when interrupted */
|
||||
signal(SIGTERM, signal_exit); /* ... or killed */
|
||||
/* Detach task_es when interrupted */
|
||||
if (options.interactive)
|
||||
signal(SIGINT, SIG_IGN);
|
||||
else
|
||||
signal(SIGINT, signal_exit);
|
||||
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_RESTART;
|
||||
act.sa_handler = sigchld_handler;
|
||||
|
||||
if (sigaction(SIGCHLD, &act, NULL)) {
|
||||
perror("sigaction(SIGCHLD)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sigemptyset(&block_sigset);
|
||||
sigaddset(&block_sigset, SIGCHLD);
|
||||
|
||||
ret = pthread_sigmask(SIG_BLOCK, &block_sigset, NULL);
|
||||
if (ret) {
|
||||
fprintf(stderr, "pthread_sigmask %d (%s)\n", ret, strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
/* ... or killed */
|
||||
signal(SIGTERM, signal_exit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user