From: Justin Seyster Date: Thu, 17 Mar 2011 01:35:30 +0000 (-0400) Subject: tc_report_match() is overridable. X-Git-Tag: release-v1.1~9^2~10 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=787fc690aaaaf536dedefbbf0900ea9bc30b42d1;p=interaspect.git tc_report_match() is overridable. --- diff --git a/Doxyfile b/Doxyfile index a537fa5..56333d8 100644 --- a/Doxyfile +++ b/Doxyfile @@ -585,7 +585,7 @@ INPUT_ENCODING = UTF-8 # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 -FILE_PATTERNS = aop.h tracecut.h *.c +FILE_PATTERNS = aop.h tracecut.h tracecut-advice.h *.c # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. diff --git a/src/Makefile.am b/src/Makefile.am index 9326eab..f8a359b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,4 +11,4 @@ libinteraspect_la_CPPFLAGS = -DHAVE_CONFIG_H -DIN_GCC -I$(gcc_includes) libtracecut_la_SOURCES = tracecut-advice.c nfa.c nfa.h libtracecut_la_CFLAGS = -Wall -Werror -fvisibility=hidden -include_HEADERS = aop.h tracecut.h +include_HEADERS = aop.h tracecut.h tracecut-advice.h diff --git a/src/tracecut-advice.c b/src/tracecut-advice.c index 52bc438..fe26a8b 100644 --- a/src/tracecut-advice.c +++ b/src/tracecut-advice.c @@ -4,6 +4,7 @@ #include #include "nfa.h" +#include "tracecut-advice.h" /* Advice functions should be externally visible. */ #define ADVICE_FUNC __attribute__((visibility("default"))) @@ -26,23 +27,6 @@ struct tracecut { static struct tracecut *tracecut_array = NULL; -struct param_val { - enum { - PV_VACANT = 0, - PV_POINTER, - PV_SIGNED_INT, - PV_UNSIGNED_INT, - PV_FP - } kind; - - union { - uintptr_t ptr_value; - int64_t int_val; - uint64_t uint_val; - double fp_val; - }; -}; - struct event { int symbol_index; @@ -103,19 +87,33 @@ get_tracecut (int tc_index) } } -void -tc_report_match (struct tracecut *tc, struct tuple *tuple, int symbol_index) +__attribute__((weak)) __attribute__((noinline)) void +tc_report_match (const char *symbol, const struct matched_param *param_array, + int num_params) { - fprintf (stderr, "(Tracecut) Match triggered by symbol: %s.", tc->symbol_names[symbol_index]); + fprintf (stderr, "(Tracecut) Match triggered by symbol: %s.", symbol); - if (tc->num_params > 0) + if (num_params > 0) { int i; fprintf (stderr, " Param values follow:\n"); - for (i = 0; i < tc->num_params; i++) - fprintf (stderr, " Param %s: 0x%p\n", tc->param_names[i], - (void *)tuple->param_vals[i].ptr_value); + for (i = 0; i < num_params; i++) + { + const char *name = param_array[i].name; + const struct param_val *value = param_array[i].value; + + fprintf (stderr, " Param %s: ", name); + + switch (value->kind) + { + case PV_POINTER: + fprintf (stderr, " %p\n", (void *)value->ptr_value); + break; + default: + fprintf (stderr, " Bad value\n"); + } + } } else { @@ -124,6 +122,22 @@ tc_report_match (struct tracecut *tc, struct tuple *tuple, int symbol_index) } } +static void +report_match (struct tracecut *tc, struct tuple *tuple, int symbol_index) +{ + int i; + struct matched_param *param_array; + + param_array = alloca (tc->num_params * sizeof (struct matched_param)); + for (i = 0; i < tc->num_params; i++) + { + param_array[i].name = tc->param_names[i]; + param_array[i].value = &tuple->param_vals[i]; + } + + tc_report_match (tc->symbol_names[symbol_index], param_array, tc->num_params); +} + static void insert_tuple (struct tracecut *tc, struct tuple *tuple) { @@ -176,7 +190,7 @@ advance_state_machine (struct tracecut *tc, struct tuple *tuple, int symbol_inde { step (tuple->states[i], symbol_index); if (ismatch (tuple->states[i])) - tc_report_match (tc, tuple, symbol_index); + report_match (tc, tuple, symbol_index); if (isatstart (tuple->states[i])) num_trivial++; @@ -214,21 +228,21 @@ event_matches_tuple (struct event *event, struct tuple *tuple) break; case PV_SIGNED_INT: if (tuple->param_vals[i].kind != PV_SIGNED_INT - || event->param_vals[i].int_val != tuple->param_vals[i].int_val) + || event->param_vals[i].int_value != tuple->param_vals[i].int_value) return 0; /* Mismatch. */ else ; /* This param matches; keep looking. */ break; case PV_UNSIGNED_INT: if (tuple->param_vals[i].kind != PV_UNSIGNED_INT - || event->param_vals[i].uint_val != tuple->param_vals[i].uint_val) + || event->param_vals[i].uint_value != tuple->param_vals[i].uint_value) return 0; /* Mismatch. */ else ; /* This param matches; keep looking. */ break; case PV_FP: if (tuple->param_vals[i].kind != PV_FP - || event->param_vals[i].fp_val != tuple->param_vals[i].fp_val) + || event->param_vals[i].fp_value != tuple->param_vals[i].fp_value) return 0; /* Mismatch. */ else ; /* This param matches; keep looking. */ @@ -538,8 +552,8 @@ _tc_capture_signed_int_param (int tc_index, int symbol_index, int param_index, fatal_tracecut_error ("Out-of-bounds param value."); } - current_event->param_vals[param_index].kind = PV_SIGNED_INT; - current_event->param_vals[param_index].int_val = param_val; + current_event->param_vals[param_index].kind = PV_SIGNED_INT; + current_event->param_vals[param_index].int_value = param_val; } ADVICE_FUNC void @@ -561,8 +575,8 @@ _tc_capture_unsigned_int_param (int tc_index, int symbol_index, int param_index, fatal_tracecut_error ("Out-of-bounds param value."); } - current_event->param_vals[param_index].kind = PV_UNSIGNED_INT; - current_event->param_vals[param_index].uint_val = param_val; + current_event->param_vals[param_index].kind = PV_UNSIGNED_INT; + current_event->param_vals[param_index].uint_value = param_val; } ADVICE_FUNC void @@ -584,8 +598,8 @@ _tc_capture_float_param (int tc_index, int symbol_index, int param_index, fatal_tracecut_error ("Out-of-bounds param value."); } - current_event->param_vals[param_index].kind = PV_FP; - current_event->param_vals[param_index].fp_val = param_val; + current_event->param_vals[param_index].kind = PV_FP; + current_event->param_vals[param_index].fp_value = param_val; } diff --git a/src/tracecut-advice.h b/src/tracecut-advice.h new file mode 100644 index 0000000..f5dd535 --- /dev/null +++ b/src/tracecut-advice.h @@ -0,0 +1,100 @@ +#ifndef __AOP_TRACECUT_ADVICE_H__ +#define __AOP_TRACECUT_ADVICE_H__ + +/* Copyright (c) 2011 Justin Seyster + Copyright (c) 2011 Erez Zadok + Copyright (c) 2011 Stony Brook University + Copyright (c) 2011 The Research Foundation of SUNY + + This program is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License + and a copy of the GCC Runtime Library Exception along with this + program; see the files COPYING and COPYING.RUNTIME respectively. + If not, see . */ + +/** + * \file tracecut-advice.h + * \brief Public interface for implementing tracut advice functions. + * + * When the tracecut monitoring engine matches a tracecut rule, it + * calls the tracecut match function, tc_report_match(). By default, + * tc_report_match() just prints information about the match to + * stderr, but it is possible to override + * tc_report_match() to perform some other action. + * + * Note that this include file is not intended for tracecut + * plug-ins. Rather, it is intended for tracecut advice, which + * gets compiled and linked with the target program. + */ + +/** + * \brief Value of a param. + * + * Stores the value of a param, along with what kind of param it is. + * There are four kinds of param, PV_POINTER, PV_SIGNED_INT, + * PV_UNSIGNED_INT, and PV_FP. PV_VACANT is used internally; no param + * with kind PV_VACANT will ever be passed to tc_report_match(). + * + * The param's value itself is stored in a transparent union. You + * should only ever access the vaue using the union member that + * corresponds to the param's kind. You can access a transparent + * union member as if it were a member of the struct. + */ +struct param_val { + enum { + PV_VACANT = 0, + PV_POINTER, + PV_SIGNED_INT, + PV_UNSIGNED_INT, + PV_FP + } kind; + + union { + uintptr_t ptr_value; + int64_t int_value; + uint64_t uint_value; + double fp_value; + }; +}; + +/** + * \brief The name and value of a param. + */ +struct matched_param +{ + const char *name; + const struct param_val *value; +}; + +/** + * This function gets called at runtime when a tracecut rule matches. + * Because it is marked as a weak symbol, if the target program (or + * some other library) implements tc_report_match(), it will override + * the default implementation. + * + * The default implementation prints the symbol that triggered the + * match and the value of each param to stderr. + * + * \param symbol The name of the symbol that triggered the match. + * \param param_array A list of params associated with the tracecut. + * Each entry in the array has the param's name, as well as its value. + * \param num_params The number of elements in the param_array list. + */ +extern void tc_report_match (const char *symbol, + const struct matched_param *param_array, + int num_params); + +#endif