Support array and pointer types in scanf generated function
authorBrenden Blanco <bblanco@plumgrid.com>
Sun, 7 Feb 2016 04:59:10 +0000 (20:59 -0800)
committerBrenden Blanco <bblanco@plumgrid.com>
Sun, 7 Feb 2016 05:16:54 +0000 (21:16 -0800)
The rewriter-created sscanf and snprintf routines did not support map
structs with arrays or pointer types in them. Add such support.

Signed-off-by: Brenden Blanco <bblanco@plumgrid.com>
src/cc/bpf_module.cc
tests/cc/test_clang.py

index 7e1a409..fbdb71b 100644 (file)
@@ -148,6 +148,19 @@ static void parse_type(IRBuilder<> &B, vector<Value *> *args, string *fmt,
       *fmt += " ";
     }
     *fmt += "}";
+  } else if (ArrayType *at = dyn_cast<ArrayType>(type)) {
+    *fmt += "[ ";
+    for (size_t i = 0; i < at->getNumElements(); ++i) {
+      parse_type(B, args, fmt, at->getElementType(), B.CreateStructGEP(type, out, i), is_writer);
+      *fmt += " ";
+    }
+    *fmt += "]";
+  } else if (PointerType *pt = dyn_cast<PointerType>(type)) {
+    *fmt += "0xl";
+    if (is_writer)
+      *fmt += "x";
+    else
+      *fmt += "i";
   } else if (IntegerType *it = dyn_cast<IntegerType>(type)) {
     if (is_writer)
       *fmt += "0x";
index 87f2bd4..ae19519 100755 (executable)
@@ -3,6 +3,7 @@
 # Licensed under the Apache License, Version 2.0 (the "License")
 
 from bcc import BPF
+import ctypes
 from unittest import main, TestCase
 
 class TestClang(TestCase):
@@ -89,6 +90,22 @@ int foo(void *ctx) {
         self.assertEqual(l.s.a, 5)
         self.assertEqual(l.s.b, 6)
 
+    def test_sscanf_array(self):
+        text = """
+BPF_TABLE("hash", int, struct { u32 a[3]; u32 b; }, stats, 10);
+"""
+        b = BPF(text=text, debug=0)
+        t = b.get_table("stats")
+        s1 = t.key_sprintf(t.Key(2))
+        self.assertEqual(s1, b"0x2")
+        s2 = t.leaf_sprintf(t.Leaf((ctypes.c_uint * 3)(1,2,3), 4))
+        self.assertEqual(s2, b"{ [ 0x1 0x2 0x3 ] 0x4 }")
+        l = t.leaf_scanf(s2)
+        self.assertEqual(l.a[0], 1)
+        self.assertEqual(l.a[1], 2)
+        self.assertEqual(l.a[2], 3)
+        self.assertEqual(l.b, 4)
+
     def test_iosnoop(self):
         text = """
 #include <linux/blkdev.h>