mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Merge branch 'btf-inline-functionality-followups'
Alan Maguire says: ==================== BTF inline functionality followups Include additional vlen/flags verification for BTF_KIND_LOC_PARAM (patch 1), and add function signatures to LOCSEC entries (patch 2), adjusting test to cover these (patch 3). Changes since v2 [1] - Improved flag/vlen verification to check combinations (Alexei, patch 1) - Simplified overrun ellipsis printing (Quentin, patch 2) Changes since v1 [2] - Fixed sign to appear after const (bots, patch 2) - Simplified loc printing to remove vsnprintf() logic, updated to retain name in json (Quentin, patch 2) - For oversized signature strings, append "..." (Quentin, patch 2) [1] https://lore.kernel.org/bpf/20260925170854.1240637-1-alan.maguire@oracle.com/ [2] https://lore.kernel.org/bpf/20260925095231.879708-1-alan.maguire@oracle.com/ ==================== Acked-by: Jiri Olsa <jolsa@kernel.org> Acked-by: Quentin Monnet <qmo@kernel.org> Link: https://patch.msgid.link/20260926175113.2368566-1-alan.maguire@oracle.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
cc6010e6e5
|
|
@ -4823,10 +4823,53 @@ static s32 btf_loc_param_check_meta(struct btf_verifier_env *env,
|
|||
btf_verifier_log_type(env, t, "Invalid btf_info kind_flag");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* All LOC_PARAMs have vlen of at least 1 */
|
||||
if (vlen < 1)
|
||||
goto invalid_vlen;
|
||||
|
||||
switch (p->flags) {
|
||||
case BTF_LOC_PARAM_CONST:
|
||||
case BTF_LOC_PARAM_CONST | BTF_LOC_PARAM_SIGNED:
|
||||
case BTF_LOC_PARAM_CONST | BTF_LOC_PARAM_ADDR:
|
||||
case BTF_LOC_PARAM_CONST | BTF_LOC_PARAM_ADDR | BTF_LOC_PARAM_SIGNED:
|
||||
if (vlen > 2)
|
||||
goto invalid_vlen;
|
||||
/* Ensure size/vlen are consistent */
|
||||
if (size > sizeof(__u32) && vlen != 2)
|
||||
goto invalid_vlen;
|
||||
if (size > sizeof(__u64))
|
||||
goto invalid_vlen;
|
||||
break;
|
||||
case BTF_LOC_PARAM_REG:
|
||||
/* Reg or reg/reg pair */
|
||||
if (vlen > 2)
|
||||
goto invalid_vlen;
|
||||
break;
|
||||
case BTF_LOC_PARAM_REG | BTF_LOC_PARAM_DEREF:
|
||||
/* A reg deref without offset can only have vlen 1 */
|
||||
if (vlen != 1)
|
||||
goto invalid_vlen;
|
||||
break;
|
||||
case BTF_LOC_PARAM_REG | BTF_LOC_PARAM_OFFSET:
|
||||
case BTF_LOC_PARAM_REG | BTF_LOC_PARAM_OFFSET | BTF_LOC_PARAM_SIGNED:
|
||||
case BTF_LOC_PARAM_REG | BTF_LOC_PARAM_DEREF | BTF_LOC_PARAM_OFFSET:
|
||||
case BTF_LOC_PARAM_REG | BTF_LOC_PARAM_DEREF | BTF_LOC_PARAM_OFFSET |
|
||||
BTF_LOC_PARAM_SIGNED:
|
||||
if (vlen < 2 || vlen > 3)
|
||||
goto invalid_vlen;
|
||||
break;
|
||||
default:
|
||||
btf_verifier_log_type(env, t, "Invalid flags");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
btf_verifier_log_type(env, t, NULL);
|
||||
|
||||
return meta_needed;
|
||||
|
||||
invalid_vlen:
|
||||
btf_verifier_log_type(env, t, "Invalid vlen");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void btf_loc_param_log(struct btf_verifier_env *env,
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ static void btf_loc_param_raw_str(const struct btf_loc_param *p, __u32 vlen,
|
|||
|
||||
static void btf_loc_param_str(const struct btf_type *t, char *str, size_t sz)
|
||||
{
|
||||
const char *op = "", *prefix = "";
|
||||
const struct btf_loc_param *p;
|
||||
__u32 i = 0, vlen;
|
||||
__u64 value;
|
||||
|
|
@ -157,7 +158,6 @@ static void btf_loc_param_str(const struct btf_type *t, char *str, size_t sz)
|
|||
bool negative = false;
|
||||
char regs[32] = {};
|
||||
char num[32] = {};
|
||||
const char *op = "";
|
||||
|
||||
if (!t || !btf_is_loc_param(t)) {
|
||||
snprintf(str, sz, "<invalid>");
|
||||
|
|
@ -234,8 +234,12 @@ static void btf_loc_param_str(const struct btf_type *t, char *str, size_t sz)
|
|||
(1ULL << bits) - value;
|
||||
}
|
||||
}
|
||||
snprintf(num, sizeof(num), "0x%llx%s", (unsigned long long)value,
|
||||
p->flags & BTF_LOC_PARAM_ADDR ? " (addr)" : "");
|
||||
if (p->flags & BTF_LOC_PARAM_ADDR)
|
||||
prefix = "address ";
|
||||
else if (p->flags & BTF_LOC_PARAM_CONST)
|
||||
prefix = "const ";
|
||||
snprintf(num, sizeof(num), "0x%llx",
|
||||
(unsigned long long)value);
|
||||
}
|
||||
if (i != vlen) {
|
||||
btf_loc_param_raw_str(p, vlen, str, sz);
|
||||
|
|
@ -244,14 +248,111 @@ static void btf_loc_param_str(const struct btf_type *t, char *str, size_t sz)
|
|||
if (num[0])
|
||||
op = regs[0] ? (negative ? " - " : " + ") : negative ? "-" : "";
|
||||
|
||||
snprintf(str, sz, "%s%s%s%s%s",
|
||||
snprintf(str, sz, "%s%s%s%s%s%s",
|
||||
p->flags & BTF_LOC_PARAM_DEREF ? "*(" : "",
|
||||
prefix,
|
||||
regs,
|
||||
op,
|
||||
num,
|
||||
p->flags & BTF_LOC_PARAM_DEREF ? ")" : "");
|
||||
}
|
||||
|
||||
static bool btf_locsec_append(char *str, size_t sz, size_t *off,
|
||||
const char *suffix)
|
||||
{
|
||||
static const char nospace_suffix[] = "...";
|
||||
bool space_left = true;
|
||||
size_t left = 0, len;
|
||||
|
||||
if (*off >= sz || sz < sizeof(nospace_suffix))
|
||||
return false;
|
||||
left = sz - *off;
|
||||
|
||||
/*
|
||||
* Copy as much of the string as we can in remaining space, and
|
||||
* append "..." if we would have overrun.
|
||||
*/
|
||||
len = strlen(suffix) + 1;
|
||||
if (len > left) {
|
||||
len = left;
|
||||
space_left = false;
|
||||
}
|
||||
|
||||
memcpy(str + *off, suffix, len);
|
||||
*off += len - 1;
|
||||
|
||||
if (!space_left)
|
||||
memcpy(str + sz - sizeof(nospace_suffix), nospace_suffix, sizeof(nospace_suffix));
|
||||
|
||||
return space_left;
|
||||
}
|
||||
|
||||
static void btf_locsec_func_str(const struct btf *btf,
|
||||
const struct btf_loc *loc, char *str, size_t sz)
|
||||
{
|
||||
const struct btf_type *func, *func_proto, *loc_proto;
|
||||
const struct btf_param *params;
|
||||
const __u32 *loc_params;
|
||||
const char *name;
|
||||
__u32 i, vlen;
|
||||
size_t off = 0;
|
||||
|
||||
if (!sz)
|
||||
return;
|
||||
|
||||
str[0] = '\0';
|
||||
func = btf__type_by_id(btf, loc->func);
|
||||
if (!func || !btf_is_func(func))
|
||||
goto invalid;
|
||||
|
||||
name = btf_str(btf, func->name_off);
|
||||
func_proto = btf__type_by_id(btf, func->type);
|
||||
loc_proto = btf__type_by_id(btf, loc->loc_proto);
|
||||
if (!func_proto || !btf_is_func_proto(func_proto) ||
|
||||
!loc_proto || !btf_is_loc_proto(loc_proto) ||
|
||||
btf_vlen(func_proto) != btf_vlen(loc_proto))
|
||||
goto invalid;
|
||||
|
||||
params = (const void *)(func_proto + 1);
|
||||
loc_params = btf_loc_proto_params(loc_proto);
|
||||
vlen = btf_vlen(func_proto);
|
||||
if (!btf_locsec_append(str, sz, &off, name) ||
|
||||
!btf_locsec_append(str, sz, &off, "("))
|
||||
return;
|
||||
for (i = 0; i < vlen; i++) {
|
||||
const struct btf_type *param_loc;
|
||||
char param_str[256] = {};
|
||||
|
||||
if (!params[i].type) {
|
||||
/* Handle varargs func proto, must be last parameter */
|
||||
if (i != vlen - 1)
|
||||
goto invalid;
|
||||
if (!btf_locsec_append(str, sz, &off, i ? ", " : "") ||
|
||||
!btf_locsec_append(str, sz, &off, "..."))
|
||||
return;
|
||||
break;
|
||||
} else if (loc_params[i]) {
|
||||
param_loc = btf__type_by_id(btf, loc_params[i]);
|
||||
btf_loc_param_str(param_loc, param_str, sizeof(param_str));
|
||||
} else {
|
||||
snprintf(param_str, sizeof(param_str), "<unavailable>");
|
||||
}
|
||||
|
||||
if (!btf_locsec_append(str, sz, &off, i ? ", " : "") ||
|
||||
!btf_locsec_append(str, sz, &off,
|
||||
btf_str(btf, params[i].name_off)) ||
|
||||
!btf_locsec_append(str, sz, &off, " [") ||
|
||||
!btf_locsec_append(str, sz, &off, param_str) ||
|
||||
!btf_locsec_append(str, sz, &off, "]"))
|
||||
return;
|
||||
}
|
||||
(void) btf_locsec_append(str, sz, &off, ")");
|
||||
return;
|
||||
|
||||
invalid:
|
||||
snprintf(str, sz, "<invalid>");
|
||||
}
|
||||
|
||||
static int dump_btf_type(const struct btf *btf, __u32 id,
|
||||
const struct btf_type *t)
|
||||
{
|
||||
|
|
@ -617,22 +718,26 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
|
|||
}
|
||||
|
||||
for (i = 0; i < vlen; i++, locs++) {
|
||||
const struct btf_type *f = btf__type_by_id(btf, locs->func);
|
||||
const struct btf_type *func;
|
||||
const char *name = "<invalid>";
|
||||
char func_str[1024] = {};
|
||||
|
||||
if (f && btf_is_func(f))
|
||||
name = btf_str(btf, f->name_off);
|
||||
func = btf__type_by_id(btf, locs->func);
|
||||
if (func && btf_is_func(func))
|
||||
name = btf_str(btf, func->name_off);
|
||||
btf_locsec_func_str(btf, locs, func_str, sizeof(func_str));
|
||||
|
||||
if (json_output) {
|
||||
jsonw_start_object(w);
|
||||
jsonw_uint_field(w, "func_type_id", locs->func);
|
||||
jsonw_string_field(w, "name", name);
|
||||
jsonw_string_field(w, "func", func_str);
|
||||
jsonw_uint_field(w, "loc_proto_type_id", locs->loc_proto);
|
||||
jsonw_uint_field(w, "offset", locs->offset);
|
||||
jsonw_end_object(w);
|
||||
} else {
|
||||
printf("\n\tname='%s' func_type_id=%u loc_proto_type_id=%u offset=%u",
|
||||
name, locs->func, locs->loc_proto, locs->offset);
|
||||
printf("\n\tfunc='%s' func_type_id=%u loc_proto_type_id=%u offset=%u",
|
||||
func_str, locs->func, locs->loc_proto, locs->offset);
|
||||
}
|
||||
}
|
||||
if (json_output)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ static struct btf *mk_loc_btf(void)
|
|||
btf__add_func_param(btf, "arg3", 1);
|
||||
btf__add_func_param(btf, "arg4", 1);
|
||||
btf__add_func_param(btf, "arg5", 1);
|
||||
btf__add_func_param(btf, "arg6", 1);
|
||||
btf__add_func(btf, "foo", BTF_FUNC_STATIC, 2);
|
||||
|
||||
btf__add_loc_param(btf, 4, BTF_LOC_PARAM_REG);
|
||||
|
|
@ -230,28 +231,29 @@ static void test_loc_dump(const char *btf_path)
|
|||
{
|
||||
const char expected[] =
|
||||
"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED\n"
|
||||
"[2] FUNC_PROTO '(anon)' ret_type_id=1 vlen=5\n"
|
||||
"[2] FUNC_PROTO '(anon)' ret_type_id=1 vlen=6\n"
|
||||
"\t'arg1' type_id=1\n"
|
||||
"\t'arg2' type_id=1\n"
|
||||
"\t'arg3' type_id=1\n"
|
||||
"\t'arg4' type_id=1\n"
|
||||
"\t'arg5' type_id=1\n"
|
||||
"\t'arg6' type_id=1\n"
|
||||
"[3] FUNC 'foo' type_id=2 linkage=static\n"
|
||||
"[4] LOC_PARAM '(anon)' size=4 flags=0x8 vlen=1 values='reg1'\n"
|
||||
"[5] LOC_PARAM '(anon)' size=8 flags=0x38 vlen=2 values='*(reg2 + 0x10)'\n"
|
||||
"[6] LOC_PARAM '(anon)' size=8 flags=0x29 vlen=2 values='fbreg - 0x10'\n"
|
||||
"[7] LOC_PARAM '(anon)' size=8 flags=0x6 vlen=2 values='0x123456789abcdef0 (addr)'\n"
|
||||
"[8] LOC_PARAM '(anon)' size=8 flags=0x2 vlen=2 values='0xdeadbeeffeedface'\n"
|
||||
"[7] LOC_PARAM '(anon)' size=8 flags=0x6 vlen=2 values='address 0x123456789abcdef0'\n"
|
||||
"[8] LOC_PARAM '(anon)' size=8 flags=0x2 vlen=2 values='const 0xdeadbeeffeedface'\n"
|
||||
"[9] LOC_PARAM '(anon)' size=8 flags=0x39 vlen=2 values='*(fbreg - 0x20)'\n"
|
||||
"[10] LOC_PROTO '(anon)' vlen=6\n"
|
||||
"\ttype_id=4 value='reg1'\n"
|
||||
"\ttype_id=5 value='*(reg2 + 0x10)'\n"
|
||||
"\ttype_id=6 value='fbreg - 0x10'\n"
|
||||
"\ttype_id=7 value='0x123456789abcdef0 (addr)'\n"
|
||||
"\ttype_id=8 value='0xdeadbeeffeedface'\n"
|
||||
"\ttype_id=7 value='address 0x123456789abcdef0'\n"
|
||||
"\ttype_id=8 value='const 0xdeadbeeffeedface'\n"
|
||||
"\ttype_id=9 value='*(fbreg - 0x20)'\n"
|
||||
"[11] LOCSEC 'inline.text' vlen=1\n"
|
||||
"\tname='foo' func_type_id=3 loc_proto_type_id=10 offset=64\n";
|
||||
"\tfunc='foo(arg1 [reg1], arg2 [*(reg2 + 0x10)], arg3 [fbreg - 0x10], arg4 [address 0x123456789abcdef0], arg5 [const 0xdeadbeeffeedface], arg6 [*(fbreg - 0x20)])' func_type_id=3 loc_proto_type_id=10 offset=64\n";
|
||||
char *dump;
|
||||
|
||||
dump = dump_raw(btf_path);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user