capture: rename PidRoot to Overlay and add src/dst

Really what we want to deal with here is tracking an overlay that we may
need to be able to decode after the fact (in case processes exit or we
need to do post-processing symbol resolution).

For the podman case, that is $some_path mapped to root (/), generally
speaking. For flatpak though, that would have two mappings, one for
/app and another for /usr (possibly more).
This commit is contained in:
Christian Hergert
2021-02-25 13:43:09 -08:00
parent 8b0f3f4682
commit 14139232d5
11 changed files with 153 additions and 62 deletions

View File

@ -223,8 +223,8 @@ 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);
case SYSPROF_CAPTURE_FRAME_OVERLAY:
delegate = READ_DELEGATE (sysprof_capture_reader_read_overlay);
break;
default:

View File

@ -354,14 +354,18 @@ sysprof_capture_reader_bswap_mark (SysprofCaptureReader *self,
}
static inline void
sysprof_capture_reader_bswap_pid_root (SysprofCaptureReader *self,
SysprofCapturePidRoot *pr)
sysprof_capture_reader_bswap_overlay (SysprofCaptureReader *self,
SysprofCaptureOverlay *pr)
{
assert (self != NULL);
assert (pr != NULL);
if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER))
pr->layer = bswap_32 (pr->layer);
{
pr->layer = bswap_32 (pr->layer);
pr->src_len = bswap_32 (pr->src_len);
pr->dst_len = bswap_32 (pr->dst_len);
}
}
static inline void
@ -690,10 +694,10 @@ sysprof_capture_reader_read_mark (SysprofCaptureReader *self)
return mark;
}
const SysprofCapturePidRoot *
sysprof_capture_reader_read_pid_root (SysprofCaptureReader *self)
const SysprofCaptureOverlay *
sysprof_capture_reader_read_overlay (SysprofCaptureReader *self)
{
SysprofCapturePidRoot *pr;
SysprofCaptureOverlay *pr;
assert (self != NULL);
assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0);
@ -702,22 +706,30 @@ sysprof_capture_reader_read_pid_root (SysprofCaptureReader *self)
if (!sysprof_capture_reader_ensure_space_for (self, sizeof *pr + 1))
return NULL;
pr = (SysprofCapturePidRoot *)(void *)&self->buf[self->pos];
pr = (SysprofCaptureOverlay *)(void *)&self->buf[self->pos];
sysprof_capture_reader_bswap_frame (self, &pr->frame);
if (pr->frame.type != SYSPROF_CAPTURE_FRAME_PID_ROOT)
if (pr->frame.type != SYSPROF_CAPTURE_FRAME_OVERLAY)
return NULL;
if (pr->frame.len < (sizeof *pr + 1))
if (pr->frame.len < (sizeof *pr + 2))
return NULL;
if (!sysprof_capture_reader_ensure_space_for (self, pr->frame.len))
return NULL;
pr = (SysprofCapturePidRoot *)(void *)&self->buf[self->pos];
pr = (SysprofCaptureOverlay *)(void *)&self->buf[self->pos];
sysprof_capture_reader_bswap_pid_root (self, pr);
sysprof_capture_reader_bswap_overlay (self, pr);
/* Make sure there is enough space for paths and trailing \0 */
if (((size_t)pr->src_len + (size_t)pr->dst_len) > (pr->frame.len - sizeof *pr - 2))
return NULL;
/* Enforce trailing \0 */
pr->data[pr->src_len] = 0;
pr->data[pr->src_len+1+pr->dst_len] = 0;
self->pos += pr->frame.len;

View File

@ -121,7 +121,7 @@ const SysprofCaptureFileChunk *sysprof_capture_reader_read_file (
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);
const SysprofCaptureOverlay *sysprof_capture_reader_read_overlay (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
bool sysprof_capture_reader_reset (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL

View File

@ -139,7 +139,7 @@ typedef enum
SYSPROF_CAPTURE_FRAME_LOG = 12,
SYSPROF_CAPTURE_FRAME_FILE_CHUNK = 13,
SYSPROF_CAPTURE_FRAME_ALLOCATION = 14,
SYSPROF_CAPTURE_FRAME_PID_ROOT = 15,
SYSPROF_CAPTURE_FRAME_OVERLAY = 15,
} SysprofCaptureFrameType;
/* Not part of ABI */
@ -177,9 +177,12 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct
{
SysprofCaptureFrame frame;
uint32_t layer;
char path[0];
} SysprofCapturePidRoot
uint32_t layer : 8;
uint32_t padding : 24;
uint32_t src_len : 16;
uint32_t dst_len : 16;
char data[0];
} SysprofCaptureOverlay
SYSPROF_ALIGNED_END(1);
SYSPROF_ALIGNED_BEGIN(1)
@ -366,7 +369,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 (sizeof (SysprofCaptureOverlay) == 32, "SysprofCaptureOverlay 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");

View File

@ -532,19 +532,28 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self,
break;
}
case SYSPROF_CAPTURE_FRAME_PID_ROOT:
case SYSPROF_CAPTURE_FRAME_OVERLAY:
{
const SysprofCapturePidRoot *frame;
const SysprofCaptureOverlay *frame;
const char *src;
const char *dst;
if (!(frame = sysprof_capture_reader_read_pid_root (reader)))
if (!(frame = sysprof_capture_reader_read_overlay (reader)))
goto panic;
sysprof_capture_writer_add_pid_root (self,
frame->frame.time,
frame->frame.cpu,
frame->frame.pid,
frame->path,
frame->layer);
/* This should have been verified alrady when decoding */
assert (frame->frame.len >= (sizeof *frame + frame->src_len + 1 + frame->dst_len + 1));
src = &frame->data[0];
dst = &frame->data[frame->src_len+1];
sysprof_capture_writer_add_overlay (self,
frame->frame.time,
frame->frame.cpu,
frame->frame.pid,
frame->layer,
src,
dst);
break;
}

View File

@ -828,20 +828,27 @@ sysprof_capture_writer_add_fork (SysprofCaptureWriter *self,
}
bool
sysprof_capture_writer_add_pid_root (SysprofCaptureWriter *self,
int64_t time,
int cpu,
int32_t pid,
const char *path,
uint32_t layer)
sysprof_capture_writer_add_overlay (SysprofCaptureWriter *self,
int64_t time,
int cpu,
int32_t pid,
uint32_t layer,
const char *src,
const char *dst)
{
SysprofCapturePidRoot *ev;
size_t strl = strlen (path);
size_t len = sizeof *ev + strl + 1;
SysprofCaptureOverlay *ev;
size_t srclen = strlen (src);
size_t dstlen = strlen (dst);
size_t len = sizeof *ev + srclen + 1 + dstlen + 1;
assert (self != NULL);
assert (src != NULL);
assert (dst != NULL);
ev = (SysprofCapturePidRoot *)sysprof_capture_writer_allocate (self, &len);
if (srclen > INT16_MAX || dstlen > INT16_MAX)
return false;
ev = (SysprofCaptureOverlay *)sysprof_capture_writer_allocate (self, &len);
if (!ev)
return false;
@ -850,12 +857,19 @@ sysprof_capture_writer_add_pid_root (SysprofCaptureWriter *self,
cpu,
pid,
time,
SYSPROF_CAPTURE_FRAME_PID_ROOT);
ev->layer = layer;
memcpy (ev->path, path, strl);
ev->path[strl] = 0;
SYSPROF_CAPTURE_FRAME_OVERLAY);
self->stat.frame_count[SYSPROF_CAPTURE_FRAME_PID_ROOT]++;
ev->layer = layer;
ev->src_len = srclen;
ev->dst_len = dstlen;
memcpy (&ev->data[0], src, srclen);
memcpy (&ev->data[srclen+1], dst, dstlen);
ev->data[srclen] = 0;
ev->data[srclen+1+dstlen] = 0;
self->stat.frame_count[SYSPROF_CAPTURE_FRAME_OVERLAY]++;
return true;
}

View File

@ -202,12 +202,13 @@ bool sysprof_capture_writer_add_allocation_copy (Sy
const SysprofCaptureAddress *addrs,
unsigned int n_addrs);
SYSPROF_AVAILABLE_IN_3_40
bool sysprof_capture_writer_add_pid_root (SysprofCaptureWriter *self,
bool sysprof_capture_writer_add_overlay (SysprofCaptureWriter *self,
int64_t time,
int cpu,
int32_t pid,
const char *path,
uint32_t layer);
uint32_t layer,
const char *src,
const char *dst);
SYSPROF_AVAILABLE_IN_ALL
bool sysprof_capture_writer_flush (SysprofCaptureWriter *self);
SYSPROF_AVAILABLE_IN_ALL

View File

@ -162,10 +162,12 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
sysprof_map_lookaside_insert (lookaside, &map);
}
else if (type == SYSPROF_CAPTURE_FRAME_PID_ROOT)
else if (type == SYSPROF_CAPTURE_FRAME_OVERLAY)
{
const SysprofCapturePidRoot *ev = sysprof_capture_reader_read_pid_root (reader);
const SysprofCaptureOverlay *ev = sysprof_capture_reader_read_overlay (reader);
SysprofMapLookaside *lookaside = g_hash_table_lookup (self->lookasides, GINT_TO_POINTER (ev->frame.pid));
const char *src = ev->data;
const char *dst = &ev->data[ev->src_len+1];
if (lookaside == NULL)
{
@ -173,11 +175,9 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
g_hash_table_insert (self->lookasides, GINT_TO_POINTER (ev->frame.pid), lookaside);
}
/* Someday we might need to support more layers, but currently
* only the base layer (0) is used.
*/
if (ev->layer == 0)
sysprof_map_lookaside_set_root (lookaside, ev->path);
/* FIXME: use dst to map to things other than / */
if (ev->dst_len == 1 && *dst == '/')
sysprof_map_lookaside_set_root (lookaside, src);
}
else
{

View File

@ -259,12 +259,9 @@ sysprof_proc_source_populate_pid_podman (SysprofProcSource *self,
info->layers[i],
"diff",
NULL);
sysprof_capture_writer_add_pid_root (self->writer,
SYSPROF_CAPTURE_CURRENT_TIME,
-1,
pid,
path,
i);
sysprof_capture_writer_add_overlay (self->writer,
SYSPROF_CAPTURE_CURRENT_TIME,
-1, pid, i, path, "/");
}
}
}

View File

@ -947,6 +947,58 @@ test_writer_memory_alloc_free (void)
g_unlink ("memory.syscap");
}
static void
test_reader_writer_overlay (void)
{
SysprofCaptureWriter *writer;
SysprofCaptureReader *reader;
const SysprofCaptureOverlay *ev;
SysprofCaptureFrameType type;
gint r;
writer = sysprof_capture_writer_new ("overlay1.syscap", 0);
sysprof_capture_writer_add_overlay (writer, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1, 123, "/foo", "/bar");
sysprof_capture_writer_add_overlay (writer, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1, 0, "/app", "/bin");
sysprof_capture_writer_add_overlay (writer, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1, 7, "/home/user/.local/share/containers/storage/overlay/1111111111111111111111111111111111111111111111111111111111111111/diff", "/");
g_clear_pointer (&writer, sysprof_capture_writer_unref);
reader = sysprof_capture_reader_new ("overlay1.syscap");
g_assert_nonnull (reader);
ev = sysprof_capture_reader_read_overlay (reader);
g_assert_nonnull (ev);
g_assert_cmpint (ev->layer, ==, 123);
g_assert_cmpint (ev->src_len, ==, 4);
g_assert_cmpint (ev->dst_len, ==, 4);
g_assert_cmpstr (ev->data, ==, "/foo");
g_assert_cmpstr (ev->data+ev->src_len+1, ==, "/bar");
ev = sysprof_capture_reader_read_overlay (reader);
g_assert_nonnull (ev);
g_assert_cmpint (ev->layer, ==, 0);
g_assert_cmpint (ev->src_len, ==, 4);
g_assert_cmpint (ev->dst_len, ==, 4);
g_assert_cmpstr (ev->data, ==, "/app");
g_assert_cmpstr (ev->data+ev->src_len+1, ==, "/bin");
ev = sysprof_capture_reader_read_overlay (reader);
g_assert_nonnull (ev);
g_assert_cmpint (ev->layer, ==, 7);
g_assert_cmpint (ev->src_len, ==, 120);
g_assert_cmpint (ev->dst_len, ==, 1);
g_assert_cmpstr (ev->data, ==, "/home/user/.local/share/containers/storage/overlay/1111111111111111111111111111111111111111111111111111111111111111/diff");
g_assert_cmpstr (ev->data+ev->src_len+1, ==, "/");
r = sysprof_capture_reader_peek_type (reader, &type);
g_assert_cmpint (r, ==, FALSE);
g_clear_pointer (&reader, sysprof_capture_reader_unref);
g_unlink ("overlay1.syscap");
}
int
main (int argc,
char *argv[])
@ -962,5 +1014,6 @@ main (int argc,
g_test_add_func ("/SysprofCapture/ReaderWriter/metadata", test_reader_writer_metadata);
g_test_add_func ("/SysprofCapture/ReaderWriter/file", test_reader_writer_file);
g_test_add_func ("/SysprofCapture/ReaderWriter/cat-jitmap", test_reader_writer_cat_jitmap);
g_test_add_func ("/SysprofCapture/ReaderWriter/overlay", test_reader_writer_overlay);
return g_test_run ();
}

View File

@ -115,14 +115,16 @@ main (gint argc,
break;
}
case SYSPROF_CAPTURE_FRAME_PID_ROOT:
case SYSPROF_CAPTURE_FRAME_OVERLAY:
{
const SysprofCapturePidRoot *pr = sysprof_capture_reader_read_pid_root (reader);
const SysprofCaptureOverlay *pr = sysprof_capture_reader_read_overlay (reader);
const char *src = pr->data;
const char *dst = &pr->data[pr->src_len+1];
if (pr == NULL)
return EXIT_FAILURE;
g_print ("PID ROOT: pid=%d layer=%u path=%s\n", pr->frame.pid, pr->layer, pr->path);
g_print ("OVERLAY: pid=%d layer=%u src=%s dst=%s\n", pr->frame.pid, pr->layer, src, dst);
break;
}