void open_pid(pid_t pid) { Process *proc; char *filename; if (trace_pid(pid) < 0) { fprintf(stderr, "Cannot attach to pid %u: %s\n", pid, strerror(errno)); return; } filename = pid2name(pid); if (!filename) { fprintf(stderr, "Cannot trace pid %u: %s\n", pid, strerror(errno)); return; } proc = open_program(filename, pid); continue_process(pid); proc->breakpoints_enabled = 1; //modify for android attach_child_thread(proc); }
int process_clone(struct Process *retp, struct Process *proc, pid_t pid) { if (process_bare_init(retp, proc->filename, pid, 0) < 0) { fail1: fprintf(stderr, "failed to clone process %d->%d : %s\n", proc->pid, pid, strerror(errno)); return -1; } retp->tracesysgood = proc->tracesysgood; retp->e_machine = proc->e_machine; retp->e_class = proc->e_class; /* For non-leader processes, that's all we need to do. */ if (retp->leader != retp) return 0; /* Clone symbols first so that we can clone and relink * breakpoints. */ struct library *lib; struct library **nlibp = &retp->libraries; for (lib = proc->leader->libraries; lib != NULL; lib = lib->next) { *nlibp = malloc(sizeof(**nlibp)); if (*nlibp == NULL || library_clone(*nlibp, lib) < 0) { fail2: process_bare_destroy(retp, 0); /* Error when cloning. Unroll what was done. */ for (lib = retp->libraries; lib != NULL; ) { struct library *next = lib->next; library_destroy(lib); free(lib); lib = next; } goto fail1; } nlibp = &(*nlibp)->next; } /* Now clone breakpoints. Symbol relinking is done in * clone_single_bp. */ struct clone_single_bp_data data = { .old_proc = proc, .new_proc = retp, .error = 0, }; dict_apply_to_all(proc->leader->breakpoints, &clone_single_bp, &data); if (data.error < 0) goto fail2; /* And finally the call stack. */ /* XXX clearly the callstack handling should be moved to a * separate module and this whole business extracted to * callstack_clone, or callstack_element_clone. */ memcpy(retp->callstack, proc->callstack, sizeof(retp->callstack)); retp->callstack_depth = proc->callstack_depth; size_t i; for (i = 0; i < retp->callstack_depth; ++i) { struct callstack_element *elem = &retp->callstack[i]; struct fetch_context *ctx = elem->fetch_context; if (ctx != NULL) { struct fetch_context *nctx = fetch_arg_clone(retp, ctx); if (nctx == NULL) { size_t j; fail3: for (j = 0; j < i; ++j) { nctx = elem->fetch_context; fetch_arg_done(nctx); elem->fetch_context = NULL; } goto fail2; } elem->fetch_context = nctx; } struct value_dict *args = elem->arguments; if (args != NULL) { struct value_dict *nargs = malloc(sizeof(*nargs)); if (nargs == NULL || val_dict_clone(nargs, args) < 0) { size_t j; for (j = 0; j < i; ++j) { nargs = elem->arguments; val_dict_destroy(nargs); free(nargs); elem->arguments = NULL; } /* Pretend that this round went well, * so that fail3 frees I-th * fetch_context. */ ++i; goto fail3; } elem->arguments = nargs; } /* If it's not a syscall, we need to find the * corresponding library symbol in the cloned * library. */ if (!elem->is_syscall && elem->c_un.libfunc != NULL) { struct library_symbol *libfunc = elem->c_un.libfunc; int rc = proc_find_symbol(retp, libfunc, NULL, &elem->c_un.libfunc); assert(rc == 0); } } /* At this point, retp is fully initialized, except for OS and * arch parts, and we can call private_process_destroy. */ if (os_process_clone(retp, proc) < 0) { private_process_destroy(retp, 0); return -1; } if (arch_process_clone(retp, proc) < 0) { os_process_destroy(retp); private_process_destroy(retp, 0); return -1; } return 0; } static int open_one_pid(pid_t pid) { Process *proc; char *filename; debug(DEBUG_PROCESS, "open_one_pid(pid=%d)", pid); /* Get the filename first. Should the trace_pid fail, we can * easily free it, untracing is more work. */ if ((filename = pid2name(pid)) == NULL || trace_pid(pid) < 0) { fail: free(filename); return -1; } proc = open_program(filename, pid); if (proc == NULL) goto fail; free(filename); trace_set_options(proc); return 0; }