ctf-reader: CTF debug info for some symbols is not found

Message ID 20220507015025.1416958-1-guillermo.e.martinez@oracle.com
State New
Headers
Series ctf-reader: CTF debug info for some symbols is not found |

Commit Message

Guillermo E. Martinez May 7, 2022, 1:50 a.m. UTC
  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
  

Patch

diff --git a/src/abg-ctf-reader.cc b/src/abg-ctf-reader.cc
index 5cb6fe19..3f8c3d03 100644
--- a/src/abg-ctf-reader.cc
+++ b/src/abg-ctf-reader.cc
@@ -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;
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index 787a05ff..a1fd4e6c 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -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, &section_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.
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index afaff24a..ee406863 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -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);