--with-ia-src-dir=$(top_srcdir) --with-tests-dir=$(srcdir)
TESTS = int-types.xml float-types.xml pointer-types.xml struct-types.xml \
reinst.xml noinstrument.xml duplicate.xml inparam.xml constants.xml \
- return.xml cast.xml
+ return.xml cast.xml tracecut.xml
endif
--- /dev/null
+#include <aop.h>
+#include <tracecut.h>
+#include <stddef.h>
+
+AOP_I_AM_GPL_COMPATIBLE();
+
+static struct tc_tracecut *tc_foo;
+static struct tc_tracecut *tc_bar;
+static struct tc_tracecut *tc_both;
+
+static void join_on_main(struct aop_joinpoint *jp, void *data)
+{
+ tc_insert_tracecut_init_advice(jp);
+}
+
+static unsigned int init_pass()
+{
+ struct aop_pointcut *pc;
+
+ pc = aop_match_function_entry();
+ aop_filter_entry_by_name(pc, "run_test");
+ aop_join_on(pc, join_on_main, NULL);
+
+ return 0;
+}
+
+AOP_MAIN_PROTO aop_main()
+{
+ /* Tracecut for foo objects. */
+ tc_foo = tc_create_tracecut();
+
+ tc_add_param(tc_foo, "foo", aop_t_struct_ptr("foo"));
+
+ tc_add_call_symbol(tc_foo, "get", "get_foo", AOP_INSERT_AFTER);
+ tc_bind_to_return_value(tc_foo, "foo", "get");
+
+ tc_add_call_symbol(tc_foo, "inc", "inc_foo", AOP_INSERT_AFTER);
+ tc_bind_to_call_param(tc_foo, "foo", "inc", 0);
+
+ tc_add_call_symbol(tc_foo, "dec", "dec_foo", AOP_INSERT_AFTER);
+ tc_bind_to_call_param(tc_foo, "foo", "dec", 0);
+
+ /* Tracecut for bar objects. */
+ tc_bar = tc_create_tracecut();
+
+ tc_add_param(tc_bar, "bar", aop_t_struct_ptr("bar"));
+
+ tc_add_call_symbol(tc_bar, "get", "get_bar", AOP_INSERT_AFTER);
+ tc_bind_to_return_value(tc_bar, "bar", "get");
+
+ tc_add_call_symbol(tc_bar, "double", "double_bar", AOP_INSERT_AFTER);
+ tc_bind_to_call_param(tc_bar, "bar", "double", 0);
+
+ tc_add_call_symbol(tc_bar, "half", "half_bar", AOP_INSERT_AFTER);
+ tc_bind_to_call_param(tc_bar, "bar", "half", 0);
+
+ /* Tracecut for both objects. */
+ tc_both = tc_create_tracecut();
+
+ tc_add_param(tc_both, "foo", aop_t_struct_ptr("foo"));
+ tc_add_param(tc_both, "bar", aop_t_struct_ptr("bar"));
+
+ tc_add_call_symbol(tc_both, "transfer", "transfer", AOP_INSERT_AFTER);
+ tc_bind_to_call_param(tc_both, "foo", "transfer", 0);
+ tc_bind_to_call_param(tc_both, "bar", "transfer", 1);
+
+ aop_register_pass("init_tracecut", init_pass);
+ tc_register_tracecut_pass();
+}
+
+void aop_finish()
+{
+ tc_free_tracecut(tc_foo);
+ tc_free_tracecut(tc_bar);
+ tc_free_tracecut(tc_both);
+}
--- /dev/null
+#include <stdio.h>
+
+void _tc_init(int num_tracecuts)
+{
+ printf("Init -- n: %d\n", num_tracecuts);
+}
+
+void _tc_new_tracecut(int tc, int num_params, int num_symbols)
+{
+ printf("New tracecut -- tc: %d, params: %d, symbols: %d\n", tc, num_params, num_params);
+}
+
+void _tc_name_symbol(int tc, int symbol_index, const char *symbol_name)
+{
+ printf("Name symbol -- tc: %d, symbol: %d, name: %s\n", tc, symbol_index, symbol_name);
+}
+
+void _tc_compile_tracecut(int tc)
+{
+ printf("Compile -- tc: %d\n", tc);
+}
+
+void _tc_event_begin(int tc)
+{
+ printf("Beginning event -- tc: %d\n", tc);
+}
+
+void _tc_capture_pointer_param(int tc, int symbol, int param_index, void *param_val)
+{
+ printf("Param -- tc: %d, symbol: %d, param: %d, value: %p\n", tc, symbol, param_index, param_val);
+}
+
+void _tc_event_transition(int tc, int symbol)
+{
+ printf("Transition event -- tc: %d, symbol: %d\n", tc, symbol);
+}
--- /dev/null
+struct foo {
+ int a;
+};
+
+struct bar {
+ float a;
+};
+
+/* We have to use phone pointer values so we can check their outputs.
+ If we try to use actual structs, their addresses will change
+ across architectures. */
+struct foo *foo_obj = (struct foo *)0x8;
+struct bar *bar_obj = (struct bar *)0x16;
+
+struct foo *get_foo(void)
+{
+ return foo_obj;
+}
+
+void inc_foo(struct foo *foo)
+{
+}
+
+void dec_foo(struct foo *foo)
+{
+}
+
+struct bar *get_bar(void)
+{
+ return bar_obj;
+}
+
+void double_bar(struct bar *bar)
+{
+}
+
+void half_bar(struct bar *bar)
+{
+}
+
+void transfer(struct foo *foo, struct bar *bar)
+{
+}
+
+void run_test()
+{
+ struct foo *foo;
+ struct bar *bar;
+
+ foo = get_foo();
+ bar = get_bar();
+
+ inc_foo(foo);
+ double_bar(bar);
+ dec_foo(foo);
+ half_bar(bar);
+
+ transfer(foo, bar);
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE testcase SYSTEM "testcase.dtd">
+<testcase name="Tracecut">
+ <plugin id="plugin-tracecut" source="plugin-tracecut.c" />
+ <run name="Tracecut hooks" target="tracecut-target.c" hooks="tracecut-hooks.c">
+ <using plugin="plugin-tracecut" />
+ <output>
+ Init -- n: 3
+ New tracecut -- tc: 0, params: 2, symbols: 2
+ Name symbol -- tc: 0, symbol: 0, name: transfer
+ Compile -- tc: 0
+ New tracecut -- tc: 1, params: 1, symbols: 1
+ Name symbol -- tc: 1, symbol: 2, name: half
+ Name symbol -- tc: 1, symbol: 1, name: double
+ Name symbol -- tc: 1, symbol: 0, name: get
+ Compile -- tc: 1
+ New tracecut -- tc: 2, params: 1, symbols: 1
+ Name symbol -- tc: 2, symbol: 2, name: dec
+ Name symbol -- tc: 2, symbol: 1, name: inc
+ Name symbol -- tc: 2, symbol: 0, name: get
+ Compile -- tc: 2
+ Beginning event -- tc: 2
+ Param -- tc: 2, symbol: 0, param: 0, value: 0x8
+ Transition event -- tc: 2, symbol: 0
+ Beginning event -- tc: 1
+ Param -- tc: 1, symbol: 0, param: 0, value: 0x16
+ Transition event -- tc: 1, symbol: 0
+ Beginning event -- tc: 2
+ Param -- tc: 2, symbol: 1, param: 0, value: 0x8
+ Transition event -- tc: 2, symbol: 1
+ Beginning event -- tc: 1
+ Param -- tc: 1, symbol: 1, param: 0, value: 0x16
+ Transition event -- tc: 1, symbol: 1
+ Beginning event -- tc: 2
+ Param -- tc: 2, symbol: 2, param: 0, value: 0x8
+ Transition event -- tc: 2, symbol: 2
+ Beginning event -- tc: 1
+ Param -- tc: 1, symbol: 2, param: 0, value: 0x16
+ Transition event -- tc: 1, symbol: 2
+ Beginning event -- tc: 0
+ Param -- tc: 0, symbol: 0, param: 0, value: 0x8
+ Param -- tc: 0, symbol: 0, param: 1, value: 0x16
+ Transition event -- tc: 0, symbol: 0
+ </output>
+ </run>
+</testcase>