Add clang support for nested struct/union as key field
authorBrenden Blanco <bblanco@plumgrid.com>
Mon, 2 May 2016 04:29:08 +0000 (21:29 -0700)
committerBrenden Blanco <bblanco@plumgrid.com>
Mon, 2 May 2016 04:29:08 +0000 (21:29 -0700)
Clang was up until now not able to parse nested structs or unions as a
field in the table key or leaf. Add support in the library side, as well
as python support for the exported json description.

src/cc/frontends/clang/b_frontend_action.cc
src/python/bcc/__init__.py

index 852abc0..17ead62 100644 (file)
@@ -67,6 +67,12 @@ bool BMapDeclVisitor::VisitRecordDecl(RecordDecl *D) {
   result_ += D->getName();
   result_ += "\", [";
   for (auto F : D->getDefinition()->fields()) {
+    if (F->isAnonymousStructOrUnion()) {
+      if (const RecordType *R = dyn_cast<RecordType>(F->getType()))
+        TraverseDecl(R->getDecl());
+      result_ += ", ";
+      continue;
+    }
     result_ += "[";
     TraverseDecl(F);
     if (const ConstantArrayType *T = dyn_cast<ConstantArrayType>(F->getType()))
index 5a393c1..55bbbaa 100644 (file)
@@ -250,6 +250,7 @@ class BPF(object):
     def _decode_table_type(desc):
         if isinstance(desc, basestring):
             return BPF.str2ctype[desc]
+        anon = []
         fields = []
         for t in desc[1]:
             if len(t) == 2:
@@ -257,8 +258,17 @@ class BPF(object):
             elif len(t) == 3:
                 if isinstance(t[2], list):
                     fields.append((t[0], BPF._decode_table_type(t[1]) * t[2][0]))
-                else:
+                elif isinstance(t[2], int):
                     fields.append((t[0], BPF._decode_table_type(t[1]), t[2]))
+                elif isinstance(t[2], basestring) and (
+                        t[2] == u"union" or t[2] == u"struct"):
+                    name = t[0]
+                    if name == "":
+                        name = "__anon%d" % len(anon)
+                        anon.append(name)
+                    fields.append((name, BPF._decode_table_type(t)))
+                else:
+                    raise Exception("Failed to decode type %s" % str(t))
             else:
                 raise Exception("Failed to decode type %s" % str(t))
         base = ct.Structure
@@ -267,7 +277,8 @@ class BPF(object):
                 base = ct.Union
             elif desc[2] == u"struct":
                 base = ct.Structure
-        cls = type(str(desc[0]), (base,), dict(_fields_=fields))
+        cls = type(str(desc[0]), (base,), dict(_anonymous_=anon,
+            _fields_=fields))
         return cls
 
     def get_table(self, name, keytype=None, leaftype=None, reducer=None):