2012-04-09 13:11:44 +04:00
/*
* Common header file for probe - based Dynamic events .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* 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 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
* This code was copied from kernel / trace / trace_kprobe . h written by
* Masami Hiramatsu < masami . hiramatsu . pt @ hitachi . com >
*
* Updates to make this generic :
* Copyright ( C ) IBM Corporation , 2010 - 2011
* Author : Srikar Dronamraju
*/
# include <linux/seq_file.h>
# include <linux/slab.h>
# include <linux/smp.h>
# include <linux/debugfs.h>
# include <linux/types.h>
# include <linux/string.h>
# include <linux/ctype.h>
# include <linux/ptrace.h>
# include <linux/perf_event.h>
# include <linux/kprobes.h>
# include <linux/stringify.h>
# include <linux/limits.h>
# include <linux/uaccess.h>
# include <asm/bitsperlong.h>
# include "trace.h"
# include "trace_output.h"
# define MAX_TRACE_ARGS 128
# define MAX_ARGSTR_LEN 63
# define MAX_EVENT_NAME_LEN 64
# define MAX_STRING_SIZE PATH_MAX
/* Reserved field names */
# define FIELD_STRING_IP "__probe_ip"
# define FIELD_STRING_RETIP "__probe_ret_ip"
# define FIELD_STRING_FUNC "__probe_func"
# undef DEFINE_FIELD
# define DEFINE_FIELD(type, item, name, is_signed) \
do { \
ret = trace_define_field ( event_call , # type , name , \
offsetof ( typeof ( field ) , item ) , \
sizeof ( field . item ) , is_signed , \
FILTER_OTHER ) ; \
if ( ret ) \
return ret ; \
} while ( 0 )
/* Flags for trace_probe */
# define TP_FLAG_TRACE 1
# define TP_FLAG_PROFILE 2
# define TP_FLAG_REGISTERED 4
/* data_rloc: data relative location, compatible with u32 */
# define make_data_rloc(len, roffs) \
( ( ( u32 ) ( len ) < < 16 ) | ( ( u32 ) ( roffs ) & 0xffff ) )
# define get_rloc_len(dl) ((u32)(dl) >> 16)
# define get_rloc_offs(dl) ((u32)(dl) & 0xffff)
/*
* Convert data_rloc to data_loc :
* data_rloc stores the offset from data_rloc itself , but data_loc
* stores the offset from event entry .
*/
# define convert_rloc_to_loc(dl, offs) ((u32)(dl) + (offs))
/* Data fetch function type */
typedef void ( * fetch_func_t ) ( struct pt_regs * , void * , void * ) ;
/* Printing function type */
typedef int ( * print_type_func_t ) ( struct trace_seq * , const char * , void * , void * ) ;
/* Fetch types */
enum {
FETCH_MTD_reg = 0 ,
FETCH_MTD_stack ,
FETCH_MTD_retval ,
FETCH_MTD_memory ,
FETCH_MTD_symbol ,
FETCH_MTD_deref ,
FETCH_MTD_bitfield ,
FETCH_MTD_END ,
} ;
/* Fetch type information table */
struct fetch_type {
const char * name ; /* Name of type */
size_t size ; /* Byte size of type */
int is_signed ; /* Signed flag */
print_type_func_t print ; /* Print functions */
const char * fmt ; /* Fromat string */
const char * fmttype ; /* Name in format file */
/* Fetch functions */
fetch_func_t fetch [ FETCH_MTD_END ] ;
} ;
struct fetch_param {
fetch_func_t fn ;
void * data ;
} ;
struct probe_arg {
struct fetch_param fetch ;
struct fetch_param fetch_size ;
unsigned int offset ; /* Offset from argument entry */
const char * name ; /* Name of this argument */
const char * comm ; /* Command of this argument */
const struct fetch_type * type ; /* Type of this argument */
} ;
static inline __kprobes void call_fetch ( struct fetch_param * fprm ,
struct pt_regs * regs , void * dest )
{
return fprm - > fn ( regs , fprm - > data , dest ) ;
}
/* Check the name is good for event/group/fields */
static inline int is_good_name ( const char * name )
{
if ( ! isalpha ( * name ) & & * name ! = ' _ ' )
return 0 ;
while ( * + + name ! = ' \0 ' ) {
if ( ! isalpha ( * name ) & & ! isdigit ( * name ) & & * name ! = ' _ ' )
return 0 ;
}
return 1 ;
}
extern int traceprobe_parse_probe_arg ( char * arg , ssize_t * size ,
2012-04-11 14:30:43 +04:00
struct probe_arg * parg , bool is_return , bool is_kprobe ) ;
2012-04-09 13:11:44 +04:00
extern int traceprobe_conflict_field_name ( const char * name ,
struct probe_arg * args , int narg ) ;
extern void traceprobe_update_arg ( struct probe_arg * arg ) ;
extern void traceprobe_free_probe_arg ( struct probe_arg * arg ) ;
extern int traceprobe_split_symbol_offset ( char * symbol , unsigned long * offset ) ;
extern ssize_t traceprobe_probes_write ( struct file * file ,
const char __user * buffer , size_t count , loff_t * ppos ,
int ( * createfn ) ( int , char * * ) ) ;
extern int traceprobe_command ( const char * buf , int ( * createfn ) ( int , char * * ) ) ;