From 4758fb42ce97d4d0af34dfc9ee96e8de2fe564da Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Wed, 24 Feb 2021 17:50:36 -0800 Subject: [PATCH] capture: add pid-root frame type While I'm not thrilled to add new frame types for every sort of thing, I think having this will be relatively useful so we can improve decoding operations. This adds SysprofCapturePidRoot which lets us specify a root directory on the host system for which is the real root (/) of the PID. This can be useful when reconstructing overlays for containers and you need to direct access to alternate roots. The layer gives us some ability to try to deal with overlayfs, albeit at a very rudimentary level. In most cases I anticipate we just deal with the main root and ignore overlays until necessary. --- .../sysprof-capture-cursor.c | 4 ++ .../sysprof-capture-reader.c | 51 +++++++++++++++++++ .../sysprof-capture-reader.h | 2 + .../sysprof-capture-types.h | 13 ++++- .../sysprof-capture-writer-cat.c | 18 ++++++- .../sysprof-capture-writer.c | 33 ++++++++++++ .../sysprof-capture-writer.h | 7 +++ src/tools/sysprof-dump.c | 12 +++++ 8 files changed, 138 insertions(+), 2 deletions(-) diff --git a/src/libsysprof-capture/sysprof-capture-cursor.c b/src/libsysprof-capture/sysprof-capture-cursor.c index 6d4c83a5..eab3acae 100644 --- a/src/libsysprof-capture/sysprof-capture-cursor.c +++ b/src/libsysprof-capture/sysprof-capture-cursor.c @@ -223,6 +223,10 @@ sysprof_capture_cursor_foreach (SysprofCaptureCursor *self, delegate = READ_DELEGATE (sysprof_capture_reader_read_allocation); break; + case SYSPROF_CAPTURE_FRAME_PID_ROOT: + delegate = READ_DELEGATE (sysprof_capture_reader_read_pid_root); + break; + default: if (!sysprof_capture_reader_skip (self->reader)) return; diff --git a/src/libsysprof-capture/sysprof-capture-reader.c b/src/libsysprof-capture/sysprof-capture-reader.c index b07ad2dc..5ba52730 100644 --- a/src/libsysprof-capture/sysprof-capture-reader.c +++ b/src/libsysprof-capture/sysprof-capture-reader.c @@ -353,6 +353,17 @@ sysprof_capture_reader_bswap_mark (SysprofCaptureReader *self, mark->duration = bswap_64 (mark->duration); } +static inline void +sysprof_capture_reader_bswap_pid_root (SysprofCaptureReader *self, + SysprofCapturePidRoot *pr) +{ + assert (self != NULL); + assert (pr != NULL); + + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) + pr->layer = bswap_32 (pr->layer); +} + static inline void sysprof_capture_reader_bswap_jitmap (SysprofCaptureReader *self, SysprofCaptureJitmap *jitmap) @@ -679,6 +690,46 @@ sysprof_capture_reader_read_mark (SysprofCaptureReader *self) return mark; } +const SysprofCapturePidRoot * +sysprof_capture_reader_read_pid_root (SysprofCaptureReader *self) +{ + SysprofCapturePidRoot *pr; + + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); + + if (!sysprof_capture_reader_ensure_space_for (self, sizeof *pr + 1)) + return NULL; + + pr = (SysprofCapturePidRoot *)(void *)&self->buf[self->pos]; + + sysprof_capture_reader_bswap_frame (self, &pr->frame); + + if (pr->frame.type != SYSPROF_CAPTURE_FRAME_PID_ROOT) + return NULL; + + if (pr->frame.len < (sizeof *pr + 1)) + return NULL; + + if (!sysprof_capture_reader_ensure_space_for (self, pr->frame.len)) + return NULL; + + pr = (SysprofCapturePidRoot *)(void *)&self->buf[self->pos]; + + sysprof_capture_reader_bswap_pid_root (self, pr); + + self->pos += pr->frame.len; + + if ((self->pos % SYSPROF_CAPTURE_ALIGN) != 0) + return NULL; + + /* Ensure trailing \0 in name and message */ + ((char *)pr)[pr->frame.len-1] = 0; + + return pr; +} + const SysprofCaptureMetadata * sysprof_capture_reader_read_metadata (SysprofCaptureReader *self) { diff --git a/src/libsysprof-capture/sysprof-capture-reader.h b/src/libsysprof-capture/sysprof-capture-reader.h index 0fdd8b37..1d7b72a2 100644 --- a/src/libsysprof-capture/sysprof-capture-reader.h +++ b/src/libsysprof-capture/sysprof-capture-reader.h @@ -120,6 +120,8 @@ SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureFileChunk *sysprof_capture_reader_read_file (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_3_36 const SysprofCaptureAllocation *sysprof_capture_reader_read_allocation (SysprofCaptureReader *self); +SYSPROF_AVAILABLE_IN_3_40 +const SysprofCapturePidRoot *sysprof_capture_reader_read_pid_root (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL bool sysprof_capture_reader_reset (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL diff --git a/src/libsysprof-capture/sysprof-capture-types.h b/src/libsysprof-capture/sysprof-capture-types.h index 2f5b4b46..1fbcbec1 100644 --- a/src/libsysprof-capture/sysprof-capture-types.h +++ b/src/libsysprof-capture/sysprof-capture-types.h @@ -139,10 +139,11 @@ typedef enum SYSPROF_CAPTURE_FRAME_LOG = 12, SYSPROF_CAPTURE_FRAME_FILE_CHUNK = 13, SYSPROF_CAPTURE_FRAME_ALLOCATION = 14, + SYSPROF_CAPTURE_FRAME_PID_ROOT = 15, } SysprofCaptureFrameType; /* Not part of ABI */ -#define SYSPROF_CAPTURE_FRAME_LAST 15 +#define SYSPROF_CAPTURE_FRAME_LAST 16 SYSPROF_ALIGNED_BEGIN(1) typedef struct @@ -172,6 +173,15 @@ typedef struct } SysprofCaptureFrame SYSPROF_ALIGNED_END(1); +SYSPROF_ALIGNED_BEGIN(1) +typedef struct +{ + SysprofCaptureFrame frame; + uint32_t layer; + char path[0]; +} SysprofCapturePidRoot +SYSPROF_ALIGNED_END(1); + SYSPROF_ALIGNED_BEGIN(1) typedef struct { @@ -356,6 +366,7 @@ SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureMetadata) == 64, "SysprofCaptureMet SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureLog) == 64, "SysprofCaptureLog changed size"); SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureFileChunk) == 284, "SysprofCaptureFileChunk changed size"); SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureAllocation) == 48, "SysprofCaptureAllocation changed size"); +SYSPROF_STATIC_ASSERT (sizeof (SysprofCapturePidRoot) == 28, "SysprofCapturePidRoot changed size"); SYSPROF_STATIC_ASSERT ((offsetof (SysprofCaptureAllocation, addrs) % SYSPROF_CAPTURE_ALIGN) == 0, "SysprofCaptureAllocation.addrs is not aligned"); SYSPROF_STATIC_ASSERT ((offsetof (SysprofCaptureSample, addrs) % SYSPROF_CAPTURE_ALIGN) == 0, "SysprofCaptureSample.addrs is not aligned"); diff --git a/src/libsysprof-capture/sysprof-capture-writer-cat.c b/src/libsysprof-capture/sysprof-capture-writer-cat.c index a157ed73..0cb69df5 100644 --- a/src/libsysprof-capture/sysprof-capture-writer-cat.c +++ b/src/libsysprof-capture/sysprof-capture-writer-cat.c @@ -108,7 +108,7 @@ compare_by_src (const void *a, return -1; else if (itema->src > itemb->src) return 1; - else + else return 0; } @@ -532,6 +532,22 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self, break; } + case SYSPROF_CAPTURE_FRAME_PID_ROOT: + { + const SysprofCapturePidRoot *frame; + + if (!(frame = sysprof_capture_reader_read_pid_root (reader))) + goto panic; + + sysprof_capture_writer_add_pid_root (self, + frame->frame.time, + frame->frame.cpu, + frame->frame.pid, + frame->path, + frame->layer); + break; + } + default: /* Silently drop, which is better than looping. We could potentially * copy this over using the raw bytes at some point. diff --git a/src/libsysprof-capture/sysprof-capture-writer.c b/src/libsysprof-capture/sysprof-capture-writer.c index 8fa89d2a..5a09b6a9 100644 --- a/src/libsysprof-capture/sysprof-capture-writer.c +++ b/src/libsysprof-capture/sysprof-capture-writer.c @@ -827,6 +827,39 @@ sysprof_capture_writer_add_fork (SysprofCaptureWriter *self, return true; } +bool +sysprof_capture_writer_add_pid_root (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + const char *path, + uint32_t layer) +{ + SysprofCapturePidRoot *ev; + size_t strl = strlen (path); + size_t len = sizeof *ev + strl + 1; + + assert (self != NULL); + + ev = (SysprofCapturePidRoot *)sysprof_capture_writer_allocate (self, &len); + if (!ev) + return false; + + sysprof_capture_writer_frame_init (&ev->frame, + len, + cpu, + pid, + time, + SYSPROF_CAPTURE_FRAME_PID_ROOT); + ev->layer = layer; + memcpy (ev->path, path, strl); + ev->path[strl] = 0; + + self->stat.frame_count[SYSPROF_CAPTURE_FRAME_PID_ROOT]++; + + return true; +} + bool sysprof_capture_writer_add_exit (SysprofCaptureWriter *self, int64_t time, diff --git a/src/libsysprof-capture/sysprof-capture-writer.h b/src/libsysprof-capture/sysprof-capture-writer.h index 8a65726e..2432aee2 100644 --- a/src/libsysprof-capture/sysprof-capture-writer.h +++ b/src/libsysprof-capture/sysprof-capture-writer.h @@ -201,6 +201,13 @@ bool sysprof_capture_writer_add_allocation_copy (Sy int64_t alloc_size, const SysprofCaptureAddress *addrs, unsigned int n_addrs); +SYSPROF_AVAILABLE_IN_3_40 +bool sysprof_capture_writer_add_pid_root (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + const char *path, + uint32_t layer); SYSPROF_AVAILABLE_IN_ALL bool sysprof_capture_writer_flush (SysprofCaptureWriter *self); SYSPROF_AVAILABLE_IN_ALL diff --git a/src/tools/sysprof-dump.c b/src/tools/sysprof-dump.c index 2b3936a7..4875b697 100644 --- a/src/tools/sysprof-dump.c +++ b/src/tools/sysprof-dump.c @@ -115,6 +115,18 @@ main (gint argc, break; } + case SYSPROF_CAPTURE_FRAME_PID_ROOT: + { + const SysprofCapturePidRoot *pr = sysprof_capture_reader_read_pid_root (reader); + + if (pr == NULL) + return EXIT_FAILURE; + + g_print ("PID ROOT: pid=%d layer=%u path=%s\n", pr->frame.pid, pr->layer, pr->path); + + break; + } + case SYSPROF_CAPTURE_FRAME_JITMAP: { const SysprofCaptureJitmap *jitmap = sysprof_capture_reader_read_jitmap (reader);