diff --git a/backend.h b/backend.h index aabf329..5efaeb4 100644 --- a/backend.h +++ b/backend.h @@ -34,16 +34,19 @@ #include #include -/* Convert a PID to a path to the corresponding binary. */ +/* Convert a pid to a path to the corresponding binary. */ char *pid2name(pid_t pid); -/* Given a PID, find a leader of thread group. */ +/* return the cwd of a pid. */ +char *pid2cwd(pid_t pid); + +/* Given a pid, find a leader of thread group. */ pid_t process_leader(pid_t pid); -/* Given a PID of leader thread, fill in PIDs of all the tasks. The - * function will initialize the pointer *RET_TASKS to a +/* Given a pid of leader thread, fill in pids of all the tasks. The + * function will initialize the pointer *ret_tasks to a * newly-allocated array, and will store number of elements in that - * array to *RET_N. You have to free that buffer when you don't need + * array to *ret_n. You have to free that buffer when you don't need * it anymore. */ int process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n); @@ -56,8 +59,7 @@ void trace_me(void); /* stop tracing a task. */ int untrace_task(struct task *task, int signum); -/* Called when mtrace needs to attach to task, such as when it attaches - * to a running process, whose PID is given on the command line. */ +/* Called when mtrace needs to attach to task */ int trace_attach(struct task *task); /* wait for a task ready for tracing */ @@ -127,7 +129,7 @@ int linkmap_init(struct task *task, arch_addr_t dyn_addr); /* This should extract entry point address and interpreter (dynamic * linker) bias if possible. Returns 0 if there were no errors, -1 - * otherwise. Sets *ENTRYP and *INTERP_BIASP to non-zero values if + * otherwise. Sets *entryp and *interp_biasp to non-zero values if * the corresponding value is known, or zero otherwise; this is not * done for pointers that are NULL. */ int process_get_entry(struct task *task, unsigned long *entryp, unsigned long *interp_biasp); diff --git a/mtelf.c b/mtelf.c index aa0fdb5..6e0552c 100644 --- a/mtelf.c +++ b/mtelf.c @@ -48,14 +48,32 @@ #include "common.h" #include "report.h" -static int open_elf(struct mt_elf *mte, const char *filename) +static int open_elf(struct mt_elf *mte, struct task *task, const char *filename) { - mte->filename = filename; + char *cwd; - if (options.cwd != -1) - mte->fd = openat(options.cwd, filename, O_RDONLY); - else - mte->fd = open(filename, O_RDONLY); + mte->filename = filename; + mte->fd = -1; + + cwd = pid2cwd(task->pid); + if (cwd) { + int fd = open(cwd, O_RDONLY|O_DIRECTORY); + + if (fd != -1) { + mte->fd = openat(fd, filename, O_RDONLY); + + close(fd); + } + + free(cwd); + } + + if (mte->fd == -1) { + if (options.cwd != -1) + mte->fd = openat(options.cwd, filename, O_RDONLY); + else + mte->fd = open(filename, O_RDONLY); + } if (mte->fd == -1) return 1; @@ -236,11 +254,11 @@ static void close_elf(struct mt_elf *mte) } } -static int elf_read(struct mt_elf *mte, const char *filename, GElf_Addr bias) +static int elf_read(struct mt_elf *mte, struct task *task, const char *filename, GElf_Addr bias) { debug(DEBUG_FUNCTION, "filename=%s", filename); - if (open_elf(mte, filename) < 0) + if (open_elf(mte, task, filename) < 0) return -1; GElf_Phdr phdr; @@ -351,7 +369,7 @@ int elf_read_library(struct task *task, struct library *lib, const char *filenam library_set_filename(lib, filename); - if (elf_read(&mte, filename, bias) == -1) + if (elf_read(&mte, task, filename, bias) == -1) return -1; mte.bias = bias; @@ -456,7 +474,7 @@ struct library *elf_read_main_binary(struct task *task) library_set_filename(lib, strdup(fname)); - if (elf_read(&mte, filename, 0) == -1) + if (elf_read(&mte, task, filename, 0) == -1) goto fail3; task->is_64bit = is_64bit(&mte); @@ -490,7 +508,7 @@ struct library *elf_read_main_binary(struct task *task) copy_str_from_proc(task, ARCH_ADDR_T(mte.interp), fname, sizeof(fname)); - if (!elf_read(&mte_ld, fname, (GElf_Addr)base)) { + if (!elf_read(&mte_ld, task, fname, (GElf_Addr)base)) { mte_ld.bias = (GElf_Addr)base; mte_ld.entry_addr = mte_ld.ehdr.e_entry + (GElf_Addr)base; diff --git a/sysdeps/linux-gnu/proc.c b/sysdeps/linux-gnu/proc.c index cf7467c..ff3c59a 100644 --- a/sysdeps/linux-gnu/proc.c +++ b/sysdeps/linux-gnu/proc.c @@ -71,6 +71,24 @@ char *pid2name(pid_t pid) return strdup(proc_exe); } +/* + * Returns a (malloc'd) file name corresponding to a running pid + */ +char *pid2cwd(pid_t pid) +{ + int ret; + char fname[PATH_MAX]; + PROC_PID_FILE(proc_cwd, "/proc/%d/cwd", pid); + + ret = readlink(proc_cwd, fname, sizeof(fname) - 1); + if (ret == -1) + return NULL; + + fname[ret] = 0; + + return strdup(fname); +} + static FILE *open_status_file(pid_t pid) { PROC_PID_FILE(fn, "/proc/%d/status", pid);