From 50486ff50fa3e049f4620d47e82db41dde71f815 Mon Sep 17 00:00:00 2001 From: Sasha Goldshtein Date: Mon, 16 Jan 2017 18:36:52 +0000 Subject: [PATCH 1/5] tplist: Print one-based location and argument indices The `trace` and `argdist` tools expect location and argument indices to start at 1 -- the first argument is arg1, and so on. The `tplist` tool now prints UDST argument indices (and location indices, for consistency) as 1-based as well. --- tools/tplist.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/tplist.py b/tools/tplist.py index 627f20ed35a0..c7656a68bff9 100755 --- a/tools/tplist.py +++ b/tools/tplist.py @@ -68,7 +68,7 @@ def print_tracepoints(): def print_usdt_argument_details(location): for idx in xrange(0, location.num_arguments): arg = location.get_argument(idx) - print(" argument #%d %s" % (idx, arg)) + print(" argument #%d %s" % (idx+1, arg)) def print_usdt_details(probe): if args.verbosity > 0: @@ -76,7 +76,7 @@ def print_usdt_details(probe): if args.verbosity > 1: for idx in xrange(0, probe.num_locations): loc = probe.get_location(idx) - print(" location #%d %s" % (idx, loc)) + print(" location #%d %s" % (idx+1, loc)) print_usdt_argument_details(loc) else: print(" %d location(s)" % probe.num_locations) From fd44cd244afa088303ee4b5a878980dda0f836ce Mon Sep 17 00:00:00 2001 From: Sasha Goldshtein Date: Mon, 16 Jan 2017 18:38:30 +0000 Subject: [PATCH 2/5] argdist: Generated streq-helper to ignore null terminator Oftentimes we want to use the STRCMP helper to compare strings that are not null-terminated, e.g. in USDT probes this often happens. Ignore the null terminator (i.e. loop until the last character excluding the null terminator). --- tools/argdist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/argdist.py b/tools/argdist.py index 3bcf43a47740..f6bb8bfed8d9 100755 --- a/tools/argdist.py +++ b/tools/argdist.py @@ -258,7 +258,7 @@ def _generate_streq_function(self, string): char needle[] = %s; char haystack[sizeof(needle)]; bpf_probe_read(&haystack, sizeof(haystack), (void *)str); - for (int i = 0; i < sizeof(needle); ++i) { + for (int i = 0; i < sizeof(needle)-1; ++i) { if (needle[i] != haystack[i]) { return false; } From b9aec34d9ad620feede3a60068b4edc3d172cad5 Mon Sep 17 00:00:00 2001 From: Sasha Goldshtein Date: Mon, 16 Jan 2017 18:41:22 +0000 Subject: [PATCH 3/5] trace: Generated streq-helper to ignore null terminator --- tools/trace.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/trace.py b/tools/trace.py index 8ac92010f159..d12e26b9cff1 100755 --- a/tools/trace.py +++ b/tools/trace.py @@ -217,11 +217,11 @@ def _generate_streq_function(self, string): fname = "streq_%d" % Probe.streq_index Probe.streq_index += 1 self.streq_functions += """ -static inline bool %s(char const *ignored, unsigned long str) { +static inline bool %s(char const *ignored, uintptr_t str) { char needle[] = %s; char haystack[sizeof(needle)]; bpf_probe_read(&haystack, sizeof(haystack), (void *)str); - for (int i = 0; i < sizeof(needle); ++i) { + for (int i = 0; i < sizeof(needle)-1; ++i) { if (needle[i] != haystack[i]) { return false; } From b630092fdb53ed19352db567ef7c92bb67865f03 Mon Sep 17 00:00:00 2001 From: Sasha Goldshtein Date: Mon, 16 Jan 2017 18:43:11 +0000 Subject: [PATCH 4/5] trace: Use correct argument index and tgid for filters `trace` would use the incorrect argument index for USDT probes when filtering specifically, e.g. `trace u:lib:tp (arg1 != 0) ...` would actually use the type of the 2nd argument, and not the 1st argument for the type of the filter variable in the generated program. This could cause compilation errors or subtle bugs where the data would be either extended or contracted to fit the wrong argument's type. Additionally, `trace` would use the pid (thread id, `-L`) filter with the `attach_uprobe` API, which expects a tgid (process id). As a result, incorrect filtering would happen. --- tools/trace.py | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/tools/trace.py b/tools/trace.py index d12e26b9cff1..ebe13408f6ac 100755 --- a/tools/trace.py +++ b/tools/trace.py @@ -354,33 +354,35 @@ def _generate_field_assign(self, idx): def _generate_usdt_filter_read(self): text = "" - if self.probe_type == "u": - for arg, _ in Probe.aliases.items(): - if not (arg.startswith("arg") and - (arg in self.filter)): - continue - arg_index = int(arg.replace("arg", "")) - arg_ctype = self.usdt.get_probe_arg_ctype( - self.usdt_name, arg_index) - if not arg_ctype: - self._bail("Unable to determine type of {} " - "in the filter".format(arg)) - text += """ + if self.probe_type != "u": + return text + for arg, _ in Probe.aliases.items(): + if not (arg.startswith("arg") and + (arg in self.filter)): + continue + arg_index = int(arg.replace("arg", "")) + arg_ctype = self.usdt.get_probe_arg_ctype( + self.usdt_name, arg_index-1) + if not arg_ctype: + self._bail("Unable to determine type of {} " + "in the filter".format(arg)) + text += """ {} {}_filter; bpf_usdt_readarg({}, ctx, &{}_filter); - """.format(arg_ctype, arg, arg_index, arg) - self.filter = self.filter.replace( - arg, "{}_filter".format(arg)) + """.format(arg_ctype, arg, arg_index, arg) + self.filter = self.filter.replace( + arg, "{}_filter".format(arg)) return text def generate_program(self, include_self): data_decl = self._generate_data_decl() - # kprobes don't have built-in pid filters, so we have to add - # it to the function body: - if len(self.library) == 0 and Probe.pid != -1: + if Probe.pid != -1: pid_filter = """ if (__pid != %d) { return 0; } """ % Probe.pid + # uprobes can have a built-in tgid filter passed to + # attach_uprobe, hence the check here -- for kprobes, we + # need to do the tgid test by hand: elif len(self.library) == 0 and Probe.tgid != -1: pid_filter = """ if (__tgid != %d) { return 0; } @@ -542,12 +544,12 @@ def _attach_u(self, bpf): bpf.attach_uretprobe(name=libpath, sym=self.function, fn_name=self.probe_name, - pid=Probe.pid) + pid=Probe.tgid) else: bpf.attach_uprobe(name=libpath, sym=self.function, fn_name=self.probe_name, - pid=Probe.pid) + pid=Probe.tgid) class Tool(object): examples = """ From dcf1675a744913212b04eae1a0dbebc552ad55db Mon Sep 17 00:00:00 2001 From: Sasha Goldshtein Date: Tue, 17 Jan 2017 07:40:57 +0000 Subject: [PATCH 5/5] trace, argdist: Fix code formatting nits --- tools/argdist.py | 2 +- tools/trace.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/argdist.py b/tools/argdist.py index f6bb8bfed8d9..f5422d90c827 100755 --- a/tools/argdist.py +++ b/tools/argdist.py @@ -258,7 +258,7 @@ def _generate_streq_function(self, string): char needle[] = %s; char haystack[sizeof(needle)]; bpf_probe_read(&haystack, sizeof(haystack), (void *)str); - for (int i = 0; i < sizeof(needle)-1; ++i) { + for (int i = 0; i < sizeof(needle) - 1; ++i) { if (needle[i] != haystack[i]) { return false; } diff --git a/tools/trace.py b/tools/trace.py index ebe13408f6ac..52fc99d10146 100755 --- a/tools/trace.py +++ b/tools/trace.py @@ -221,7 +221,7 @@ def _generate_streq_function(self, string): char needle[] = %s; char haystack[sizeof(needle)]; bpf_probe_read(&haystack, sizeof(haystack), (void *)str); - for (int i = 0; i < sizeof(needle)-1; ++i) { + for (int i = 0; i < sizeof(needle) - 1; ++i) { if (needle[i] != haystack[i]) { return false; } @@ -362,7 +362,7 @@ def _generate_usdt_filter_read(self): continue arg_index = int(arg.replace("arg", "")) arg_ctype = self.usdt.get_probe_arg_ctype( - self.usdt_name, arg_index-1) + self.usdt_name, arg_index - 1) if not arg_ctype: self._bail("Unable to determine type of {} " "in the filter".format(arg))