We use the DWARF location information to match a variable with its associated ELF section. In the case of per-CPU variables their ELF section address range starts at 0, so any 0 address variables will appear to belong in that ELF section. However, for "discard" sections DWARF encodes the associated variables with address location 0 so we need to double-check that address 0 variables really are in the associated section by checking the ELF symbol table. This resolves an issue exposed by CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y kernel builds where __pcpu_* dummary variables in a .discard section get misclassified as belonging in the per-CPU variable section since they specify location address 0. Reported-by: Cong Wang <xiyou.wangcong@xxxxxxxxx> Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx> --- btf_encoder.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/btf_encoder.c b/btf_encoder.c index 3754884..04f547c 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -2189,6 +2189,26 @@ static bool filter_variable_name(const char *name) return false; } +bool variable_in_sec(struct btf_encoder *encoder, const char *name, size_t shndx) +{ + uint32_t sym_sec_idx; + uint32_t core_id; + GElf_Sym sym; + + elf_symtab__for_each_symbol_index(encoder->symtab, core_id, sym, sym_sec_idx) { + const char *sym_name; + + if (sym_sec_idx != shndx || elf_sym__type(&sym) != STT_OBJECT) + continue; + sym_name = elf_sym__name(&sym, encoder->symtab); + if (!sym_name) + continue; + if (strcmp(name, sym_name) == 0) + return true; + } + return false; +} + static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder) { struct cu *cu = encoder->cu; @@ -2258,6 +2278,13 @@ static int btf_encoder__encode_cu_variables(struct btf_encoder *encoder) if (filter_variable_name(name)) continue; + /* A 0 address may be in a "discard" section; DWARF provides + * location information with address 0 for such variables. + * Ensure the variable really is in this section by checking + * the ELF symtab. + */ + if (addr == 0 && !variable_in_sec(encoder, name, shndx)) + continue; /* Check for invalid BTF names */ if (!btf_name_valid(name)) { dump_invalid_symbol("Found invalid variable name when encoding btf", -- 2.31.1