Python 3 compatibility fixes around string handling (#986)
authorRafael F <r4f4rfs@gmail.com>
Sun, 26 Mar 2017 12:54:25 +0000 (14:54 +0200)
committerSasha Goldshtein <goldshtn@gmail.com>
Sun, 26 Mar 2017 12:54:25 +0000 (15:54 +0300)
This fixes the bcc module and all the affected tools for issues related to string handling in Python 3. Specifically, when passing Python strings to C libraries they are encoded as ASCII, and when constructing Python strings from C strings, they are decoded first.

34 files changed:
src/python/bcc/__init__.py
src/python/bcc/usdt.py
tools/bashreadline.py
tools/biosnoop.py
tools/biotop.py
tools/bitesize.py
tools/btrfsslower.py
tools/cachetop.py
tools/capable.py
tools/dcsnoop.py
tools/ext4dist.py
tools/ext4slower.py
tools/filelife.py
tools/fileslower.py
tools/gethostlatency.py
tools/hardirqs.py
tools/killsnoop.py
tools/mdflush.py
tools/offcputime.py
tools/offwaketime.py
tools/oomkill.py
tools/opensnoop.py
tools/profile.py
tools/slabratetop.py
tools/sslsniff.py
tools/stacksnoop.py
tools/statsnoop.py
tools/tcpaccept.py
tools/tcpconnect.py
tools/tcpconnlat.py
tools/tcplife.py
tools/trace.py
tools/ttysnoop.py
tools/wakeuptime.py

index 189db2a..5ad8929 100644 (file)
@@ -759,11 +759,12 @@ class BPF(object):
     def get_user_functions_and_addresses(name, sym_re):
         addresses = []
         def sym_cb(sym_name, addr):
-            if re.match(sym_re, sym_name):
-                addresses.append((sym_name, addr))
+            dname = sym_name.decode()
+            if re.match(sym_re, dname):
+                addresses.append((dname, addr))
             return 0
 
-        res = lib.bcc_foreach_symbol(name, _SYM_CB_TYPE(sym_cb))
+        res = lib.bcc_foreach_symbol(name.encode('ascii'), _SYM_CB_TYPE(sym_cb))
         if res < 0:
             raise Exception("Error %d enumerating symbols in %s" % (res, name))
         return addresses
index 4f50413..5e3f228 100644 (file)
@@ -138,7 +138,8 @@ class USDT(object):
                     "either a pid or a binary path must be specified")
 
     def enable_probe(self, probe, fn_name):
-        if lib.bcc_usdt_enable_probe(self.context, probe, fn_name) != 0:
+        if lib.bcc_usdt_enable_probe(self.context, probe.encode('ascii'),
+                fn_name.encode('ascii')) != 0:
             raise USDTException(
                     ("failed to enable probe '%s'; a possible cause " +
                      "can be that the probe requires a pid to enable") %
@@ -146,7 +147,8 @@ class USDT(object):
                   )
 
     def enable_probe_or_bail(self, probe, fn_name):
-        if lib.bcc_usdt_enable_probe(self.context, probe, fn_name) != 0:
+        if lib.bcc_usdt_enable_probe(self.context, probe.encode('ascii'),
+                fn_name.encode('ascii')) != 0:
             print(
 """Error attaching USDT probes: the specified pid might not contain the
 given language's runtime, or the runtime was not built with the required
@@ -175,7 +177,7 @@ tplist tool.""")
     def attach_uprobes(self, bpf):
         probes = self.enumerate_active_probes()
         for (binpath, fn_name, addr, pid) in probes:
-            bpf.attach_uprobe(name=binpath, fn_name=fn_name,
+            bpf.attach_uprobe(name=binpath.decode(), fn_name=fn_name.decode(),
                               addr=addr, pid=pid)
 
     def enumerate_active_probes(self):
index 2c1ff2a..db48e83 100755 (executable)
@@ -56,7 +56,7 @@ print("%-9s %-6s %s" % ("TIME", "PID", "COMMAND"))
 
 def print_event(cpu, data, size):
     event = ct.cast(data, ct.POINTER(Data)).contents
-    print("%-9s %-6d %s" % (strftime("%H:%M:%S"), event.pid, event.str))
+    print("%-9s %-6d %s" % (strftime("%H:%M:%S"), event.pid, event.str.decode()))
 
 b["events"].open_perf_buffer(print_event)
 while 1:
index 3d77e52..314a19e 100755 (executable)
@@ -175,7 +175,8 @@ def print_event(cpu, data, size):
         delta = float(delta) + (event.ts - prev_ts)
 
     print("%-14.9f %-14.14s %-6s %-7s %-2s %-9s %-7s %7.2f" % (
-        delta / 1000000, event.name, event.pid, event.disk_name, rwflg, val,
+        delta / 1000000, event.name.decode(), event.pid,
+        event.disk_name.decode(), rwflg, val,
         event.len, float(event.delta) / 1000000))
 
     prev_ts = event.ts
index f827e62..8da9255 100755 (executable)
@@ -212,9 +212,9 @@ while 1:
 
         # print line
         avg_ms = (float(v.us) / 1000) / v.io
-        print("%-6d %-16s %1s %-3d %-3d %-8s %5s %7s %6.2f" % (k.pid, k.name,
-            "W" if k.rwflag else "R", k.major, k.minor, diskname, v.io,
-            v.bytes / 1024, avg_ms))
+        print("%-6d %-16s %1s %-3d %-3d %-8s %5s %7s %6.2f" % (k.pid,
+            k.name.decode(), "W" if k.rwflag else "R", k.major, k.minor,
+            diskname, v.io, v.bytes / 1024, avg_ms))
 
         line += 1
         if line >= maxrows:
index 9141ab6..f70f091 100755 (executable)
@@ -72,4 +72,5 @@ dist = b.get_table("dist")
 try:
     sleep(99999999)
 except KeyboardInterrupt:
-    dist.print_log2_hist("Kbytes", "Process Name")
+    dist.print_log2_hist("Kbytes", "Process Name",
+            section_print_fn=bytes.decode)
index 8b34900..d9a40d7 100755 (executable)
@@ -311,12 +311,12 @@ def print_event(cpu, data, size):
 
     if (csv):
         print("%d,%s,%d,%s,%d,%d,%d,%s" % (
-            event.ts_us, event.task, event.pid, type, event.size,
-            event.offset, event.delta_us, event.file))
+            event.ts_us, event.task.decode(), event.pid, type, event.size,
+            event.offset, event.delta_us, event.file.decode()))
         return
     print("%-8s %-14.14s %-6s %1s %-7s %-8d %7.2f %s" % (strftime("%H:%M:%S"),
-        event.task, event.pid, type, event.size, event.offset / 1024,
-        float(event.delta_us) / 1000, event.file))
+        event.task.decode(), event.pid, type, event.size, event.offset / 1024,
+        float(event.delta_us) / 1000, event.file.decode()))
 
 # initialize BPF
 b = BPF(text=bpf_text)
index aed3f49..bb5f6d8 100755 (executable)
@@ -72,7 +72,7 @@ def get_processes_stats(
     counts = bpf.get_table("counts")
     stats = defaultdict(lambda: defaultdict(int))
     for k, v in counts.items():
-        stats["%d-%d-%s" % (k.pid, k.uid, k.comm)][k.ip] = v.value
+        stats["%d-%d-%s" % (k.pid, k.uid, k.comm.decode())][k.ip] = v.value
     stats_list = []
 
     for pid, count in sorted(stats.items(), key=lambda stat: stat[0]):
index defeab9..83bfd98 100755 (executable)
@@ -148,7 +148,8 @@ def print_event(cpu, data, size):
     else:
         name = "?"
     print("%-9s %-6d %-6d %-16s %-4d %-20s %d" % (strftime("%H:%M:%S"),
-        event.uid, event.pid, event.comm, event.cap, name, event.audit))
+        event.uid, event.pid, event.comm.decode(), event.cap, name,
+        event.audit))
 
 # loop with callback to print_event
 b["events"].open_perf_buffer(print_event)
index a72ba41..45fc6be 100755 (executable)
@@ -147,8 +147,8 @@ start_ts = time.time()
 def print_event(cpu, data, size):
     event = ct.cast(data, ct.POINTER(Data)).contents
     print("%-11.6f %-6d %-16s %1s %s" % (
-            time.time() - start_ts, event.pid, event.comm, mode_s[event.type],
-            event.filename))
+            time.time() - start_ts, event.pid, event.comm.decode(),
+            mode_s[event.type], event.filename.decode()))
 
 # header
 print("%-11s %-6s %-16s %1s %s" % ("TIME(s)", "PID", "COMM", "T", "FILE"))
index cd51b8a..dfc456a 100755 (executable)
@@ -196,7 +196,7 @@ while (1):
     if args.interval and (not args.notimestamp):
         print(strftime("%H:%M:%S:"))
 
-    dist.print_log2_hist(label, "operation")
+    dist.print_log2_hist(label, "operation", section_print_fn=bytes.decode)
     dist.clear()
 
     countdown -= 1
index 4950325..3b5e7ae 100755 (executable)
@@ -305,12 +305,12 @@ def print_event(cpu, data, size):
 
     if (csv):
         print("%d,%s,%d,%s,%d,%d,%d,%s" % (
-            event.ts_us, event.task, event.pid, type, event.size,
-            event.offset, event.delta_us, event.file))
+            event.ts_us, event.task.decode(), event.pid, type, event.size,
+            event.offset, event.delta_us, event.file.decode()))
         return
     print("%-8s %-14.14s %-6s %1s %-7s %-8d %7.2f %s" % (strftime("%H:%M:%S"),
-        event.task, event.pid, type, event.size, event.offset / 1024,
-        float(event.delta_us) / 1000, event.file))
+        event.task.decode(), event.pid, type, event.size, event.offset / 1024,
+        float(event.delta_us) / 1000, event.file.decode()))
 
 # initialize BPF
 b = BPF(text=bpf_text)
index f73d1ee..a00d3d7 100755 (executable)
@@ -132,7 +132,7 @@ print("%-8s %-6s %-16s %-7s %s" % ("TIME", "PID", "COMM", "AGE(s)", "FILE"))
 def print_event(cpu, data, size):
     event = ct.cast(data, ct.POINTER(Data)).contents
     print("%-8s %-6d %-16s %-7.2f %s" % (strftime("%H:%M:%S"), event.pid,
-        event.comm, float(event.delta) / 1000, event.fname))
+        event.comm.decode(), float(event.delta) / 1000, event.fname.decode()))
 
 b["events"].open_perf_buffer(print_event)
 while 1:
index ab29990..996ab58 100755 (executable)
@@ -235,13 +235,13 @@ def print_event(cpu, data, size):
     event = ct.cast(data, ct.POINTER(Data)).contents
 
     ms = float(event.delta_us) / 1000
-    name = event.name
+    name = event.name.decode()
     if event.name_len > DNAME_INLINE_LEN:
         name = name[:-3] + "..."
 
     print("%-8.3f %-14.14s %-6s %1s %-7s %7.2f %s" % (
-        time.time() - start_ts, event.comm, event.pid, mode_s[event.mode],
-        event.sz, ms, name))
+        time.time() - start_ts, event.comm.decode(), event.pid,
+        mode_s[event.mode], event.sz, ms, name))
 
 b["events"].open_perf_buffer(print_event, page_cnt=64)
 while 1:
index f3f975e..4eb445c 100755 (executable)
@@ -123,7 +123,7 @@ print("%-9s %-6s %-16s %10s %s" % ("TIME", "PID", "COMM", "LATms", "HOST"))
 def print_event(cpu, data, size):
     event = ct.cast(data, ct.POINTER(Data)).contents
     print("%-9s %-6d %-16s %10.2f %s" % (strftime("%H:%M:%S"), event.pid,
-        event.comm, (event.delta / 1000000), event.host))
+        event.comm.decode(), (event.delta / 1000000), event.host.decode()))
 
 # loop with callback to print_event
 b["events"].open_perf_buffer(print_event)
index 36549c7..7159731 100755 (executable)
@@ -148,7 +148,7 @@ while (1):
     else:
         print("%-26s %11s" % ("HARDIRQ", "TOTAL_" + label))
         for k, v in sorted(dist.items(), key=lambda dist: dist[1].value):
-            print("%-26s %11d" % (k.name, v.value / factor))
+            print("%-26s %11d" % (k.name.decode(), v.value / factor))
     dist.clear()
 
     countdown -= 1
index 90b6f7e..2ca1586 100755 (executable)
@@ -131,7 +131,7 @@ def print_event(cpu, data, size):
         return
 
     print("%-9s %-6d %-16s %-4d %-6d %d" % (strftime("%H:%M:%S"),
-        event.pid, event.comm, event.sig, event.tpid, event.ret))
+        event.pid, event.comm.decode(), event.sig, event.tpid, event.ret))
 
 # loop with callback to print_event
 b["events"].open_perf_buffer(print_event)
index b023b76..32d7ba2 100755 (executable)
@@ -60,8 +60,8 @@ print("%-8s %-6s %-16s %s" % ("TIME", "PID", "COMM", "DEVICE"))
 # process event
 def print_event(cpu, data, size):
     event = ct.cast(data, ct.POINTER(Data)).contents
-    print("%-8s %-6d %-16s %s" % (strftime("%H:%M:%S"), event.pid, event.comm,
-        event.disk))
+    print("%-8s %-6d %-16s %s" % (strftime("%H:%M:%S"), event.pid,
+        event.comm.decode(), event.disk.decode()))
 
 # read events
 b["events"].open_perf_buffer(print_event)
index 9d3c847..5727d98 100755 (executable)
@@ -276,7 +276,7 @@ for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
             print("    --")
         for addr in user_stack:
             print("    %s" % b.sym(addr, k.tgid))
-        print("    %-16s %s (%d)" % ("-", k.name, k.pid))
+        print("    %-16s %s (%d)" % ("-", k.name.decode(), k.pid))
         print("        %d\n" % v.value)
 
 if missing_stacks > 0:
index 5020fda..964f062 100755 (executable)
@@ -306,7 +306,7 @@ for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
 
     else:
         # print wakeup name then stack in reverse order
-        print("    %-16s %s %s" % ("waker:", k.waker, k.t_pid))
+        print("    %-16s %s %s" % ("waker:", k.waker.decode(), k.t_pid))
         for addr in waker_user_stack:
             print("    %s" % b.sym(addr, k.tgid))
         if args.delimited:
@@ -324,7 +324,7 @@ for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
             print("    -")
         for addr in target_user_stack:
             print("    %s" % b.sym(addr, k.tgid))
-        print("    %-16s %s %s" % ("target:", k.target, k.w_pid))
+        print("    %-16s %s %s" % ("target:", k.target.decode(), k.w_pid))
         print("        %d\n" % v.value)
 
 if missing_stacks > 0:
index 75f26c5..f0837f0 100755 (executable)
@@ -68,7 +68,8 @@ def print_event(cpu, data, size):
         avgline = stats.read().rstrip()
     print(("%s Triggered by PID %d (\"%s\"), OOM kill of PID %d (\"%s\")"
         ", %d pages, loadavg: %s") % (strftime("%H:%M:%S"), event.fpid,
-        event.fcomm, event.tpid, event.tcomm, event.pages, avgline))
+        event.fcomm.decode(), event.tpid, event.tcomm.decode(), event.pages,
+        avgline))
 
 # initialize BPF
 b = BPF(text=bpf_text)
index dae4ff4..112c56a 100755 (executable)
@@ -175,7 +175,7 @@ def print_event(cpu, data, size):
 
     print("%-6d %-16s %4d %3d %s" %
           (event.id & 0xffffffff if args.tid else event.id >> 32,
-           event.comm, fd_s, err, event.fname))
+           event.comm.decode(), fd_s, err, event.fname.decode()))
 
 # loop with callback to print_event
 b["events"].open_perf_buffer(print_event, page_cnt=64)
index 0658306..687a162 100755 (executable)
@@ -292,7 +292,7 @@ for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
             print("    --")
         for addr in user_stack:
             print("    %s" % b.sym(addr, k.pid))
-        print("    %-16s %s (%d)" % ("-", k.name, k.pid))
+        print("    %-16s %s (%d)" % ("-", k.name.decode(), k.pid))
         print("        %d\n" % v.value)
 
 # check missing
index af379dc..aa1a7b4 100755 (executable)
@@ -120,7 +120,7 @@ while 1:
     line = 0
     for k, v in reversed(sorted(counts.items(),
                                 key=lambda counts: counts[1].size)):
-        print("%-32s %6d %10d" % (k.name, v.count, v.size))
+        print("%-32s %6d %10d" % (k.name.decode(), v.count, v.size))
 
         line += 1
         if line >= maxrows:
index 19a4e1d..ea6e262 100755 (executable)
@@ -200,10 +200,11 @@ def print_event(cpu, data, size, rw):
                 " bytes lost) " + "-" * 5
 
     print("%-12s %-18.9f %-16s %-6d %-6d\n%s\n%s\n%s\n\n" % (rw, time_s,
-                                                             event.comm,
+                                                             event.comm.decode(),
                                                              event.pid,
                                                              event.len,
-                                                             s_mark, event.v0,
+                                                             s_mark,
+                                                             event.v0.decode(),
                                                              e_mark))
 
 b["perf_SSL_write"].open_perf_buffer(print_event_write)
index 3cd7062..a54d524 100755 (executable)
@@ -115,7 +115,7 @@ def print_event(cpu, data, size):
 
     if verbose:
         print("%-18.9f %-12.12s %-6d %-3d %s" %
-              (ts, event.comm, event.pid, cpu, function))
+              (ts, event.comm.decode(), event.pid, cpu, function))
     else:
         print("%-18.9f %s" % (ts, function))
 
index d9164b6..7886730 100755 (executable)
@@ -155,8 +155,8 @@ def print_event(cpu, data, size):
     if args.timestamp:
         print("%-14.9f" % (float(event.ts_ns - start_ts) / 1000000000), end="")
 
-    print("%-6d %-16s %4d %3d %s" % (event.pid, event.comm,
-        fd_s, err, event.fname))
+    print("%-6d %-16s %4d %3d %s" % (event.pid, event.comm.decode(),
+        fd_s, err, event.fname.decode()))
 
 # loop with callback to print_event
 b["events"].open_perf_buffer(print_event, page_cnt=64)
index 0c556a2..8593837 100755 (executable)
@@ -159,8 +159,9 @@ def print_ipv4_event(cpu, data, size):
         if start_ts == 0:
             start_ts = event.ts_us
         print("%-9.3f" % ((float(event.ts_us) - start_ts) / 1000000), end="")
-    print("%-6d %-12.12s %-2d %-16s %-16s %-4d" % (event.pid, event.task,
-        event.ip, inet_ntop(AF_INET, pack("I", event.daddr)),
+    print("%-6d %-12.12s %-2d %-16s %-16s %-4d" % (event.pid,
+        event.task.decode(), event.ip,
+        inet_ntop(AF_INET, pack("I", event.daddr)),
         inet_ntop(AF_INET, pack("I", event.saddr)), event.lport))
 
 def print_ipv6_event(cpu, data, size):
@@ -170,8 +171,8 @@ def print_ipv6_event(cpu, data, size):
         if start_ts == 0:
             start_ts = event.ts_us
         print("%-9.3f" % ((float(event.ts_us) - start_ts) / 1000000), end="")
-    print("%-6d %-12.12s %-2d %-16s %-16s %-4d" % (event.pid, event.task,
-        event.ip, inet_ntop(AF_INET6, event.daddr),
+    print("%-6d %-12.12s %-2d %-16s %-16s %-4d" % (event.pid,
+        event.task.decode(), event.ip, inet_ntop(AF_INET6, event.daddr),
         inet_ntop(AF_INET6, event.saddr), event.lport))
 
 # initialize BPF
index 5b7f187..1117030 100755 (executable)
@@ -201,8 +201,9 @@ def print_ipv4_event(cpu, data, size):
         if start_ts == 0:
             start_ts = event.ts_us
         print("%-9.3f" % ((float(event.ts_us) - start_ts) / 1000000), end="")
-    print("%-6d %-12.12s %-2d %-16s %-16s %-4d" % (event.pid, event.task,
-        event.ip, inet_ntop(AF_INET, pack("I", event.saddr)),
+    print("%-6d %-12.12s %-2d %-16s %-16s %-4d" % (event.pid,
+        event.task.decode(), event.ip,
+        inet_ntop(AF_INET, pack("I", event.saddr)),
         inet_ntop(AF_INET, pack("I", event.daddr)), event.dport))
 
 def print_ipv6_event(cpu, data, size):
@@ -213,7 +214,7 @@ def print_ipv6_event(cpu, data, size):
             start_ts = event.ts_us
         print("%-9.3f" % ((float(event.ts_us) - start_ts) / 1000000), end="")
     print("%-6d %-12.12s %-2d %-16s %-16s %-4d" % (event.pid,
-        event.task, event.ip, inet_ntop(AF_INET6, event.saddr),
+        event.task.decode(), event.ip, inet_ntop(AF_INET6, event.saddr),
         inet_ntop(AF_INET6, event.daddr), event.dport))
 
 # initialize BPF
index 8a8377f..7854874 100755 (executable)
@@ -199,8 +199,9 @@ def print_ipv4_event(cpu, data, size):
         if start_ts == 0:
             start_ts = event.ts_us
         print("%-9.3f" % ((float(event.ts_us) - start_ts) / 1000000), end="")
-    print("%-6d %-12.12s %-2d %-16s %-16s %-5d %.2f" % (event.pid, event.task,
-        event.ip, inet_ntop(AF_INET, pack("I", event.saddr)),
+    print("%-6d %-12.12s %-2d %-16s %-16s %-5d %.2f" % (event.pid,
+        event.task.decode(), event.ip,
+        inet_ntop(AF_INET, pack("I", event.saddr)),
         inet_ntop(AF_INET, pack("I", event.daddr)), event.dport,
         float(event.delta_us) / 1000))
 
@@ -211,8 +212,8 @@ def print_ipv6_event(cpu, data, size):
         if start_ts == 0:
             start_ts = event.ts_us
         print("%-9.3f" % ((float(event.ts_us) - start_ts) / 1000000), end="")
-    print("%-6d %-12.12s %-2d %-16s %-16s %-5d %.2f" % (event.pid, event.task,
-        event.ip, inet_ntop(AF_INET6, event.saddr),
+    print("%-6d %-12.12s %-2d %-16s %-16s %-5d %.2f" % (event.pid,
+        event.task.decode(), event.ip, inet_ntop(AF_INET6, event.saddr),
         inet_ntop(AF_INET6, event.daddr), event.dport,
         float(event.delta_us) / 1000))
 
index 69ba174..490e568 100755 (executable)
@@ -305,7 +305,7 @@ def print_ipv4_event(cpu, data, size):
             print("%.6f," % delta_s, end="")
         else:
             print("%-9.6f " % delta_s, end="")
-    print(format_string % (event.pid, event.task,
+    print(format_string % (event.pid, event.task.decode(),
         "4" if args.wide or args.csv else "",
         inet_ntop(AF_INET, pack("I", event.saddr)), event.ports >> 32,
         inet_ntop(AF_INET, pack("I", event.daddr)), event.ports & 0xffffffff,
@@ -327,7 +327,7 @@ def print_ipv6_event(cpu, data, size):
             print("%.6f," % delta_s, end="")
         else:
             print("%-9.6f " % delta_s, end="")
-    print(format_string % (event.pid, event.task,
+    print(format_string % (event.pid, event.task.decode(),
         "6" if args.wide or args.csv else "",
         inet_ntop(AF_INET6, event.saddr), event.ports >> 32,
         inet_ntop(AF_INET6, event.daddr), event.ports & 0xffffffff,
index aac60e3..1553157 100755 (executable)
@@ -486,13 +486,13 @@ BPF_PERF_OUTPUT(%s);
                 msg = self._format_message(bpf, event.tgid, values)
                 if not Probe.print_time:
                     print("%-6d %-6d %-12s %-16s %s" %
-                          (event.tgid, event.pid, event.comm,
+                          (event.tgid, event.pid, event.comm.decode(),
                            self._display_function(), msg))
                 else:
                     time = strftime("%H:%M:%S") if Probe.use_localtime else \
                            Probe._time_off_str(event.timestamp_ns)
                     print("%-8s %-6d %-6d %-12s %-16s %s" %
-                          (time[:8], event.tgid, event.pid, event.comm,
+                          (time[:8], event.tgid, event.pid, event.comm.decode(),
                            self._display_function(), msg))
 
                 if self.kernel_stack:
index 846882c..1510d7b 100755 (executable)
@@ -111,7 +111,7 @@ if not args.noclear:
 # process event
 def print_event(cpu, data, size):
     event = ct.cast(data, ct.POINTER(Data)).contents
-    print("%s" % event.buf[0:event.count], end="")
+    print("%s" % event.buf[0:event.count].decode(), end="")
     sys.stdout.flush()
 
 # loop with callback to print_event
index ad11b9e..a750d6e 100755 (executable)
@@ -193,23 +193,23 @@ while (1):
     for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
         if folded:
             # print folded stack output
-            line = k.waker + ";"
+            line = k.waker.decode() + ";"
             for i in reversed(range(0, maxdepth)):
                 if k.ret[i] == 0:
                     continue
                 line = line + b.ksym(k.ret[i])
                 if i != 0:
                     line = line + ";"
-            print("%s;%s %d" % (line, k.target, v.value))
+            print("%s;%s %d" % (line, k.target.decode(), v.value))
         else:
             # print default multi-line stack output
-            print("    %-16s %s" % ("target:", k.target))
+            print("    %-16s %s" % ("target:", k.target.decode()))
             for i in range(0, maxdepth):
                 if k.ret[i] == 0:
                     break
                 print("    %-16x %s" % (k.ret[i],
                     b.ksym(k.ret[i])))
-            print("    %-16s %s" % ("waker:", k.waker))
+            print("    %-16s %s" % ("waker:", k.waker.decode()))
             print("        %d\n" % v.value)
     counts.clear()