tracing/probes: Support BTF based data structure field access
Using BTF to access the fields of a data structure. You can use this for accessing the field with '->' or '.' operation with BTF argument. # echo 't sched_switch next=next->pid vruntime=next->se.vruntime' \ > dynamic_events # echo 1 > events/tracepoints/sched_switch/enable # head -n 40 trace | tail <idle>-0 [000] d..3. 272.565382: sched_switch: (__probestub_sched_switch+0x4/0x10) next=26 vruntime=956533179 kcompactd0-26 [000] d..3. 272.565406: sched_switch: (__probestub_sched_switch+0x4/0x10) next=0 vruntime=0 <idle>-0 [000] d..3. 273.069441: sched_switch: (__probestub_sched_switch+0x4/0x10) next=9 vruntime=956533179 kworker/0:1-9 [000] d..3. 273.069464: sched_switch: (__probestub_sched_switch+0x4/0x10) next=26 vruntime=956579181 kcompactd0-26 [000] d..3. 273.069480: sched_switch: (__probestub_sched_switch+0x4/0x10) next=0 vruntime=0 <idle>-0 [000] d..3. 273.141434: sched_switch: (__probestub_sched_switch+0x4/0x10) next=22 vruntime=956533179 kworker/u2:1-22 [000] d..3. 273.141461: sched_switch: (__probestub_sched_switch+0x4/0x10) next=0 vruntime=0 <idle>-0 [000] d..3. 273.480872: sched_switch: (__probestub_sched_switch+0x4/0x10) next=22 vruntime=956585857 kworker/u2:1-22 [000] d..3. 273.480905: sched_switch: (__probestub_sched_switch+0x4/0x10) next=70 vruntime=959533179 sh-70 [000] d..3. 273.481102: sched_switch: (__probestub_sched_switch+0x4/0x10) next=0 vruntime=0 Link: https://lore.kernel.org/all/169272157251.160970.9318175874130965571.stgit@devnote2/ Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Reviewed-by: Alan Maguire <alan.maguire@oracle.com> Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
302db0f5b3
commit
c440adfbe3
3 changed files with 216 additions and 28 deletions
|
@ -5717,7 +5717,8 @@ static const char readme_msg[] =
|
||||||
"\t fetcharg: (%<register>|$<efield>), @<address>, @<symbol>[+|-<offset>],\n"
|
"\t fetcharg: (%<register>|$<efield>), @<address>, @<symbol>[+|-<offset>],\n"
|
||||||
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
|
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
|
||||||
#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
|
#ifdef CONFIG_PROBE_EVENTS_BTF_ARGS
|
||||||
"\t $stack<index>, $stack, $retval, $comm, $arg<N>, <argname>\n"
|
"\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
|
||||||
|
"\t <argname>[->field[->field|.field...]],\n"
|
||||||
#else
|
#else
|
||||||
"\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
|
"\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -310,16 +310,14 @@ static u32 btf_type_int(const struct btf_type *t)
|
||||||
return *(u32 *)(t + 1);
|
return *(u32 *)(t + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *type_from_btf_id(struct btf *btf, s32 id)
|
static const char *fetch_type_from_btf_type(struct btf *btf,
|
||||||
|
const struct btf_type *type,
|
||||||
|
struct traceprobe_parse_context *ctx)
|
||||||
{
|
{
|
||||||
const struct btf_type *t;
|
|
||||||
u32 intdata;
|
u32 intdata;
|
||||||
s32 tid;
|
|
||||||
|
|
||||||
/* TODO: const char * could be converted as a string */
|
/* TODO: const char * could be converted as a string */
|
||||||
t = btf_type_skip_modifiers(btf, id, &tid);
|
switch (BTF_INFO_KIND(type->info)) {
|
||||||
|
|
||||||
switch (BTF_INFO_KIND(t->info)) {
|
|
||||||
case BTF_KIND_ENUM:
|
case BTF_KIND_ENUM:
|
||||||
/* enum is "int", so convert to "s32" */
|
/* enum is "int", so convert to "s32" */
|
||||||
return "s32";
|
return "s32";
|
||||||
|
@ -332,7 +330,7 @@ static const char *type_from_btf_id(struct btf *btf, s32 id)
|
||||||
else
|
else
|
||||||
return "x32";
|
return "x32";
|
||||||
case BTF_KIND_INT:
|
case BTF_KIND_INT:
|
||||||
intdata = btf_type_int(t);
|
intdata = btf_type_int(type);
|
||||||
if (BTF_INT_ENCODING(intdata) & BTF_INT_SIGNED) {
|
if (BTF_INT_ENCODING(intdata) & BTF_INT_SIGNED) {
|
||||||
switch (BTF_INT_BITS(intdata)) {
|
switch (BTF_INT_BITS(intdata)) {
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -355,6 +353,10 @@ static const char *type_from_btf_id(struct btf *btf, s32 id)
|
||||||
case 64:
|
case 64:
|
||||||
return "u64";
|
return "u64";
|
||||||
}
|
}
|
||||||
|
/* bitfield, size is encoded in the type */
|
||||||
|
ctx->last_bitsize = BTF_INT_BITS(intdata);
|
||||||
|
ctx->last_bitoffs += BTF_INT_OFFSET(intdata);
|
||||||
|
return "u64";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* TODO: support other types */
|
/* TODO: support other types */
|
||||||
|
@ -406,15 +408,136 @@ static void clear_btf_context(struct traceprobe_parse_context *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_btf_arg(const char *varname, struct fetch_insn *code,
|
/* Return 1 if the field separater is arrow operator ('->') */
|
||||||
|
static int split_next_field(char *varname, char **next_field,
|
||||||
|
struct traceprobe_parse_context *ctx)
|
||||||
|
{
|
||||||
|
char *field;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
field = strpbrk(varname, ".-");
|
||||||
|
if (field) {
|
||||||
|
if (field[0] == '-' && field[1] == '>') {
|
||||||
|
field[0] = '\0';
|
||||||
|
field += 2;
|
||||||
|
ret = 1;
|
||||||
|
} else if (field[0] == '.') {
|
||||||
|
field[0] = '\0';
|
||||||
|
field += 1;
|
||||||
|
} else {
|
||||||
|
trace_probe_log_err(ctx->offset + field - varname, BAD_HYPHEN);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
*next_field = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the field of data structure. The @type must be a pointer type
|
||||||
|
* pointing the target data structure type.
|
||||||
|
*/
|
||||||
|
static int parse_btf_field(char *fieldname, const struct btf_type *type,
|
||||||
|
struct fetch_insn **pcode, struct fetch_insn *end,
|
||||||
|
struct traceprobe_parse_context *ctx)
|
||||||
|
{
|
||||||
|
struct fetch_insn *code = *pcode;
|
||||||
|
const struct btf_member *field;
|
||||||
|
u32 bitoffs, anon_offs;
|
||||||
|
char *next;
|
||||||
|
int is_ptr;
|
||||||
|
s32 tid;
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* Outer loop for solving arrow operator ('->') */
|
||||||
|
if (BTF_INFO_KIND(type->info) != BTF_KIND_PTR) {
|
||||||
|
trace_probe_log_err(ctx->offset, NO_PTR_STRCT);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
/* Convert a struct pointer type to a struct type */
|
||||||
|
type = btf_type_skip_modifiers(ctx->btf, type->type, &tid);
|
||||||
|
if (!type) {
|
||||||
|
trace_probe_log_err(ctx->offset, BAD_BTF_TID);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitoffs = 0;
|
||||||
|
do {
|
||||||
|
/* Inner loop for solving dot operator ('.') */
|
||||||
|
next = NULL;
|
||||||
|
is_ptr = split_next_field(fieldname, &next, ctx);
|
||||||
|
if (is_ptr < 0)
|
||||||
|
return is_ptr;
|
||||||
|
|
||||||
|
anon_offs = 0;
|
||||||
|
field = btf_find_struct_member(ctx->btf, type, fieldname,
|
||||||
|
&anon_offs);
|
||||||
|
if (!field) {
|
||||||
|
trace_probe_log_err(ctx->offset, NO_BTF_FIELD);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
/* Add anonymous structure/union offset */
|
||||||
|
bitoffs += anon_offs;
|
||||||
|
|
||||||
|
/* Accumulate the bit-offsets of the dot-connected fields */
|
||||||
|
if (btf_type_kflag(type)) {
|
||||||
|
bitoffs += BTF_MEMBER_BIT_OFFSET(field->offset);
|
||||||
|
ctx->last_bitsize = BTF_MEMBER_BITFIELD_SIZE(field->offset);
|
||||||
|
} else {
|
||||||
|
bitoffs += field->offset;
|
||||||
|
ctx->last_bitsize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = btf_type_skip_modifiers(ctx->btf, field->type, &tid);
|
||||||
|
if (!type) {
|
||||||
|
trace_probe_log_err(ctx->offset, BAD_BTF_TID);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->offset += next - fieldname;
|
||||||
|
fieldname = next;
|
||||||
|
} while (!is_ptr && fieldname);
|
||||||
|
|
||||||
|
if (++code == end) {
|
||||||
|
trace_probe_log_err(ctx->offset, TOO_MANY_OPS);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
code->op = FETCH_OP_DEREF; /* TODO: user deref support */
|
||||||
|
code->offset = bitoffs / 8;
|
||||||
|
*pcode = code;
|
||||||
|
|
||||||
|
ctx->last_bitoffs = bitoffs % 8;
|
||||||
|
ctx->last_type = type;
|
||||||
|
} while (fieldname);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_btf_arg(char *varname,
|
||||||
|
struct fetch_insn **pcode, struct fetch_insn *end,
|
||||||
struct traceprobe_parse_context *ctx)
|
struct traceprobe_parse_context *ctx)
|
||||||
{
|
{
|
||||||
|
struct fetch_insn *code = *pcode;
|
||||||
const struct btf_param *params;
|
const struct btf_param *params;
|
||||||
int i;
|
const struct btf_type *type;
|
||||||
|
char *field = NULL;
|
||||||
|
int i, is_ptr;
|
||||||
|
u32 tid;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!ctx->funcname))
|
if (WARN_ON_ONCE(!ctx->funcname))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
is_ptr = split_next_field(varname, &field, ctx);
|
||||||
|
if (is_ptr < 0)
|
||||||
|
return is_ptr;
|
||||||
|
if (!is_ptr && field) {
|
||||||
|
/* dot-connected field on an argument is not supported. */
|
||||||
|
trace_probe_log_err(ctx->offset + field - varname,
|
||||||
|
NOSUP_DAT_ARG);
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ctx->params) {
|
if (!ctx->params) {
|
||||||
params = find_btf_func_param(ctx->funcname,
|
params = find_btf_func_param(ctx->funcname,
|
||||||
&ctx->nr_params, &ctx->btf,
|
&ctx->nr_params, &ctx->btf,
|
||||||
|
@ -436,24 +559,39 @@ static int parse_btf_arg(const char *varname, struct fetch_insn *code,
|
||||||
code->param = i + 1;
|
code->param = i + 1;
|
||||||
else
|
else
|
||||||
code->param = i;
|
code->param = i;
|
||||||
return 0;
|
|
||||||
|
tid = params[i].type;
|
||||||
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trace_probe_log_err(ctx->offset, NO_BTFARG);
|
trace_probe_log_err(ctx->offset, NO_BTFARG);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
|
found:
|
||||||
|
type = btf_type_skip_modifiers(ctx->btf, tid, &tid);
|
||||||
|
if (!type) {
|
||||||
|
trace_probe_log_err(ctx->offset, BAD_BTF_TID);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
/* Initialize the last type information */
|
||||||
|
ctx->last_type = type;
|
||||||
|
ctx->last_bitoffs = 0;
|
||||||
|
ctx->last_bitsize = 0;
|
||||||
|
if (field) {
|
||||||
|
ctx->offset += field - varname;
|
||||||
|
return parse_btf_field(field, type, pcode, end, ctx);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct fetch_type *parse_btf_arg_type(int arg_idx,
|
static const struct fetch_type *parse_btf_arg_type(
|
||||||
struct traceprobe_parse_context *ctx)
|
struct traceprobe_parse_context *ctx)
|
||||||
{
|
{
|
||||||
struct btf *btf = ctx->btf;
|
struct btf *btf = ctx->btf;
|
||||||
const char *typestr = NULL;
|
const char *typestr = NULL;
|
||||||
|
|
||||||
if (btf && ctx->params) {
|
if (btf && ctx->last_type)
|
||||||
if (ctx->flags & TPARG_FL_TPOINT)
|
typestr = fetch_type_from_btf_type(btf, ctx->last_type, ctx);
|
||||||
arg_idx--;
|
|
||||||
typestr = type_from_btf_id(btf, ctx->params[arg_idx].type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return find_fetch_type(typestr, ctx->flags);
|
return find_fetch_type(typestr, ctx->flags);
|
||||||
}
|
}
|
||||||
|
@ -462,14 +600,16 @@ static const struct fetch_type *parse_btf_retval_type(
|
||||||
struct traceprobe_parse_context *ctx)
|
struct traceprobe_parse_context *ctx)
|
||||||
{
|
{
|
||||||
const char *typestr = NULL;
|
const char *typestr = NULL;
|
||||||
const struct btf_type *t;
|
const struct btf_type *type;
|
||||||
struct btf *btf;
|
struct btf *btf;
|
||||||
|
|
||||||
if (ctx->funcname) {
|
if (ctx->funcname) {
|
||||||
/* Do not use ctx->btf, because it must be used with ctx->param */
|
/* Do not use ctx->btf, because it must be used with ctx->param */
|
||||||
t = btf_find_func_proto(ctx->funcname, &btf);
|
type = btf_find_func_proto(ctx->funcname, &btf);
|
||||||
if (t) {
|
if (type) {
|
||||||
typestr = type_from_btf_id(btf, t->type);
|
type = btf_type_skip_modifiers(btf, type->type, NULL);
|
||||||
|
if (!IS_ERR_OR_NULL(type))
|
||||||
|
typestr = fetch_type_from_btf_type(btf, type, ctx);
|
||||||
btf_put(btf);
|
btf_put(btf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,6 +617,28 @@ static const struct fetch_type *parse_btf_retval_type(
|
||||||
return find_fetch_type(typestr, ctx->flags);
|
return find_fetch_type(typestr, ctx->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_btf_bitfield(struct fetch_insn **pcode,
|
||||||
|
struct traceprobe_parse_context *ctx)
|
||||||
|
{
|
||||||
|
struct fetch_insn *code = *pcode;
|
||||||
|
|
||||||
|
if ((ctx->last_bitsize % 8 == 0) && ctx->last_bitoffs == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
code++;
|
||||||
|
if (code->op != FETCH_OP_NOP) {
|
||||||
|
trace_probe_log_err(ctx->offset, TOO_MANY_OPS);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
*pcode = code;
|
||||||
|
|
||||||
|
code->op = FETCH_OP_MOD_BF;
|
||||||
|
code->lshift = 64 - (ctx->last_bitsize + ctx->last_bitoffs);
|
||||||
|
code->rshift = 64 - ctx->last_bitsize;
|
||||||
|
code->basesize = 64 / 8;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool is_btf_retval_void(const char *funcname)
|
static bool is_btf_retval_void(const char *funcname)
|
||||||
{
|
{
|
||||||
const struct btf_type *t;
|
const struct btf_type *t;
|
||||||
|
@ -503,14 +665,22 @@ static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_btf_arg(const char *varname, struct fetch_insn *code,
|
static int parse_btf_arg(char *varname,
|
||||||
|
struct fetch_insn **pcode, struct fetch_insn *end,
|
||||||
struct traceprobe_parse_context *ctx)
|
struct traceprobe_parse_context *ctx)
|
||||||
{
|
{
|
||||||
trace_probe_log_err(ctx->offset, NOSUP_BTFARG);
|
trace_probe_log_err(ctx->offset, NOSUP_BTFARG);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define parse_btf_arg_type(idx, ctx) \
|
static int parse_btf_bitfield(struct fetch_insn **pcode,
|
||||||
|
struct traceprobe_parse_context *ctx)
|
||||||
|
{
|
||||||
|
trace_probe_log_err(ctx->offset, NOSUP_BTFARG);
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define parse_btf_arg_type(ctx) \
|
||||||
find_fetch_type(NULL, ctx->flags)
|
find_fetch_type(NULL, ctx->flags)
|
||||||
|
|
||||||
#define parse_btf_retval_type(ctx) \
|
#define parse_btf_retval_type(ctx) \
|
||||||
|
@ -778,6 +948,8 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
|
||||||
|
|
||||||
code->op = deref;
|
code->op = deref;
|
||||||
code->offset = offset;
|
code->offset = offset;
|
||||||
|
/* Reset the last type if used */
|
||||||
|
ctx->last_type = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '\\': /* Immediate value */
|
case '\\': /* Immediate value */
|
||||||
|
@ -801,7 +973,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
|
||||||
trace_probe_log_err(ctx->offset, NOSUP_BTFARG);
|
trace_probe_log_err(ctx->offset, NOSUP_BTFARG);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ret = parse_btf_arg(arg, code, ctx);
|
ret = parse_btf_arg(arg, pcode, end, ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -947,6 +1119,7 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
|
||||||
goto out;
|
goto out;
|
||||||
code[FETCH_INSN_MAX - 1].op = FETCH_OP_END;
|
code[FETCH_INSN_MAX - 1].op = FETCH_OP_END;
|
||||||
|
|
||||||
|
ctx->last_type = NULL;
|
||||||
ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1],
|
ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1],
|
||||||
ctx);
|
ctx);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -954,9 +1127,9 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
|
||||||
|
|
||||||
/* Update storing type if BTF is available */
|
/* Update storing type if BTF is available */
|
||||||
if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) && !t) {
|
if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) && !t) {
|
||||||
if (code->op == FETCH_OP_ARG)
|
if (ctx->last_type)
|
||||||
parg->type = parse_btf_arg_type(code->param, ctx);
|
parg->type = parse_btf_arg_type(ctx);
|
||||||
else if (code->op == FETCH_OP_RETVAL)
|
else if (ctx->flags & TPARG_FL_RETURN)
|
||||||
parg->type = parse_btf_retval_type(ctx);
|
parg->type = parse_btf_retval_type(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,6 +1204,11 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
|
||||||
trace_probe_log_err(ctx->offset + t - arg, BAD_BITFIELD);
|
trace_probe_log_err(ctx->offset + t - arg, BAD_BITFIELD);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
} else if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) &&
|
||||||
|
ctx->last_type) {
|
||||||
|
ret = parse_btf_bitfield(&code, ctx);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
/* Loop(Array) operation */
|
/* Loop(Array) operation */
|
||||||
|
|
|
@ -388,6 +388,9 @@ struct traceprobe_parse_context {
|
||||||
const struct btf_param *params; /* Parameter of the function */
|
const struct btf_param *params; /* Parameter of the function */
|
||||||
s32 nr_params; /* The number of the parameters */
|
s32 nr_params; /* The number of the parameters */
|
||||||
struct btf *btf; /* The BTF to be used */
|
struct btf *btf; /* The BTF to be used */
|
||||||
|
const struct btf_type *last_type; /* Saved type */
|
||||||
|
u32 last_bitoffs; /* Saved bitoffs */
|
||||||
|
u32 last_bitsize; /* Saved bitsize */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int offset;
|
int offset;
|
||||||
};
|
};
|
||||||
|
@ -503,7 +506,13 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
|
||||||
C(BAD_VAR_ARGS, "$arg* must be an independent parameter without name etc."),\
|
C(BAD_VAR_ARGS, "$arg* must be an independent parameter without name etc."),\
|
||||||
C(NOFENTRY_ARGS, "$arg* can be used only on function entry"), \
|
C(NOFENTRY_ARGS, "$arg* can be used only on function entry"), \
|
||||||
C(DOUBLE_ARGS, "$arg* can be used only once in the parameters"), \
|
C(DOUBLE_ARGS, "$arg* can be used only once in the parameters"), \
|
||||||
C(ARGS_2LONG, "$arg* failed because the argument list is too long"),
|
C(ARGS_2LONG, "$arg* failed because the argument list is too long"), \
|
||||||
|
C(ARGIDX_2BIG, "$argN index is too big"), \
|
||||||
|
C(NO_PTR_STRCT, "This is not a pointer to union/structure."), \
|
||||||
|
C(NOSUP_DAT_ARG, "Non pointer structure/union argument is not supported."),\
|
||||||
|
C(BAD_HYPHEN, "Failed to parse single hyphen. Forgot '>'?"), \
|
||||||
|
C(NO_BTF_FIELD, "This field is not found."), \
|
||||||
|
C(BAD_BTF_TID, "Failed to get BTF type info."),
|
||||||
|
|
||||||
#undef C
|
#undef C
|
||||||
#define C(a, b) TP_ERR_##a
|
#define C(a, b) TP_ERR_##a
|
||||||
|
|
Loading…
Add table
Reference in a new issue