Corrected and Pushed, with the following little change to resolve a warning I missed before, the patch introduced was:
diff --git a/gcc/config/bpf/btfext-out.cc b/gcc/config/bpf/btfext-out.cc index 6ebbb54ef73e..00d2501a976b 100644 --- a/gcc/config/bpf/btfext-out.cc +++ b/gcc/config/bpf/btfext-out.cc @@ -200,7 +200,7 @@ btfext_info_sec_find_or_add (const char *sec_name, bool add) return ret; } -#define SEARCH_NODE_AND_RETURN(TYPE, FIELD, CONDITION) ({ \ +#define SEARCH_NODE_AND_RETURN(TYPE, FIELD, CONDITION) __extension__ ({ \ TYPE **head = &(FIELD); \ while (*head != NULL) \ { \ Thanks, Cupertino David Faust writes: > Hi Cupertino, > > On 2/27/24 11:04, Cupertino Miranda wrote: >> Kernel verifier complains in some particular cases for missing func_info >> implementation in .BTF.ext. This patch implements it. >> >> Strings are cached locally in coreout.cc to avoid adding duplicated >> strings in the string list. This string deduplication should eventually >> be moved to the CTFC functions such that this happens widely. >> >> With this implementation, the CO-RE relocations information was also >> simplified and integrated with the FuncInfo structures. >> > > I have just a couple small comments inline in the patch below, but they > are very minor and only suggestions/nits. > > The ChangeLog has the same past/present tense issue as the other patches > in the series, but apart from that I see no issues. Great work! Thanks > for implementing this. > > Patch is OK with the ChangeLog fixed up, and the inline nits - if > you agree. > Thanks! > >> gcc/Changelog: >> >> PR target/113453 >> * config/bpf/bpf.cc (bpf_function_prologue): Defined target >> hook. >> * config/bpf/coreout.cc (brf_ext_info_section) >> (btf_ext_info): Moved from coreout.h >> (btf_ext_funcinfo, btf_ext_lineinfo): Added struct. >> (bpf_core_reloc): Renamed to btf_ext_core_reloc. >> (btf_ext): Added static variable. >> (btfext_info_sec_find_or_add, SEARCH_NODE_AND_RETURN) >> (bpf_create_or_find_funcinfo, bpt_create_core_reloc) >> (btf_ext_add_string, btf_funcinfo_type_callback) >> (btf_add_func_info_for, btf_validate_funcinfo) >> (btf_ext_info_len, output_btfext_func_info): Added function. >> (output_btfext_header, bpf_core_reloc_add) >> (output_btfext_core_relocs, btf_ext_init, btf_ext_output): >> Changed to support new structs. >> * config/bpf/coreout.h (btf_ext_funcinfo, btf_ext_lineinfo): >> Moved and changed in coreout.cc. >> (btf_add_func_info_for, btf_ext_add_string): Added prototypes. >> >> gcc/testsuite/ChangeLog: >> PR target/113453 >> * gcc.target/bpf/btfext-funcinfo-nocore.c: Added. >> * gcc.target/bpf/btfext-funcinfo.c: Added. >> * gcc.target/bpf/core-attr-5.c: Fixed regexp. >> * gcc.target/bpf/core-attr-6.c: Fixed regexp. >> * gcc.target/bpf/core-builtin-fieldinfo-offset-1.c: Fixed regexp. >> * gcc.target/bpf/core-section-1.c: Fixed regexp >> --- >> gcc/config/bpf/bpf.cc | 12 + >> gcc/config/bpf/coreout.cc | 518 +++++++++++++----- >> gcc/config/bpf/coreout.h | 20 +- >> .../gcc.target/bpf/btfext-funcinfo-nocore.c | 42 ++ >> .../gcc.target/bpf/btfext-funcinfo.c | 46 ++ >> gcc/testsuite/gcc.target/bpf/core-attr-5.c | 9 +- >> gcc/testsuite/gcc.target/bpf/core-attr-6.c | 6 +- >> .../bpf/core-builtin-fieldinfo-offset-1.c | 13 +- >> gcc/testsuite/gcc.target/bpf/core-section-1.c | 2 +- >> 9 files changed, 506 insertions(+), 162 deletions(-) >> create mode 100644 gcc/testsuite/gcc.target/bpf/btfext-funcinfo-nocore.c >> create mode 100644 gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c >> >> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc >> index 4318b26b9cda..ea47e3a8dbfb 100644 >> --- a/gcc/config/bpf/bpf.cc >> +++ b/gcc/config/bpf/bpf.cc >> @@ -385,6 +385,18 @@ bpf_compute_frame_layout (void) >> #undef TARGET_COMPUTE_FRAME_LAYOUT >> #define TARGET_COMPUTE_FRAME_LAYOUT bpf_compute_frame_layout >> >> +/* Defined to initialize data for func_info region in .BTF.ext section. */ >> + >> +static void >> +bpf_function_prologue (FILE *f ATTRIBUTE_UNUSED) >> +{ >> + if (btf_debuginfo_p ()) >> + btf_add_func_info_for (cfun->decl, current_function_func_begin_label); >> +} >> + >> +#undef TARGET_ASM_FUNCTION_PROLOGUE >> +#define TARGET_ASM_FUNCTION_PROLOGUE bpf_function_prologue >> + >> /* Expand to the instructions in a function prologue. This function >> is called when expanding the 'prologue' pattern in bpf.md. */ >> >> diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc >> index 2f06ec2a0f29..31b2abc3151b 100644 >> --- a/gcc/config/bpf/coreout.cc >> +++ b/gcc/config/bpf/coreout.cc >> @@ -31,6 +31,7 @@ >> #include "btf.h" >> #include "rtl.h" >> #include "tree-pretty-print.h" >> +#include "cgraph.h" >> >> #include "coreout.h" >> >> @@ -95,64 +96,193 @@ >> result, a single .BTF.ext section can contain CO-RE relocations for >> multiple >> programs in distinct sections. */ >> >> -/* Internal representation of a BPF CO-RE relocation record. */ >> +/* BTF.ext debug info section. */ >> +static GTY (()) section * btf_ext_info_section; >> + >> +#ifndef BTF_EXT_INFO_SECTION_NAME >> +#define BTF_EXT_INFO_SECTION_NAME ".BTF.ext" >> +#endif >> +#define BTF_EXT_INFO_SECTION_FLAGS (SECTION_DEBUG) >> + >> +#ifndef BTF_EXT_INFO_SECTION_LABEL >> +#define BTF_EXT_INFO_SECTION_LABEL "Lbtfext" >> +#endif >> + >> +#define MAX_BTF_EXT_LABEL_BYTES 40 >> +static char btf_ext_info_section_label[MAX_BTF_EXT_LABEL_BYTES]; >> + >> +/* A funcinfo record, in the .BTF.ext funcinfo section. */ >> +struct GTY ((chain_next ("%h.next"))) btf_ext_funcinfo >> +{ >> + uint32_t type; /* Type ID of a BTF_KIND_FUNC type. */ >> + const char *fnname; >> + const char *label; >> + >> + struct btf_ext_funcinfo *next; /* Linked list to collect func_info elems. >> */ >> +}; >> + >> +/* A lineinfo record, in the .BTF.ext lineinfo section. */ >> +struct GTY ((chain_next ("%h.next"))) btf_ext_lineinfo >> +{ >> + uint32_t insn_off; /* Offset of the instruction. */ >> + uint32_t file_name_off; /* Offset of file name in BTF string table. */ >> + uint32_t line_off; /* Offset of source line in BTF string table. */ >> + uint32_t line_col; /* Line number (bits 31-11) and column (11-0). */ >> >> -typedef struct GTY (()) bpf_core_reloc { >> + struct btf_ext_lineinfo *next; /* Linked list to collect line_info elems. >> */ >> +}; >> + >> +/* Internal representation of a BPF CO-RE relocation record. */ >> +struct GTY ((chain_next ("%h.next"))) btf_ext_core_reloc { >> unsigned int bpfcr_type; /* BTF type ID of container. */ >> unsigned int bpfcr_astr_off; /* Offset of access string in >> .BTF >> string table. */ >> rtx_code_label * bpfcr_insn_label; /* RTX label attached to >> instruction >> to patch. */ >> enum btf_core_reloc_kind bpfcr_kind; /* Kind of relocation to >> perform. */ >> -} bpf_core_reloc_t; >> >> -typedef bpf_core_reloc_t * bpf_core_reloc_ref; >> + struct { >> + const char *accessor_str; >> + tree type; >> + } info; >> >> -/* Internal representation of a CO-RE relocation (sub)section of the >> - .BTF.ext information. One such section is generated for each ELF section >> - in the output object having relocations that a BPF loader must resolve. >> */ >> + struct btf_ext_core_reloc *next; >> +}; >> >> -typedef struct GTY (()) bpf_core_section { >> - /* Name of ELF section to which these CO-RE relocations apply. */ >> - const char * name; >> +/* Main data structure to keep .BTF.ext section data. */ >> +struct GTY ((chain_next ("%h.next"))) btf_ext_info_sec { >> + const char *sec_name; >> + uint32_t sec_name_off; /* offset to section name. */ >> + >> + struct { >> + uint32_t num_info; >> + struct btf_ext_funcinfo *head; >> + } func_info; >> + struct { >> + uint32_t num_info; >> + struct btf_ext_lineinfo *head; >> + } line_info; >> + struct { >> + uint32_t num_info; >> + struct btf_ext_core_reloc *head; >> + } core_info; >> + >> + struct btf_ext_info_sec *next; >> +}; >> >> - /* Offset of section name in .BTF string table. */ >> - uint32_t name_offset; >> +static GTY (()) struct btf_ext_info_sec *btf_ext = NULL; >> >> - /* Relocations in the section. */ >> - vec <bpf_core_reloc_ref, va_gc> * GTY (()) relocs; >> -} bpf_core_section_t; >> +/* Helper function to add a section structure to the linked list with entry >> + point in info static variable. */ >> >> -typedef bpf_core_section_t * bpf_core_section_ref; >> +static struct btf_ext_info_sec * >> +btfext_info_sec_find_or_add (const char *sec_name, bool add) >> +{ >> + struct btf_ext_info_sec **tmp = &btf_ext; >> >> -/* BTF.ext debug info section. */ >> + while (*tmp != NULL) >> + { >> + if (strcmp ((*tmp)->sec_name, sec_name) == 0) >> + return *tmp; >> + tmp = &((*tmp)->next); >> + } >> >> -static GTY (()) section * btf_ext_info_section; >> + if (add == false) >> + return NULL; >> >> -static int btf_ext_label_num; >> + struct btf_ext_info_sec *ret = ggc_cleared_alloc<struct btf_ext_info_sec> >> (); >> + *tmp = ret; >> >> -#ifndef BTF_EXT_INFO_SECTION_NAME >> -#define BTF_EXT_INFO_SECTION_NAME ".BTF.ext" >> -#endif >> + /* Set data for section info. */ >> + ret->sec_name = sec_name; >> + ret->sec_name_off = btf_ext_add_string (sec_name); >> >> -#define BTF_EXT_INFO_SECTION_FLAGS (SECTION_DEBUG) >> + return ret; >> +} >> >> -#define MAX_BTF_EXT_LABEL_BYTES 40 >> +#define SEARCH_NODE_AND_RETURN(TYPE, FIELD, CONDITION) ({ \ >> + TYPE **head = &(FIELD); \ >> + while (*head != NULL) \ >> + { \ >> + if (CONDITION) \ >> + return (*head); \ >> + head = &((*head)->next); \ >> + } \ >> + head; \ >> +}) >> + >> +/* Function to create or find a funcinfo node in info. */ >> + >> +static struct btf_ext_funcinfo * >> +bpf_create_or_find_funcinfo (const char *fnname, const char *sec_name, >> + btf_ext_info_sec **in_sec = NULL) >> +{ >> + struct btf_ext_info_sec *sec_elem = >> + btfext_info_sec_find_or_add (sec_name, true); >> >> -static char btf_ext_info_section_label[MAX_BTF_EXT_LABEL_BYTES]; >> + if (in_sec != NULL) >> + *in_sec = sec_elem; >> >> -#ifndef BTF_EXT_INFO_SECTION_LABEL >> -#define BTF_EXT_INFO_SECTION_LABEL "Lbtfext" >> -#endif >> + struct btf_ext_funcinfo **head = >> + SEARCH_NODE_AND_RETURN(struct btf_ext_funcinfo, >> + sec_elem->func_info.head, >> + strcmp ((*head)->fnname, fnname) == 0); >> >> -static GTY (()) vec<bpf_core_section_ref, va_gc> *bpf_core_sections; >> + *head = ggc_cleared_alloc<struct btf_ext_funcinfo> (); >> + (*head)->fnname = fnname; >> + (*head)->label = NULL; >> >> -struct GTY(()) bpf_core_extra { >> - const char *accessor_str; >> - tree type; >> + return *head; >> +} >> + >> +/* Function to create a core_reloc node in info. */ >> + >> +static struct btf_ext_core_reloc * >> +bpf_create_core_reloc (const char *sec_name, >> + struct btf_ext_info_sec **in_sec = NULL) >> +{ >> + struct btf_ext_info_sec *sec_elem = >> + btfext_info_sec_find_or_add (sec_name, true); >> + >> + if (in_sec != NULL) >> + *in_sec = sec_elem; >> + >> + struct btf_ext_core_reloc **head = >> + SEARCH_NODE_AND_RETURN(struct btf_ext_core_reloc, >> + sec_elem->core_info.head, >> + false); >> + >> + *head = ggc_cleared_alloc<struct btf_ext_core_reloc> (); >> + >> + return *head; >> +} >> + >> +/* String caching to avoid repeated strings added to BTF string table. */ >> +struct GTY((chain_next ("%h.next"))) string_cache { >> + const char *str; >> + unsigned int offset; >> + struct string_cache *next; >> }; >> -typedef struct bpf_core_extra *bpf_core_extra_ref; >> -static GTY(()) hash_map<bpf_core_reloc_ref, bpf_core_extra_ref> >> *bpf_comment_info; >> +static GTY(()) struct string_cache *btf_ext_strings = NULL; >> + >> +unsigned int >> +btf_ext_add_string (const char *str) >> +{ >> + ctf_container_ref ctfc = ctf_get_tu_ctfc (); >> + struct string_cache **tmp = &btf_ext_strings; >> + while (*tmp != NULL) >> + { >> + if (strcmp ((*tmp)->str, str) == 0) >> + return (*tmp)->offset; >> + tmp = &((*tmp)->next); >> + } >> + >> + *tmp = ggc_cleared_alloc<struct string_cache> (); >> + (*tmp)->str = ggc_strdup (str); >> + ctf_add_string (ctfc, (*tmp)->str, &((*tmp)->offset), CTF_AUX_STRTAB); >> + >> + return (*tmp)->offset; >> +} >> >> /* Create a new BPF CO-RE relocation record, and add it to the appropriate >> CO-RE section. */ >> @@ -162,42 +292,23 @@ bpf_core_reloc_add (const tree type, const char * >> section_name, >> rtx_code_label *label, >> enum btf_core_reloc_kind kind) >> { >> - bpf_core_reloc_ref bpfcr = ggc_cleared_alloc<bpf_core_reloc_t> (); >> - bpf_core_extra_ref info = ggc_cleared_alloc<struct bpf_core_extra> (); >> + struct btf_ext_info_sec *sec = NULL; >> + struct btf_ext_core_reloc *bpfcr = bpf_create_core_reloc (section_name, >> &sec); >> + >> ctf_container_ref ctfc = ctf_get_tu_ctfc (); >> >> /* Buffer the access string in the auxiliary strtab. */ >> - ctf_add_string (ctfc, accessor, &(bpfcr->bpfcr_astr_off), CTF_AUX_STRTAB); >> + bpfcr->bpfcr_astr_off = 0; >> + if (accessor != NULL) >> + bpfcr->bpfcr_astr_off = btf_ext_add_string (accessor); >> bpfcr->bpfcr_type = get_btf_id (ctf_lookup_tree_type (ctfc, type)); >> bpfcr->bpfcr_insn_label = label; >> bpfcr->bpfcr_kind = kind; >> >> - info->accessor_str = accessor; >> - info->type = type; >> - bpf_comment_info->put (bpfcr, info); >> - >> - /* Add the CO-RE reloc to the appropriate section. */ >> - bpf_core_section_ref sec; >> - int i; >> - FOR_EACH_VEC_ELT (*bpf_core_sections, i, sec) >> - if (strcmp (sec->name, section_name) == 0) >> - { >> - vec_safe_push (sec->relocs, bpfcr); >> - return; >> - } >> + bpfcr->info.accessor_str = accessor; >> + bpfcr->info.type = type; >> >> - /* If the CO-RE section does not yet exist, create it. */ >> - sec = ggc_cleared_alloc<bpf_core_section_t> (); >> - >> - ctf_add_string (ctfc, section_name, &sec->name_offset, CTF_AUX_STRTAB); >> - if (strcmp (section_name, "")) >> - ctfc->ctfc_aux_strlen += strlen (section_name) + 1; >> - >> - sec->name = section_name; >> - vec_alloc (sec->relocs, 1); >> - vec_safe_push (sec->relocs, bpfcr); >> - >> - vec_safe_push (bpf_core_sections, sec); >> + sec->core_info.num_info += 1; >> } >> >> /* Return the 0-based index of the field NODE in its containing struct or >> union >> @@ -243,6 +354,113 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, >> const tree node) >> return -1; >> } >> >> +/* Helper function to check if a particular named function exists as a >> + BTF_KIND_FUNC type record. */ >> + >> +static bool >> +btf_funcinfo_type_callback (ctf_dtdef_ref func, void *data) >> +{ >> + struct btf_ext_funcinfo *info = (struct btf_ext_funcinfo *) data; >> + if (strcmp (func->dtd_name, info->fnname) == 0) >> + { >> + uint32_t type = func->dtd_type; >> + info->type = type; >> + return true; >> + } >> + return false; >> +} >> + >> +/* Entry point function to add a func_info in local data structures >> + represented by info static variable. >> + This function is used in bpf.cc. */ >> + >> +struct btf_ext_funcinfo * >> +btf_add_func_info_for (tree decl, const char *label) >> +{ >> + const char *fnname = IDENTIFIER_POINTER (DECL_NAME (decl)); >> + const char *sec_name = decl_section_name (decl); >> + >> + /* Finding suffixed function names, due to the function cloning base on >> + optimizations. >> + This is required to recover the original function name that is the one >> + used in BTF_KIND_FUNC type records. */ > > I find this comment hard to follow, it took me some time to understand. > It may be helpful to simply say something like > "Recover the original function name, which may have been mangled > by optimizations." > >> + const char *cp_ptr = strstr (fnname, "."); >> + if (cp_ptr != NULL) >> + { >> + char new_name[100]; >> + strcpy (new_name, fnname); >> + int pos = cp_ptr - fnname; >> + new_name[pos] = 0; >> + fnname = ggc_strdup (new_name); >> + } >> + >> + if (sec_name == NULL) >> + sec_name = ".text"; >> + >> + struct btf_ext_info_sec *sec = NULL; >> + struct btf_ext_funcinfo *info = >> + bpf_create_or_find_funcinfo (fnname, sec_name, &sec); >> + >> + info->label = label; >> + return info; >> +} >> + >> +/* This function traverses all func_info entries and verified they do have a >> + BTF_KIND_FUNC type record associated. If they do not it is marked as >> + invalided by clearing the associated label. */ >> + >> +static void >> +btf_validate_funcinfo (btf_ext_info_sec *sec) >> +{ >> + while (sec != NULL) >> + { >> + struct btf_ext_funcinfo *funcinfo = sec->func_info.head; >> + while (funcinfo != NULL) >> + { >> + bool found = traverse_btf_func_types (btf_funcinfo_type_callback, >> + funcinfo); >> + if (found == true) >> + sec->func_info.num_info += 1; >> + else >> + funcinfo->label = NULL; >> + >> + funcinfo = funcinfo->next; >> + } >> + sec = sec->next; >> + } >> +} >> + >> +/* Compute the section size in section for func_info, line_info and >> core_info >> + regions of .BTF.ext. */ >> + >> +static void >> +btf_ext_info_len (uint32_t *fi_len, uint32_t *li_len, uint32_t *cr_len) >> +{ >> + *fi_len = *li_len = *cr_len = 0; >> + struct btf_ext_info_sec *tmp = btf_ext; >> + if (tmp != NULL) >> + while (tmp != NULL) >> + { >> + /* Size computation does 8 bytes per section entry plus num_info of >> the >> + * respective structure size: >> + - 8 bytes for func_info, >> + - 16 bytes for both line_info and core_info. */ >> + if (tmp->func_info.num_info > 0) >> + *fi_len += 8 + (8 * tmp->func_info.num_info); >> + if (tmp->line_info.num_info > 0) >> + *li_len += 8 + (16 * tmp->line_info.num_info); >> + if (tmp->core_info.num_info > 0) >> + *cr_len += 8 + (16 * tmp->core_info.num_info); >> + tmp = tmp->next; >> + } >> + >> + /* If there are entries within the regions, add 4 bytes to set the header >> of >> + the respective sections that contains the size for each of the entry. >> */ >> + *fi_len += *fi_len != 0 ? 4 : 0; >> + *li_len += *li_len != 0 ? 4 : 0; >> + *cr_len += *cr_len != 0 ? 4 : 0; >> +} >> + >> /* Compute and output the header of a .BTF.ext debug info section. */ >> >> static void >> @@ -256,23 +474,19 @@ output_btfext_header (void) >> dw2_asm_output_data (1, 0, "btfext_flags"); >> dw2_asm_output_data (4, sizeof (struct btf_ext_header), "btfext_hdr_len"); >> >> - uint32_t func_info_off = 0, func_info_len = 0; >> - uint32_t line_info_off = 0, line_info_len = 0; >> - uint32_t core_relo_off = 0, core_relo_len = 0; >> + btf_validate_funcinfo (btf_ext); >> >> - /* Header core_relo_len is the sum total length in bytes of all CO-RE >> - relocation sections, plus the 4 byte record size. */ >> - size_t i; >> - bpf_core_section_ref sec; >> - core_relo_len += vec_safe_length (bpf_core_sections) >> - * sizeof (struct btf_ext_section_header); >> + uint32_t func_info_len = 0; >> + uint32_t line_info_len = 0; >> + uint32_t core_info_len = 0; >> + btf_ext_info_len (&func_info_len, &line_info_len, &core_info_len); >> >> - FOR_EACH_VEC_ELT (*bpf_core_sections, i, sec) >> - core_relo_len += >> - vec_safe_length (sec->relocs) * sizeof (struct btf_ext_reloc); >> + if (!TARGET_BPF_CORE) >> + core_info_len = 0; >> >> - if (core_relo_len) >> - core_relo_len += sizeof (uint32_t); >> + uint32_t func_info_off = 0; >> + uint32_t line_info_off = func_info_len; >> + uint32_t core_info_off = line_info_off + line_info_len; >> >> dw2_asm_output_data (4, func_info_off, "func_info_offset"); >> dw2_asm_output_data (4, func_info_len, "func_info_len"); >> @@ -280,47 +494,47 @@ output_btfext_header (void) >> dw2_asm_output_data (4, line_info_off, "line_info_offset"); >> dw2_asm_output_data (4, line_info_len, "line_info_len"); >> >> - dw2_asm_output_data (4, core_relo_off, "core_relo_offset"); >> - dw2_asm_output_data (4, core_relo_len, "core_relo_len"); >> + dw2_asm_output_data (4, core_info_off, "core_relo_offset"); >> + dw2_asm_output_data (4, core_info_len, "core_relo_len"); >> } >> >> -/* Output a single CO-RE relocation record. */ >> +/* Outputs func_info region on .BTF.ext. */ >> >> static void >> -output_asm_btfext_core_reloc (bpf_core_reloc_ref bpfcr) >> +output_btfext_func_info (struct btf_ext_info_sec *sec) >> { >> - bpf_core_extra_ref *info = bpf_comment_info->get (bpfcr); >> - gcc_assert (info != NULL); >> - >> - bpfcr->bpfcr_astr_off += ctfc_get_strtab_len (ctf_get_tu_ctfc (), >> - CTF_STRTAB); >> - >> - dw2_assemble_integer (4, gen_rtx_LABEL_REF (Pmode, >> bpfcr->bpfcr_insn_label)); >> - fprintf (asm_out_file, "\t%s%s\n", >> - flag_debug_asm ? ASM_COMMENT_START : "", >> - (flag_debug_asm ? " bpfcr_insn" : "")); >> - >> - /* Extract the pretty print for the type expression. */ >> - pretty_printer pp; >> - dump_generic_node (&pp, (*info)->type, 0, TDF_VOPS|TDF_MEMSYMS|TDF_SLIM, >> - false); >> - char *str = xstrdup (pp_formatted_text (&pp)); >> - >> - dw2_asm_output_data (4, bpfcr->bpfcr_type, "bpfcr_type (%s)", str); >> - dw2_asm_output_data (4, bpfcr->bpfcr_astr_off, "bpfcr_astr_off (\"%s\")", >> - (*info)->accessor_str); >> - dw2_asm_output_data (4, bpfcr->bpfcr_kind, "bpfcr_kind"); >> -} >> - >> -/* Output all CO-RE relocation records for a section. */ >> - >> -static void >> -output_btfext_core_relocs (bpf_core_section_ref sec) >> -{ >> - size_t i; >> - bpf_core_reloc_ref bpfcr; >> - FOR_EACH_VEC_ELT (*(sec->relocs), i, bpfcr) >> - output_asm_btfext_core_reloc (bpfcr); >> + unsigned int str_aux_off = ctfc_get_strtab_len (ctf_get_tu_ctfc (), >> + CTF_STRTAB); >> + bool executed = false; >> + while (sec != NULL) >> + { >> + uint32_t count = 0; >> + if (sec->func_info.num_info > 0) >> + { >> + if (executed == false && (executed = true)) >> + dw2_asm_output_data (4, 8, "FuncInfo entry size"); >> + dw2_asm_output_data (4, sec->sec_name_off + str_aux_off, >> + "FuncInfo section string for %s", >> + sec->sec_name); >> + dw2_asm_output_data (4, sec->func_info.num_info, "Number of entries"); >> + >> + struct btf_ext_funcinfo *elem = sec->func_info.head; >> + while (elem != NULL) >> + { >> + if (elem->label != NULL) >> + { >> + count += 1; >> + dw2_asm_output_offset (4, elem->label, >> + NULL, "label for function %s", elem->fnname); >> + dw2_asm_output_data (4, elem->type, "btf_type_id"); >> + } >> + elem = elem->next; >> + } >> + } >> + >> + gcc_assert (count == sec->func_info.num_info); >> + sec = sec->next; >> + } >> } >> >> /* Output all CO-RE relocation sections. */ >> @@ -328,28 +542,51 @@ output_btfext_core_relocs (bpf_core_section_ref sec) >> static void >> output_btfext_core_sections (void) >> { >> - size_t i; >> - bpf_core_section_ref sec; >> - >> - /* BTF Ext section info. */ >> - dw2_asm_output_data (4, sizeof (struct btf_ext_reloc), >> - "btfext_core_info_rec_size"); >> - >> - FOR_EACH_VEC_ELT (*bpf_core_sections, i, sec) >> + struct btf_ext_info_sec *sec = btf_ext; >> + unsigned int str_aux_off = ctfc_get_strtab_len (ctf_get_tu_ctfc (), >> + CTF_STRTAB); >> + bool executed = false; >> + while (sec != NULL) >> { >> - /* Section name offset, refers to the offset of a string with the >> name of >> - the section to which these CORE relocations refer, e.g. '.text'. >> - The string is buffered in the BTF strings table. */ >> - >> - /* BTF specific strings are in CTF_AUX_STRTAB, which is concatenated >> - after CTF_STRTAB. Add the length of STRTAB to the final offset. */ >> - sec->name_offset += ctfc_get_strtab_len (ctf_get_tu_ctfc (), >> CTF_STRTAB); >> - >> - dw2_asm_output_data (4, sec->name_offset, >> "btfext_secinfo_sec_name_off"); >> - dw2_asm_output_data (4, vec_safe_length (sec->relocs), >> - "btfext_secinfo_num_recs"); >> - >> - output_btfext_core_relocs (sec); >> + uint32_t count = 0; >> + if (sec->core_info.num_info > 0) >> + { >> + if (executed == false && (executed = true)) >> + dw2_asm_output_data (4, 16, "CoreInfo entry size"); >> + dw2_asm_output_data (4, sec->sec_name_off + str_aux_off, >> + "CoreInfo section string for %s", >> + sec->sec_name); >> + dw2_asm_output_data (4, sec->core_info.num_info, "Number of entries"); >> + >> + struct btf_ext_core_reloc *bpfcr = sec->core_info.head; >> + while (bpfcr != NULL) >> + { >> + count += 1; >> + dw2_assemble_integer (4, >> + gen_rtx_LABEL_REF (Pmode, bpfcr->bpfcr_insn_label)); >> + fprintf (asm_out_file, "\t%s%s\n", >> + flag_debug_asm ? ASM_COMMENT_START : "", >> + (flag_debug_asm ? " bpfcr_insn" : "")); >> + >> + /* Extract the pretty print for the type expression. */ >> + pretty_printer pp; >> + dump_generic_node (&pp, bpfcr->info.type, 0, >> + TDF_VOPS|TDF_MEMSYMS|TDF_SLIM, >> + false); >> + char *str = xstrdup (pp_formatted_text (&pp)); >> + >> + dw2_asm_output_data (4, bpfcr->bpfcr_type, "bpfcr_type (%s)", >> + str); >> + dw2_asm_output_data (4, bpfcr->bpfcr_astr_off + str_aux_off, >> + "bpfcr_astr_off (\"%s\")", >> + bpfcr->info.accessor_str); >> + dw2_asm_output_data (4, bpfcr->bpfcr_kind, "bpfcr_kind"); >> + bpfcr = bpfcr->next; >> + } >> + } >> + >> + gcc_assert (count == sec->core_info.num_info); >> + sec = sec->next; >> } >> } >> >> @@ -362,22 +599,23 @@ btf_ext_init (void) >> BTF_EXT_INFO_SECTION_FLAGS, NULL); >> >> ASM_GENERATE_INTERNAL_LABEL (btf_ext_info_section_label, >> - BTF_EXT_INFO_SECTION_LABEL, >> - btf_ext_label_num++); >> - >> - vec_alloc (bpf_core_sections, 1); >> - bpf_comment_info = hash_map<bpf_core_reloc_ref, >> bpf_core_extra_ref>::create_ggc (); >> + "Lbtfext", 0); >> } >> >> + > > nit: extraneous newline > >> /* Output the entire .BTF.ext section. */ >> >> void >> btf_ext_output (void) >> { >> output_btfext_header (); >> - output_btfext_core_sections (); >> + output_btfext_func_info (btf_ext); >> + if (TARGET_BPF_CORE) >> + output_btfext_core_sections (); >> >> - bpf_core_sections = NULL; >> + /* Extra padding required by BPF code, just in case all structures are >> empty. >> + */ > > nit: trailing */ on newline. > >> + dw2_asm_output_data (4, 0, "Required padding by libbpf structs"); >> } >> >> #include "gt-coreout.h" >> diff --git a/gcc/config/bpf/coreout.h b/gcc/config/bpf/coreout.h >> index 8a209f26e94b..1c26b9274739 100644 >> --- a/gcc/config/bpf/coreout.h >> +++ b/gcc/config/bpf/coreout.h >> @@ -38,22 +38,6 @@ struct btf_ext_section_header >> uint32_t num_records; >> }; >> >> -/* A funcinfo record, in the .BTF.ext funcinfo section. */ >> -struct btf_ext_funcinfo >> -{ >> - uint32_t insn_off; /* Offset of the first instruction of the function. */ >> - uint32_t type; /* Type ID of a BTF_KIND_FUNC type. */ >> -}; >> - >> -/* A lineinfo record, in the .BTF.ext lineinfo section. */ >> -struct btf_ext_lineinfo >> -{ >> - uint32_t insn_off; /* Offset of the instruction. */ >> - uint32_t file_name_off; /* Offset of file name in BTF string table. */ >> - uint32_t line_off; /* Offset of source line in BTF string table. */ >> - uint32_t line_col; /* Line number (bits 31-11) and column (11-0). */ >> -}; >> - >> enum btf_core_reloc_kind >> { >> BPF_RELO_INVALID = -1, >> @@ -113,6 +97,10 @@ bpf_core_reloc_add (const tree type, const char * >> section_name, >> >> extern int bpf_core_get_sou_member_index (ctf_container_ref, const tree); >> >> +struct btf_ext_funcinfo *btf_add_func_info_for (tree decl, >> + const char *label); >> +unsigned int btf_ext_add_string (const char *str); >> + >> #ifdef __cplusplus >> } >> #endif >> diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo-nocore.c >> b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo-nocore.c >> new file mode 100644 >> index 000000000000..09d3acc8c2d4 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo-nocore.c >> @@ -0,0 +1,42 @@ >> +/* { dg-do compile } */ >> +/* { dg-options "-O2 -dA -gbtf -mno-co-re" } */ >> + >> +struct T { >> + int a; >> + int b; >> + struct U { >> + int c; >> + struct V { >> + int d; >> + int e[4]; >> + int f; >> + } v; >> + } u; >> +} __attribute__((preserve_access_index)); >> + >> +__attribute__((section("foo_sec"), used)) >> +int foo_func (struct T *t) >> +{ >> + t->u.c = 5; >> + return t->u.v.e[3]; >> +} >> + >> +__attribute__((section("bar_sec"), used)) >> +int bar_func (struct T *t) >> +{ >> + int *x = &(t->u.v.f); >> + int old = *x; >> + *x = 4; >> + return old; >> +} >> + >> +/* { dg-final { scan-assembler-times "FuncInfo section string for foo_sec" >> 1 } } */ >> +/* { dg-final { scan-assembler-times "FuncInfo section string for bar_sec" >> 1 } } */ >> +/* { dg-final { scan-assembler-times "label for function foo_func" 1 } } */ >> +/* { dg-final { scan-assembler-times "label for function bar_func" 1 } } */ >> +/* { dg-final { scan-assembler-times ".4byte\t0x1\t# Number of entries" 2 } >> } */ >> +/* { dg-final { scan-assembler-times "Required padding" 1 } } */ >> + >> +/* { dg-final { scan-assembler-times "ascii \"foo_sec.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> +/* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> + >> diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c >> b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c >> new file mode 100644 >> index 000000000000..a59c5bd37eb9 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c >> @@ -0,0 +1,46 @@ >> +/* { dg-do compile } */ >> +/* { dg-options "-O2 -dA -gbtf" } */ >> + >> +struct T { >> + int a; >> + int b; >> + struct U { >> + int c; >> + struct V { >> + int d; >> + int e[4]; >> + int f; >> + } v; >> + } u; >> +} __attribute__((preserve_access_index)); >> + >> +__attribute__((section("foo_sec"), used)) >> +int foo_func (struct T *t) >> +{ >> + t->u.c = 5; >> + return t->u.v.e[3]; >> +} >> + >> +__attribute__((section("bar_sec"), used)) >> +int bar_func (struct T *t) >> +{ >> + int *x = &(t->u.v.f); >> + int old = *x; >> + *x = 4; >> + return old; >> +} >> + >> +/* { dg-final { scan-assembler-times "FuncInfo section string for foo_sec" >> 1 } } */ >> +/* { dg-final { scan-assembler-times "FuncInfo section string for bar_sec" >> 1 } } */ >> +/* { dg-final { scan-assembler-times "label for function foo_func" 1 } } */ >> +/* { dg-final { scan-assembler-times "label for function bar_func" 1 } } */ >> + >> +/* { dg-final { scan-assembler-times "ascii \"0:2:1:1:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> +/* { dg-final { scan-assembler-times "ascii \"0:2:1:2.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> +/* { dg-final { scan-assembler-times "ascii \"foo_sec.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> +/* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> +/* { dg-final { scan-assembler-times "FuncInfo entry size" 1 } } */ >> + >> +/* { dg-final { scan-assembler-times ".4byte\t0x1\t# Number of entries" 3 } >> } */ >> +/* { dg-final { scan-assembler-times ".4byte\t0x2\t# Number of entries" 1 } >> } */ >> +/* { dg-final { scan-assembler-times "Required padding" 1 } } */ >> diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-5.c >> b/gcc/testsuite/gcc.target/bpf/core-attr-5.c >> index c0dc15fbb271..e71901d0d4d1 100644 >> --- a/gcc/testsuite/gcc.target/bpf/core-attr-5.c >> +++ b/gcc/testsuite/gcc.target/bpf/core-attr-5.c >> @@ -55,8 +55,13 @@ func (struct T *t, int i) >> /* { dg-final { scan-assembler-times "ascii \"0:4.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:1:1:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:1:1:1.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> -/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 2 } } */ >> +/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:1:3\"\\)" 1 } >> } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:4\"\\)" 1 } } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:3\"\\)" 2 } } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:2\"\\)" 1 } } >> */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:1:1\"\\)" 1 } >> } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:0\"\\)" 1 } } */ >> /* { dg-final { scan-assembler-times "bpfcr_type \\(struct T \\*\\)" 4 } } >> */ >> /* { dg-final { scan-assembler-times "bpfcr_type \\(struct U \\*\\)" 4 { >> xfail *-*-* } } } */ >> - >> diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-6.c >> b/gcc/testsuite/gcc.target/bpf/core-attr-6.c >> index 858ae627cb8b..34a4c367e528 100644 >> --- a/gcc/testsuite/gcc.target/bpf/core-attr-6.c >> +++ b/gcc/testsuite/gcc.target/bpf/core-attr-6.c >> @@ -37,10 +37,14 @@ func (struct T *t, int i) >> mset (&t->a); >> } >> >> -/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 2 } } */ >> +/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:1:1:1.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:1:2.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:1:1\"\\)" 1 } >> } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:3\"\\)" 2 } } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:2\"\\)" 1 } } >> */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:0\"\\)" 1 } } */ >> /* { dg-final { scan-assembler-times "bpfcr_type \\(struct T \\*\\)" 3 } } >> */ >> /* { dg-final { scan-assembler-times "bpfcr_type \\(struct U \\*\\)" 2 } } >> */ >> >> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c >> b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c >> index a4af9a53282a..27654205287d 100644 >> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c >> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c >> @@ -52,9 +52,18 @@ unsigned int foo (struct T *t) >> /* { dg-final { scan-assembler-times "ascii \"0:1:0:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:1:0:4.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:1:1:0.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> -/* { dg-final { scan-assembler-times "ascii \"0:1:1:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 2 } } */ >> +/* { dg-final { scan-assembler-times "ascii \"0:1:1:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:1:1:4.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> -/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 2 } } */ >> +/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> + >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:0:0\"\\)" 1 } >> } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:0:3\"\\)" 1 } >> } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:0:4\"\\)" 1 } >> } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:1:0\"\\)" 1 } >> } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:1:3\"\\)" 2 } >> } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:1:4\"\\)" 1 } >> } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:2\"\\)" 1 } } */ >> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:3\"\\)" 2 } } */ >> >> /* { dg-final { scan-assembler-times "0\[\t \]+\[^\n\]*bpfcr_kind" 10 } } */ >> diff --git a/gcc/testsuite/gcc.target/bpf/core-section-1.c >> b/gcc/testsuite/gcc.target/bpf/core-section-1.c >> index 4f16b087c1a2..c2bac46cee78 100644 >> --- a/gcc/testsuite/gcc.target/bpf/core-section-1.c >> +++ b/gcc/testsuite/gcc.target/bpf/core-section-1.c >> @@ -35,4 +35,4 @@ int bar_func (struct T *t) >> /* { dg-final { scan-assembler-times "ascii \"foo_sec.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t >> \]+\[^\n\]*btf_aux_string" 1 } } */ >> /* { dg-final { scan-assembler-times "bpfcr_type" 2 } } */ >> -/* { dg-final { scan-assembler-times "btfext_core_info_rec_size" 1 } } */ >> +/* { dg-final { scan-assembler-times "CoreInfo entry size" 1 } } */