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>
2018-04-25 15:21:26 +03:00
# include <linux/bitops.h>
2012-04-09 13:11:44 +04:00
# include <asm/bitsperlong.h>
# include "trace.h"
# include "trace_output.h"
# define MAX_TRACE_ARGS 128
# define MAX_ARGSTR_LEN 63
2018-04-25 15:21:55 +03:00
# define MAX_ARRAY_LEN 64
2019-03-14 07:30:30 +03:00
# define MAX_ARG_NAME_LEN 32
2012-04-09 13:11:44 +04:00
# 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
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
}
2018-04-25 15:21:55 +03:00
static nokprobe_inline u32 update_data_loc ( u32 loc , int consumed )
{
u32 maxlen = get_loc_len ( loc ) ;
u32 offset = get_loc_offs ( loc ) ;
return make_data_loc ( maxlen - consumed , offset + consumed ) ;
}
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 */
2018-04-25 15:21:26 +03:00
FETCH_OP_ARG , /* Function argument : .param */
2018-04-25 15:18:03 +03:00
FETCH_OP_FOFFS , /* File offset: .immediate */
2019-06-19 18:08:37 +03:00
FETCH_OP_DATA , /* Allocated data: .data */
2018-04-25 15:18:03 +03:00
// Stage 2 (dereference) op
FETCH_OP_DEREF , /* Dereference: .offset */
2019-05-15 08:38:42 +03:00
FETCH_OP_UDEREF , /* User-space Dereference: .offset */
2018-04-25 15:18:03 +03:00
// Stage 3 (store) ops
FETCH_OP_ST_RAW , /* Raw: .size */
FETCH_OP_ST_MEM , /* Mem: .offset, .size */
2019-05-15 08:38:42 +03:00
FETCH_OP_ST_UMEM , /* Mem: .offset, .size */
2018-04-25 15:18:03 +03:00
FETCH_OP_ST_STRING , /* String: .offset, .size */
2019-05-15 08:38:30 +03:00
FETCH_OP_ST_USTRING , /* User String: .offset, .size */
2018-04-25 15:18:03 +03:00
// Stage 4 (modify) op
FETCH_OP_MOD_BF , /* Bitfield: .basesize, .lshift, .rshift */
2018-04-25 15:21:55 +03:00
// Stage 5 (loop) op
FETCH_OP_LP_ARRAY , /* Array: .param = loop count */
2018-04-25 15:18:03 +03:00
FETCH_OP_END ,
2018-08-28 19:18:43 +03:00
FETCH_NOP_SYMBOL , /* Unresolved Symbol holder */
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 ;
2018-08-28 19:18:43 +03:00
void * data ;
2018-04-25 15:18:03 +03:00
} ;
} ;
/* fetch + deref*N + store + mod + end <= 16, this allows N=12, enough */
# define FETCH_INSN_MAX 16
2019-05-07 16:55:41 +03:00
# define FETCH_TOKEN_COMM (-ECOMM)
2018-04-25 15:18:03 +03:00
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 {}
2018-04-25 15:21:55 +03:00
# define MAX_ARRAY_LEN 64
2013-11-26 09:56:28 +04:00
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 */
2018-04-25 15:21:55 +03:00
unsigned int count ; /* Array count */
2012-04-09 13:11:44 +04:00
const char * name ; /* Name of this argument */
const char * comm ; /* Command of this argument */
2018-04-25 15:21:55 +03:00
char * fmt ; /* Format string if needed */
2012-04-09 13:11:44 +04:00
const struct fetch_type * type ; /* Type of this argument */
} ;
2019-06-19 18:07:20 +03:00
/* Event call and class holder */
struct trace_probe_event {
2013-07-03 08:50:51 +04:00
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 ;
2019-06-19 18:07:20 +03:00
struct list_head probes ;
} ;
struct trace_probe {
struct list_head list ;
struct trace_probe_event * event ;
2013-07-03 08:50:51 +04:00
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 ;
} ;
2019-05-31 18:17:37 +03:00
static inline bool trace_probe_test_flag ( struct trace_probe * tp ,
unsigned int flag )
{
2019-06-19 18:07:20 +03:00
return ! ! ( tp - > event - > flags & flag ) ;
2019-05-31 18:17:37 +03:00
}
static inline void trace_probe_set_flag ( struct trace_probe * tp ,
unsigned int flag )
{
2019-06-19 18:07:20 +03:00
tp - > event - > flags | = flag ;
2019-05-31 18:17:37 +03:00
}
static inline void trace_probe_clear_flag ( struct trace_probe * tp ,
unsigned int flag )
{
2019-06-19 18:07:20 +03:00
tp - > event - > flags & = ~ flag ;
2019-05-31 18:17:37 +03:00
}
2013-07-03 08:50:51 +04:00
static inline bool trace_probe_is_enabled ( struct trace_probe * tp )
{
2019-05-31 18:17:37 +03:00
return trace_probe_test_flag ( tp , TP_FLAG_TRACE | TP_FLAG_PROFILE ) ;
2013-07-03 08:50:51 +04:00
}
2019-05-31 18:17:47 +03:00
static inline const char * trace_probe_name ( struct trace_probe * tp )
{
2019-06-19 18:07:20 +03:00
return trace_event_name ( & tp - > event - > call ) ;
2019-05-31 18:17:47 +03:00
}
static inline const char * trace_probe_group_name ( struct trace_probe * tp )
{
2019-06-19 18:07:20 +03:00
return tp - > event - > call . class - > system ;
2019-05-31 18:17:47 +03:00
}
2019-05-31 18:17:57 +03:00
static inline struct trace_event_call *
trace_probe_event_call ( struct trace_probe * tp )
{
2019-06-19 18:07:20 +03:00
return & tp - > event - > call ;
}
static inline struct trace_probe_event *
trace_probe_event_from_call ( struct trace_event_call * event_call )
{
return container_of ( event_call , struct trace_probe_event , call ) ;
}
static inline struct trace_probe *
trace_probe_primary_from_call ( struct trace_event_call * call )
{
struct trace_probe_event * tpe = trace_probe_event_from_call ( call ) ;
return list_first_entry ( & tpe - > probes , struct trace_probe , list ) ;
}
static inline struct list_head * trace_probe_probe_list ( struct trace_probe * tp )
{
return & tp - > event - > probes ;
2019-05-31 18:17:57 +03:00
}
2019-06-19 18:07:49 +03:00
static inline bool trace_probe_has_sibling ( struct trace_probe * tp )
{
struct list_head * list = trace_probe_probe_list ( tp ) ;
return ! list_empty ( list ) & & ! list_is_singular ( list ) ;
}
2019-05-31 18:17:16 +03:00
static inline int trace_probe_unregister_event_call ( struct trace_probe * tp )
{
/* tp->event is unregistered in trace_remove_event_call() */
2019-06-19 18:07:20 +03:00
return trace_remove_event_call ( & tp - > event - > call ) ;
2019-05-31 18:17:16 +03:00
}
2019-05-31 18:17:06 +03:00
2019-05-31 18:17:26 +03:00
static inline bool trace_probe_has_single_file ( struct trace_probe * tp )
{
2019-06-19 18:07:20 +03:00
return ! ! list_is_singular ( & tp - > event - > files ) ;
2019-05-31 18:17:26 +03:00
}
int trace_probe_init ( struct trace_probe * tp , const char * event ,
const char * group ) ;
void trace_probe_cleanup ( struct trace_probe * tp ) ;
2019-06-19 18:07:49 +03:00
int trace_probe_append ( struct trace_probe * tp , struct trace_probe * to ) ;
void trace_probe_unlink ( struct trace_probe * tp ) ;
2019-05-31 18:17:26 +03:00
int trace_probe_register_event_call ( struct trace_probe * tp ) ;
int trace_probe_add_file ( struct trace_probe * tp , struct trace_event_file * file ) ;
int trace_probe_remove_file ( struct trace_probe * tp ,
struct trace_event_file * file ) ;
struct event_file_link * trace_probe_get_file_link ( struct trace_probe * tp ,
struct trace_event_file * file ) ;
2019-06-19 18:07:49 +03:00
int trace_probe_compare_arg_type ( struct trace_probe * a , struct trace_probe * b ) ;
2019-06-19 18:08:08 +03:00
bool trace_probe_match_command_args ( struct trace_probe * tp ,
int argc , const char * * argv ) ;
2019-05-31 18:17:26 +03:00
# define trace_probe_for_each_link(pos, tp) \
2019-06-19 18:07:20 +03:00
list_for_each_entry ( pos , & ( tp ) - > event - > files , list )
2019-05-31 18:17:26 +03:00
# define trace_probe_for_each_link_rcu(pos, tp) \
2019-06-19 18:07:20 +03:00
list_for_each_entry_rcu ( pos , & ( tp ) - > event - > files , list )
2019-05-31 18:17:26 +03:00
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
}
2018-04-25 15:21:26 +03:00
# define TPARG_FL_RETURN BIT(0)
# define TPARG_FL_KERNEL BIT(1)
# define TPARG_FL_FENTRY BIT(2)
# define TPARG_FL_MASK GENMASK(2, 0)
2018-11-05 12:01:40 +03:00
extern int traceprobe_parse_probe_arg ( struct trace_probe * tp , int i ,
char * arg , unsigned int flags ) ;
2012-04-09 13:11:44 +04:00
2018-08-28 19:18:43 +03:00
extern int traceprobe_update_arg ( struct probe_arg * arg ) ;
2012-04-09 13:11:44 +04:00
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 ) ;
2019-04-01 02:48:19 +03:00
int traceprobe_parse_event_name ( const char * * pevent , const char * * pgroup ,
char * buf , int 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 ) ;
2019-04-01 02:48:19 +03:00
# undef ERRORS
# define ERRORS \
C ( FILE_NOT_FOUND , " Failed to find the given file " ) , \
C ( NO_REGULAR_FILE , " Not a regular file " ) , \
C ( BAD_REFCNT , " Invalid reference counter offset " ) , \
C ( REFCNT_OPEN_BRACE , " Reference counter brace is not closed " ) , \
C ( BAD_REFCNT_SUFFIX , " Reference counter has wrong suffix " ) , \
C ( BAD_UPROBE_OFFS , " Invalid uprobe offset " ) , \
C ( MAXACT_NO_KPROBE , " Maxactive is not for kprobe " ) , \
C ( BAD_MAXACT , " Invalid maxactive number " ) , \
C ( MAXACT_TOO_BIG , " Maxactive is too big " ) , \
C ( BAD_PROBE_ADDR , " Invalid probed address or symbol " ) , \
C ( BAD_RETPROBE , " Retprobe address must be an function entry " ) , \
C ( NO_GROUP_NAME , " Group name is not specified " ) , \
C ( GROUP_TOO_LONG , " Group name is too long " ) , \
C ( BAD_GROUP_NAME , " Group name must follow the same rules as C identifiers " ) , \
C ( NO_EVENT_NAME , " Event name is not specified " ) , \
C ( EVENT_TOO_LONG , " Event name is too long " ) , \
C ( BAD_EVENT_NAME , " Event name must follow the same rules as C identifiers " ) , \
C ( RETVAL_ON_PROBE , " $retval is not available on probe " ) , \
C ( BAD_STACK_NUM , " Invalid stack number " ) , \
C ( BAD_ARG_NUM , " Invalid argument number " ) , \
C ( BAD_VAR , " Invalid $-valiable specified " ) , \
C ( BAD_REG_NAME , " Invalid register name " ) , \
C ( BAD_MEM_ADDR , " Invalid memory address " ) , \
2019-06-19 18:08:27 +03:00
C ( BAD_IMM , " Invalid immediate value " ) , \
2019-06-19 18:08:37 +03:00
C ( IMMSTR_NO_CLOSE , " String is not closed with ' \" ' " ) , \
2019-04-01 02:48:19 +03:00
C ( FILE_ON_KPROBE , " File offset is not available with kprobe " ) , \
C ( BAD_FILE_OFFS , " Invalid file offset value " ) , \
C ( SYM_ON_UPROBE , " Symbol is not available with uprobe " ) , \
C ( TOO_MANY_OPS , " Dereference is too much nested " ) , \
C ( DEREF_NEED_BRACE , " Dereference needs a brace " ) , \
C ( BAD_DEREF_OFFS , " Invalid dereference offset " ) , \
C ( DEREF_OPEN_BRACE , " Dereference brace is not closed " ) , \
C ( COMM_CANT_DEREF , " $comm can not be dereferenced " ) , \
C ( BAD_FETCH_ARG , " Invalid fetch argument " ) , \
C ( ARRAY_NO_CLOSE , " Array is not closed " ) , \
C ( BAD_ARRAY_SUFFIX , " Array has wrong suffix " ) , \
C ( BAD_ARRAY_NUM , " Invalid array size " ) , \
C ( ARRAY_TOO_BIG , " Array number is too big " ) , \
C ( BAD_TYPE , " Unknown type is specified " ) , \
C ( BAD_STRING , " String accepts only memory argument " ) , \
C ( BAD_BITFIELD , " Invalid bitfield " ) , \
C ( ARG_NAME_TOO_LONG , " Argument name is too long " ) , \
C ( NO_ARG_NAME , " Argument name is not specified " ) , \
C ( BAD_ARG_NAME , " Argument name must follow the same rules as C identifiers " ) , \
C ( USED_ARG_NAME , " This argument name is already used " ) , \
C ( ARG_TOO_LONG , " Argument expression is too long " ) , \
C ( NO_ARG_BODY , " No argument expression " ) , \
C ( BAD_INSN_BNDRY , " Probe point is not an instruction boundary " ) , \
2019-06-19 18:07:49 +03:00
C ( FAIL_REG_PROBE , " Failed to register probe event " ) , \
C ( DIFF_PROBE_TYPE , " Probe type is different from existing probe " ) , \
2019-09-18 11:55:46 +03:00
C ( DIFF_ARG_TYPE , " Argument type or name is different from existing probe " ) , \
C ( SAME_PROBE , " There is already the exact same probe event " ) ,
2019-04-01 02:48:19 +03:00
# undef C
# define C(a, b) TP_ERR_##a
/* Define TP_ERR_ */
enum { ERRORS } ;
/* Error text is defined in trace_probe.c */
struct trace_probe_log {
const char * subsystem ;
const char * * argv ;
int argc ;
int index ;
} ;
void trace_probe_log_init ( const char * subsystem , int argc , const char * * argv ) ;
void trace_probe_log_set_index ( int index ) ;
void trace_probe_log_clear ( void ) ;
void __trace_probe_log_err ( int offset , int err ) ;
# define trace_probe_log_err(offs, err) \
__trace_probe_log_err ( offs , TP_ERR_ # # err )