static FILE * open_status_file(pid_t pid) { PROC_PID_FILE(fn, "/proc/%d/status", pid); /* Don't complain if we fail. This would typically happen when the process is about to terminate, and these files are not available anymore. This function is called from the event loop, and we don't want to clutter the output just because the process terminates. */ return fopen(fn, "r"); }
int process_get_entry(struct Process *proc, arch_addr_t *entryp, arch_addr_t *interp_biasp) { PROC_PID_FILE(fn, "/proc/%d/auxv", proc->pid); int fd = open(fn, O_RDONLY); int ret = 0; if (fd == -1) { fail: fprintf(stderr, "couldn't read %s: %s", fn, strerror(errno)); ret = -1; done: if (fd != -1) close(fd); return ret; } arch_addr_t at_entry = 0; arch_addr_t at_bias = 0; while (1) { Elf64_auxv_t entry = {}; if (auxv_fetcher(proc)(fd, &entry) < 0) goto fail; switch (entry.a_type) { case AT_BASE: /* XXX The double cast should be removed when * arch_addr_t becomes integral type. */ at_bias = (arch_addr_t)(uintptr_t)entry.a_un.a_val; continue; case AT_ENTRY: /* XXX The double cast should be removed when * arch_addr_t becomes integral type. */ at_entry = (arch_addr_t)(uintptr_t)entry.a_un.a_val; default: continue; case AT_NULL: break; } break; } if (entryp != NULL) *entryp = at_entry; if (interp_biasp != NULL) *interp_biasp = at_bias; goto done; }
/* * Returns a (malloc'd) file name corresponding to a running pid */ char * pid2name(pid_t pid) { if (!kill(pid, 0)) { int delay = 0; PROC_PID_FILE(proc_exe, "/proc/%d/exe", pid); while (delay < MAX_DELAY) { if (!access(proc_exe, F_OK)) { return strdup(proc_exe); } delay += 1000; /* 1 milisecond */ } } return NULL; }
int process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n) { PROC_PID_FILE(fn, "/proc/%d/task", pid); DIR * d = opendir(fn); if (d == NULL) return -1; pid_t *tasks = NULL; size_t n = 0; size_t alloc = 0; while (1) { struct dirent entry; struct dirent *result; if (readdir_r(d, &entry, &result) != 0) { free(tasks); return -1; } if (result == NULL) break; if (result->d_type == DT_DIR && all_digits(result->d_name)) { pid_t npid = atoi(result->d_name); if (n >= alloc) { alloc = alloc > 0 ? (2 * alloc) : 8; pid_t *ntasks = realloc(tasks, sizeof(*tasks) * alloc); if (ntasks == NULL) { free(tasks); return -1; } tasks = ntasks; } if (n >= alloc) abort(); tasks[n++] = npid; } } closedir(d); *ret_tasks = tasks; *ret_n = n; return 0; }