2018-08-16 18:23:53 +03:00
// SPDX-License-Identifier: GPL-2.0
2012-04-09 13:11:44 +04:00
/*
* Common header file for probe - based Dynamic events .
*
* 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>
2015-01-20 20:13:40 +03:00
# include <linux/tracefs.h>
2012-04-09 13:11:44 +04:00
# 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_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
2018-04-25 15:19:01 +03:00
/* data_loc: data location, compatible with u32 */
# define make_data_loc(len, offs) \
( ( ( u32 ) ( len ) < < 16 ) | ( ( u32 ) ( offs ) & 0xffff ) )
# define get_loc_len(dl) ((u32)(dl) >> 16)
# define get_loc_offs(dl) ((u32)(dl) & 0xffff)
2012-04-09 13:11:44 +04:00
2014-04-17 12:18:28 +04:00
static nokprobe_inline void * get_loc_data ( u32 * dl , void * ent )
2013-11-26 09:19:59 +04:00
{
2018-04-25 15:19:01 +03:00
return ( u8 * ) ent + get_loc_offs ( * dl ) ;
2013-11-26 09:19:59 +04:00
}
2012-04-09 13:11:44 +04:00
/* Printing function type */
2018-04-25 15:16:36 +03:00
typedef int ( * print_type_func_t ) ( struct trace_seq * , void * , void * ) ;
2012-04-09 13:11:44 +04:00
2018-04-25 15:18:03 +03:00
enum fetch_op {
FETCH_OP_NOP = 0 ,
// Stage 1 (load) ops
FETCH_OP_REG , /* Register : .param = offset */
FETCH_OP_STACK , /* Stack : .param = index */
FETCH_OP_STACKP , /* Stack pointer */
FETCH_OP_RETVAL , /* Return value */
FETCH_OP_IMM , /* Immediate : .immediate */
FETCH_OP_COMM , /* Current comm */
FETCH_OP_FOFFS , /* File offset: .immediate */
// Stage 2 (dereference) op
FETCH_OP_DEREF , /* Dereference: .offset */
// Stage 3 (store) ops
FETCH_OP_ST_RAW , /* Raw: .size */
FETCH_OP_ST_MEM , /* Mem: .offset, .size */
FETCH_OP_ST_STRING , /* String: .offset, .size */
// Stage 4 (modify) op
FETCH_OP_MOD_BF , /* Bitfield: .basesize, .lshift, .rshift */
FETCH_OP_END ,
2012-04-09 13:11:44 +04:00
} ;
2018-04-25 15:18:03 +03:00
struct fetch_insn {
enum fetch_op op ;
union {
unsigned int param ;
struct {
unsigned int size ;
int offset ;
} ;
struct {
unsigned char basesize ;
unsigned char lshift ;
unsigned char rshift ;
} ;
unsigned long immediate ;
} ;
} ;
/* fetch + deref*N + store + mod + end <= 16, this allows N=12, enough */
# define FETCH_INSN_MAX 16
2012-04-09 13:11:44 +04:00
/* 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 */
} ;
2013-11-26 09:56:28 +04:00
/* For defining macros, define string/string_size types */
typedef u32 string ;
typedef u32 string_size ;
2013-11-26 09:19:59 +04:00
# define PRINT_TYPE_FUNC_NAME(type) print_type_##type
# define PRINT_TYPE_FMT_NAME(type) print_type_format_##type
/* Printing in basic type function template */
# define DECLARE_BASIC_PRINT_TYPE_FUNC(type) \
2018-04-25 15:16:36 +03:00
int PRINT_TYPE_FUNC_NAME ( type ) ( struct trace_seq * s , void * data , void * ent ) ; \
2013-11-26 09:19:59 +04:00
extern const char PRINT_TYPE_FMT_NAME ( type ) [ ]
DECLARE_BASIC_PRINT_TYPE_FUNC ( u8 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( u16 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( u32 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( u64 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( s8 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( s16 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( s32 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( s64 ) ;
2016-08-18 11:57:50 +03:00
DECLARE_BASIC_PRINT_TYPE_FUNC ( x8 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( x16 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( x32 ) ;
DECLARE_BASIC_PRINT_TYPE_FUNC ( x64 ) ;
2013-11-26 09:19:59 +04:00
DECLARE_BASIC_PRINT_TYPE_FUNC ( string ) ;
2018-04-25 15:20:28 +03:00
DECLARE_BASIC_PRINT_TYPE_FUNC ( symbol ) ;
2013-11-26 09:19:59 +04:00
/* Default (unsigned long) fetch type */
2016-08-18 11:59:21 +03:00
# define __DEFAULT_FETCH_TYPE(t) x##t
2013-11-26 09:19:59 +04:00
# define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t)
# define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG)
# define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE)
2018-04-25 15:20:28 +03:00
# define __ADDR_FETCH_TYPE(t) u##t
# define _ADDR_FETCH_TYPE(t) __ADDR_FETCH_TYPE(t)
# define ADDR_FETCH_TYPE _ADDR_FETCH_TYPE(BITS_PER_LONG)
2013-11-26 09:19:59 +04:00
# define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \
{ . name = _name , \
. size = _size , \
. is_signed = sign , \
. print = PRINT_TYPE_FUNC_NAME ( ptype ) , \
. fmt = PRINT_TYPE_FMT_NAME ( ptype ) , \
. fmttype = _fmttype , \
}
2018-04-25 15:20:28 +03:00
# define _ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \
__ASSIGN_FETCH_TYPE ( _name , ptype , ftype , _size , sign , # _fmttype )
2013-11-26 09:19:59 +04:00
# define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \
2018-04-25 15:20:28 +03:00
_ASSIGN_FETCH_TYPE ( # ptype , ptype , ftype , sizeof ( ftype ) , sign , ptype )
2013-11-26 09:19:59 +04:00
2016-08-18 11:57:50 +03:00
/* If ptype is an alias of atype, use this macro (show atype in format) */
# define ASSIGN_FETCH_TYPE_ALIAS(ptype, atype, ftype, sign) \
2018-04-25 15:20:28 +03:00
_ASSIGN_FETCH_TYPE ( # ptype , ptype , ftype , sizeof ( ftype ) , sign , atype )
2016-08-18 11:57:50 +03:00
2013-11-26 09:56:28 +04:00
# define ASSIGN_FETCH_TYPE_END {}
2017-02-16 09:00:50 +03:00
# ifdef CONFIG_KPROBE_EVENTS
2018-01-12 20:54:04 +03:00
bool trace_kprobe_on_func_entry ( struct trace_event_call * call ) ;
bool trace_kprobe_error_injectable ( struct trace_event_call * call ) ;
2013-11-26 10:21:04 +04:00
# else
2018-01-12 20:54:04 +03:00
static inline bool trace_kprobe_on_func_entry ( struct trace_event_call * call )
2017-12-11 19:36:48 +03:00
{
2018-01-12 20:54:04 +03:00
return false ;
2017-12-11 19:36:48 +03:00
}
2018-01-12 20:54:04 +03:00
static inline bool trace_kprobe_error_injectable ( struct trace_event_call * call )
2017-12-11 19:36:48 +03:00
{
2018-01-12 20:54:04 +03:00
return false ;
2017-12-11 19:36:48 +03:00
}
2017-02-16 09:00:50 +03:00
# endif /* CONFIG_KPROBE_EVENTS */
2013-11-26 10:21:04 +04:00
2012-04-09 13:11:44 +04:00
struct probe_arg {
2018-04-25 15:18:03 +03:00
struct fetch_insn * code ;
bool dynamic ; /* Dynamic array (string) is used */
2012-04-09 13:11:44 +04:00
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 */
} ;
2013-07-03 08:50:51 +04:00
struct trace_probe {
unsigned int flags ; /* For TP_FLAG_* */
2015-05-05 18:45:27 +03:00
struct trace_event_class class ;
struct trace_event_call call ;
2013-07-03 08:50:51 +04:00
struct list_head files ;
ssize_t size ; /* trace entry size */
unsigned int nr_args ;
struct probe_arg args [ ] ;
} ;
2014-01-17 12:08:38 +04:00
struct event_file_link {
2015-05-05 17:09:53 +03:00
struct trace_event_file * file ;
2014-01-17 12:08:38 +04:00
struct list_head list ;
} ;
2013-07-03 08:50:51 +04:00
static inline bool trace_probe_is_enabled ( struct trace_probe * tp )
{
return ! ! ( tp - > flags & ( TP_FLAG_TRACE | TP_FLAG_PROFILE ) ) ;
}
static inline bool trace_probe_is_registered ( struct trace_probe * tp )
{
return ! ! ( tp - > flags & TP_FLAG_REGISTERED ) ;
}
2012-04-09 13:11:44 +04:00
/* Check the name is good for event/group/fields */
2015-09-22 16:43:13 +03:00
static inline bool is_good_name ( const char * name )
2012-04-09 13:11:44 +04:00
{
if ( ! isalpha ( * name ) & & * name ! = ' _ ' )
2015-09-22 16:43:13 +03:00
return false ;
2012-04-09 13:11:44 +04:00
while ( * + + name ! = ' \0 ' ) {
if ( ! isalpha ( * name ) & & ! isdigit ( * name ) & & * name ! = ' _ ' )
2015-09-22 16:43:13 +03:00
return false ;
2012-04-09 13:11:44 +04:00
}
2015-09-22 16:43:13 +03:00
return true ;
2012-04-09 13:11:44 +04:00
}
2014-01-17 12:08:38 +04:00
static inline struct event_file_link *
2015-05-05 17:09:53 +03:00
find_event_file_link ( struct trace_probe * tp , struct trace_event_file * file )
2014-01-17 12:08:38 +04:00
{
struct event_file_link * link ;
list_for_each_entry ( link , & tp - > files , list )
if ( link - > file = = file )
return link ;
return NULL ;
}
2012-04-09 13:11:44 +04:00
extern int traceprobe_parse_probe_arg ( char * arg , ssize_t * size ,
2018-04-25 15:18:32 +03: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 ) ;
2018-03-17 15:38:10 +03:00
extern int traceprobe_split_symbol_offset ( char * symbol , long * offset ) ;
2012-04-09 13:11:44 +04:00
2018-04-25 15:19:30 +03:00
extern int traceprobe_set_print_fmt ( struct trace_probe * tp , bool is_return ) ;
2017-12-07 01:45:15 +03:00
# ifdef CONFIG_PERF_EVENTS
extern struct trace_event_call *
create_local_trace_kprobe ( char * func , void * addr , unsigned long offs ,
bool is_return ) ;
extern void destroy_local_trace_kprobe ( struct trace_event_call * event_call ) ;
2017-12-07 01:45:16 +03:00
extern struct trace_event_call *
2018-10-02 08:36:36 +03:00
create_local_trace_uprobe ( char * name , unsigned long offs ,
unsigned long ref_ctr_offset , bool is_return ) ;
2017-12-07 01:45:16 +03:00
extern void destroy_local_trace_uprobe ( struct trace_event_call * event_call ) ;
2017-12-07 01:45:15 +03:00
# endif
2018-04-25 15:17:05 +03:00
extern int traceprobe_define_arg_fields ( struct trace_event_call * event_call ,
size_t offset , struct trace_probe * tp ) ;