Hello libabigail team,
This patch fix missing symbols in the CTF reader backend. It depends of:
* https://sourceware.org/pipermail/libabigail/2022q2/004340.html
* https://sourceware.org/pipermail/libabigail/2022q2/004343.html
Please let me know your comments, I'll really appreciate them.
Kind regards,
Guillermo
Running `abidw --ctf' tool for some executable ELF files, seems that ctf
reader is unable to get debug information for some symbols so, they will
not be neither the corpus nor in abixml file. This is happening because
internally the reader uses `ctf_arc_bufopen' expecting as argument the
sections: symbol table (.dynsym) and string table (.dynstr) for ELF
types: ET_{EXEC,DYN}, currently those sections are read by `elf_helpers'
but it uses .symtab when it is present and `symtab_shdr->sh_link' to
get .strtab, instead.
* src/abg-ctf-reader.cc (read_context::is_elf_exec): Remove
data member.
(ctf_reader::process_ctf_qualified_type): Add condition to avoid
use qualifier in functions.
(ctf_reader::process_ctf_archive): Use `ctf_lookup_by_symbol_name'
to find debug information when `ctf_lookup_variable' was not
lucky iff `corpus::CTF_ORIGIN'.
(ctf_reader::slurp_elf_info): Use `elf_helpers::find_section_by_name'
to read .dynsym and .dynstr when {EXEC,DYN}.
* src/abg-elf-helpers.h (elf_helpers::find_section_by_name): Add new
declaration.
* src/abg-elf-helpers.cc (elf_helpers::find_section_by_name): Add new
definition.
Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
---
src/abg-ctf-reader.cc | 53 ++++++++++++++++++++++++++++--------------
src/abg-elf-helpers.cc | 29 +++++++++++++++++++++++
src/abg-elf-helpers.h | 3 +++
3 files changed, 67 insertions(+), 18 deletions(-)
base-commit: c96463e1ad974b7c4561886d7a3aa8a3c9a35607
prerequisite-patch-id: 781b026536589341e1e4378d9529fe258633bb53
prerequisite-patch-id: e6191c510bc90e225bd0858d333e2e01b6e52a62
@@ -70,8 +70,6 @@ public:
Elf *elf_handler;
int elf_fd;
- /// set when ELF is ET_EXEC
- bool is_elf_exec;
/// The symtab read from the ELF file.
symtab_reader::symtab_sptr symtab;
@@ -240,9 +238,13 @@ public:
/// Constructor.
///
- /// ctfa data member can be used per courpus group.
- ///
/// @param elf_path the path to the ELF file.
+ ///
+ /// @param environment the environment used by the current context.
+ /// This environment contains resources needed by the reader and by
+ /// the types and declarations that are to be created later. Note
+ /// that ABI artifacts that are to be compared all need to be
+ /// created within the same environment.
read_context(const string& elf_path, ir::environment *env) :
ctfa(NULL)
{
@@ -271,7 +273,6 @@ public:
ir_env = env;
elf_handler = NULL;
elf_fd = -1;
- is_elf_exec = false;
symtab.reset();
cur_corpus_group_.reset();
exported_decls_builder_ = 0;
@@ -895,8 +896,11 @@ process_ctf_qualified_type(read_context *ctxt,
else
ABG_ASSERT_NOT_REACHED;
- result.reset(new qualified_type_def(utype, qualifiers, location()));
+ // qualifiers are not be use in functions
+ if (is_function_type(utype))
+ return result;
+ result.reset(new qualified_type_def(utype, qualifiers, location()));
if (result)
{
decl_base_sptr qualified_type_decl = get_type_declaration(result);
@@ -1213,16 +1217,16 @@ process_ctf_archive(read_context *ctxt, corpus_sptr corp)
std::string sym_name = symbol->get_name();
ctf_id_t ctf_sym_type;
- if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN)
- || ctxt->is_elf_exec)
- ctf_sym_type= ctf_lookup_variable (ctf_dict, sym_name.c_str());
- else
+ ctf_sym_type = ctf_lookup_variable(ctf_dict, sym_name.c_str());
+ if (ctf_sym_type == (ctf_id_t) -1
+ && !(corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN))
+ // lookup in function objects
ctf_sym_type = ctf_lookup_by_symbol_name(ctf_dict, sym_name.c_str());
if (ctf_sym_type == (ctf_id_t) -1)
continue;
- if (ctf_type_kind (ctf_dict, ctf_sym_type) != CTF_K_FUNCTION)
+ if (ctf_type_kind(ctf_dict, ctf_sym_type) != CTF_K_FUNCTION)
{
const char *var_name = sym_name.c_str();
type_base_sptr var_type = lookup_type(ctxt, corp, ir_translation_unit,
@@ -1262,7 +1266,7 @@ process_ctf_archive(read_context *ctxt, corpus_sptr corp)
func_declaration->set_symbol(symbol);
add_decl_to_scope(func_declaration,
ir_translation_unit->get_global_scope());
- func_declaration->set_is_in_public_symbol_table(true);
+ func_declaration->set_is_in_public_symbol_table(true);
ctxt->maybe_add_fn_to_exported_decls(func_declaration.get());
}
}
@@ -1353,10 +1357,13 @@ fill_ctf_section(Elf_Scn *elf_section, ctf_sect_t *ctf_section)
static int
slurp_elf_info(read_context *ctxt, corpus_sptr corp)
{
- /* Set the ELF architecture. */
+ Elf_Scn *symtab_scn;
+ Elf_Scn *ctf_scn;
+ Elf_Scn *strtab_scn;
GElf_Ehdr eh_mem;
GElf_Ehdr *ehdr = gelf_getehdr(ctxt->elf_handler, &eh_mem);
- ctxt->is_elf_exec = (ehdr->e_type == ET_EXEC);
+
+ /* Set the ELF architecture. */
corp->set_architecture_name(elf_helpers::e_machine_to_string(ehdr->e_machine));
/* Read the symtab from the ELF file and set it in the corpus. */
@@ -1369,10 +1376,20 @@ slurp_elf_info(read_context *ctxt, corpus_sptr corp)
return 1;
/* Get the raw ELF section contents for libctf. */
- Elf_Scn *ctf_scn = elf_helpers::find_section(ctxt->elf_handler, ".ctf", SHT_PROGBITS);
- Elf_Scn *symtab_scn = elf_helpers::find_symbol_table_section(ctxt->elf_handler);
- Elf_Scn *strtab_scn = elf_helpers::find_strtab_for_symtab_section(ctxt->elf_handler,
- symtab_scn);
+ ctf_scn = elf_helpers::find_section(ctxt->elf_handler, ".ctf", SHT_PROGBITS);
+
+ // ET_{EXEC,DYN} needs .dyn{sym,str} in ctf_arc_bufopen
+ const char *symtab_name = ".dynsym";
+ const char *strtab_name = ".dynstr";
+
+ if (ehdr->e_type == ET_REL)
+ {
+ symtab_name = ".symtab";
+ strtab_name = ".strtab";
+ }
+
+ symtab_scn = elf_helpers::find_section_by_name(ctxt->elf_handler, symtab_name);
+ strtab_scn = elf_helpers::find_section_by_name(ctxt->elf_handler, strtab_name);
if (ctf_scn == NULL || symtab_scn == NULL || strtab_scn == NULL)
return 0;
@@ -296,6 +296,35 @@ e_machine_to_string(GElf_Half e_machine)
}
}
+/// Find and return a section by its name.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @return the section found, nor nil if none was found.
+Elf_Scn*
+find_section_by_name(Elf* elf_handle, const std::string& name)
+{
+ size_t section_header_string_index = 0;
+ if (elf_getshdrstrndx (elf_handle, §ion_header_string_index) < 0)
+ return 0;
+
+ Elf_Scn* section = 0;
+ GElf_Shdr header_mem, *header;
+ while ((section = elf_nextscn(elf_handle, section)) != 0)
+ {
+ header = gelf_getshdr(section, &header_mem);
+ if (header == NULL)
+ continue;
+
+ const char* section_name =
+ elf_strptr(elf_handle, section_header_string_index, header->sh_name);
+ if (section_name && name == section_name)
+ return section;
+ }
+
+ return 0;
+}
+
/// Find and return a section by its name and its type.
///
/// @param elf_handle the elf handle to use.
@@ -49,6 +49,9 @@ find_section(Elf* elf_handle,
const std::string& name,
Elf64_Word section_type);
+Elf_Scn*
+find_section_by_name(Elf* elf_handle, const std::string& name);
+
Elf_Scn*
find_section(Elf* elf_handle, Elf64_Word section_type);