bpf,btf: enable BTF pruning by default for BPF
This patch enables -gprune-btf by default in the BPF backend when generating BTF information, and fixes BPF CO-RE generation when using -gprune-btf. When generating BPF CO-RE information, we must ensure that types used in CO-RE relocations always have sufficient BTF information emited so that the CO-RE relocations can be processed by a BPF loader. The BTF pruning algorithm on its own does not have sufficient information to determine which types are used in a BPF CO-RE relocation, so this information must be supplied by the BPF backend, using a new btf_mark_type_used function. Co-authored-by: Cupertino Miranda <cupertino.miranda@oracle.com> gcc/ * btfout.cc (btf_mark_type_used): New. * ctfc.h (btf_mark_type_used): Declare it here. * config/bpf/bpf.cc (bpf_option_override): Enable -gprune-btf by default if -gbtf is enabled. * config/bpf/core-builtins.cc (extra_fn): New typedef. (compute_field_expr): Add callback parameter, and call it if supplied. Fix computation for MEM_REF. (mark_component_type_as_used): New. (bpf_mark_types_as_used): Likewise. (bpf_expand_core_builtin): Call here. * doc/invoke.texi (Debugging Options): Note that -gprune-btf is enabled by default for BPF target when generating BTF. gcc/testsuite/ * gcc.dg/debug/btf/btf-variables-5.c: Adjust one test for bpf-*-* target.
This commit is contained in:
parent
b8977d928a
commit
189d0f1fc2
6 changed files with 100 additions and 8 deletions
|
@ -1503,6 +1503,28 @@ btf_assign_datasec_ids (ctf_container_ref ctfc)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Manually mark that type T is used to ensure it will not be pruned.
|
||||
Used by the BPF backend when generating BPF CO-RE to mark types used
|
||||
in CO-RE relocations. */
|
||||
|
||||
void
|
||||
btf_mark_type_used (tree t)
|
||||
{
|
||||
/* If we are not going to prune anyway, this is a no-op. */
|
||||
if (!debug_prune_btf)
|
||||
return;
|
||||
|
||||
gcc_assert (TYPE_P (t));
|
||||
ctf_container_ref ctfc = ctf_get_tu_ctfc ();
|
||||
ctf_dtdef_ref dtd = ctf_lookup_tree_type (ctfc, t);
|
||||
|
||||
if (!dtd)
|
||||
return;
|
||||
|
||||
btf_add_used_type (ctfc, dtd, false, false, true);
|
||||
}
|
||||
|
||||
/* Callback used for assembling the only-used-types list. Note that this is
|
||||
the same as btf_type_list_cb above, but the hash_set traverse requires a
|
||||
different function signature. */
|
||||
|
|
|
@ -221,6 +221,11 @@ bpf_option_override (void)
|
|||
&& !(target_flags_explicit & MASK_BPF_CORE))
|
||||
target_flags |= MASK_BPF_CORE;
|
||||
|
||||
/* -gbtf implies -gprune-btf for BPF target. */
|
||||
if (btf_debuginfo_p ())
|
||||
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
|
||||
debug_prune_btf, true);
|
||||
|
||||
/* Determine available features from ISA setting (-mcpu=). */
|
||||
if (bpf_has_jmpext == -1)
|
||||
bpf_has_jmpext = (bpf_isa >= ISA_V2);
|
||||
|
|
|
@ -624,13 +624,20 @@ bpf_core_get_index (const tree node, bool *valid)
|
|||
|
||||
ALLOW_ENTRY_CAST is an input arguments and specifies if the function should
|
||||
consider as valid expressions in which NODE entry is a cast expression (or
|
||||
tree code nop_expr). */
|
||||
tree code nop_expr).
|
||||
|
||||
EXTRA_FN is a callback function to allow extra functionality with this
|
||||
function traversal. Currently used for marking used type during expand
|
||||
pass. */
|
||||
|
||||
typedef void (*extra_fn) (tree);
|
||||
|
||||
static unsigned char
|
||||
compute_field_expr (tree node, unsigned int *accessors,
|
||||
bool *valid,
|
||||
tree *access_node,
|
||||
bool allow_entry_cast = true)
|
||||
bool allow_entry_cast = true,
|
||||
extra_fn callback = NULL)
|
||||
{
|
||||
unsigned char n = 0;
|
||||
unsigned int fake_accessors[MAX_NR_ACCESSORS];
|
||||
|
@ -647,6 +654,9 @@ compute_field_expr (tree node, unsigned int *accessors,
|
|||
|
||||
*access_node = node;
|
||||
|
||||
if (callback != NULL)
|
||||
callback (node);
|
||||
|
||||
switch (TREE_CODE (node))
|
||||
{
|
||||
case INDIRECT_REF:
|
||||
|
@ -664,17 +674,19 @@ compute_field_expr (tree node, unsigned int *accessors,
|
|||
case COMPONENT_REF:
|
||||
n = compute_field_expr (TREE_OPERAND (node, 0), accessors,
|
||||
valid,
|
||||
access_node, false);
|
||||
access_node, false, callback);
|
||||
accessors[n] = bpf_core_get_index (TREE_OPERAND (node, 1), valid);
|
||||
return n + 1;
|
||||
case ARRAY_REF:
|
||||
case ARRAY_RANGE_REF:
|
||||
case MEM_REF:
|
||||
n = compute_field_expr (TREE_OPERAND (node, 0), accessors,
|
||||
valid,
|
||||
access_node, false);
|
||||
access_node, false, callback);
|
||||
accessors[n++] = bpf_core_get_index (node, valid);
|
||||
return n;
|
||||
case MEM_REF:
|
||||
accessors[0] = bpf_core_get_index (node, valid);
|
||||
return 1;
|
||||
case NOP_EXPR:
|
||||
if (allow_entry_cast == true)
|
||||
{
|
||||
|
@ -683,7 +695,7 @@ compute_field_expr (tree node, unsigned int *accessors,
|
|||
}
|
||||
n = compute_field_expr (TREE_OPERAND (node, 0), accessors,
|
||||
valid,
|
||||
access_node, false);
|
||||
access_node, false, callback);
|
||||
return n;
|
||||
|
||||
case ADDR_EXPR:
|
||||
|
@ -1549,6 +1561,51 @@ bpf_resolve_overloaded_core_builtin (location_t loc, tree fndecl,
|
|||
return construct_builtin_core_reloc (loc, fndecl, args, argsvec->length ());
|
||||
}
|
||||
|
||||
/* Callback function for bpf_mark_field_expr_types_as_used. */
|
||||
|
||||
static void
|
||||
mark_component_type_as_used (tree node)
|
||||
{
|
||||
if (TREE_CODE (node) == COMPONENT_REF)
|
||||
btf_mark_type_used (TREE_TYPE (TREE_OPERAND (node, 0)));
|
||||
}
|
||||
|
||||
/* Mark types needed for BPF CO-RE relocations as used. Doing so ensures that
|
||||
these types do not get pruned from the BTF information. */
|
||||
|
||||
static void
|
||||
bpf_mark_types_as_used (struct cr_builtins *data)
|
||||
{
|
||||
tree expr = data->expr;
|
||||
switch (data->kind)
|
||||
{
|
||||
case BPF_RELO_FIELD_BYTE_OFFSET:
|
||||
case BPF_RELO_FIELD_BYTE_SIZE:
|
||||
case BPF_RELO_FIELD_EXISTS:
|
||||
case BPF_RELO_FIELD_SIGNED:
|
||||
case BPF_RELO_FIELD_LSHIFT_U64:
|
||||
case BPF_RELO_FIELD_RSHIFT_U64:
|
||||
if (TREE_CODE (expr) == ADDR_EXPR)
|
||||
expr = TREE_OPERAND (expr, 0);
|
||||
|
||||
expr = root_for_core_field_info (expr);
|
||||
compute_field_expr (data->expr, NULL, NULL, NULL, false,
|
||||
mark_component_type_as_used);
|
||||
break;
|
||||
case BPF_RELO_TYPE_ID_LOCAL:
|
||||
case BPF_RELO_TYPE_ID_TARGET:
|
||||
case BPF_RELO_TYPE_EXISTS:
|
||||
case BPF_RELO_TYPE_SIZE:
|
||||
case BPF_RELO_ENUMVAL_EXISTS:
|
||||
case BPF_RELO_ENUMVAL_VALUE:
|
||||
case BPF_RELO_TYPE_MATCHES:
|
||||
btf_mark_type_used (data->type);
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Used in bpf_expand_builtin. This function is called in RTL expand stage to
|
||||
convert the internal __builtin_core_reloc in unspec:UNSPEC_CORE_RELOC RTL,
|
||||
which will contain a third argument that is the index in the vec collected
|
||||
|
@ -1567,6 +1624,8 @@ bpf_expand_core_builtin (tree exp, enum bpf_builtins code)
|
|||
tree index = CALL_EXPR_ARG (exp, 0);
|
||||
struct cr_builtins *data = get_builtin_data (TREE_INT_CST_LOW (index));
|
||||
|
||||
bpf_mark_types_as_used (data);
|
||||
|
||||
rtx v = expand_normal (data->default_value);
|
||||
rtx i = expand_normal (index);
|
||||
return gen_rtx_UNSPEC (DImode,
|
||||
|
|
|
@ -457,6 +457,7 @@ extern ctf_dtdef_ref ctf_lookup_tree_type (ctf_container_ref, const tree);
|
|||
|
||||
typedef bool (*funcs_traverse_callback) (ctf_dtdef_ref, void *);
|
||||
bool traverse_btf_func_types (funcs_traverse_callback, void *);
|
||||
extern void btf_mark_type_used (tree);
|
||||
|
||||
/* CTF section does not emit location information; at this time, location
|
||||
information is needed for BTF CO-RE use-cases. */
|
||||
|
|
|
@ -12044,6 +12044,9 @@ It is primarily useful when compiling for the BPF target, to minimize
|
|||
the size of the resulting object, and to eliminate BTF information
|
||||
which is not immediately relevant to the BPF program loading process.
|
||||
|
||||
This option is enabled by default for the BPF target when generating
|
||||
BTF information.
|
||||
|
||||
@opindex gctf
|
||||
@item -gctf
|
||||
@itemx -gctf@var{level}
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
/* { dg-final { scan-assembler-times "\[\t \]0xe000000\[\t \]+\[^\n\]*btv_info" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*btv_linkage" 1 } } */
|
||||
|
||||
/* Expect 2 array types, one of which is unsized. */
|
||||
/* Expect 2 array types, one of which is unsized. For BPF target, -gprune-btf
|
||||
is the default and will remove the unsized array type. */
|
||||
/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t \]+\[^\n\]*bta_nelems" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*bta_nelems" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*bta_nelems" 1 { target { !bpf-*-* } } } } */
|
||||
/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*bta_nelems" 0 { target { bpf-*-* } } } } */
|
||||
|
||||
extern const char FOO[];
|
||||
const char FOO[] = "foo";
|
||||
|
|
Loading…
Add table
Reference in a new issue