table: Implement a StackWalker for StackTrace tables
authorVicent Marti <tanoku@gmail.com>
Fri, 25 Mar 2016 16:12:11 +0000 (17:12 +0100)
committerVicent Marti <tanoku@gmail.com>
Fri, 25 Mar 2016 16:12:11 +0000 (17:12 +0100)
The StackWalker iterator lets us call `stack_trace.walk(id)` to iterate
through the addresses in any given stack. The constructor of this
iterator takes an optional `resolver` to convert the addresses in the
iterator into symbols (or to format them according to the users' needs).

src/python/bcc/table.py

index c33cb39..70ef973 100644 (file)
@@ -412,9 +412,37 @@ class PerCpuArray(ArrayBase):
         raise Exception("Unsupported")
 
 class StackTrace(TableBase):
+    MAX_DEPTH = 127
+
     def __init__(self, *args, **kwargs):
         super(StackTrace, self).__init__(*args, **kwargs)
 
+    class StackWalker(object):
+        def __init__(self, stack, resolve=None):
+            self.stack = stack
+            self.n = -1
+            self.resolve = resolve
+
+        def __iter__(self):
+            return self
+
+        def __next__(self):
+            return self.next()
+
+        def next(self):
+            self.n += 1
+            if self.n == StackTrace.MAX_DEPTH:
+                raise StopIteration()
+
+            addr = self.stack.ip[self.n]
+            if addr == 0 :
+                raise StopIteration()
+
+            return self.resolve(addr) if self.resolve else addr
+
+    def walk(self, stack_id, resolve=None):
+        return StackTrace.StackWalker(self[self.Key(stack_id)], resolve)
+
     def __len__(self):
         i = 0
         for k in self: i += 1