mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-06 08:46:41 +08:00
fixes
This commit is contained in:
parent
a6c7ba8fcc
commit
87f73f3220
@ -45,7 +45,7 @@ include_directories(
|
||||
"${PROJECT_SOURCE_DIR}/sysdeps"
|
||||
)
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined -D__FORITFY_SOURCE=2 -rdynamic")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined -D__FORITFY_SOURCE=2 -rdynamic -DDEBUG")
|
||||
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined")
|
||||
|
||||
set(CMAKE_C_FLAGS_LTO "${CMAKE_C_FLAGS_RELEASE} -flto")
|
||||
|
||||
@ -92,8 +92,7 @@ struct realloc_entry {
|
||||
unsigned long addr;
|
||||
unsigned long size;
|
||||
unsigned long flags;
|
||||
struct rb_stack *stack;
|
||||
enum mt_operation operation;
|
||||
struct rb_stack *stack_node;
|
||||
};
|
||||
|
||||
struct regex_list {
|
||||
@ -815,8 +814,8 @@ static void process_init(struct process *process, unsigned int swap_endian, unsi
|
||||
|
||||
static void realloc_del(struct realloc_entry *re)
|
||||
{
|
||||
if (re->stack)
|
||||
stack_put(re->stack);
|
||||
if (re->stack_node)
|
||||
stack_put(re->stack_node);
|
||||
list_del(&re->list);
|
||||
free(re);
|
||||
}
|
||||
@ -1390,6 +1389,22 @@ static int is_sane(struct rb_block *block, enum mt_operation op)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void realloc_add(struct process *process, unsigned long pid, unsigned long addr, unsigned long size, unsigned long flags, struct rb_stack *stack_node)
|
||||
{
|
||||
struct realloc_entry *re = malloc(sizeof(*re));
|
||||
|
||||
re->addr = addr;
|
||||
re->size = size;
|
||||
re->flags = flags;
|
||||
re->pid = pid;
|
||||
re->stack_node = stack_node;
|
||||
|
||||
if (re->stack_node)
|
||||
stack_get(re->stack_node);
|
||||
|
||||
list_add_tail(&re->list, &process->realloc_list);
|
||||
}
|
||||
|
||||
void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||
{
|
||||
struct rb_block *block = NULL;
|
||||
@ -1444,20 +1459,8 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||
}
|
||||
}
|
||||
|
||||
if (mt_msg->operation == MT_REALLOC_ENTER) {
|
||||
struct realloc_entry *re = malloc(sizeof(*re));
|
||||
|
||||
re->addr = block->addr;
|
||||
re->size = block->size;
|
||||
re->flags = block->flags;
|
||||
re->operation = block->stack_node->stack->operation;
|
||||
re->pid = pid;
|
||||
re->stack = block->stack_node;
|
||||
|
||||
stack_get(re->stack);
|
||||
|
||||
list_add_tail(&re->list, &process->realloc_list);
|
||||
}
|
||||
if (mt_msg->operation == MT_REALLOC_ENTER)
|
||||
realloc_add(process, pid, block->addr, block->size, block->flags, block->stack_node);
|
||||
|
||||
process_rb_delete_block(process, block);
|
||||
}
|
||||
@ -1475,6 +1478,9 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||
stack->tsc = process->tsc++;
|
||||
}
|
||||
}
|
||||
|
||||
if (mt_msg->operation == MT_REALLOC_ENTER)
|
||||
realloc_add(process, pid, 0, 0, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1509,7 +1515,7 @@ void process_realloc_done(struct process *process, struct mt_msg *mt_msg, void *
|
||||
|
||||
if (re->pid == pid) {
|
||||
if (!ptr && re->addr)
|
||||
process_rb_insert_block(process, re->addr, re->size, re->stack, re->flags, re->operation);
|
||||
process_rb_insert_block(process, re->addr, re->size, re->stack_node, re->flags, re->stack_node->stack->operation);
|
||||
|
||||
realloc_del(re);
|
||||
return;
|
||||
|
||||
12
debug.h
12
debug.h
@ -25,16 +25,14 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define DEBUG
|
||||
|
||||
/* debug levels:
|
||||
*/
|
||||
enum {
|
||||
DEBUG_EVENT_HANDLER = 01,
|
||||
DEBUG_DWARF = 02,
|
||||
DEBUG_EVENT = 010,
|
||||
DEBUG_PROCESS = 020,
|
||||
DEBUG_FUNCTION = 040
|
||||
DEBUG_TRACE = 1,
|
||||
DEBUG_DWARF = 2,
|
||||
DEBUG_EVENT = 4,
|
||||
DEBUG_PROCESS = 8,
|
||||
DEBUG_FUNCTION = 16,
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
6
dwarf.c
6
dwarf.c
@ -483,8 +483,8 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
|
||||
|
||||
if (*addr < ARCH_ADDR_T(libref->mmap_addr))
|
||||
fatal("invalid access mem: addr %#lx < %p", *addr, libref->mmap_addr);
|
||||
if (*addr >= ARCH_ADDR_T(libref->mmap_addr + libref->txt_size))
|
||||
fatal("invalid access mem: addr %#lx >= %p", *addr, libref->mmap_addr + libref->txt_size);
|
||||
if (*addr >= ARCH_ADDR_T(libref->mmap_addr + libref->mmap_size))
|
||||
fatal("invalid access mem: addr %#lx >= %p", *addr, libref->mmap_addr + libref->mmap_size);
|
||||
#endif
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
@ -937,7 +937,7 @@ static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip
|
||||
return -DWARF_ENOINFO;
|
||||
}
|
||||
|
||||
fde_addr = libref->mmap_addr - libref->mmap_offset + e->fde_offset + libref->eh_frame_hdr;
|
||||
fde_addr = libref->mmap_addr - (libref->txt_offset - libref->mmap_offset) + e->fde_offset + libref->eh_frame_hdr;
|
||||
|
||||
if (unlikely((ret = dwarf_extract_cfi_from_fde(as, fde_addr)) < 0))
|
||||
return ret;
|
||||
|
||||
@ -61,6 +61,7 @@ struct libref {
|
||||
/* executable segment */
|
||||
unsigned long txt_vaddr;
|
||||
unsigned long txt_size;
|
||||
unsigned long txt_offset;
|
||||
|
||||
/* loadable segments */
|
||||
unsigned int loadsegs;
|
||||
|
||||
17
mtelf.c
17
mtelf.c
@ -223,7 +223,7 @@ static inline int elf_map_image(struct mt_elf *mte, void **mmap_addr)
|
||||
{
|
||||
void *addr;
|
||||
|
||||
addr = mmap(NULL, mte->txt_hdr.p_filesz, PROT_READ, MAP_PRIVATE, mte->fd, mte->txt_hdr.p_offset);
|
||||
addr = mmap(NULL, mte->loadsize, PROT_READ, MAP_PRIVATE, mte->fd, mte->loadbase);
|
||||
if (addr == MAP_FAILED) {
|
||||
fprintf(stderr, "mmap failed\n");
|
||||
return -1;
|
||||
@ -240,10 +240,11 @@ static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *li
|
||||
return -1;
|
||||
|
||||
libref->entry = ARCH_ADDR_T(mte->entry_addr);
|
||||
libref->mmap_offset = mte->txt_hdr.p_offset;
|
||||
libref->mmap_offset = mte->loadbase;
|
||||
libref->mmap_size = mte->loadsize;
|
||||
libref->txt_vaddr = mte->txt_hdr.p_vaddr + mte->bias;
|
||||
libref->txt_size = mte->txt_hdr.p_filesz;
|
||||
libref->txt_offset = mte->txt_hdr.p_offset;
|
||||
libref->bias = mte->bias;
|
||||
libref->eh_frame_hdr = mte->eh_hdr.p_offset;
|
||||
libref->pltgot = mte->pltgot;
|
||||
@ -262,7 +263,7 @@ static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *li
|
||||
#endif
|
||||
|
||||
if (mte->eh_hdr.p_filesz && mte->dyn) {
|
||||
if (dwarf_get_unwind_table(task, libref, (struct dwarf_eh_frame_hdr *)(libref->mmap_addr - libref->mmap_offset + mte->eh_hdr.p_offset)) < 0)
|
||||
if (dwarf_get_unwind_table(task, libref, (struct dwarf_eh_frame_hdr *)(libref->mmap_addr - libref->txt_offset + mte->eh_hdr.p_offset)) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -310,8 +311,8 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
||||
|
||||
mte->loadseg[mte->loadsegs++] = phdr;
|
||||
|
||||
if (loadbase > phdr.p_vaddr)
|
||||
loadbase = phdr.p_vaddr;
|
||||
if (loadbase > phdr.p_offset)
|
||||
loadbase = phdr.p_offset;
|
||||
|
||||
if (loadsize < phdr.p_offset + phdr.p_filesz)
|
||||
loadsize = phdr.p_offset + phdr.p_filesz;
|
||||
@ -344,12 +345,12 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s:%d %s loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, filename, loadbase, loadsize);
|
||||
//fprintf(stderr, "%s:%d %s loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, filename, loadbase, loadsize);
|
||||
mte->loadbase = loadbase & ~PAGEALIGN;
|
||||
mte->loadsize = (loadsize + (loadbase - mte->loadbase) + PAGEALIGN) & ~PAGEALIGN;
|
||||
fprintf(stderr, "%s:%d loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, mte->loadbase, mte->loadsize);
|
||||
//fprintf(stderr, "%s:%d loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, mte->loadbase, mte->loadsize);
|
||||
|
||||
debug(DEBUG_FUNCTION, "filename=`%s' mmap_offset=%#llx addr=%#llx size=%#llx",
|
||||
debug(DEBUG_FUNCTION, "filename=`%s' text offset=%#llx addr=%#llx size=%#llx",
|
||||
filename,
|
||||
(unsigned long long)mte->txt_hdr.p_offset,
|
||||
(unsigned long long)mte->txt_hdr.p_vaddr + bias,
|
||||
|
||||
13
report.c
13
report.c
@ -189,16 +189,17 @@ static void report_delete_array(struct task *task, struct library_symbol *libsym
|
||||
|
||||
static void _report_realloc(struct task *task, struct library_symbol *libsym)
|
||||
{
|
||||
unsigned long addr = fetch_param(task, 0);
|
||||
unsigned long size = fetch_param(task, 1);
|
||||
unsigned long ret = fetch_retval(task);
|
||||
|
||||
if (!addr) {
|
||||
if (!task->in_realloc) {
|
||||
if (ret)
|
||||
report_alloc(task, MT_REALLOC, ret, size, options.bt_depth, libsym);
|
||||
return;
|
||||
}
|
||||
|
||||
task->in_realloc = 0;
|
||||
|
||||
if (ret)
|
||||
report_alloc(task, MT_REALLOC, ret, size, options.bt_depth, libsym);
|
||||
|
||||
@ -224,9 +225,13 @@ static void report_realloc(struct task *task, struct library_symbol *libsym)
|
||||
{
|
||||
unsigned long addr = fetch_param(task, 0);
|
||||
|
||||
if (addr)
|
||||
assert(!task->in_realloc);
|
||||
|
||||
if (addr) {
|
||||
task->in_realloc = 1;
|
||||
report_alloc(task, MT_REALLOC_ENTER, addr, task->pid, options.sanity ? options.bt_depth : 0, libsym);
|
||||
}
|
||||
}
|
||||
|
||||
static void _report_calloc(struct task *task, struct library_symbol *libsym)
|
||||
{
|
||||
@ -440,7 +445,7 @@ int _report_map(struct task *task, struct library *lib, enum mt_operation op)
|
||||
struct mt_map_payload *payload = alloca(sizeof(struct mt_map_payload) + len);
|
||||
|
||||
payload->addr = libref->txt_vaddr;
|
||||
payload->offset = libref->mmap_offset;
|
||||
payload->offset = libref->txt_offset;
|
||||
payload->size = libref->txt_size;
|
||||
payload->bias = libref->bias;
|
||||
|
||||
|
||||
@ -127,10 +127,10 @@ static int child_event(struct task *task, enum event_type ev)
|
||||
{
|
||||
unsigned long data = 0;
|
||||
|
||||
debug(DEBUG_EVENT, "child event %d pid=%d, newpid=%d", ev, task->pid, task->event.e_un.newpid);
|
||||
debug(DEBUG_TRACE, "child event %d pid=%d, newpid=%d", ev, task->pid, task->event.e_un.newpid);
|
||||
|
||||
if (unlikely(ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1))
|
||||
debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
||||
debug(DEBUG_TRACE, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
||||
|
||||
int pid = data;
|
||||
|
||||
@ -161,7 +161,7 @@ static int _process_event(struct task *task, int status)
|
||||
assert(task->event.type == EVENT_NONE);
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
debug(DEBUG_EVENT, "EXIT_SIGNAL: pid=%d, signum=%d", task->pid, task->event.e_un.signum);
|
||||
debug(DEBUG_TRACE, "EXIT_SIGNAL: pid=%d, signum=%d", task->pid, task->event.e_un.signum);
|
||||
|
||||
task->event.type = EVENT_EXIT_SIGNAL;
|
||||
task->event.e_un.signum = WTERMSIG(status);
|
||||
@ -169,7 +169,7 @@ static int _process_event(struct task *task, int status)
|
||||
}
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
debug(DEBUG_EVENT, "EXIT: pid=%d, status=%d", task->pid, task->event.e_un.ret_val);
|
||||
debug(DEBUG_TRACE, "EXIT: pid=%d, status=%d", task->pid, task->event.e_un.ret_val);
|
||||
|
||||
task->event.type = EVENT_EXIT;
|
||||
task->event.e_un.ret_val = WEXITSTATUS(status);
|
||||
@ -201,26 +201,26 @@ static int _process_event(struct task *task, int status)
|
||||
case 0:
|
||||
break;
|
||||
case PTRACE_EVENT_VFORK:
|
||||
debug(DEBUG_EVENT, "VFORK: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid);
|
||||
debug(DEBUG_TRACE, "VFORK: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid);
|
||||
return child_event(task, EVENT_VFORK);
|
||||
case PTRACE_EVENT_FORK:
|
||||
debug(DEBUG_EVENT, "FORK: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid);
|
||||
debug(DEBUG_TRACE, "FORK: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid);
|
||||
return child_event(task, EVENT_FORK);
|
||||
case PTRACE_EVENT_CLONE:
|
||||
debug(DEBUG_EVENT, "CLONE: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid);
|
||||
debug(DEBUG_TRACE, "CLONE: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid);
|
||||
return child_event(task, EVENT_CLONE);
|
||||
case PTRACE_EVENT_EXEC:
|
||||
task->event.type = EVENT_EXEC;
|
||||
debug(DEBUG_EVENT, "EXEC: pid=%d", task->pid);
|
||||
debug(DEBUG_TRACE, "EXEC: pid=%d", task->pid);
|
||||
return 0;
|
||||
case PTRACE_EVENT_EXIT:
|
||||
{
|
||||
unsigned long data = 0;
|
||||
|
||||
debug(DEBUG_EVENT, "ABOUT_EXIT: pid=%d", task->pid);
|
||||
debug(DEBUG_TRACE, "ABOUT_EXIT: pid=%d", task->pid);
|
||||
|
||||
if (unlikely(ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1))
|
||||
debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
||||
debug(DEBUG_TRACE, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
||||
|
||||
task->event.e_un.ret_val = WEXITSTATUS(data);
|
||||
task->event.type = EVENT_ABOUT_EXIT;
|
||||
@ -253,7 +253,7 @@ static int _process_event(struct task *task, int status)
|
||||
task->event.type = EVENT_SIGNAL;
|
||||
task->event.e_un.signum = sig;
|
||||
|
||||
debug(DEBUG_EVENT, "SIGNAL: pid=%d, signum=%d", task->pid, sig);
|
||||
debug(DEBUG_TRACE, "SIGNAL: pid=%d, signum=%d", task->pid, sig);
|
||||
return sig;
|
||||
}
|
||||
|
||||
@ -334,7 +334,7 @@ static struct task * process_event(struct task *task, int status)
|
||||
task->event.type = EVENT_BREAKPOINT;
|
||||
task->event.e_un.breakpoint = breakpoint_get(bp);
|
||||
|
||||
debug(DEBUG_EVENT, "BREAKPOINT: pid=%d, addr=%#lx", task->pid, task->event.e_un.breakpoint->addr);
|
||||
debug(DEBUG_TRACE, "BREAKPOINT: pid=%d, addr=%#lx", task->pid, task->event.e_un.breakpoint->addr);
|
||||
|
||||
return task;
|
||||
}
|
||||
@ -467,7 +467,7 @@ static void do_stop_cb(struct task *task, void *data)
|
||||
if (task->stopped)
|
||||
return;
|
||||
|
||||
debug(DEBUG_EVENT, "task stop pid=%d", task->pid);
|
||||
debug(DEBUG_TRACE, "task stop pid=%d", task->pid);
|
||||
|
||||
task_kill(task, SIGSTOP);
|
||||
}
|
||||
@ -478,7 +478,7 @@ void stop_threads(struct task *task)
|
||||
|
||||
assert(task->leader != NULL);
|
||||
|
||||
debug(DEBUG_EVENT, "stop threads pid=%d", task->pid);
|
||||
debug(DEBUG_TRACE, "stop threads pid=%d", task->pid);
|
||||
|
||||
if (leader->threads != leader->threads_stopped) {
|
||||
struct timespec start;
|
||||
@ -581,7 +581,7 @@ struct task *wait_event(void)
|
||||
pid = wait_task(NULL, &status);
|
||||
if (unlikely(pid == -1)) {
|
||||
if (errno == ECHILD)
|
||||
debug(DEBUG_EVENT, "No more traced programs");
|
||||
debug(DEBUG_TRACE, "No more traced programs");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -631,10 +631,10 @@ struct task *wait_event(void)
|
||||
if (unlikely(options.verbose))
|
||||
fprintf(stderr, "!!!%s: exit event for stopped pid=%d\n", __func__, task->pid);
|
||||
|
||||
debug(DEBUG_EVENT, "ABOUT_EXIT: pid=%d", task->pid);
|
||||
debug(DEBUG_TRACE, "ABOUT_EXIT: pid=%d", task->pid);
|
||||
|
||||
if (unlikely(ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1))
|
||||
debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
||||
debug(DEBUG_TRACE, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
||||
|
||||
task->event.e_un.ret_val = WEXITSTATUS(data);
|
||||
task->event.type = EVENT_ABOUT_EXIT;
|
||||
|
||||
1
task.c
1
task.c
@ -283,6 +283,7 @@ struct task *task_new(pid_t pid)
|
||||
task->attached = 0;
|
||||
task->stopped = 0;
|
||||
task->bp_skipped = 0;
|
||||
task->in_realloc = 0;
|
||||
task->is_new = 1;
|
||||
task->defer_func = NULL;
|
||||
task->defer_data = NULL;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user