mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-06 16:56:41 +08:00
fix attach for 64 bit processes
init the backtrace for the cloned threads after the leader is initialized
This commit is contained in:
parent
201ac47155
commit
e3652d8901
20
dwarf.c
20
dwarf.c
@ -467,7 +467,7 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
|
||||
struct dwarf_addr_space *indirect_as = as;
|
||||
arch_addr_t val, initial_addr = *addr;
|
||||
arch_addr_t gp = as->cursor.lib->gp;
|
||||
int is_64bit = as->task->is_64bit;
|
||||
int is_64bit = task_is_64bit(as->task);
|
||||
void *tmp_ptr;
|
||||
int ret;
|
||||
union {
|
||||
@ -641,7 +641,7 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
||||
"address-unit sized constants". The `R' augmentation can be used
|
||||
to override this, but by default, we pick an address-sized unit
|
||||
for fde_encoding. */
|
||||
if (as->task->is_64bit)
|
||||
if (task_is_64bit(as->task))
|
||||
fde_encoding = DW_EH_PE_udata8;
|
||||
else
|
||||
fde_encoding = DW_EH_PE_udata4;
|
||||
@ -958,8 +958,8 @@ static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip
|
||||
|
||||
dci->start_ip -= ARCH_ADDR_T(lib->image_addr) - lib->load_addr;
|
||||
|
||||
if (!as->task->is_64bit)
|
||||
dci->start_ip = (uint32_t)dci->start_ip;
|
||||
if (!task_is_64bit(as->task))
|
||||
dci->start_ip &= 0xffffffff;
|
||||
|
||||
if (ip < dci->start_ip || ip >= dci->start_ip + dci->ip_range) {
|
||||
debug(DEBUG_DWARF, "IP %#lx out of range %#lx-%#lx", ip, dci->start_ip, dci->start_ip + dci->ip_range);
|
||||
@ -991,11 +991,11 @@ int dwarf_get(struct dwarf_addr_space *as, struct dwarf_loc loc, arch_addr_t *va
|
||||
if (DWARF_IS_REG_LOC(loc))
|
||||
return dwarf_access_reg(as, val, valp);
|
||||
|
||||
if (!as->task->is_64bit)
|
||||
if (!task_is_64bit(as->task))
|
||||
val &= 0xffffffff;
|
||||
|
||||
if (DWARF_IS_MEM_LOC(loc))
|
||||
return dwarf_readw(as, &val, valp, as->task->is_64bit);
|
||||
return dwarf_readw(as, &val, valp, task_is_64bit(as->task));
|
||||
|
||||
*valp = val;
|
||||
return 0;
|
||||
@ -1331,7 +1331,7 @@ static int parse_fde(struct dwarf_addr_space *as, arch_addr_t ip, struct dwarf_r
|
||||
|
||||
static long sword(struct dwarf_addr_space *as, arch_addr_t val)
|
||||
{
|
||||
if (as->task->is_64bit)
|
||||
if (task_is_64bit(as->task))
|
||||
return (int64_t)val;
|
||||
else
|
||||
return (int32_t)val;
|
||||
@ -1348,7 +1348,7 @@ static arch_addr_t read_operand(struct dwarf_addr_space *as, arch_addr_t *addr,
|
||||
int ret;
|
||||
|
||||
if (operand_type == ADDR) {
|
||||
if (as->task->is_64bit)
|
||||
if (task_is_64bit(as->task))
|
||||
operand_type = VAL64;
|
||||
else
|
||||
operand_type = VAL32;
|
||||
@ -1509,7 +1509,7 @@ do { \
|
||||
break;
|
||||
case DW_OP_deref:
|
||||
tmp1 = pop();
|
||||
if ((ret = dwarf_readw(as, &tmp1, &tmp2, as->task->is_64bit)) < 0)
|
||||
if ((ret = dwarf_readw(as, &tmp1, &tmp2, task_is_64bit(as->task))) < 0)
|
||||
return ret;
|
||||
push(tmp2);
|
||||
break;
|
||||
@ -1945,7 +1945,7 @@ fail:
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < 16; ++i) {
|
||||
if (dwarf_readw(as, &cfa, &ip, as->task->is_64bit))
|
||||
if (dwarf_readw(as, &cfa, &ip, task_is_64bit(as->task)))
|
||||
break;
|
||||
|
||||
if (!dwarf_locate_map(as, ip)) {
|
||||
|
||||
2
dwarf.h
2
dwarf.h
@ -46,7 +46,7 @@
|
||||
#define DWARF_IS_REG_LOC(l) ((l).type == DWARF_LOC_TYPE_REG)
|
||||
#define DWARF_IS_VAL_LOC(l) ((l).type == DWARF_LOC_TYPE_VAL)
|
||||
|
||||
#define DWARF_ADDR_SIZE(as) ((as)->task->is_64bit ? 8 : 4)
|
||||
#define DWARF_ADDR_SIZE(as) (task_is_64bit((as)->task) ? 8 : 4)
|
||||
|
||||
#define DWARF_ENOMEM 1 /* out of memory */
|
||||
#define DWARF_EBADREG 2 /* bad register number */
|
||||
|
||||
1
event.c
1
event.c
@ -265,7 +265,6 @@ static struct task *handle_breakpoint(struct task *task)
|
||||
}
|
||||
|
||||
if (breakpoint_on_hit(task, bp)) {
|
||||
set_instruction_pointer(task, bp->addr);
|
||||
continue_task(task, 0);
|
||||
return task;
|
||||
}
|
||||
|
||||
8
report.c
8
report.c
@ -98,7 +98,7 @@ static int report_alloc(struct task *task, enum mt_operation op, unsigned long p
|
||||
|
||||
debug(DEBUG_FUNCTION, "%d [%d]: %#lx %lu", op, task->pid, ptr, size);
|
||||
|
||||
if (task->is_64bit)
|
||||
if (task_is_64bit(task))
|
||||
return report_alloc64(task, op, ptr, size, depth);
|
||||
else
|
||||
return report_alloc32(task, op, ptr, size, depth);
|
||||
@ -202,7 +202,7 @@ static int _report_mmap64(struct task *task, struct library_symbol *libsym)
|
||||
|
||||
size.l = fetch_param(task, 1);
|
||||
|
||||
if (!task->is_64bit) {
|
||||
if (!task_is_64bit(task)) {
|
||||
size.v.v1 = fetch_param(task, 1);
|
||||
size.v.v2 = fetch_param(task, 2);
|
||||
}
|
||||
@ -248,7 +248,7 @@ static int _report_posix_memalign(struct task *task, struct library_symbol *libs
|
||||
unsigned long ptr = fetch_param(task, 0);
|
||||
unsigned long new_ptr;
|
||||
|
||||
if (task->is_64bit)
|
||||
if (task_is_64bit(task))
|
||||
copy_from_proc(task, ARCH_ADDR_T(ptr), &new_ptr, sizeof(new_ptr));
|
||||
else {
|
||||
uint32_t tmp;
|
||||
@ -421,7 +421,7 @@ int report_attach(struct task *task)
|
||||
if (!server_connected())
|
||||
return -1;
|
||||
|
||||
return server_send_msg(task->is_64bit ? MT_ATTACH64 : MT_ATTACH, task->pid, 0, &state, sizeof(state));
|
||||
return server_send_msg(task_is_64bit(task) ? MT_ATTACH64 : MT_ATTACH, task->pid, 0, &state, sizeof(state));
|
||||
}
|
||||
|
||||
int report_fork(struct task *task, struct task *ptask)
|
||||
|
||||
@ -56,9 +56,11 @@ void set_instruction_pointer(struct task *task, arch_addr_t addr)
|
||||
|
||||
task->context.regs.ARM_pc = val;
|
||||
|
||||
if (ptrace(PTRACE_POKEUSER, task->pid, offsetof(struct pt_regs, ARM_pc), val) == -1)
|
||||
if (ptrace(PTRACE_POKEUSER, task->pid, offsetof(struct pt_regs, ARM_pc), val) == -1) {
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "pid=%d Couldn't set instruction pointer: %s\n", task->pid, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
arch_addr_t get_return_addr(struct task *task)
|
||||
{
|
||||
@ -67,8 +69,13 @@ arch_addr_t get_return_addr(struct task *task)
|
||||
|
||||
int fetch_context(struct task *task)
|
||||
{
|
||||
if (ptrace(PTRACE_GETREGS, task->pid, 0, &task->context.regs) == -1)
|
||||
if (ptrace(PTRACE_GETREGS, task->pid, 0, &task->context.regs) == -1) {
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "pid=%d Couldn't fetch register context: %s\n", task->pid, strerror(errno));
|
||||
|
||||
memset(&task->context.regs, 0, sizeof(task->context.regs));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
static inline unsigned long fix_machine(struct task *task, unsigned long val)
|
||||
{
|
||||
if (!task->is_64bit)
|
||||
if (!task_is_64bit(task))
|
||||
val &= 0xffffffff;
|
||||
|
||||
return val;
|
||||
@ -70,9 +70,11 @@ void set_instruction_pointer(struct task *task, arch_addr_t addr)
|
||||
|
||||
task->context.regs.nip = val;
|
||||
|
||||
if (ptrace(PTRACE_POKEUSER, task->pid, (sizeof(unsigned long) * PT_NIP), val) == -1)
|
||||
if (ptrace(PTRACE_POKEUSER, task->pid, sizeof(unsigned long) * PT_NIP, val) == -1) {
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "pid=%d Couldn't set instruction pointer: %s\n", task->pid, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
arch_addr_t get_return_addr(struct task *task)
|
||||
{
|
||||
@ -84,9 +86,13 @@ arch_addr_t get_return_addr(struct task *task)
|
||||
|
||||
int fetch_context(struct task *task)
|
||||
{
|
||||
if (ptrace(PTRACE_GETREGS, task->pid, 0, &task->context.regs) == -1)
|
||||
if (ptrace(PTRACE_GETREGS, task->pid, 0, &task->context.regs) == -1) {
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "pid=%d Couldn't fetch register context: %s\n", task->pid, strerror(errno));
|
||||
|
||||
memset(&task->context.regs, 0, sizeof(task->context.regs));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -146,7 +152,7 @@ unsigned long fetch_param(struct task *task, unsigned int param)
|
||||
break;
|
||||
default:
|
||||
#ifdef __powerpc64__
|
||||
if (task->is_64bit) {
|
||||
if (task_is_64bit(task)) {
|
||||
val = fetch_stack_64(task, param);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ int process_tasks(pid_t pid, pid_t ** ret_tasks, size_t *ret_n)
|
||||
* branch. */
|
||||
static void *select_32_64(struct task *task, void *p32, void *p64)
|
||||
{
|
||||
if (sizeof(long) == 4 || !task->is_64bit)
|
||||
if (sizeof(long) == 4 || !task_is_64bit(task))
|
||||
return p32;
|
||||
else
|
||||
return p64;
|
||||
|
||||
@ -219,7 +219,6 @@ static void process_event(struct task *task, int status)
|
||||
int stop_signal;
|
||||
struct task *leader = task->leader;
|
||||
struct breakpoint *bp = NULL;
|
||||
unsigned int i;
|
||||
arch_addr_t ip;
|
||||
|
||||
assert(leader != NULL);
|
||||
@ -248,11 +247,11 @@ static void process_event(struct task *task, int status)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!leader)
|
||||
return;
|
||||
|
||||
ip = get_instruction_pointer(task);
|
||||
|
||||
#if HW_BREAKPOINTS > 0
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < HW_BREAKPOINTS; ++i) {
|
||||
if (task->hw_bp[i] && task->hw_bp[i]->addr == ip) {
|
||||
bp = task->hw_bp[i];
|
||||
@ -261,13 +260,13 @@ static void process_event(struct task *task, int status)
|
||||
}
|
||||
|
||||
if (bp) {
|
||||
#if HW_BREAKPOINTS > 0
|
||||
assert(bp->type != SW_BP);
|
||||
assert(bp->hw_bp_slot == i);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
bp = breakpoint_find(leader, get_instruction_pointer(task) - DECR_PC_AFTER_BREAK);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bp = breakpoint_find(leader, ip - DECR_PC_AFTER_BREAK);
|
||||
if (!bp)
|
||||
return;
|
||||
assert(bp->type == SW_BP);
|
||||
@ -373,6 +372,7 @@ int trace_attach(struct task *task)
|
||||
assert(task->traced == 0);
|
||||
|
||||
if (ptrace(PTRACE_ATTACH, task->pid, 0, 0) == -1) {
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "PTRACE_ATTACH pid=%d %s\n", task->pid, strerror(errno));
|
||||
trace_fail_warning();
|
||||
return -1;
|
||||
@ -393,6 +393,7 @@ int trace_set_options(struct task *task)
|
||||
debug(DEBUG_PROCESS, "pid=%d", task->pid);
|
||||
|
||||
if (ptrace(PTRACE_SETOPTIONS, task->pid, 0, (void *)options) == -1) {
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "PTRACE_SETOPTIONS pid=%d %s\n", task->pid, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
@ -410,6 +411,7 @@ int continue_task(struct task *task, int signum)
|
||||
task->stopped = 0;
|
||||
|
||||
if (ptrace(PTRACE_CONT, task->pid, 0, fix_signal(task, signum)) == -1) {
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "PTRACE_CONT pid=%d %s\n", task->pid, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ static int set_breakpoint_addr(struct task *task, arch_addr_t addr, unsigned int
|
||||
long ret;
|
||||
|
||||
#ifdef __x86_64__
|
||||
if (!task->is_64bit)
|
||||
if (!task_is_64bit(task))
|
||||
addr &= 0xffffffff;
|
||||
#endif
|
||||
|
||||
|
||||
@ -131,7 +131,7 @@ static int is_plt_entry(struct dwarf_addr_space *as)
|
||||
int dwarf_arch_init(struct dwarf_addr_space *as)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
if (as->task->is_64bit) {
|
||||
if (task_is_64bit(as->task)) {
|
||||
as->ip_reg = arch_reg64.ip;
|
||||
as->ret_reg = arch_reg64.sp;
|
||||
as->num_regs = ARRAY_SIZE(dwarf_to_regnum_map64);
|
||||
@ -151,7 +151,7 @@ int dwarf_arch_init_unwind(struct dwarf_addr_space *as)
|
||||
struct dwarf_cursor *c = &as->cursor;
|
||||
|
||||
#ifdef __x86_64__
|
||||
if (as->task->is_64bit) {
|
||||
if (task_is_64bit(as->task)) {
|
||||
c->loc[DWARF_X86_RAX] = DWARF_REG_LOC(DWARF_X86_RAX);
|
||||
c->loc[DWARF_X86_RDX] = DWARF_REG_LOC(DWARF_X86_RDX);
|
||||
c->loc[DWARF_X86_RCX] = DWARF_REG_LOC(DWARF_X86_RCX);
|
||||
@ -204,7 +204,7 @@ int dwarf_arch_step(struct dwarf_addr_space *as)
|
||||
int ret;
|
||||
|
||||
#ifdef __x86_64__
|
||||
arch_reg = as->task->is_64bit ? &arch_reg64 : &arch_reg32;
|
||||
arch_reg = task_is_64bit(as->task) ? &arch_reg64 : &arch_reg32;
|
||||
#else
|
||||
arch_reg = &arch_reg32;
|
||||
#endif
|
||||
@ -268,7 +268,7 @@ int dwarf_arch_step(struct dwarf_addr_space *as)
|
||||
int dwarf_arch_map_reg(struct dwarf_addr_space *as, unsigned int reg)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
if (as->task->is_64bit) {
|
||||
if (task_is_64bit(as->task)) {
|
||||
if (reg >= ARRAY_SIZE(dwarf_to_regnum_map64))
|
||||
return -DWARF_EBADREG;
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
|
||||
static inline unsigned long fix_machine(struct task *task, unsigned long val)
|
||||
{
|
||||
if (!task->is_64bit)
|
||||
if (!task_is_64bit(task))
|
||||
val &= 0xffffffff;
|
||||
|
||||
return val;
|
||||
@ -75,16 +75,17 @@ void set_instruction_pointer(struct task *task, arch_addr_t addr)
|
||||
return;
|
||||
|
||||
task->context.iregs.rip = val;
|
||||
if (ptrace(PTRACE_POKEUSER, task->pid, (sizeof(unsigned long) * RIP), val) != -1)
|
||||
if (ptrace(PTRACE_POKEUSER, task->pid, sizeof(unsigned long) * RIP, val) != -1)
|
||||
return;
|
||||
#else
|
||||
if (task->context.iregs.eip == (long)val)
|
||||
return;
|
||||
|
||||
task->context.iregs.eip = val;
|
||||
if (ptrace(PTRACE_POKEUSER, task->pid, (sizeof(unsigned long) * EIP), val) != -1)
|
||||
if (ptrace(PTRACE_POKEUSER, task->pid, sizeof(unsigned long) * EIP, val) != -1)
|
||||
return;
|
||||
#endif
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "pid=%d Couldn't set instruction pointer: %s\n", task->pid, strerror(errno));
|
||||
}
|
||||
|
||||
@ -96,7 +97,9 @@ arch_addr_t get_return_addr(struct task *task)
|
||||
|
||||
a = ptrace(PTRACE_PEEKTEXT, task->pid, get_stack_pointer(task), 0);
|
||||
if (a == -1 && errno) {
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "pid=%d Couldn't read return value: %s\n", task->pid, strerror(errno));
|
||||
|
||||
return ARCH_ADDR_T(0);
|
||||
}
|
||||
|
||||
@ -109,7 +112,10 @@ arch_addr_t get_return_addr(struct task *task)
|
||||
int fetch_context(struct task *task)
|
||||
{
|
||||
if (ptrace(PTRACE_GETREGS, task->pid, 0, &task->context.iregs) == -1) {
|
||||
if (errno != ESRCH)
|
||||
fprintf(stderr, "pid=%d Couldn't fetch register context: %s\n", task->pid, strerror(errno));
|
||||
|
||||
memset(&task->context.iregs, 0, sizeof(task->context.iregs));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -156,7 +162,7 @@ static unsigned long fetch_param_64(struct task *task, unsigned int param)
|
||||
unsigned long fetch_param(struct task *task, unsigned int param)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
if (task->is_64bit)
|
||||
if (task_is_64bit(task))
|
||||
return fetch_param_64(task, param);
|
||||
|
||||
unsigned long sp = fix_machine(task, task->saved_context.iregs.rsp);
|
||||
|
||||
21
task.c
21
task.c
@ -403,6 +403,7 @@ static void show_attached(struct task *task, void *data)
|
||||
void open_pid(pid_t pid)
|
||||
{
|
||||
struct task *leader;
|
||||
struct list_head *it;
|
||||
|
||||
debug(DEBUG_PROCESS, "pid=%d", pid);
|
||||
|
||||
@ -441,14 +442,7 @@ void open_pid(pid_t pid)
|
||||
have_all = 1;
|
||||
for (i = 0; i < ntasks; ++i) {
|
||||
if (!pid2task(tasks[i])) {
|
||||
struct task *task = open_one_pid(tasks[i]);
|
||||
|
||||
if (task) {
|
||||
if (backtrace_init(task) < 0) {
|
||||
fprintf(stderr, "Cannot init backtrace for pid %d: %s\n", pid, strerror(errno));
|
||||
goto fail1;
|
||||
}
|
||||
}
|
||||
open_one_pid(tasks[i]);
|
||||
|
||||
have_all = 0;
|
||||
}
|
||||
@ -464,6 +458,17 @@ void open_pid(pid_t pid)
|
||||
if (leader_setup(leader) < 0)
|
||||
goto fail1;
|
||||
|
||||
list_for_each(it, &leader->task_list) {
|
||||
struct task *task = container_of(it, struct task, task_list);
|
||||
|
||||
task->is_64bit = leader->is_64bit;
|
||||
|
||||
if (backtrace_init(task) < 0) {
|
||||
fprintf(stderr, "Cannot init backtrace for pid %d: %s\n", pid, strerror(errno));
|
||||
goto fail1;
|
||||
}
|
||||
};
|
||||
|
||||
if (options.verbose)
|
||||
each_task(leader, &show_attached, NULL);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user