From 11cb3bc18d18b1c58321f6b0aaa1747a5445e79c Mon Sep 17 00:00:00 2001 From: Sasha Goldshtein Date: Thu, 24 Mar 2016 09:56:12 -0700 Subject: [PATCH] Allowing more natural syntax for tracepoints with no "tp" struct prefix --- man/man8/argdist.8 | 7 ++++--- man/man8/trace.8 | 6 ++++-- src/python/bcc/tracepoint.py | 22 ++++++++++++++++++---- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/man/man8/argdist.8 b/man/man8/argdist.8 index 385b308..60a970b 100644 --- a/man/man8/argdist.8 +++ b/man/man8/argdist.8 @@ -92,7 +92,8 @@ You may use the parameters directly, or valid C expressions that involve the parameters, such as "size % 10". Tracepoints may access a special structure called "tp" that is formatted according to the tracepoint format (which you can obtain using tplist). For example, the -block:block_rq_complete tracepoint can access tp.nr_sector. +block:block_rq_complete tracepoint can access tp.nr_sector. You may also use the +members of the "tp" struct directly, e.g. "nr_sector" instead of "tp.nr_sector". Return probes can use the argument values received by the function when it was entered, through the $entry(paramname) special variable. Return probes can also access the function's return value in $retval, and the @@ -147,11 +148,11 @@ Count fork() calls in libc across all processes, grouped by pid: .TP Print histogram of number of sectors in completing block I/O requests: # -.B argdist -H 't:block:block_rq_complete():u32:tp.nr_sector' +.B argdist -H 't:block:block_rq_complete():u32:nr_sector' .TP Aggregate interrupts by interrupt request (IRQ): # -.B argdist -C 't:irq:irq_handler_entry():int:tp.irq' +.B argdist -C 't:irq:irq_handler_entry():int:irq' .TP Print histograms of sleep() and nanosleep() parameter values: # diff --git a/man/man8/trace.8 b/man/man8/trace.8 index 6c69522..c4e3546 100644 --- a/man/man8/trace.8 +++ b/man/man8/trace.8 @@ -92,7 +92,9 @@ same special keywords as in the predicate (arg1, arg2, etc.). In tracepoints, both the predicate and the arguments may refer to the tracepoint format structure, which is stored in the special "tp" variable. For example, the block:block_rq_complete tracepoint can print or filter by tp.nr_sector. To -discover the format of your tracepoint, use the tplist tool. +discover the format of your tracepoint, use the tplist tool. Note that you can +also use the members of the "tp" struct directly, e.g "nr_sector" instead of +"tp.nr_sector". The predicate expression and the format specifier replacements for printing may also use the following special keywords: $pid, $tgid to refer to the @@ -118,7 +120,7 @@ Trace returns from the readline function in bash and print the return value as a .TP Trace the block:block_rq_complete tracepoint and print the number of sectors completed: # -.B trace 't:block:block_rq_complete """%d sectors"", tp.nr_sector' +.B trace 't:block:block_rq_complete """%d sectors"", nr_sector' .SH SOURCE This is from bcc. .IP diff --git a/src/python/bcc/tracepoint.py b/src/python/bcc/tracepoint.py index 24ef402..c2b0665 100644 --- a/src/python/bcc/tracepoint.py +++ b/src/python/bcc/tracepoint.py @@ -109,11 +109,12 @@ int __trace_entry_update(struct pt_regs *ctx) self.category = category self.event = event self.tp_id = tp_id + self._retrieve_struct_fields() - def _generate_struct_fields(self): + def _retrieve_struct_fields(self): + self.struct_fields = [] format_lines = Tracepoint.get_tpoint_format(self.category, self.event) - text = "" for line in format_lines: match = re.search(r'field:([^;]*);.*size:(\d+);', line) if match is None: @@ -126,6 +127,11 @@ int __trace_entry_update(struct pt_regs *ctx) continue if field_name.startswith("common_"): continue + self.struct_fields.append((field_type, field_name)) + + def _generate_struct_fields(self): + text = "" + for field_type, field_name in self.struct_fields: text += " %s %s;\n" % (field_type, field_name) return text @@ -134,10 +140,17 @@ int __trace_entry_update(struct pt_regs *ctx) return """ struct %s { u64 __do_not_use__; - %s +%s }; """ % (self.struct_name, self._generate_struct_fields()) + def _generate_struct_locals(self): + text = "" + for field_type, field_name in self.struct_fields: + text += " %s %s = tp.%s;\n" % ( + field_type, field_name, field_name) + return text + def generate_get_struct(self): return """ u64 tid = bpf_get_current_pid_tgid(); @@ -145,7 +158,8 @@ struct %s { if (di == 0) { return 0; } struct %s tp = {}; bpf_probe_read(&tp, sizeof(tp), (void *)*di); - """ % self.struct_name +%s + """ % (self.struct_name, self._generate_struct_locals()) @classmethod def enable_tracepoint(cls, category, event): -- 2.7.4