aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@kernel.org>2016-05-05 18:34:28 -0700
committerLuis R. Rodriguez <mcgrof@kernel.org>2016-05-06 16:08:12 -0700
commitd2c9fe5406dafbbf01d5edfff1e05dc221182ba9 (patch)
tree27fa56912be94334c7a07f94641bb59e7575c5ce
parent1fe7b2f133f45592f9dedb3254e9aeee7d50f32d (diff)
downloadcocci-tact-d2c9fe5406dafbbf01d5edfff1e05dc221182ba9.tar.gz
add initial cocci instrumentation demoHEADmaster
This doesn't yet fix anything, but adds enough basics to show what is intended. Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
-rw-r--r--Makefile4
-rw-r--r--README61
-rw-r--r--fix-lock.cocci159
3 files changed, 224 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 122bbfb..4eb4364 100644
--- a/Makefile
+++ b/Makefile
@@ -5,3 +5,7 @@ main: main.c
clean:
rm -f main
+
+coccicheck:
+
+ pycocci fix-lock.cocci ./
diff --git a/README b/README
new file mode 100644
index 0000000..9dc0bbf
--- /dev/null
+++ b/README
@@ -0,0 +1,61 @@
+ cocci-tact: Demo for instrumenting with Coccinelle
+====================================================
+
+This is a basic demo to show how one can do instrumentation with Coccinelle.
+
+ The problem
+=============
+
+Some Linux kernel debugging features often require adding a lot of debug data
+structures to a source code repository, often this is addressed with
+CONFIG_DEBUG_* features but sometimes maintaining this upstream on Linux is not
+really welcomed due to how intrusive your changes may be or the difficulty
+in maintaining it properly. Sometimes such code can simply increase the
+complexity of what developers see, and can often riddle developers how to
+address its use / extending it / or replacing your instrumentation code.
+
+ Instrumenting with Coccinelle
+===============================
+
+Coccinelle enables a possible alternative: modify upstream code only when
+you need it, for a throw away debugging kernel. Your instrumentation then
+can be compartamentalized as much as possible upstream, and changes to
+existing code kept separate, outside of what developers see.
+
+This demo illustrates adding some form of instrumentation basic templates
+to code in userspace by trying to take advantage of a simple line which
+would be assumed to be upstream: on code pthread_mutex_protects_3().
+
+In this case pthread_mutex_protects_3() provides Coccinelle with hints
+over what data structures a mutex protects. It is the goal of the
+instrumentation mechanisms being developed here to either fix or
+debug this code without affecting readability for users or average
+developers of the code.
+
+This demo is written in userspace to help facilitate testing of ideas.
+Instrumentation ideas are not yet complete but its the hope this provides
+enough examples to show how this sort of work might look like. Locking
+would just be one area that could use this. There are obviously other
+domains that could benefit from this.
+
+ Requirements
+==============
+
+ * Coccinelle >= 1.0.2
+ * gcc
+ * make
+
+ Usage
+=======
+
+To see the problem run:
+
+ make
+ ./main
+
+To see what the instrumentation does:
+
+ make coccicheck
+ git diff
+
+This doesn't do anything quite useful just yet.
diff --git a/fix-lock.cocci b/fix-lock.cocci
new file mode 100644
index 0000000..7ea7f7c
--- /dev/null
+++ b/fix-lock.cocci
@@ -0,0 +1,159 @@
+@ find_drv_name @
+identifier drv;
+identifier mutex;
+@@
+
+pthread_mutex_protects_3(&drv->mutex, ...);
+
+@ find_hint @
+type T;
+T *drv;
+identifier mutex, item_1, item_2, item_3;
+@@
+
+pthread_mutex_protects_3(&drv->mutex, drv->item_1, drv->item_2, drv->item_3);
+
+@ add_instrumentation_vars @
+type find_hint.T;
+identifier find_hint.mutex, find_hint.item_1, find_hint.item_2, find_hint.item_3;
+type T1, T2;
+fresh identifier instr_item_1 = "__instr_" ## item_1;
+fresh identifier instr_item_2 = "__instr_" ## item_2;
+fresh identifier instr_item_3 = "__instr_" ## item_3;
+@@
+
+T {
+ ...
++ int instr_item_1;
+ T1 item_1;
+ ...
++ int instr_item_2;
+ T2 item_2;
+ ...
++ int instr_item_3;
+ T2 item_3;
+ ...
+};
+
+@ add_counter depends on add_instrumentation_vars @
+type find_hint.T;
+identifier find_hint.mutex, find_hint.item_1, find_hint.item_2, find_hint.item_3;
+identifier find_drv_name.drv;
+fresh identifier fn_instr = "__instr_" ## mutex;
+@@
+
+#include <string.h>
++
++T;
++static void fn_instr(T *drv)
++{
++}
++
+
+@ find_pthread_fn depends on find_hint @
+identifier fn, ret;
+expression thread, attr, val;
+@@
+
+ret = pthread_create(thread, attr, fn, val);
+
+@ check_fn_access @
+identifier find_pthread_fn.fn;
+type find_hint.T;
+T *drv;
+//identifier find_drv_name.drv;
+identifier add_counter.fn_instr;
+identifier find_hint.mutex;
+identifier find_hint.item_1;
+identifier find_hint.item_2;
+identifier find_hint.item_3;
+@@
+
+fn (...)
+{
+ <+...
+(
+ drv->item_1
+|
+ drv->item_2
+|
+ drv->item_3
+)
+ ...+>
++
++ /* top level routine accesses drv */
++ fn_instr(drv);
++
+}
+
+@ check_helpers depends on find_pthread_fn @
+identifier helper;
+identifier find_pthread_fn.fn;
+identifier find_hint.mutex;
+type find_hint.T;
+T *drv;
+@@
+
+fn (...)
+{
+ <+... when != pthread_mutex_lock(&drv->mutex);
++ /* going to check this routine */
+ helper(...);
+ ...+>
+}
+
+@ helper_accessing_with_lock exists @
+identifier check_helpers.helper;
+type find_hint.T;
+T *drv;
+identifier find_hint.mutex;
+identifier find_hint.item_1;
+identifier find_hint.item_2;
+identifier find_hint.item_3;
+position p1, p2;
+identifier add_counter.fn_instr;
+@@
+
+helper(...)
+{
+ ...
+ pthread_mutex_lock@p1(&drv->mutex);
+ <+...
+(
+ drv->item_1
+|
+ drv->item_2
+|
+ drv->item_3
+)
+ ...+>
+ pthread_mutex_unlock@p2(&drv->mutex);
++ /* routine had a lock */
++ fn_instr(drv);
+}
+
+@ helper_accessing_without_lock exists @
+identifier check_helpers.helper;
+type find_hint.T;
+T *drv;
+identifier find_hint.mutex;
+identifier find_hint.item_1;
+identifier find_hint.item_2;
+identifier find_hint.item_3;
+identifier add_counter.fn_instr;
+@@
+
+helper(...)
+{
+ <+... when != pthread_mutex_lock(&drv->mutex);
+(
+ drv->item_1
+|
+ drv->item_2
+|
+ drv->item_3
+)
+ ...+>
++ /* was missing lock */
++ fn_instr(drv);
+}