summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheron Spiegl <tspiegl@gmail.com>2020-06-10 00:28:02 -0500
committerTheron Spiegl <tspiegl@gmail.com>2020-06-10 00:28:02 -0500
commit7444090e98299b51b4e4205c8cbd174f3a172796 (patch)
tree1b357b886566134f8fdc874d80e818fa36135254
parentefc171b69f7abf0ad42e58e67af41f945bf38c26 (diff)
debugging launching of chromium-browser and firefox. chromium seems to be fixed, firefox not quite. fclose and typos.
-rw-r--r--src/attach.c24
-rw-r--r--src/utilities.c2
-rw-r--r--src/whatfiles.c88
-rw-r--r--src/whatfiles.h4
4 files changed, 67 insertions, 51 deletions
diff --git a/src/attach.c b/src/attach.c
index ebf02a8..b40739d 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -50,20 +50,23 @@ char read_status(pid_t pid)
c = *(str->data + pmatch[1].rm_so);
}
free(str->data);
+ fclose(h_status);
return c;
}
-void read_task(pid_t tid, struct String *str)
+bool read_task(pid_t tid, struct String *str)
{
char path[128] = {0};
sprintf(path, "/proc/%d/comm", tid);
FILE *h_comm = fopen(path, "rb");
if (!h_comm) {
- fprintf(stderr, "tried to read nonexistent /proc/%d/comm\n", tid);
- exit(1);
+ DEBUG("tried to read nonexistent /proc/%d/comm\n", tid);
+ return false;
}
read_file(str, 4096, h_comm);
if (str->data[str->len-1] == '\n') delete_char(str); // remove newline if present
+ fclose(h_comm);
+ return str->len > 0;
}
int attach_to_process(pid_t pid, HashMap map)
@@ -118,8 +121,9 @@ int attach_to_process(pid_t pid, HashMap map)
insert(tid[t], 0, map);
struct String str = {0};
init_string(&str, 4096);
- read_task(tid[t], &str);
- set_name(tid[t], str.data, map);
+ if (read_task(tid[t], &str)) {
+ set_name(tid[t], str.data, map);
+ }
free(str.data);
}
@@ -137,7 +141,7 @@ int attach_to_process(pid_t pid, HashMap map)
}
// used upon exit as signal handler when whatfiles was used to attach to a process already in progress
-void detatch_from_process(HashMap map)
+void detach_from_process(HashMap map)
{
for (int i = 0; i < map->size; i++) {
pid_t pid = map->keys[i];
@@ -154,17 +158,17 @@ void detatch_from_process(HashMap map)
nanosleep(&ts, &ts);
DEBUG("waiting for PID %d to stop\n", pid);
if (counter > 9) {
- DEBUG("could not detatch from PID %d\n", pid);
+ DEBUG("could not detach from PID %d\n", pid);
break;
}
counter++;
}
- if (counter > 9) continue; // if we weren't able to detatch from this process, move on
+ if (counter > 9) continue; // if we weren't able to detach from this process, move on
do {
r = ptrace(PTRACE_DETACH, pid, (void *)0, (void *)0);
} while (r == -1L && (errno == EBUSY || errno == EFAULT || errno == ESRCH));
- if (r == -1) fprintf(stderr, "error detatching from PID %d\n", pid);
- else DEBUG("detatched from process %d\n", pid);
+ if (r == -1) fprintf(stderr, "error detaching from PID %d\n", pid);
+ else DEBUG("detached from process %d\n", pid);
kill(pid, SIGCONT);
}
}
diff --git a/src/utilities.c b/src/utilities.c
index c1a04ed..9bfecba 100644
--- a/src/utilities.c
+++ b/src/utilities.c
@@ -68,8 +68,8 @@ void get_command(pid_t current_pid, char *command, size_t len)
proc_file = fopen(proc_str, "r");
if (proc_file) {
getline(&command, &len, proc_file);
+ fclose(proc_file);
}
- fclose(proc_file);
}
bool peek_filename(pid_t pid, unsigned long long p_reg, struct String *str)
diff --git a/src/whatfiles.c b/src/whatfiles.c
index ae8c3e1..9681820 100644
--- a/src/whatfiles.c
+++ b/src/whatfiles.c
@@ -34,6 +34,10 @@ void check_syscall(pid_t current_pid, struct user_regs_struct regs, HashMap map)
size_t index;
HashError err = find_index(current_pid, map, &index);
if (err) DEBUG("unknown pid %d, syscall %lld\n", current_pid, regs.orig_rax);
+ // struct String *proc_string = err ? NULL : &map->names[index];
+ // char *proc_name = proc_string && proc_string->data && *proc_string->data
+ // ? proc_string->data
+ // : "[unknown]";
switch (regs.orig_rax)
{
@@ -84,7 +88,7 @@ void check_syscall(pid_t current_pid, struct user_regs_struct regs, HashMap map)
OUTPUT("%s", output.data);
break;
default:
- // DEBUG("syscall: %lld, pid: %d\n", regs.orig_rax, current_pid);
+ // DEBUG("syscall: %lld, pid: %d, %s\n", regs.orig_rax, current_pid, proc_name);
break;
}
free(filename.data);
@@ -99,26 +103,32 @@ void check_ptrace_event(pid_t current_pid, int proc_status, HashMap map)
unsigned long ptrace_event;
long res = ptrace(PTRACE_GETEVENTMSG, current_pid, (char*)0, &ptrace_event);
- if (res == -1L) SYS_ERR("ptrace() failed to get event msg");
+ if (res == -1L) {
+ DEBUG("ptrace() failed to get event msg");
+ return;
+ }
switch (proc_status >> 8)
{
case SIGTRAP | (PTRACE_EVENT_FORK << 8):
DEBUG("caught PTRACE_EVENT_FORK from pid %d. new pid: %ld\n", current_pid, ptrace_event);
insert((pid_t)ptrace_event, ENTRY, map);
- read_task((pid_t)ptrace_event, &new_proc);
- set_name((pid_t)ptrace_event, new_proc.data, map);
+ if (read_task((pid_t)ptrace_event, &new_proc)) {
+ set_name((pid_t)ptrace_event, new_proc.data, map);
+ }
break;
case SIGTRAP | (PTRACE_EVENT_CLONE << 8):
DEBUG("caught PTRACE_EVENT_CLONE from pid %d. new pid: %ld\n", current_pid, ptrace_event);
insert((pid_t)ptrace_event, ENTRY, map);
- read_task((pid_t)ptrace_event, &new_proc);
- set_name((pid_t)ptrace_event, new_proc.data, map);
+ if (read_task((pid_t)ptrace_event, &new_proc)) {
+ set_name((pid_t)ptrace_event, new_proc.data, map);
+ }
break;
case SIGTRAP | (PTRACE_EVENT_VFORK << 8):
DEBUG("caught PTRACE_EVENT_VFORK from pid %d. new pid: %ld\n", current_pid, ptrace_event);
insert((pid_t)ptrace_event, ENTRY, map);
- read_task((pid_t)ptrace_event, &new_proc);
- set_name((pid_t)ptrace_event, new_proc.data, map);
+ if (read_task((pid_t)ptrace_event, &new_proc)) {
+ set_name((pid_t)ptrace_event, new_proc.data, map);
+ }
break;
case SIGTRAP | (PTRACE_EVENT_EXEC << 8):
DEBUG("caught PTRACE_EVENT_EXEC from pid %d. former pid: %ld\n", current_pid, ptrace_event);
@@ -148,31 +158,38 @@ void check_ptrace_event(pid_t current_pid, int proc_status, HashMap map)
free(new_proc.data);
}
-void step_syscall(pid_t current_pid, int proc_status, HashMap map)
+bool step_syscall(pid_t current_pid, int proc_status, HashMap map)
{
long res;
- struct user_regs_struct regs;
-
+ struct user_regs_struct regs;
+ bool could_read = false;
// get current register values
- do {
- res = ptrace(PTRACE_GETREGS, current_pid, &regs, &regs);
- } while (res == -1L && errno == ESRCH);
- if (res == -1L && errno != ESRCH) SYS_ERR("ptrace() failed to get registers");
+ // TODO: make this fault tolerant to a dead PID
+ res = ptrace(PTRACE_GETREGS, current_pid, &regs, &regs);
+ if (res == -1L) {
+ DEBUG("CURRENT PID: %d, failed to get registers\n", current_pid);
+ }
- // If it's the same PID performing the same syscall (has same orig_rax) as last time, we don't care. Just means it's exiting the syscall.
- // Might want to keep for debug mode? This might result in missing some output, in the case where two threads of the same process enter the same syscall before either exits,
- // because they will both return the same PID to wait() when given SIGTRAP as part of the syscall-enter-exit loop. Might also result in double-printing,
- // because if two threads (that report the same PID) enter two different syscalls before either exits, the "last" syscall for the PID won't be the entry by that thread.
- if (!is_exiting(current_pid, regs.orig_rax) /*|| Debug*/) {
- check_syscall(current_pid, regs, map);
+ // can't get some registers for some reason
+ if (regs.orig_rax != -1) {
+ could_read = true;
+ // If it's the same PID performing the same syscall (has same orig_rax) as last time, we don't care. Just means it's exiting the syscall.
+ // Might want to keep for debug mode? This might result in missing some output, in the case where two threads of the same process enter the same syscall before either exits,
+ // because they will both return the same PID to wait() when given SIGTRAP as part of the syscall-enter-exit loop. Might also result in double-printing,
+ // because if two threads (that report the same PID) enter two different syscalls before either exits, the "last" syscall for the PID won't be the entry by that thread.
+ if (!is_exiting(current_pid, regs.orig_rax) /*|| Debug*/) {
+ check_syscall(current_pid, regs, map);
+ }
+ LastSyscall.pid = current_pid;
+ LastSyscall.syscall = regs.orig_rax;
+ check_ptrace_event(current_pid, proc_status, map);
+ // continue, catching next entry or exit from syscall
+ res = ptrace(PTRACE_SYSCALL, current_pid, 0, 0);
+ if (res == -1L) DEBUG("ptrace() failed to resume");
+ } else {
+ DEBUG("can't get registers\n");
}
- LastSyscall.pid = current_pid;
- LastSyscall.syscall = regs.orig_rax;
- check_ptrace_event(current_pid, proc_status, map);
- // continue, catching next entry or exit from syscall
- res = ptrace(PTRACE_SYSCALL, current_pid, 0, 0);
- if (res == -1L) SYS_ERR("ptrace() failed to resume");
- fflush(stdout);
+ return could_read;
}
int main(int argc, char* argv[])
@@ -209,7 +226,6 @@ int main(int argc, char* argv[])
}
DEBUG("whatfiles pid: %d\n", getpid());
- fflush(stdout);
if (attach) {
OUTPUT("attaching to pid %d\n", pid);
@@ -219,7 +235,6 @@ int main(int argc, char* argv[])
// child process starts here
if((pid = fork()) == 0) {
DEBUG("whatfiles child pid: %d\n", getpid());
- fflush(stdout);
sys_err = ptrace(PTRACE_TRACEME, 0, 0, 0);
if (sys_err == -1) SYS_ERR("ptrace() failed to TRACEME");
/*
@@ -269,7 +284,7 @@ int main(int argc, char* argv[])
// options should be in place and all processes/threads should be resumed with PTRACE_SYSCALL
// if we're attaching to a process already in progress, block SIGINT and SIGTERM signals
- // so that we can detatch from everything if whatfiles is closed while the process is still running
+ // so that we can detach from everything if whatfiles is closed while the process is still running
sigset_t block_mask, pending_mask;
if (attach) {
sigemptyset(&block_mask);
@@ -284,26 +299,23 @@ int main(int argc, char* argv[])
sigpending(&pending_mask);
if (sigismember(&pending_mask, SIGINT) || sigismember(&pending_mask, SIGTERM)) {
DEBUG("pending signal caught\n");
- detatch_from_process(hashmap);
+ detach_from_process(hashmap);
exit(errno);
}
}
// catch any traced process' or thread's next state change
- // can't call wait here if we don't actually have a child process...
pid = wait(&status);
if (pid == -1) SYS_ERR("waiting for any child process failed");
- if (WIFEXITED(status)) {
+ if (WIFEXITED(status) || WIFSIGNALED(status)) {
DEBUG("exited %d at entry to syscall\n", pid);
- fflush(stdout);
err = remove_pid(pid, hashmap);
- HASH_ERR_CHECK(err, "deletion from hashmap failed.");
+ DEBUG("deletion of %d from hashmap failed\n", pid);
}
if (WIFSTOPPED(status)) {
- step_syscall(pid, status, hashmap);
+ /*bool could_read = */ step_syscall(pid, status, hashmap);
}
if (hashmap->used == 0) {
DEBUG("all children exited\n");
- fflush(stdout);
break;
}
}
diff --git a/src/whatfiles.h b/src/whatfiles.h
index 681638c..1738010 100644
--- a/src/whatfiles.h
+++ b/src/whatfiles.h
@@ -53,9 +53,9 @@ void about();
// attach.c
size_t get_tids(pid_t **const listptr, size_t *const sizeptr, const pid_t pid);
int attach_to_process(pid_t pid, HashMap map);
-void detatch_from_process(HashMap map);
+void detach_from_process(HashMap map);
void read_file(struct String *str, size_t size, FILE *file);
char read_status(pid_t pid);
-void read_task(pid_t tid, struct String *str);
+bool read_task(pid_t tid, struct String *str);
#endif /* !WHATFILES_H */