Prior to this, we only collected ELF symbols which were in the percpu section. Now, collect all ELF symbols of type STT_OBJECT, and rely on the setting of "include" in the elf_secinfo to decide whether to include in the final output. Signed-off-by: Stephen Brennan <stephen.s.brennan@xxxxxxxxxx> --- btf_encoder.c | 70 +++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/btf_encoder.c b/btf_encoder.c index 83aca61..1804500 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -1123,7 +1123,7 @@ int btf_encoder__encode(struct btf_encoder *encoder) return err; } -static int percpu_var_cmp(const void *_a, const void *_b) +static int var_cmp(const void *_a, const void *_b) { const struct var_info *a = _a; const struct var_info *b = _b; @@ -1133,28 +1133,24 @@ static int percpu_var_cmp(const void *_a, const void *_b) return a->addr < b->addr ? -1 : 1; } -static bool btf_encoder__percpu_var_exists(struct btf_encoder *encoder, uint64_t addr, uint32_t *sz, const char **name) +static bool btf_encoder__var_exists(struct btf_encoder *encoder, uint64_t addr, struct var_info **info) { struct var_info key = { .addr = addr }; - const struct var_info *p = bsearch(&key, encoder->variables.vars, encoder->variables.var_cnt, - sizeof(encoder->variables.vars[0]), percpu_var_cmp); + struct var_info *p = bsearch(&key, encoder->variables.vars, encoder->variables.var_cnt, + sizeof(encoder->variables.vars[0]), var_cmp); if (!p) return false; - *sz = p->sz; - *name = p->name; + *info = p; return true; } -static int btf_encoder__collect_percpu_var(struct btf_encoder *encoder, GElf_Sym *sym, uint32_t sym_sec_idx) +static int btf_encoder__collect_var(struct btf_encoder *encoder, GElf_Sym *sym, uint32_t sym_sec_idx) { const char *sym_name; uint64_t addr; uint32_t size; - /* compare a symbol's shndx to determine if it's a percpu variable */ - if (sym_sec_idx != encoder->variables.percpu_shndx) - return 0; if (elf_sym__type(sym) != STT_OBJECT) return 0; @@ -1213,7 +1209,7 @@ static int btf_encoder__collect_symbols(struct btf_encoder *encoder, bool collec /* search within symtab for percpu variables */ elf_symtab__for_each_symbol_index(encoder->symtab, core_id, sym, sym_sec_idx) { - if (collect_percpu_vars && btf_encoder__collect_percpu_var(encoder, &sym, sym_sec_idx)) + if (collect_percpu_vars && btf_encoder__collect_var(encoder, &sym, sym_sec_idx)) return -1; if (btf_encoder__collect_function(encoder, &sym)) return -1; @@ -1221,7 +1217,7 @@ static int btf_encoder__collect_symbols(struct btf_encoder *encoder, bool collec if (collect_percpu_vars) { if (encoder->variables.var_cnt) - qsort(encoder->variables.vars, encoder->variables.var_cnt, sizeof(encoder->variables.vars[0]), percpu_var_cmp); + qsort(encoder->variables.vars, encoder->variables.var_cnt, sizeof(encoder->variables.vars[0]), var_cmp); if (encoder->verbose) printf("Found %d per-CPU variables!\n", encoder->variables.var_cnt); @@ -1263,17 +1259,19 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, struct cu__for_each_variable(cu, core_id, pos) { struct variable *var = tag__variable(pos); - uint32_t size, type, linkage; - const char *name, *dwarf_name; + uint32_t type, linkage; + const char *dwarf_name; struct llvm_annotation *annot; const struct tag *tag; + struct var_info *info; + struct elf_secinfo *sec = NULL; uint64_t addr; int id; if (var->declaration && !var->spec) continue; - /* percpu variables are allocated in global space */ + /* we want global variables, or those with a definition */ if (variable__scope(var) != VSCOPE_GLOBAL && !var->spec) continue; @@ -1281,13 +1279,16 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, struct addr = var->ip.addr; dwarf_name = variable__name(var); - /* Make sure addr is in the percpu section */ - if (addr < pcpu_scn->addr || addr >= pcpu_scn->addr + pcpu_scn->sz) - continue; - - if (!btf_encoder__percpu_var_exists(encoder, addr, &size, &name)) + if (!btf_encoder__var_exists(encoder, addr, &info)) continue; /* not a per-CPU variable */ + /* Get the ELF section info */ + if (info->shndx && info->shndx < encoder->seccnt) + sec = &encoder->secinfo[info->shndx]; + /* Only continue if the section is to be included */ + if (!sec || !sec->include) + continue; + /* A lot of "special" DWARF variables (e.g, __UNIQUE_ID___xxx) * have addr == 0, which is the same as, say, valid * fixed_percpu_data per-CPU variable. To distinguish between @@ -1306,7 +1307,7 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, struct * per-CPU symbols have non-zero values. */ if (var->ip.addr == 0) { - if (!dwarf_name || strcmp(dwarf_name, name)) + if (!dwarf_name || strcmp(dwarf_name, info->name)) continue; } @@ -1315,7 +1316,7 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, struct if (var->ip.tag.type == 0) { fprintf(stderr, "error: found variable '%s' in CU '%s' that has void type\n", - name, cu->name); + info->name, cu->name); if (encoder->force) continue; err = -1; @@ -1325,7 +1326,7 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, struct tag = cu__type(cu, var->ip.tag.type); if (tag__size(tag, cu) == 0) { if (encoder->verbose) - fprintf(stderr, "Ignoring zero-sized per-CPU variable '%s'...\n", dwarf_name ?: "<missing name>"); + fprintf(stderr, "Ignoring zero-sized variable '%s'...\n", dwarf_name ?: "<missing name>"); continue; } @@ -1334,14 +1335,14 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, struct if (encoder->verbose) { printf("Variable '%s' from CU '%s' at address 0x%" PRIx64 " encoded\n", - name, cu->name, addr); + info->name, cu->name, addr); } /* add a BTF_KIND_VAR in encoder->types */ - id = btf_encoder__add_var(encoder, type, name, linkage); + id = btf_encoder__add_var(encoder, type, info->name, linkage); if (id < 0) { fprintf(stderr, "error: failed to encode variable '%s' at addr 0x%" PRIx64 "\n", - name, addr); + info->name, addr); goto out; } @@ -1349,20 +1350,23 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, struct int tag_type_id = btf_encoder__add_decl_tag(encoder, annot->value, id, annot->component_idx); if (tag_type_id < 0) { fprintf(stderr, "error: failed to encode tag '%s' to variable '%s' with component_idx %d\n", - annot->value, name, annot->component_idx); + annot->value, info->name, annot->component_idx); goto out; } } /* - * add a BTF_VAR_SECINFO in encoder->percpu_secinfo, which will be added into + * For percpu variables, add a BTF_VAR_SECINFO in + * encoder->percpu_secinfo, which will be added into * encoder->types later when we add BTF_VAR_DATASEC. */ - id = btf_encoder__add_var_secinfo(encoder, id, addr - pcpu_scn->addr, size); - if (id < 0) { - fprintf(stderr, "error: failed to encode section info for variable '%s' at addr 0x%" PRIx64 "\n", - name, addr); - goto out; + if (info->shndx == encoder->variables.percpu_shndx) { + id = btf_encoder__add_var_secinfo(encoder, id, addr - pcpu_scn->addr, info->sz); + if (id < 0) { + fprintf(stderr, "error: failed to encode section info for variable '%s' at addr 0x%" PRIx64 "\n", + info->name, addr); + goto out; + } } } -- 2.34.1