Commit c7bdb079 authored by Beau Belgrave's avatar Beau Belgrave Committed by Steven Rostedt (Google)

tracing: Fix print_fields() for __dyn_loc/__rel_loc

Both print_fields() and print_array() do not handle if dynamic data ends
at the last byte of the payload for both __dyn_loc and __rel_loc field
types. For __rel_loc, the offset was off by 4 bytes, leading to
incorrect strings and data being printed out. In print_array() the
buffer pos was missed from being advanced, which results in the first
payload byte being used as the offset base instead of the field offset.

Advance __rel_loc offset by 4 to ensure correct offset and advance pos
to the field offset to ensure correct data is displayed when printing
arrays. Change >= to > when checking if data is in-bounds, since it's
valid for dynamic data to include the last byte of the payload.

Example outputs for event format:
        field:unsigned short common_type;       offset:0;       size:2; signed:0;
        field:unsigned char common_flags;       offset:2;       size:1; signed:0;
        field:unsigned char common_preempt_count;       offset:3;       size:1; signed:0;
        field:int common_pid;   offset:4;       size:4; signed:1;

        field:__rel_loc char text[];  offset:8;      size:4; signed:1;

Output before:
tp_rel_loc: text=<OVERFLOW>

Output after:
tp_rel_loc: text=Test

Link: https://lkml.kernel.org/r/20230419214140.4158-3-beaub@linux.microsoft.com

Fixes: 80a76994 ("tracing: Add "fields" option to show raw trace event fields")
Reported-by: default avatarDoug Cook <dcook@linux.microsoft.com>
Signed-off-by: default avatarBeau Belgrave <beaub@linux.microsoft.com>
Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
parent 9872c07b
...@@ -819,13 +819,15 @@ static void print_array(struct trace_iterator *iter, void *pos, ...@@ -819,13 +819,15 @@ static void print_array(struct trace_iterator *iter, void *pos,
len = *(int *)pos >> 16; len = *(int *)pos >> 16;
if (field) if (field)
offset += field->offset; offset += field->offset + sizeof(int);
if (offset + len >= iter->ent_size) { if (offset + len > iter->ent_size) {
trace_seq_puts(&iter->seq, "<OVERFLOW>"); trace_seq_puts(&iter->seq, "<OVERFLOW>");
return; return;
} }
pos = (void *)iter->ent + offset;
for (i = 0; i < len; i++, pos++) { for (i = 0; i < len; i++, pos++) {
if (i) if (i)
trace_seq_putc(&iter->seq, ','); trace_seq_putc(&iter->seq, ',');
...@@ -861,9 +863,9 @@ static void print_fields(struct trace_iterator *iter, struct trace_event_call *c ...@@ -861,9 +863,9 @@ static void print_fields(struct trace_iterator *iter, struct trace_event_call *c
len = *(int *)pos >> 16; len = *(int *)pos >> 16;
if (field->filter_type == FILTER_RDYN_STRING) if (field->filter_type == FILTER_RDYN_STRING)
offset += field->offset; offset += field->offset + sizeof(int);
if (offset + len >= iter->ent_size) { if (offset + len > iter->ent_size) {
trace_seq_puts(&iter->seq, "<OVERFLOW>"); trace_seq_puts(&iter->seq, "<OVERFLOW>");
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment