From 48d4b68bb51f67b16ea3182f1fea1ac4f0185915 Mon Sep 17 00:00:00 2001 From: Guy Bortnikov Date: Thu, 6 May 2021 15:31:40 +0300 Subject: [PATCH] fetch comm of pids and support outputing it --- event_fout.c | 4 ++++ phpspy.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++- phpspy.h | 4 ++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/event_fout.c b/event_fout.c index 0f06b1b..dfd951f 100644 --- a/event_fout.c +++ b/event_fout.c @@ -132,6 +132,10 @@ int event_handler_fout(struct trace_context_s *context, int event_type) { try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 1, "# phpv = %s", context->target.phpv)); try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 0, "%c", opt_frame_delim)); } + if (opt_verbose_fields_comm) { + try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 1, "# comm = %s", context->target.comm)); + try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 0, "%c", opt_frame_delim)); + } try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 0, "%c", opt_trace_delim)); } while (0); try(rv, event_handler_fout_write(udata)); diff --git a/phpspy.c b/phpspy.c index 1f8699c..d39516a 100644 --- a/phpspy.c +++ b/phpspy.c @@ -28,6 +28,7 @@ int opt_filter_negate = 0; int opt_verbose_fields_pid = 0; int opt_verbose_fields_ts = 0; int opt_verbose_fields_phpv = 0; +int opt_verbose_fields_comm = 0; int (*opt_event_handler)(struct trace_context_s *context, int event_type) = event_handler_fout; int opt_continue_on_error = 0; int opt_fout_buffer_size = 4096; @@ -55,6 +56,7 @@ static void varpeek_add(char *varspec); static void glopeek_add(char *glospec); static int copy_proc_mem(pid_t pid, const char *what, void *raddr, void *laddr, size_t size); static void try_get_php_version(trace_target_t *target); +static int get_comm_pid(pid_t pid, char *buf, size_t buf_size); #ifdef USE_ZEND static int do_trace(trace_context_t *context); @@ -306,9 +308,11 @@ static void parse_opts(int argc, char **argv) { case 'p': opt_verbose_fields_pid = 1; break; case 't': opt_verbose_fields_ts = 1; break; case 'v': opt_verbose_fields_phpv = 1; break; + case 'c': opt_verbose_fields_comm = 1; break; case 'P': opt_verbose_fields_pid = 0; break; case 'T': opt_verbose_fields_ts = 0; break; - case 'V': opt_verbose_fields_phpv = 1; break; + case 'V': opt_verbose_fields_phpv = 0; break; + case 'C': opt_verbose_fields_comm = 0; break; } } break; @@ -353,6 +357,7 @@ int main_pid(pid_t pid) { memset(&context, 0, sizeof(trace_context_t)); context.target.pid = pid; + get_comm_pid(pid, context.target.comm, sizeof(context.target.comm)); context.event_handler = opt_event_handler; try(rv, find_addresses(&context.target)); try(rv, context.event_handler(&context, PHPSPY_TRACE_EVENT_INIT)); @@ -796,6 +801,55 @@ void log_error(const char *fmt, ...) { } } +static int get_comm_pid(pid_t pid, char *buf, size_t buf_size) { + char proc_fs_path[PATH_MAX]; + char *line; + ssize_t fread_res; + size_t comm_len; + size_t line_len = 0; + + FILE *f = NULL; + snprintf(proc_fs_path, PATH_MAX, "/proc/%d/comm", pid); + + f = fopen(proc_fs_path, "rb"); + if (f == NULL) { + log_error("Couldn't read comm of pid %d - errno %d\n", pid, errno); + goto error; + } + + fread_res = getline(&line, &line_len, f); + if (fread_res == -1) { + log_error("Couldn't read %s file - errno %d\n", proc_fs_path, pid); + goto error; + } + comm_len = (size_t) fread_res - 1; /* remove \n delimiter */ + + +#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) + /* Copy up to comm_len / buf_size the min between them */ + memcpy(buf, line, MIN(buf_size, comm_len)); + free(line); + fclose(f); + + /* Force null termination */ + if (comm_len >= buf_size) { + buf[buf_size] = '\0'; + } else { + buf[comm_len] = '\0'; + } + + return PHPSPY_OK; + +error: + if (f != NULL) { + fclose(f); + } + + strncpy(buf, "UNKNOWN-COMM", buf_size); + buf[buf_size] = '\0'; /* terminate just in case because strncpy doesn't */ + return PHPSPY_ERR; +} + /* TODO figure out a way to make this cleaner */ #ifdef USE_ZEND #include "phpspy_trace.c" diff --git a/phpspy.h b/phpspy.h index 2979f8d..c2e1125 100644 --- a/phpspy.h +++ b/phpspy.h @@ -85,6 +85,8 @@ #define IS_REFERENCE 10 #endif +#define TASK_COMM_LEN (16) /* copied from linux/sched.h */ + typedef struct varpeek_var_s { char name[PHPSPY_STR_SIZE]; UT_hash_handle hh; @@ -145,6 +147,7 @@ typedef struct trace_glopeek_s { typedef struct trace_target_s { pid_t pid; char phpv[4]; + char comm[TASK_COMM_LEN + 1]; /* TASK_COMM_LEN is allowed to be non null terminated if reaches max size, here add null-termination */ uint64_t executor_globals_addr; uint64_t sapi_globals_addr; uint64_t alloc_globals_addr; @@ -191,6 +194,7 @@ extern int opt_filter_negate; extern int opt_verbose_fields_pid; extern int opt_verbose_fields_ts; extern int opt_verbose_fields_phpv; +extern int opt_verbose_fields_comm; extern int opt_continue_on_error; extern int opt_fout_buffer_size; extern long opt_time_limit_ms;