@@ -1172,7 +1172,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;
@@ -1182,28 +1182,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;
@@ -1262,7 +1258,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;
@@ -1270,7 +1266,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);
@@ -1313,17 +1309,19 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, uint32_
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;
@@ -1331,13 +1329,16 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, uint32_
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
@@ -1356,7 +1357,7 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, uint32_
* 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;
}
@@ -1365,7 +1366,7 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, uint32_
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;
@@ -1375,7 +1376,7 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, uint32_
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;
}
@@ -1384,14 +1385,14 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, uint32_
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;
}
@@ -1399,20 +1400,23 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder, uint32_
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;
+ }
}
}
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@oracle.com> --- btf_encoder.c | 70 +++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 33 deletions(-)