diff mbox series

[2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader

Message ID 20200420110846.218792-3-maennich@google.com
State Superseded
Headers show
Series Refactor dwarf-reader: split out ELF helpers | expand

Commit Message

Matthias Maennich April 20, 2020, 11:08 a.m. UTC
Move some definitions from abg-dwarf-reader to abg-elf-helpers that are
strictly only related to ELF.

    * abg-dwarf-reader.cc(stt_to_elf_symbol_type): Move function out.
    (stb_to_elf_symbol_binding): Likewise.
    (stv_to_elf_symbol_visibility): Likewise.
    (e_machine_to_string): Likewise.
    (find_section): Likewise.
    (find_symbol_table_section): Likewise.
    (find_symbol_table_section_index): Likewise.
    (enum hash_table_kind): Likewise.
    (find_hash_table_section_index): Likewise.
    (get_symbol_versionning_sections): Likewise.
    (find_text_section): Likewise.
    (find_bss_section): Likewise.
    (find_rodata_section): Likewise.
    (find_data_section): Likewise.
    (find_data1_section): Likewise.
    * abg-elf-helpers.cc(stt_to_elf_symbol_type): Move function in.
    (stb_to_elf_symbol_binding): Likewise.
    (stv_to_elf_symbol_visibility): Likewise.
    (e_machine_to_string): Likewise.
    (find_section): Likewise.
    (find_symbol_table_section): Likewise.
    (find_symbol_table_section_index): Likewise.
    (enum hash_table_kind): Likewise.
    (find_hash_table_section_index): Likewise.
    (get_symbol_versionning_sections): Likewise.
    (find_text_section): Likewise.
    (find_bss_section): Likewise.
    (find_rodata_section): Likewise.
    (find_data_section): Likewise.
    (find_data1_section): Likewise.
    * abg-elf-helpers.cc(stt_to_elf_symbol_type): Add declaration.
    (stb_to_elf_symbol_binding): Likewise.
    (stv_to_elf_symbol_visibility): Likewise.
    (e_machine_to_string): Likewise.
    (find_section): Likewise.
    (find_symbol_table_section): Likewise.
    (find_symbol_table_section_index): Likewise.
    (enum hash_table_kind): Likewise.
    (find_hash_table_section_index): Likewise.
    (get_symbol_versionning_sections): Likewise.
    (find_text_section): Likewise.
    (find_bss_section): Likewise.
    (find_rodata_section): Likewise.
    (find_data_section): Likewise.
    (find_data1_section): Likewise.

Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 594 +---------------------------------------
 src/abg-elf-helpers.cc  | 471 +++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h   |  65 +++++
 3 files changed, 540 insertions(+), 590 deletions(-)

Comments

Giuliano Procida April 20, 2020, 3:34 p.m. UTC | #1
Looks good.

On Mon, 20 Apr 2020 at 12:09, Matthias Maennich <maennich@google.com> wrote:
>
> Move some definitions from abg-dwarf-reader to abg-elf-helpers that are
> strictly only related to ELF.
>
>     * abg-dwarf-reader.cc(stt_to_elf_symbol_type): Move function out.
>     (stb_to_elf_symbol_binding): Likewise.
>     (stv_to_elf_symbol_visibility): Likewise.
>     (e_machine_to_string): Likewise.
>     (find_section): Likewise.
>     (find_symbol_table_section): Likewise.
>     (find_symbol_table_section_index): Likewise.
>     (enum hash_table_kind): Likewise.
>     (find_hash_table_section_index): Likewise.
>     (get_symbol_versionning_sections): Likewise.
>     (find_text_section): Likewise.
>     (find_bss_section): Likewise.
>     (find_rodata_section): Likewise.
>     (find_data_section): Likewise.
>     (find_data1_section): Likewise.
>     * abg-elf-helpers.cc(stt_to_elf_symbol_type): Move function in.
>     (stb_to_elf_symbol_binding): Likewise.
>     (stv_to_elf_symbol_visibility): Likewise.
>     (e_machine_to_string): Likewise.
>     (find_section): Likewise.
>     (find_symbol_table_section): Likewise.
>     (find_symbol_table_section_index): Likewise.
>     (enum hash_table_kind): Likewise.
>     (find_hash_table_section_index): Likewise.
>     (get_symbol_versionning_sections): Likewise.
>     (find_text_section): Likewise.
>     (find_bss_section): Likewise.
>     (find_rodata_section): Likewise.
>     (find_data_section): Likewise.
>     (find_data1_section): Likewise.

Wrong file name.

>     * abg-elf-helpers.cc(stt_to_elf_symbol_type): Add declaration.
>     (stb_to_elf_symbol_binding): Likewise.
>     (stv_to_elf_symbol_visibility): Likewise.
>     (e_machine_to_string): Likewise.
>     (find_section): Likewise.
>     (find_symbol_table_section): Likewise.
>     (find_symbol_table_section_index): Likewise.
>     (enum hash_table_kind): Likewise.
>     (find_hash_table_section_index): Likewise.
>     (get_symbol_versionning_sections): Likewise.
>     (find_text_section): Likewise.
>     (find_bss_section): Likewise.
>     (find_rodata_section): Likewise.
>     (find_data_section): Likewise.
>     (find_data1_section): Likewise.

Reviewed-by: Giuliano Procida <gprocida@google.com>

> Signed-off-by: Matthias Maennich <maennich@google.com>
> ---
>  src/abg-dwarf-reader.cc | 594 +---------------------------------------
>  src/abg-elf-helpers.cc  | 471 +++++++++++++++++++++++++++++++
>  src/abg-elf-helpers.h   |  65 +++++
>  3 files changed, 540 insertions(+), 590 deletions(-)
>
> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
> index 1c0d6ea0353f..6ec7e4b6e968 100644
> --- a/src/abg-dwarf-reader.cc
> +++ b/src/abg-dwarf-reader.cc
> @@ -50,6 +50,8 @@
>  #include "abg-suppression-priv.h"
>  #include "abg-corpus-priv.h"
>
> +#include "abg-elf-helpers.h"
> +
>  #include "abg-internal.h"
>  // <headers defining libabigail's API go under here>
>  ABG_BEGIN_EXPORT_DECLARATIONS
> @@ -84,6 +86,8 @@ using std::stack;
>  using std::deque;
>  using std::list;
>
> +using namespace elf_helpers; // TODO: avoid using namespace
> +
>  /// Where a DIE comes from. For instance, a DIE can come from the main
>  /// debug info section, the alternate debug info section or from the
>  /// type unit section.
> @@ -290,9 +294,6 @@ static void
>  add_symbol_to_map(const elf_symbol_sptr& sym,
>                   string_elf_symbols_map_type& map);
>
> -static bool
> -find_symbol_table_section(Elf* elf_handle, Elf_Scn*& section);
> -
>  static bool
>  get_symbol_versionning_sections(Elf*           elf_handle,
>                                 Elf_Scn*&       versym_section,
> @@ -546,548 +547,6 @@ compare_dies(const read_context& ctxt,
>              const Dwarf_Die *l, const Dwarf_Die *r,
>              bool update_canonical_dies_on_the_fly);
>
> -/// Convert an elf symbol type (given by the ELF{32,64}_ST_TYPE
> -/// macros) into an elf_symbol::type value.
> -///
> -/// Note that this function aborts when given an unexpected value.
> -///
> -/// @param the symbol type value to convert.
> -///
> -/// @return the converted value.
> -static elf_symbol::type
> -stt_to_elf_symbol_type(unsigned char stt)
> -{
> -  elf_symbol::type t = elf_symbol::NOTYPE_TYPE;
> -
> -  switch (stt)
> -    {
> -    case STT_NOTYPE:
> -      t = elf_symbol::NOTYPE_TYPE;
> -      break;
> -    case STT_OBJECT:
> -      t = elf_symbol::OBJECT_TYPE;
> -      break;
> -    case STT_FUNC:
> -      t = elf_symbol::FUNC_TYPE;
> -      break;
> -    case STT_SECTION:
> -      t = elf_symbol::SECTION_TYPE;
> -      break;
> -    case STT_FILE:
> -      t = elf_symbol::FILE_TYPE;
> -      break;
> -    case STT_COMMON:
> -      t = elf_symbol::COMMON_TYPE;
> -      break;
> -    case STT_TLS:
> -      t = elf_symbol::TLS_TYPE;
> -      break;
> -    case STT_GNU_IFUNC:
> -      t = elf_symbol::GNU_IFUNC_TYPE;
> -      break;
> -    default:
> -      // An unknown value that probably ought to be supported?  Let's
> -      // abort right here rather than yielding garbage.
> -      ABG_ASSERT_NOT_REACHED;
> -    }
> -
> -  return t;
> -}
> -
> -/// Convert an elf symbol binding (given by the ELF{32,64}_ST_BIND
> -/// macros) into an elf_symbol::binding value.
> -///
> -/// Note that this function aborts when given an unexpected value.
> -///
> -/// @param the symbol binding value to convert.
> -///
> -/// @return the converted value.
> -static elf_symbol::binding
> -stb_to_elf_symbol_binding(unsigned char stb)
> -{
> -  elf_symbol::binding b = elf_symbol::GLOBAL_BINDING;
> -
> -  switch (stb)
> -    {
> -    case STB_LOCAL:
> -      b = elf_symbol::LOCAL_BINDING;
> -      break;
> -    case STB_GLOBAL:
> -      b = elf_symbol::GLOBAL_BINDING;
> -      break;
> -    case STB_WEAK:
> -      b = elf_symbol::WEAK_BINDING;
> -      break;
> -    case STB_GNU_UNIQUE:
> -      b = elf_symbol::GNU_UNIQUE_BINDING;
> -      break;
> -    default:
> -      ABG_ASSERT_NOT_REACHED;
> -    }
> -
> -  return b;
> -
> -}
> -
> -/// Convert an ELF symbol visiblity given by the symbols ->st_other
> -/// data member as returned by the GELF_ST_VISIBILITY macro into a
> -/// elf_symbol::visiblity value.
> -///
> -/// @param stv the value of the ->st_other data member of the ELF
> -/// symbol.
> -///
> -/// @return the converted elf_symbol::visiblity value.
> -static elf_symbol::visibility
> -stv_to_elf_symbol_visibility(unsigned char stv)
> -{
> -
> -  elf_symbol::visibility v = elf_symbol::DEFAULT_VISIBILITY;
> -
> -  switch (stv)
> -    {
> -    case STV_DEFAULT:
> -      v = elf_symbol::DEFAULT_VISIBILITY;
> -      break;
> -    case STV_INTERNAL:
> -      v = elf_symbol::INTERNAL_VISIBILITY;
> -      break;
> -    case STV_HIDDEN:
> -      v = elf_symbol::HIDDEN_VISIBILITY;
> -      break;
> -    case STV_PROTECTED:
> -      v = elf_symbol::PROTECTED_VISIBILITY;
> -      break;
> -    default:
> -      ABG_ASSERT_NOT_REACHED;
> -    }
> -
> -  return v;
> -}
> -
> -/// Convert the value of the e_machine field of GElf_Ehdr into a
> -/// string.  This is to get a string representing the architecture of
> -/// the elf file at hand.
> -///
> -/// @param e_machine the value of GElf_Ehdr::e_machine.
> -///
> -/// @return the string representation of GElf_Ehdr::e_machine.
> -static string
> -e_machine_to_string(GElf_Half e_machine)
> -{
> -  string result;
> -  switch (e_machine)
> -    {
> -    case EM_NONE:
> -      result = "elf-no-arch";
> -      break;
> -    case EM_M32:
> -      result = "elf-att-we-32100";
> -      break;
> -    case EM_SPARC:
> -      result = "elf-sun-sparc";
> -      break;
> -    case EM_386:
> -      result = "elf-intel-80386";
> -      break;
> -    case EM_68K:
> -      result = "elf-motorola-68k";
> -      break;
> -    case EM_88K:
> -      result = "elf-motorola-88k";
> -      break;
> -    case EM_860:
> -      result = "elf-intel-80860";
> -      break;
> -    case EM_MIPS:
> -      result = "elf-mips-r3000-be";
> -      break;
> -    case EM_S370:
> -      result = "elf-ibm-s370";
> -      break;
> -    case EM_MIPS_RS3_LE:
> -      result = "elf-mips-r3000-le";
> -      break;
> -    case EM_PARISC:
> -      result = "elf-hp-parisc";
> -      break;
> -    case EM_VPP500:
> -      result = "elf-fujitsu-vpp500";
> -      break;
> -    case EM_SPARC32PLUS:
> -      result = "elf-sun-sparc-v8plus";
> -      break;
> -    case EM_960:
> -      result = "elf-intel-80960";
> -      break;
> -    case EM_PPC:
> -      result = "elf-powerpc";
> -      break;
> -    case EM_PPC64:
> -      result = "elf-powerpc-64";
> -      break;
> -    case EM_S390:
> -      result = "elf-ibm-s390";
> -      break;
> -    case EM_V800:
> -      result = "elf-nec-v800";
> -      break;
> -    case EM_FR20:
> -      result = "elf-fujitsu-fr20";
> -      break;
> -    case EM_RH32:
> -      result = "elf-trw-rh32";
> -      break;
> -    case EM_RCE:
> -      result = "elf-motorola-rce";
> -      break;
> -    case EM_ARM:
> -      result = "elf-arm";
> -      break;
> -    case EM_FAKE_ALPHA:
> -      result = "elf-digital-alpha";
> -      break;
> -    case EM_SH:
> -      result = "elf-hitachi-sh";
> -      break;
> -    case EM_SPARCV9:
> -      result = "elf-sun-sparc-v9-64";
> -      break;
> -    case EM_TRICORE:
> -      result = "elf-siemens-tricore";
> -      break;
> -    case EM_ARC:
> -      result = "elf-argonaut-risc-core";
> -      break;
> -    case EM_H8_300:
> -      result = "elf-hitachi-h8-300";
> -      break;
> -    case EM_H8_300H:
> -      result = "elf-hitachi-h8-300h";
> -      break;
> -    case EM_H8S:
> -      result = "elf-hitachi-h8s";
> -      break;
> -    case EM_H8_500:
> -      result = "elf-hitachi-h8-500";
> -      break;
> -    case EM_IA_64:
> -      result = "elf-intel-ia-64";
> -      break;
> -    case EM_MIPS_X:
> -      result = "elf-stanford-mips-x";
> -      break;
> -    case EM_COLDFIRE:
> -      result = "elf-motorola-coldfire";
> -      break;
> -    case EM_68HC12:
> -      result = "elf-motorola-68hc12";
> -      break;
> -    case EM_MMA:
> -      result = "elf-fujitsu-mma";
> -      break;
> -    case EM_PCP:
> -      result = "elf-siemens-pcp";
> -      break;
> -    case EM_NCPU:
> -      result = "elf-sony-ncpu";
> -      break;
> -    case EM_NDR1:
> -      result = "elf-denso-ndr1";
> -      break;
> -    case EM_STARCORE:
> -      result = "elf-motorola-starcore";
> -      break;
> -    case EM_ME16:
> -      result = "elf-toyota-me16";
> -      break;
> -    case EM_ST100:
> -      result = "elf-stm-st100";
> -      break;
> -    case EM_TINYJ:
> -      result = "elf-alc-tinyj";
> -      break;
> -    case EM_X86_64:
> -      result = "elf-amd-x86_64";
> -      break;
> -    case EM_PDSP:
> -      result = "elf-sony-pdsp";
> -      break;
> -    case EM_FX66:
> -      result = "elf-siemens-fx66";
> -      break;
> -    case EM_ST9PLUS:
> -      result = "elf-stm-st9+";
> -      break;
> -    case EM_ST7:
> -      result = "elf-stm-st7";
> -      break;
> -    case EM_68HC16:
> -      result = "elf-motorola-68hc16";
> -      break;
> -    case EM_68HC11:
> -      result = "elf-motorola-68hc11";
> -      break;
> -    case EM_68HC08:
> -      result = "elf-motorola-68hc08";
> -      break;
> -    case EM_68HC05:
> -      result = "elf-motorola-68hc05";
> -      break;
> -    case EM_SVX:
> -      result = "elf-sg-svx";
> -      break;
> -    case EM_ST19:
> -      result = "elf-stm-st19";
> -      break;
> -    case EM_VAX:
> -      result = "elf-digital-vax";
> -      break;
> -    case EM_CRIS:
> -      result = "elf-axis-cris";
> -      break;
> -    case EM_JAVELIN:
> -      result = "elf-infineon-javelin";
> -      break;
> -    case EM_FIREPATH:
> -      result = "elf-firepath";
> -      break;
> -    case EM_ZSP:
> -      result = "elf-lsi-zsp";
> -      break;
> -    case EM_MMIX:
> -      result = "elf-don-knuth-mmix";
> -      break;
> -    case EM_HUANY:
> -      result = "elf-harvard-huany";
> -      break;
> -    case EM_PRISM:
> -      result = "elf-sitera-prism";
> -      break;
> -    case EM_AVR:
> -      result = "elf-atmel-avr";
> -      break;
> -    case EM_FR30:
> -      result = "elf-fujistu-fr30";
> -      break;
> -    case EM_D10V:
> -      result = "elf-mitsubishi-d10v";
> -      break;
> -    case EM_D30V:
> -      result = "elf-mitsubishi-d30v";
> -      break;
> -    case EM_V850:
> -      result = "elf-nec-v850";
> -      break;
> -    case EM_M32R:
> -      result = "elf-mitsubishi-m32r";
> -      break;
> -    case EM_MN10300:
> -      result = "elf-matsushita-mn10300";
> -      break;
> -    case EM_MN10200:
> -      result = "elf-matsushita-mn10200";
> -      break;
> -    case EM_PJ:
> -      result = "elf-picojava";
> -      break;
> -    case EM_OPENRISC:
> -      result = "elf-openrisc-32";
> -      break;
> -    case EM_ARC_A5:
> -      result = "elf-arc-a5";
> -      break;
> -    case EM_XTENSA:
> -      result = "elf-tensilica-xtensa";
> -      break;
> -
> -#ifdef HAVE_EM_AARCH64_MACRO
> -    case EM_AARCH64:
> -      result = "elf-arm-aarch64";
> -      break;
> -#endif
> -
> -#ifdef HAVE_EM_TILEPRO_MACRO
> -    case EM_TILEPRO:
> -      result = "elf-tilera-tilepro";
> -      break;
> -#endif
> -
> -#ifdef HAVE_EM_TILEGX_MACRO
> -    case EM_TILEGX:
> -      result = "elf-tilera-tilegx";
> -      break;
> -#endif
> -
> -    case EM_NUM:
> -      result = "elf-last-arch-number";
> -      break;
> -    case EM_ALPHA:
> -      result = "elf-non-official-alpha";
> -      break;
> -    default:
> -      {
> -       std::ostringstream o;
> -       o << "elf-unknown-arch-value-" << e_machine;
> -       result = o.str();
> -      }
> -      break;
> -    }
> -  return result;
> -}
> -
> -/// The kind of ELF hash table found by the function
> -/// find_hash_table_section_index.
> -enum hash_table_kind
> -{
> -  NO_HASH_TABLE_KIND = 0,
> -  SYSV_HASH_TABLE_KIND,
> -  GNU_HASH_TABLE_KIND
> -};
> -
> -/// Get the offset offset of the hash table section.
> -///
> -/// @param elf_handle the elf handle to use.
> -///
> -/// @param ht_section_offset this is set to the resulting offset
> -/// of the hash table section.  This is set iff the function returns true.
> -///
> -/// @param symtab_section_offset the offset of the section of the
> -/// symbol table the hash table refers to.
> -static hash_table_kind
> -find_hash_table_section_index(Elf*     elf_handle,
> -                             size_t&   ht_section_index,
> -                             size_t&   symtab_section_index)
> -{
> -  if (!elf_handle)
> -    return NO_HASH_TABLE_KIND;
> -
> -  GElf_Shdr header_mem, *section_header;
> -  bool found_sysv_ht = false, found_gnu_ht = false;
> -  for (Elf_Scn* section = elf_nextscn(elf_handle, 0);
> -       section != 0;
> -       section = elf_nextscn(elf_handle, section))
> -    {
> -      section_header= gelf_getshdr(section, &header_mem);
> -      if (section_header->sh_type != SHT_HASH
> -         && section_header->sh_type != SHT_GNU_HASH)
> -       continue;
> -
> -      ht_section_index = elf_ndxscn(section);
> -      symtab_section_index = section_header->sh_link;
> -
> -      if (section_header->sh_type == SHT_HASH)
> -       found_sysv_ht = true;
> -      else if (section_header->sh_type == SHT_GNU_HASH)
> -       found_gnu_ht = true;
> -    }
> -
> -  if (found_gnu_ht)
> -    return GNU_HASH_TABLE_KIND;
> -  else if (found_sysv_ht)
> -    return SYSV_HASH_TABLE_KIND;
> -  else
> -    return NO_HASH_TABLE_KIND;
> -}
> -
> -/// Find the symbol table.
> -///
> -/// If we are looking at a relocatable or executable file, this
> -/// function will return the .symtab symbol table (of type
> -/// SHT_SYMTAB).  But if we are looking at a DSO it returns the
> -/// .dynsym symbol table (of type SHT_DYNSYM).
> -///
> -/// @param elf_handle the elf handle to consider.
> -///
> -/// @param symtab the symbol table found.
> -///
> -/// @return true iff the symbol table is found.
> -static bool
> -find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
> -{
> -  Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0;
> -  while ((section = elf_nextscn(elf_handle, section)) != 0)
> -    {
> -      GElf_Shdr header_mem, *header;
> -      header = gelf_getshdr(section, &header_mem);
> -      if (header->sh_type == SHT_DYNSYM)
> -       dynsym = section;
> -      else if (header->sh_type == SHT_SYMTAB)
> -       sym_tab = section;
> -    }
> -
> -  if (dynsym || sym_tab)
> -    {
> -      GElf_Ehdr eh_mem;
> -      GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
> -      if (elf_header->e_type == ET_REL
> -         || elf_header->e_type == ET_EXEC)
> -       symtab = sym_tab ? sym_tab : dynsym;
> -      else
> -       symtab = dynsym ? dynsym : sym_tab;
> -      return true;
> -    }
> -  return false;
> -}
> -
> -/// Find the index (in the section headers table) of the symbol table
> -/// section.
> -///
> -/// If we are looking at a relocatable or executable file, this
> -/// function will return the index for the .symtab symbol table (of
> -/// type SHT_SYMTAB).  But if we are looking at a DSO it returns the
> -/// index for the .dynsym symbol table (of type SHT_DYNSYM).
> -///
> -/// @param elf_handle the elf handle to use.
> -///
> -/// @param symtab_index the index of the symbol_table, that was found.
> -///
> -/// @return true iff the symbol table section index was found.
> -static bool
> -find_symbol_table_section_index(Elf* elf_handle,
> -                               size_t& symtab_index)
> -{
> -  Elf_Scn* section = 0;
> -  if (!find_symbol_table_section(elf_handle, section))
> -    return false;
> -
> -  symtab_index = elf_ndxscn(section);
> -  return true;
> -}
> -
> -/// Find and return a section by its name and its type.
> -///
> -/// @param elf_handle the elf handle to use.
> -///
> -/// @param name the name of the section.
> -///
> -/// @param section_type the type of the section.  This is the
> -/// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member.
> -/// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS.
> -///
> -/// @return the section found, nor nil if none was found.
> -static Elf_Scn*
> -find_section(Elf* elf_handle, const string& name, Elf64_Word section_type)
> -{
> -  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 || header->sh_type != section_type)
> -      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;
> -}
>
>  /// Test if the ELF binary denoted by a given ELF handle is a Linux
>  /// Kernel Module.
> @@ -1121,51 +580,6 @@ binary_is_linux_kernel(Elf *elf_handle)
>           || binary_is_linux_kernel_module(elf_handle));
>  }
>
> -/// Find and return the .text section.
> -///
> -/// @param elf_handle the elf handle to use.
> -///
> -/// @return the .text section found.
> -static Elf_Scn*
> -find_text_section(Elf* elf_handle)
> -{return find_section(elf_handle, ".text", SHT_PROGBITS);}
> -
> -/// Find and return the .bss section.
> -///
> -/// @param elf_handle.
> -///
> -/// @return the .bss section found.
> -static Elf_Scn*
> -find_bss_section(Elf* elf_handle)
> -{return find_section(elf_handle, ".bss", SHT_NOBITS);}
> -
> -/// Find and return the .rodata section.
> -///
> -/// @param elf_handle.
> -///
> -/// @return the .rodata section found.
> -static Elf_Scn*
> -find_rodata_section(Elf* elf_handle)
> -{return find_section(elf_handle, ".rodata", SHT_PROGBITS);}
> -
> -/// Find and return the .data section.
> -///
> -/// @param elf_handle the elf handle to use.
> -///
> -/// @return the .data section found.
> -static Elf_Scn*
> -find_data_section(Elf* elf_handle)
> -{return find_section(elf_handle, ".data", SHT_PROGBITS);}
> -
> -/// Find and return the .data1 section.
> -///
> -/// @param elf_handle the elf handle to use.
> -///
> -/// @return the .data1 section found.
> -static Elf_Scn*
> -find_data1_section(Elf* elf_handle)
> -{return find_section(elf_handle, ".data1", SHT_PROGBITS);}
> -
>  /// Find the __ksymtab_strings section of a Linux kernel binary.
>  ///
>  ///
> diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
> index e99fe4a5c306..b0113a4efd2c 100644
> --- a/src/abg-elf-helpers.cc
> +++ b/src/abg-elf-helpers.cc
> @@ -24,11 +24,482 @@
>
>  #include "abg-elf-helpers.h"
>
> +#include <elf.h>
> +
> +#include "abg-tools-utils.h"
> +
>  namespace abigail
>  {
>
>  namespace elf_helpers
>  {
>
> +/// Convert an elf symbol type (given by the ELF{32,64}_ST_TYPE
> +/// macros) into an elf_symbol::type value.
> +///
> +/// Note that this function aborts when given an unexpected value.
> +///
> +/// @param the symbol type value to convert.
> +///
> +/// @return the converted value.
> +elf_symbol::type
> +stt_to_elf_symbol_type(unsigned char stt)
> +{
> +  switch (stt)
> +    {
> +    case STT_NOTYPE:
> +      return elf_symbol::NOTYPE_TYPE;
> +    case STT_OBJECT:
> +      return elf_symbol::OBJECT_TYPE;
> +    case STT_FUNC:
> +      return elf_symbol::FUNC_TYPE;
> +    case STT_SECTION:
> +      return elf_symbol::SECTION_TYPE;
> +    case STT_FILE:
> +      return elf_symbol::FILE_TYPE;
> +    case STT_COMMON:
> +      return elf_symbol::COMMON_TYPE;
> +    case STT_TLS:
> +      return elf_symbol::TLS_TYPE;
> +    case STT_GNU_IFUNC:
> +      return elf_symbol::GNU_IFUNC_TYPE;
> +    default:
> +      // An unknown value that probably ought to be supported?  Let's
> +      // abort right here rather than yielding garbage.
> +      ABG_ASSERT_NOT_REACHED;
> +    }
> +}
> +
> +/// Convert an elf symbol binding (given by the ELF{32,64}_ST_BIND
> +/// macros) into an elf_symbol::binding value.
> +///
> +/// Note that this function aborts when given an unexpected value.
> +///
> +/// @param the symbol binding value to convert.
> +///
> +/// @return the converted value.
> +elf_symbol::binding
> +stb_to_elf_symbol_binding(unsigned char stb)
> +{
> +  switch (stb)
> +    {
> +    case STB_LOCAL:
> +      return elf_symbol::LOCAL_BINDING;
> +    case STB_GLOBAL:
> +      return elf_symbol::GLOBAL_BINDING;
> +    case STB_WEAK:
> +      return elf_symbol::WEAK_BINDING;
> +    case STB_GNU_UNIQUE:
> +      return elf_symbol::GNU_UNIQUE_BINDING;
> +    default:
> +      ABG_ASSERT_NOT_REACHED;
> +    }
> +}
> +
> +/// Convert an ELF symbol visiblity given by the symbols ->st_other
> +/// data member as returned by the GELF_ST_VISIBILITY macro into a
> +/// elf_symbol::visiblity value.
> +///
> +/// @param stv the value of the ->st_other data member of the ELF
> +/// symbol.
> +///
> +/// @return the converted elf_symbol::visiblity value.
> +elf_symbol::visibility
> +stv_to_elf_symbol_visibility(unsigned char stv)
> +{
> +  switch (stv)
> +    {
> +    case STV_DEFAULT:
> +      return elf_symbol::DEFAULT_VISIBILITY;
> +    case STV_INTERNAL:
> +      return elf_symbol::INTERNAL_VISIBILITY;
> +    case STV_HIDDEN:
> +      return elf_symbol::HIDDEN_VISIBILITY;
> +    case STV_PROTECTED:
> +      return elf_symbol::PROTECTED_VISIBILITY;
> +    default:
> +      ABG_ASSERT_NOT_REACHED;
> +    }
> +}
> +
> +/// Convert the value of the e_machine field of GElf_Ehdr into a
> +/// string.  This is to get a string representing the architecture of
> +/// the elf file at hand.
> +///
> +/// @param e_machine the value of GElf_Ehdr::e_machine.
> +///
> +/// @return the string representation of GElf_Ehdr::e_machine.
> +std::string
> +e_machine_to_string(GElf_Half e_machine)
> +{
> +  switch (e_machine)
> +    {
> +    case EM_NONE:
> +      return "elf-no-arch";
> +    case EM_M32:
> +      return "elf-att-we-32100";
> +    case EM_SPARC:
> +      return "elf-sun-sparc";
> +    case EM_386:
> +      return "elf-intel-80386";
> +    case EM_68K:
> +      return "elf-motorola-68k";
> +    case EM_88K:
> +      return "elf-motorola-88k";
> +    case EM_860:
> +      return "elf-intel-80860";
> +    case EM_MIPS:
> +      return "elf-mips-r3000-be";
> +    case EM_S370:
> +      return "elf-ibm-s370";
> +    case EM_MIPS_RS3_LE:
> +      return "elf-mips-r3000-le";
> +    case EM_PARISC:
> +      return "elf-hp-parisc";
> +    case EM_VPP500:
> +      return "elf-fujitsu-vpp500";
> +    case EM_SPARC32PLUS:
> +      return "elf-sun-sparc-v8plus";
> +    case EM_960:
> +      return "elf-intel-80960";
> +    case EM_PPC:
> +      return "elf-powerpc";
> +    case EM_PPC64:
> +      return "elf-powerpc-64";
> +    case EM_S390:
> +      return "elf-ibm-s390";
> +    case EM_V800:
> +      return "elf-nec-v800";
> +    case EM_FR20:
> +      return "elf-fujitsu-fr20";
> +    case EM_RH32:
> +      return "elf-trw-rh32";
> +    case EM_RCE:
> +      return "elf-motorola-rce";
> +    case EM_ARM:
> +      return "elf-arm";
> +    case EM_FAKE_ALPHA:
> +      return "elf-digital-alpha";
> +    case EM_SH:
> +      return "elf-hitachi-sh";
> +    case EM_SPARCV9:
> +      return "elf-sun-sparc-v9-64";
> +    case EM_TRICORE:
> +      return "elf-siemens-tricore";
> +    case EM_ARC:
> +      return "elf-argonaut-risc-core";
> +    case EM_H8_300:
> +      return "elf-hitachi-h8-300";
> +    case EM_H8_300H:
> +      return "elf-hitachi-h8-300h";
> +    case EM_H8S:
> +      return "elf-hitachi-h8s";
> +    case EM_H8_500:
> +      return "elf-hitachi-h8-500";
> +    case EM_IA_64:
> +      return "elf-intel-ia-64";
> +    case EM_MIPS_X:
> +      return "elf-stanford-mips-x";
> +    case EM_COLDFIRE:
> +      return "elf-motorola-coldfire";
> +    case EM_68HC12:
> +      return "elf-motorola-68hc12";
> +    case EM_MMA:
> +      return "elf-fujitsu-mma";
> +    case EM_PCP:
> +      return "elf-siemens-pcp";
> +    case EM_NCPU:
> +      return "elf-sony-ncpu";
> +    case EM_NDR1:
> +      return "elf-denso-ndr1";
> +    case EM_STARCORE:
> +      return "elf-motorola-starcore";
> +    case EM_ME16:
> +      return "elf-toyota-me16";
> +    case EM_ST100:
> +      return "elf-stm-st100";
> +    case EM_TINYJ:
> +      return "elf-alc-tinyj";
> +    case EM_X86_64:
> +      return "elf-amd-x86_64";
> +    case EM_PDSP:
> +      return "elf-sony-pdsp";
> +    case EM_FX66:
> +      return "elf-siemens-fx66";
> +    case EM_ST9PLUS:
> +      return "elf-stm-st9+";
> +    case EM_ST7:
> +      return "elf-stm-st7";
> +    case EM_68HC16:
> +      return "elf-motorola-68hc16";
> +    case EM_68HC11:
> +      return "elf-motorola-68hc11";
> +    case EM_68HC08:
> +      return "elf-motorola-68hc08";
> +    case EM_68HC05:
> +      return "elf-motorola-68hc05";
> +    case EM_SVX:
> +      return "elf-sg-svx";
> +    case EM_ST19:
> +      return "elf-stm-st19";
> +    case EM_VAX:
> +      return "elf-digital-vax";
> +    case EM_CRIS:
> +      return "elf-axis-cris";
> +    case EM_JAVELIN:
> +      return "elf-infineon-javelin";
> +    case EM_FIREPATH:
> +      return "elf-firepath";
> +    case EM_ZSP:
> +      return "elf-lsi-zsp";
> +    case EM_MMIX:
> +      return "elf-don-knuth-mmix";
> +    case EM_HUANY:
> +      return "elf-harvard-huany";
> +    case EM_PRISM:
> +      return "elf-sitera-prism";
> +    case EM_AVR:
> +      return "elf-atmel-avr";
> +    case EM_FR30:
> +      return "elf-fujistu-fr30";
> +    case EM_D10V:
> +      return "elf-mitsubishi-d10v";
> +    case EM_D30V:
> +      return "elf-mitsubishi-d30v";
> +    case EM_V850:
> +      return "elf-nec-v850";
> +    case EM_M32R:
> +      return "elf-mitsubishi-m32r";
> +    case EM_MN10300:
> +      return "elf-matsushita-mn10300";
> +    case EM_MN10200:
> +      return "elf-matsushita-mn10200";
> +    case EM_PJ:
> +      return "elf-picojava";
> +    case EM_OPENRISC:
> +      return "elf-openrisc-32";
> +    case EM_ARC_A5:
> +      return "elf-arc-a5";
> +    case EM_XTENSA:
> +      return "elf-tensilica-xtensa";
> +
> +#ifdef HAVE_EM_AARCH64_MACRO
> +    case EM_AARCH64:
> +      return "elf-arm-aarch64";
> +#endif
> +
> +#ifdef HAVE_EM_TILEPRO_MACRO
> +    case EM_TILEPRO:
> +      return "elf-tilera-tilepro";
> +#endif
> +
> +#ifdef HAVE_EM_TILEGX_MACRO
> +    case EM_TILEGX:
> +      return "elf-tilera-tilegx";
> +#endif
> +
> +    case EM_NUM:
> +      return "elf-last-arch-number";
> +    case EM_ALPHA:
> +      return "elf-non-official-alpha";
> +    default:
> +      {
> +       std::ostringstream o;
> +       o << "elf-unknown-arch-value-" << e_machine;
> +       return o.str();
> +      }
> +    }
> +}
> +
> +/// Find and return a section by its name and its type.
> +///
> +/// @param elf_handle the elf handle to use.
> +///
> +/// @param name the name of the section.
> +///
> +/// @param section_type the type of the section.  This is the
> +/// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member.
> +/// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS.
> +///
> +/// @return the section found, nor nil if none was found.
> +Elf_Scn*
> +find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
> +{
> +  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 || header->sh_type != section_type)
> +      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 the symbol table.
> +///
> +/// If we are looking at a relocatable or executable file, this
> +/// function will return the .symtab symbol table (of type
> +/// SHT_SYMTAB).  But if we are looking at a DSO it returns the
> +/// .dynsym symbol table (of type SHT_DYNSYM).
> +///
> +/// @param elf_handle the elf handle to consider.
> +///
> +/// @param symtab the symbol table found.
> +///
> +/// @return true iff the symbol table is found.
> +bool
> +find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
> +{
> +  Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0;
> +  while ((section = elf_nextscn(elf_handle, section)) != 0)
> +    {
> +      GElf_Shdr header_mem, *header;
> +      header = gelf_getshdr(section, &header_mem);
> +      if (header->sh_type == SHT_DYNSYM)
> +       dynsym = section;
> +      else if (header->sh_type == SHT_SYMTAB)
> +       sym_tab = section;
> +    }
> +
> +  if (dynsym || sym_tab)
> +    {
> +      GElf_Ehdr eh_mem;
> +      GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
> +      if (elf_header->e_type == ET_REL
> +         || elf_header->e_type == ET_EXEC)
> +       symtab = sym_tab ? sym_tab : dynsym;
> +      else
> +       symtab = dynsym ? dynsym : sym_tab;
> +      return true;
> +    }
> +  return false;
> +}
> +
> +/// Find the index (in the section headers table) of the symbol table
> +/// section.
> +///
> +/// If we are looking at a relocatable or executable file, this
> +/// function will return the index for the .symtab symbol table (of
> +/// type SHT_SYMTAB).  But if we are looking at a DSO it returns the
> +/// index for the .dynsym symbol table (of type SHT_DYNSYM).
> +///
> +/// @param elf_handle the elf handle to use.
> +///
> +/// @param symtab_index the index of the symbol_table, that was found.
> +///
> +/// @return true iff the symbol table section index was found.
> +bool
> +find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index)
> +{
> +  Elf_Scn* section = 0;
> +  if (!find_symbol_table_section(elf_handle, section))
> +    return false;
> +
> +  symtab_index = elf_ndxscn(section);
> +  return true;
> +}
> +
> +/// Get the offset offset of the hash table section.
> +///
> +/// @param elf_handle the elf handle to use.
> +///
> +/// @param ht_section_offset this is set to the resulting offset
> +/// of the hash table section.  This is set iff the function returns true.
> +///
> +/// @param symtab_section_offset the offset of the section of the
> +/// symbol table the hash table refers to.
> +hash_table_kind
> +find_hash_table_section_index(Elf*     elf_handle,
> +                             size_t&   ht_section_index,
> +                             size_t&   symtab_section_index)
> +{
> +  if (!elf_handle)
> +    return NO_HASH_TABLE_KIND;
> +
> +  GElf_Shdr header_mem, *section_header;
> +  bool found_sysv_ht = false, found_gnu_ht = false;
> +  for (Elf_Scn* section = elf_nextscn(elf_handle, 0);
> +       section != 0;
> +       section = elf_nextscn(elf_handle, section))
> +    {
> +      section_header= gelf_getshdr(section, &header_mem);
> +      if (section_header->sh_type != SHT_HASH
> +         && section_header->sh_type != SHT_GNU_HASH)
> +       continue;
> +
> +      ht_section_index = elf_ndxscn(section);
> +      symtab_section_index = section_header->sh_link;
> +
> +      if (section_header->sh_type == SHT_HASH)
> +       found_sysv_ht = true;
> +      else if (section_header->sh_type == SHT_GNU_HASH)
> +       found_gnu_ht = true;
> +    }
> +
> +  if (found_gnu_ht)
> +    return GNU_HASH_TABLE_KIND;
> +  else if (found_sysv_ht)
> +    return SYSV_HASH_TABLE_KIND;
> +  else
> +    return NO_HASH_TABLE_KIND;
> +}
> +
> +/// Find and return the .text section.
> +///
> +/// @param elf_handle the elf handle to use.
> +///
> +/// @return the .text section found.
> +Elf_Scn*
> +find_text_section(Elf* elf_handle)
> +{return find_section(elf_handle, ".text", SHT_PROGBITS);}
> +
> +/// Find and return the .bss section.
> +///
> +/// @param elf_handle.
> +///
> +/// @return the .bss section found.
> +Elf_Scn*
> +find_bss_section(Elf* elf_handle)
> +{return find_section(elf_handle, ".bss", SHT_NOBITS);}
> +
> +/// Find and return the .rodata section.
> +///
> +/// @param elf_handle.
> +///
> +/// @return the .rodata section found.
> +Elf_Scn*
> +find_rodata_section(Elf* elf_handle)
> +{return find_section(elf_handle, ".rodata", SHT_PROGBITS);}
> +
> +/// Find and return the .data section.
> +///
> +/// @param elf_handle the elf handle to use.
> +///
> +/// @return the .data section found.
> +Elf_Scn*
> +find_data_section(Elf* elf_handle)
> +{return find_section(elf_handle, ".data", SHT_PROGBITS);}
> +
> +/// Find and return the .data1 section.
> +///
> +/// @param elf_handle the elf handle to use.
> +///
> +/// @return the .data1 section found.
> +Elf_Scn*
> +find_data1_section(Elf* elf_handle)
> +{return find_section(elf_handle, ".data1", SHT_PROGBITS);}
> +
> +
>  } // end namespace elf_helpers
>  } // end namespace abigail
> diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
> index bffa46cc3c2d..58720da0fa9e 100644
> --- a/src/abg-elf-helpers.h
> +++ b/src/abg-elf-helpers.h
> @@ -25,12 +25,77 @@
>  #ifndef __ABG_ELF_HELPERS_H__
>  #define __ABG_ELF_HELPERS_H__
>
> +#include "config.h"
> +
> +#include <gelf.h>
> +#include <string>
> +
> +#include "abg-ir.h"
> +
>  namespace abigail
>  {
>
>  namespace elf_helpers
>  {
>
> +//
> +// ELF Value Converters
> +//
> +
> +elf_symbol::type
> +stt_to_elf_symbol_type(unsigned char stt);
> +
> +elf_symbol::binding
> +stb_to_elf_symbol_binding(unsigned char stb);
> +
> +elf_symbol::visibility
> +stv_to_elf_symbol_visibility(unsigned char stv);
> +
> +std::string
> +e_machine_to_string(GElf_Half e_machine);
> +
> +//
> +// ELF section helpers
> +//
> +
> +Elf_Scn*
> +find_section(Elf*              elf_handle,
> +            const std::string& name,
> +            Elf64_Word         section_type);
> +
> +bool
> +find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab);
> +
> +bool
> +find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index);
> +
> +enum hash_table_kind
> +{
> +  NO_HASH_TABLE_KIND = 0,
> +  SYSV_HASH_TABLE_KIND,
> +  GNU_HASH_TABLE_KIND
> +};
> +
> +hash_table_kind
> +find_hash_table_section_index(Elf*     elf_handle,
> +                             size_t&   ht_section_index,
> +                             size_t&   symtab_section_index);
> +
> +Elf_Scn*
> +find_text_section(Elf* elf_handle);
> +
> +Elf_Scn*
> +find_bss_section(Elf* elf_handle);
> +
> +Elf_Scn*
> +find_rodata_section(Elf* elf_handle);
> +
> +Elf_Scn*
> +find_data_section(Elf* elf_handle);
> +
> +Elf_Scn*
> +find_data1_section(Elf* elf_handle);
> +
>  } // end namespace elf_helpers
>  } // end namespace abigail
>
> --
> 2.26.1.301.g55bc3eb7cb9-goog
>
diff mbox series

Patch

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 1c0d6ea0353f..6ec7e4b6e968 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -50,6 +50,8 @@ 
 #include "abg-suppression-priv.h"
 #include "abg-corpus-priv.h"
 
+#include "abg-elf-helpers.h"
+
 #include "abg-internal.h"
 // <headers defining libabigail's API go under here>
 ABG_BEGIN_EXPORT_DECLARATIONS
@@ -84,6 +86,8 @@  using std::stack;
 using std::deque;
 using std::list;
 
+using namespace elf_helpers; // TODO: avoid using namespace
+
 /// Where a DIE comes from. For instance, a DIE can come from the main
 /// debug info section, the alternate debug info section or from the
 /// type unit section.
@@ -290,9 +294,6 @@  static void
 add_symbol_to_map(const elf_symbol_sptr& sym,
 		  string_elf_symbols_map_type& map);
 
-static bool
-find_symbol_table_section(Elf* elf_handle, Elf_Scn*& section);
-
 static bool
 get_symbol_versionning_sections(Elf*		elf_handle,
 				Elf_Scn*&	versym_section,
@@ -546,548 +547,6 @@  compare_dies(const read_context& ctxt,
 	     const Dwarf_Die *l, const Dwarf_Die *r,
 	     bool update_canonical_dies_on_the_fly);
 
-/// Convert an elf symbol type (given by the ELF{32,64}_ST_TYPE
-/// macros) into an elf_symbol::type value.
-///
-/// Note that this function aborts when given an unexpected value.
-///
-/// @param the symbol type value to convert.
-///
-/// @return the converted value.
-static elf_symbol::type
-stt_to_elf_symbol_type(unsigned char stt)
-{
-  elf_symbol::type t = elf_symbol::NOTYPE_TYPE;
-
-  switch (stt)
-    {
-    case STT_NOTYPE:
-      t = elf_symbol::NOTYPE_TYPE;
-      break;
-    case STT_OBJECT:
-      t = elf_symbol::OBJECT_TYPE;
-      break;
-    case STT_FUNC:
-      t = elf_symbol::FUNC_TYPE;
-      break;
-    case STT_SECTION:
-      t = elf_symbol::SECTION_TYPE;
-      break;
-    case STT_FILE:
-      t = elf_symbol::FILE_TYPE;
-      break;
-    case STT_COMMON:
-      t = elf_symbol::COMMON_TYPE;
-      break;
-    case STT_TLS:
-      t = elf_symbol::TLS_TYPE;
-      break;
-    case STT_GNU_IFUNC:
-      t = elf_symbol::GNU_IFUNC_TYPE;
-      break;
-    default:
-      // An unknown value that probably ought to be supported?  Let's
-      // abort right here rather than yielding garbage.
-      ABG_ASSERT_NOT_REACHED;
-    }
-
-  return t;
-}
-
-/// Convert an elf symbol binding (given by the ELF{32,64}_ST_BIND
-/// macros) into an elf_symbol::binding value.
-///
-/// Note that this function aborts when given an unexpected value.
-///
-/// @param the symbol binding value to convert.
-///
-/// @return the converted value.
-static elf_symbol::binding
-stb_to_elf_symbol_binding(unsigned char stb)
-{
-  elf_symbol::binding b = elf_symbol::GLOBAL_BINDING;
-
-  switch (stb)
-    {
-    case STB_LOCAL:
-      b = elf_symbol::LOCAL_BINDING;
-      break;
-    case STB_GLOBAL:
-      b = elf_symbol::GLOBAL_BINDING;
-      break;
-    case STB_WEAK:
-      b = elf_symbol::WEAK_BINDING;
-      break;
-    case STB_GNU_UNIQUE:
-      b = elf_symbol::GNU_UNIQUE_BINDING;
-      break;
-    default:
-      ABG_ASSERT_NOT_REACHED;
-    }
-
-  return b;
-
-}
-
-/// Convert an ELF symbol visiblity given by the symbols ->st_other
-/// data member as returned by the GELF_ST_VISIBILITY macro into a
-/// elf_symbol::visiblity value.
-///
-/// @param stv the value of the ->st_other data member of the ELF
-/// symbol.
-///
-/// @return the converted elf_symbol::visiblity value.
-static elf_symbol::visibility
-stv_to_elf_symbol_visibility(unsigned char stv)
-{
-
-  elf_symbol::visibility v = elf_symbol::DEFAULT_VISIBILITY;
-
-  switch (stv)
-    {
-    case STV_DEFAULT:
-      v = elf_symbol::DEFAULT_VISIBILITY;
-      break;
-    case STV_INTERNAL:
-      v = elf_symbol::INTERNAL_VISIBILITY;
-      break;
-    case STV_HIDDEN:
-      v = elf_symbol::HIDDEN_VISIBILITY;
-      break;
-    case STV_PROTECTED:
-      v = elf_symbol::PROTECTED_VISIBILITY;
-      break;
-    default:
-      ABG_ASSERT_NOT_REACHED;
-    }
-
-  return v;
-}
-
-/// Convert the value of the e_machine field of GElf_Ehdr into a
-/// string.  This is to get a string representing the architecture of
-/// the elf file at hand.
-///
-/// @param e_machine the value of GElf_Ehdr::e_machine.
-///
-/// @return the string representation of GElf_Ehdr::e_machine.
-static string
-e_machine_to_string(GElf_Half e_machine)
-{
-  string result;
-  switch (e_machine)
-    {
-    case EM_NONE:
-      result = "elf-no-arch";
-      break;
-    case EM_M32:
-      result = "elf-att-we-32100";
-      break;
-    case EM_SPARC:
-      result = "elf-sun-sparc";
-      break;
-    case EM_386:
-      result = "elf-intel-80386";
-      break;
-    case EM_68K:
-      result = "elf-motorola-68k";
-      break;
-    case EM_88K:
-      result = "elf-motorola-88k";
-      break;
-    case EM_860:
-      result = "elf-intel-80860";
-      break;
-    case EM_MIPS:
-      result = "elf-mips-r3000-be";
-      break;
-    case EM_S370:
-      result = "elf-ibm-s370";
-      break;
-    case EM_MIPS_RS3_LE:
-      result = "elf-mips-r3000-le";
-      break;
-    case EM_PARISC:
-      result = "elf-hp-parisc";
-      break;
-    case EM_VPP500:
-      result = "elf-fujitsu-vpp500";
-      break;
-    case EM_SPARC32PLUS:
-      result = "elf-sun-sparc-v8plus";
-      break;
-    case EM_960:
-      result = "elf-intel-80960";
-      break;
-    case EM_PPC:
-      result = "elf-powerpc";
-      break;
-    case EM_PPC64:
-      result = "elf-powerpc-64";
-      break;
-    case EM_S390:
-      result = "elf-ibm-s390";
-      break;
-    case EM_V800:
-      result = "elf-nec-v800";
-      break;
-    case EM_FR20:
-      result = "elf-fujitsu-fr20";
-      break;
-    case EM_RH32:
-      result = "elf-trw-rh32";
-      break;
-    case EM_RCE:
-      result = "elf-motorola-rce";
-      break;
-    case EM_ARM:
-      result = "elf-arm";
-      break;
-    case EM_FAKE_ALPHA:
-      result = "elf-digital-alpha";
-      break;
-    case EM_SH:
-      result = "elf-hitachi-sh";
-      break;
-    case EM_SPARCV9:
-      result = "elf-sun-sparc-v9-64";
-      break;
-    case EM_TRICORE:
-      result = "elf-siemens-tricore";
-      break;
-    case EM_ARC:
-      result = "elf-argonaut-risc-core";
-      break;
-    case EM_H8_300:
-      result = "elf-hitachi-h8-300";
-      break;
-    case EM_H8_300H:
-      result = "elf-hitachi-h8-300h";
-      break;
-    case EM_H8S:
-      result = "elf-hitachi-h8s";
-      break;
-    case EM_H8_500:
-      result = "elf-hitachi-h8-500";
-      break;
-    case EM_IA_64:
-      result = "elf-intel-ia-64";
-      break;
-    case EM_MIPS_X:
-      result = "elf-stanford-mips-x";
-      break;
-    case EM_COLDFIRE:
-      result = "elf-motorola-coldfire";
-      break;
-    case EM_68HC12:
-      result = "elf-motorola-68hc12";
-      break;
-    case EM_MMA:
-      result = "elf-fujitsu-mma";
-      break;
-    case EM_PCP:
-      result = "elf-siemens-pcp";
-      break;
-    case EM_NCPU:
-      result = "elf-sony-ncpu";
-      break;
-    case EM_NDR1:
-      result = "elf-denso-ndr1";
-      break;
-    case EM_STARCORE:
-      result = "elf-motorola-starcore";
-      break;
-    case EM_ME16:
-      result = "elf-toyota-me16";
-      break;
-    case EM_ST100:
-      result = "elf-stm-st100";
-      break;
-    case EM_TINYJ:
-      result = "elf-alc-tinyj";
-      break;
-    case EM_X86_64:
-      result = "elf-amd-x86_64";
-      break;
-    case EM_PDSP:
-      result = "elf-sony-pdsp";
-      break;
-    case EM_FX66:
-      result = "elf-siemens-fx66";
-      break;
-    case EM_ST9PLUS:
-      result = "elf-stm-st9+";
-      break;
-    case EM_ST7:
-      result = "elf-stm-st7";
-      break;
-    case EM_68HC16:
-      result = "elf-motorola-68hc16";
-      break;
-    case EM_68HC11:
-      result = "elf-motorola-68hc11";
-      break;
-    case EM_68HC08:
-      result = "elf-motorola-68hc08";
-      break;
-    case EM_68HC05:
-      result = "elf-motorola-68hc05";
-      break;
-    case EM_SVX:
-      result = "elf-sg-svx";
-      break;
-    case EM_ST19:
-      result = "elf-stm-st19";
-      break;
-    case EM_VAX:
-      result = "elf-digital-vax";
-      break;
-    case EM_CRIS:
-      result = "elf-axis-cris";
-      break;
-    case EM_JAVELIN:
-      result = "elf-infineon-javelin";
-      break;
-    case EM_FIREPATH:
-      result = "elf-firepath";
-      break;
-    case EM_ZSP:
-      result = "elf-lsi-zsp";
-      break;
-    case EM_MMIX:
-      result = "elf-don-knuth-mmix";
-      break;
-    case EM_HUANY:
-      result = "elf-harvard-huany";
-      break;
-    case EM_PRISM:
-      result = "elf-sitera-prism";
-      break;
-    case EM_AVR:
-      result = "elf-atmel-avr";
-      break;
-    case EM_FR30:
-      result = "elf-fujistu-fr30";
-      break;
-    case EM_D10V:
-      result = "elf-mitsubishi-d10v";
-      break;
-    case EM_D30V:
-      result = "elf-mitsubishi-d30v";
-      break;
-    case EM_V850:
-      result = "elf-nec-v850";
-      break;
-    case EM_M32R:
-      result = "elf-mitsubishi-m32r";
-      break;
-    case EM_MN10300:
-      result = "elf-matsushita-mn10300";
-      break;
-    case EM_MN10200:
-      result = "elf-matsushita-mn10200";
-      break;
-    case EM_PJ:
-      result = "elf-picojava";
-      break;
-    case EM_OPENRISC:
-      result = "elf-openrisc-32";
-      break;
-    case EM_ARC_A5:
-      result = "elf-arc-a5";
-      break;
-    case EM_XTENSA:
-      result = "elf-tensilica-xtensa";
-      break;
-
-#ifdef HAVE_EM_AARCH64_MACRO
-    case EM_AARCH64:
-      result = "elf-arm-aarch64";
-      break;
-#endif
-
-#ifdef HAVE_EM_TILEPRO_MACRO
-    case EM_TILEPRO:
-      result = "elf-tilera-tilepro";
-      break;
-#endif
-
-#ifdef HAVE_EM_TILEGX_MACRO
-    case EM_TILEGX:
-      result = "elf-tilera-tilegx";
-      break;
-#endif
-
-    case EM_NUM:
-      result = "elf-last-arch-number";
-      break;
-    case EM_ALPHA:
-      result = "elf-non-official-alpha";
-      break;
-    default:
-      {
-	std::ostringstream o;
-	o << "elf-unknown-arch-value-" << e_machine;
-	result = o.str();
-      }
-      break;
-    }
-  return result;
-}
-
-/// The kind of ELF hash table found by the function
-/// find_hash_table_section_index.
-enum hash_table_kind
-{
-  NO_HASH_TABLE_KIND = 0,
-  SYSV_HASH_TABLE_KIND,
-  GNU_HASH_TABLE_KIND
-};
-
-/// Get the offset offset of the hash table section.
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @param ht_section_offset this is set to the resulting offset
-/// of the hash table section.  This is set iff the function returns true.
-///
-/// @param symtab_section_offset the offset of the section of the
-/// symbol table the hash table refers to.
-static hash_table_kind
-find_hash_table_section_index(Elf*	elf_handle,
-			      size_t&	ht_section_index,
-			      size_t&	symtab_section_index)
-{
-  if (!elf_handle)
-    return NO_HASH_TABLE_KIND;
-
-  GElf_Shdr header_mem, *section_header;
-  bool found_sysv_ht = false, found_gnu_ht = false;
-  for (Elf_Scn* section = elf_nextscn(elf_handle, 0);
-       section != 0;
-       section = elf_nextscn(elf_handle, section))
-    {
-      section_header= gelf_getshdr(section, &header_mem);
-      if (section_header->sh_type != SHT_HASH
-	  && section_header->sh_type != SHT_GNU_HASH)
-	continue;
-
-      ht_section_index = elf_ndxscn(section);
-      symtab_section_index = section_header->sh_link;
-
-      if (section_header->sh_type == SHT_HASH)
-	found_sysv_ht = true;
-      else if (section_header->sh_type == SHT_GNU_HASH)
-	found_gnu_ht = true;
-    }
-
-  if (found_gnu_ht)
-    return GNU_HASH_TABLE_KIND;
-  else if (found_sysv_ht)
-    return SYSV_HASH_TABLE_KIND;
-  else
-    return NO_HASH_TABLE_KIND;
-}
-
-/// Find the symbol table.
-///
-/// If we are looking at a relocatable or executable file, this
-/// function will return the .symtab symbol table (of type
-/// SHT_SYMTAB).  But if we are looking at a DSO it returns the
-/// .dynsym symbol table (of type SHT_DYNSYM).
-///
-/// @param elf_handle the elf handle to consider.
-///
-/// @param symtab the symbol table found.
-///
-/// @return true iff the symbol table is found.
-static bool
-find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
-{
-  Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0;
-  while ((section = elf_nextscn(elf_handle, section)) != 0)
-    {
-      GElf_Shdr header_mem, *header;
-      header = gelf_getshdr(section, &header_mem);
-      if (header->sh_type == SHT_DYNSYM)
-	dynsym = section;
-      else if (header->sh_type == SHT_SYMTAB)
-	sym_tab = section;
-    }
-
-  if (dynsym || sym_tab)
-    {
-      GElf_Ehdr eh_mem;
-      GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
-      if (elf_header->e_type == ET_REL
-	  || elf_header->e_type == ET_EXEC)
-	symtab = sym_tab ? sym_tab : dynsym;
-      else
-	symtab = dynsym ? dynsym : sym_tab;
-      return true;
-    }
-  return false;
-}
-
-/// Find the index (in the section headers table) of the symbol table
-/// section.
-///
-/// If we are looking at a relocatable or executable file, this
-/// function will return the index for the .symtab symbol table (of
-/// type SHT_SYMTAB).  But if we are looking at a DSO it returns the
-/// index for the .dynsym symbol table (of type SHT_DYNSYM).
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @param symtab_index the index of the symbol_table, that was found.
-///
-/// @return true iff the symbol table section index was found.
-static bool
-find_symbol_table_section_index(Elf* elf_handle,
-				size_t& symtab_index)
-{
-  Elf_Scn* section = 0;
-  if (!find_symbol_table_section(elf_handle, section))
-    return false;
-
-  symtab_index = elf_ndxscn(section);
-  return true;
-}
-
-/// Find and return a section by its name and its type.
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @param name the name of the section.
-///
-/// @param section_type the type of the section.  This is the
-/// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member.
-/// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS.
-///
-/// @return the section found, nor nil if none was found.
-static Elf_Scn*
-find_section(Elf* elf_handle, const string& name, Elf64_Word section_type)
-{
-  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 || header->sh_type != section_type)
-      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;
-}
 
 /// Test if the ELF binary denoted by a given ELF handle is a Linux
 /// Kernel Module.
@@ -1121,51 +580,6 @@  binary_is_linux_kernel(Elf *elf_handle)
 	  || binary_is_linux_kernel_module(elf_handle));
 }
 
-/// Find and return the .text section.
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @return the .text section found.
-static Elf_Scn*
-find_text_section(Elf* elf_handle)
-{return find_section(elf_handle, ".text", SHT_PROGBITS);}
-
-/// Find and return the .bss section.
-///
-/// @param elf_handle.
-///
-/// @return the .bss section found.
-static Elf_Scn*
-find_bss_section(Elf* elf_handle)
-{return find_section(elf_handle, ".bss", SHT_NOBITS);}
-
-/// Find and return the .rodata section.
-///
-/// @param elf_handle.
-///
-/// @return the .rodata section found.
-static Elf_Scn*
-find_rodata_section(Elf* elf_handle)
-{return find_section(elf_handle, ".rodata", SHT_PROGBITS);}
-
-/// Find and return the .data section.
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @return the .data section found.
-static Elf_Scn*
-find_data_section(Elf* elf_handle)
-{return find_section(elf_handle, ".data", SHT_PROGBITS);}
-
-/// Find and return the .data1 section.
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @return the .data1 section found.
-static Elf_Scn*
-find_data1_section(Elf* elf_handle)
-{return find_section(elf_handle, ".data1", SHT_PROGBITS);}
-
 /// Find the __ksymtab_strings section of a Linux kernel binary.
 ///
 ///
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index e99fe4a5c306..b0113a4efd2c 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -24,11 +24,482 @@ 
 
 #include "abg-elf-helpers.h"
 
+#include <elf.h>
+
+#include "abg-tools-utils.h"
+
 namespace abigail
 {
 
 namespace elf_helpers
 {
 
+/// Convert an elf symbol type (given by the ELF{32,64}_ST_TYPE
+/// macros) into an elf_symbol::type value.
+///
+/// Note that this function aborts when given an unexpected value.
+///
+/// @param the symbol type value to convert.
+///
+/// @return the converted value.
+elf_symbol::type
+stt_to_elf_symbol_type(unsigned char stt)
+{
+  switch (stt)
+    {
+    case STT_NOTYPE:
+      return elf_symbol::NOTYPE_TYPE;
+    case STT_OBJECT:
+      return elf_symbol::OBJECT_TYPE;
+    case STT_FUNC:
+      return elf_symbol::FUNC_TYPE;
+    case STT_SECTION:
+      return elf_symbol::SECTION_TYPE;
+    case STT_FILE:
+      return elf_symbol::FILE_TYPE;
+    case STT_COMMON:
+      return elf_symbol::COMMON_TYPE;
+    case STT_TLS:
+      return elf_symbol::TLS_TYPE;
+    case STT_GNU_IFUNC:
+      return elf_symbol::GNU_IFUNC_TYPE;
+    default:
+      // An unknown value that probably ought to be supported?  Let's
+      // abort right here rather than yielding garbage.
+      ABG_ASSERT_NOT_REACHED;
+    }
+}
+
+/// Convert an elf symbol binding (given by the ELF{32,64}_ST_BIND
+/// macros) into an elf_symbol::binding value.
+///
+/// Note that this function aborts when given an unexpected value.
+///
+/// @param the symbol binding value to convert.
+///
+/// @return the converted value.
+elf_symbol::binding
+stb_to_elf_symbol_binding(unsigned char stb)
+{
+  switch (stb)
+    {
+    case STB_LOCAL:
+      return elf_symbol::LOCAL_BINDING;
+    case STB_GLOBAL:
+      return elf_symbol::GLOBAL_BINDING;
+    case STB_WEAK:
+      return elf_symbol::WEAK_BINDING;
+    case STB_GNU_UNIQUE:
+      return elf_symbol::GNU_UNIQUE_BINDING;
+    default:
+      ABG_ASSERT_NOT_REACHED;
+    }
+}
+
+/// Convert an ELF symbol visiblity given by the symbols ->st_other
+/// data member as returned by the GELF_ST_VISIBILITY macro into a
+/// elf_symbol::visiblity value.
+///
+/// @param stv the value of the ->st_other data member of the ELF
+/// symbol.
+///
+/// @return the converted elf_symbol::visiblity value.
+elf_symbol::visibility
+stv_to_elf_symbol_visibility(unsigned char stv)
+{
+  switch (stv)
+    {
+    case STV_DEFAULT:
+      return elf_symbol::DEFAULT_VISIBILITY;
+    case STV_INTERNAL:
+      return elf_symbol::INTERNAL_VISIBILITY;
+    case STV_HIDDEN:
+      return elf_symbol::HIDDEN_VISIBILITY;
+    case STV_PROTECTED:
+      return elf_symbol::PROTECTED_VISIBILITY;
+    default:
+      ABG_ASSERT_NOT_REACHED;
+    }
+}
+
+/// Convert the value of the e_machine field of GElf_Ehdr into a
+/// string.  This is to get a string representing the architecture of
+/// the elf file at hand.
+///
+/// @param e_machine the value of GElf_Ehdr::e_machine.
+///
+/// @return the string representation of GElf_Ehdr::e_machine.
+std::string
+e_machine_to_string(GElf_Half e_machine)
+{
+  switch (e_machine)
+    {
+    case EM_NONE:
+      return "elf-no-arch";
+    case EM_M32:
+      return "elf-att-we-32100";
+    case EM_SPARC:
+      return "elf-sun-sparc";
+    case EM_386:
+      return "elf-intel-80386";
+    case EM_68K:
+      return "elf-motorola-68k";
+    case EM_88K:
+      return "elf-motorola-88k";
+    case EM_860:
+      return "elf-intel-80860";
+    case EM_MIPS:
+      return "elf-mips-r3000-be";
+    case EM_S370:
+      return "elf-ibm-s370";
+    case EM_MIPS_RS3_LE:
+      return "elf-mips-r3000-le";
+    case EM_PARISC:
+      return "elf-hp-parisc";
+    case EM_VPP500:
+      return "elf-fujitsu-vpp500";
+    case EM_SPARC32PLUS:
+      return "elf-sun-sparc-v8plus";
+    case EM_960:
+      return "elf-intel-80960";
+    case EM_PPC:
+      return "elf-powerpc";
+    case EM_PPC64:
+      return "elf-powerpc-64";
+    case EM_S390:
+      return "elf-ibm-s390";
+    case EM_V800:
+      return "elf-nec-v800";
+    case EM_FR20:
+      return "elf-fujitsu-fr20";
+    case EM_RH32:
+      return "elf-trw-rh32";
+    case EM_RCE:
+      return "elf-motorola-rce";
+    case EM_ARM:
+      return "elf-arm";
+    case EM_FAKE_ALPHA:
+      return "elf-digital-alpha";
+    case EM_SH:
+      return "elf-hitachi-sh";
+    case EM_SPARCV9:
+      return "elf-sun-sparc-v9-64";
+    case EM_TRICORE:
+      return "elf-siemens-tricore";
+    case EM_ARC:
+      return "elf-argonaut-risc-core";
+    case EM_H8_300:
+      return "elf-hitachi-h8-300";
+    case EM_H8_300H:
+      return "elf-hitachi-h8-300h";
+    case EM_H8S:
+      return "elf-hitachi-h8s";
+    case EM_H8_500:
+      return "elf-hitachi-h8-500";
+    case EM_IA_64:
+      return "elf-intel-ia-64";
+    case EM_MIPS_X:
+      return "elf-stanford-mips-x";
+    case EM_COLDFIRE:
+      return "elf-motorola-coldfire";
+    case EM_68HC12:
+      return "elf-motorola-68hc12";
+    case EM_MMA:
+      return "elf-fujitsu-mma";
+    case EM_PCP:
+      return "elf-siemens-pcp";
+    case EM_NCPU:
+      return "elf-sony-ncpu";
+    case EM_NDR1:
+      return "elf-denso-ndr1";
+    case EM_STARCORE:
+      return "elf-motorola-starcore";
+    case EM_ME16:
+      return "elf-toyota-me16";
+    case EM_ST100:
+      return "elf-stm-st100";
+    case EM_TINYJ:
+      return "elf-alc-tinyj";
+    case EM_X86_64:
+      return "elf-amd-x86_64";
+    case EM_PDSP:
+      return "elf-sony-pdsp";
+    case EM_FX66:
+      return "elf-siemens-fx66";
+    case EM_ST9PLUS:
+      return "elf-stm-st9+";
+    case EM_ST7:
+      return "elf-stm-st7";
+    case EM_68HC16:
+      return "elf-motorola-68hc16";
+    case EM_68HC11:
+      return "elf-motorola-68hc11";
+    case EM_68HC08:
+      return "elf-motorola-68hc08";
+    case EM_68HC05:
+      return "elf-motorola-68hc05";
+    case EM_SVX:
+      return "elf-sg-svx";
+    case EM_ST19:
+      return "elf-stm-st19";
+    case EM_VAX:
+      return "elf-digital-vax";
+    case EM_CRIS:
+      return "elf-axis-cris";
+    case EM_JAVELIN:
+      return "elf-infineon-javelin";
+    case EM_FIREPATH:
+      return "elf-firepath";
+    case EM_ZSP:
+      return "elf-lsi-zsp";
+    case EM_MMIX:
+      return "elf-don-knuth-mmix";
+    case EM_HUANY:
+      return "elf-harvard-huany";
+    case EM_PRISM:
+      return "elf-sitera-prism";
+    case EM_AVR:
+      return "elf-atmel-avr";
+    case EM_FR30:
+      return "elf-fujistu-fr30";
+    case EM_D10V:
+      return "elf-mitsubishi-d10v";
+    case EM_D30V:
+      return "elf-mitsubishi-d30v";
+    case EM_V850:
+      return "elf-nec-v850";
+    case EM_M32R:
+      return "elf-mitsubishi-m32r";
+    case EM_MN10300:
+      return "elf-matsushita-mn10300";
+    case EM_MN10200:
+      return "elf-matsushita-mn10200";
+    case EM_PJ:
+      return "elf-picojava";
+    case EM_OPENRISC:
+      return "elf-openrisc-32";
+    case EM_ARC_A5:
+      return "elf-arc-a5";
+    case EM_XTENSA:
+      return "elf-tensilica-xtensa";
+
+#ifdef HAVE_EM_AARCH64_MACRO
+    case EM_AARCH64:
+      return "elf-arm-aarch64";
+#endif
+
+#ifdef HAVE_EM_TILEPRO_MACRO
+    case EM_TILEPRO:
+      return "elf-tilera-tilepro";
+#endif
+
+#ifdef HAVE_EM_TILEGX_MACRO
+    case EM_TILEGX:
+      return "elf-tilera-tilegx";
+#endif
+
+    case EM_NUM:
+      return "elf-last-arch-number";
+    case EM_ALPHA:
+      return "elf-non-official-alpha";
+    default:
+      {
+	std::ostringstream o;
+	o << "elf-unknown-arch-value-" << e_machine;
+	return o.str();
+      }
+    }
+}
+
+/// Find and return a section by its name and its type.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @param name the name of the section.
+///
+/// @param section_type the type of the section.  This is the
+/// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member.
+/// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS.
+///
+/// @return the section found, nor nil if none was found.
+Elf_Scn*
+find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
+{
+  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 || header->sh_type != section_type)
+      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 the symbol table.
+///
+/// If we are looking at a relocatable or executable file, this
+/// function will return the .symtab symbol table (of type
+/// SHT_SYMTAB).  But if we are looking at a DSO it returns the
+/// .dynsym symbol table (of type SHT_DYNSYM).
+///
+/// @param elf_handle the elf handle to consider.
+///
+/// @param symtab the symbol table found.
+///
+/// @return true iff the symbol table is found.
+bool
+find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
+{
+  Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0;
+  while ((section = elf_nextscn(elf_handle, section)) != 0)
+    {
+      GElf_Shdr header_mem, *header;
+      header = gelf_getshdr(section, &header_mem);
+      if (header->sh_type == SHT_DYNSYM)
+	dynsym = section;
+      else if (header->sh_type == SHT_SYMTAB)
+	sym_tab = section;
+    }
+
+  if (dynsym || sym_tab)
+    {
+      GElf_Ehdr eh_mem;
+      GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
+      if (elf_header->e_type == ET_REL
+	  || elf_header->e_type == ET_EXEC)
+	symtab = sym_tab ? sym_tab : dynsym;
+      else
+	symtab = dynsym ? dynsym : sym_tab;
+      return true;
+    }
+  return false;
+}
+
+/// Find the index (in the section headers table) of the symbol table
+/// section.
+///
+/// If we are looking at a relocatable or executable file, this
+/// function will return the index for the .symtab symbol table (of
+/// type SHT_SYMTAB).  But if we are looking at a DSO it returns the
+/// index for the .dynsym symbol table (of type SHT_DYNSYM).
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @param symtab_index the index of the symbol_table, that was found.
+///
+/// @return true iff the symbol table section index was found.
+bool
+find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index)
+{
+  Elf_Scn* section = 0;
+  if (!find_symbol_table_section(elf_handle, section))
+    return false;
+
+  symtab_index = elf_ndxscn(section);
+  return true;
+}
+
+/// Get the offset offset of the hash table section.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @param ht_section_offset this is set to the resulting offset
+/// of the hash table section.  This is set iff the function returns true.
+///
+/// @param symtab_section_offset the offset of the section of the
+/// symbol table the hash table refers to.
+hash_table_kind
+find_hash_table_section_index(Elf*	elf_handle,
+			      size_t&	ht_section_index,
+			      size_t&	symtab_section_index)
+{
+  if (!elf_handle)
+    return NO_HASH_TABLE_KIND;
+
+  GElf_Shdr header_mem, *section_header;
+  bool found_sysv_ht = false, found_gnu_ht = false;
+  for (Elf_Scn* section = elf_nextscn(elf_handle, 0);
+       section != 0;
+       section = elf_nextscn(elf_handle, section))
+    {
+      section_header= gelf_getshdr(section, &header_mem);
+      if (section_header->sh_type != SHT_HASH
+	  && section_header->sh_type != SHT_GNU_HASH)
+	continue;
+
+      ht_section_index = elf_ndxscn(section);
+      symtab_section_index = section_header->sh_link;
+
+      if (section_header->sh_type == SHT_HASH)
+	found_sysv_ht = true;
+      else if (section_header->sh_type == SHT_GNU_HASH)
+	found_gnu_ht = true;
+    }
+
+  if (found_gnu_ht)
+    return GNU_HASH_TABLE_KIND;
+  else if (found_sysv_ht)
+    return SYSV_HASH_TABLE_KIND;
+  else
+    return NO_HASH_TABLE_KIND;
+}
+
+/// Find and return the .text section.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @return the .text section found.
+Elf_Scn*
+find_text_section(Elf* elf_handle)
+{return find_section(elf_handle, ".text", SHT_PROGBITS);}
+
+/// Find and return the .bss section.
+///
+/// @param elf_handle.
+///
+/// @return the .bss section found.
+Elf_Scn*
+find_bss_section(Elf* elf_handle)
+{return find_section(elf_handle, ".bss", SHT_NOBITS);}
+
+/// Find and return the .rodata section.
+///
+/// @param elf_handle.
+///
+/// @return the .rodata section found.
+Elf_Scn*
+find_rodata_section(Elf* elf_handle)
+{return find_section(elf_handle, ".rodata", SHT_PROGBITS);}
+
+/// Find and return the .data section.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @return the .data section found.
+Elf_Scn*
+find_data_section(Elf* elf_handle)
+{return find_section(elf_handle, ".data", SHT_PROGBITS);}
+
+/// Find and return the .data1 section.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @return the .data1 section found.
+Elf_Scn*
+find_data1_section(Elf* elf_handle)
+{return find_section(elf_handle, ".data1", SHT_PROGBITS);}
+
+
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index bffa46cc3c2d..58720da0fa9e 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -25,12 +25,77 @@ 
 #ifndef __ABG_ELF_HELPERS_H__
 #define __ABG_ELF_HELPERS_H__
 
+#include "config.h"
+
+#include <gelf.h>
+#include <string>
+
+#include "abg-ir.h"
+
 namespace abigail
 {
 
 namespace elf_helpers
 {
 
+//
+// ELF Value Converters
+//
+
+elf_symbol::type
+stt_to_elf_symbol_type(unsigned char stt);
+
+elf_symbol::binding
+stb_to_elf_symbol_binding(unsigned char stb);
+
+elf_symbol::visibility
+stv_to_elf_symbol_visibility(unsigned char stv);
+
+std::string
+e_machine_to_string(GElf_Half e_machine);
+
+//
+// ELF section helpers
+//
+
+Elf_Scn*
+find_section(Elf*		elf_handle,
+	     const std::string& name,
+	     Elf64_Word		section_type);
+
+bool
+find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab);
+
+bool
+find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index);
+
+enum hash_table_kind
+{
+  NO_HASH_TABLE_KIND = 0,
+  SYSV_HASH_TABLE_KIND,
+  GNU_HASH_TABLE_KIND
+};
+
+hash_table_kind
+find_hash_table_section_index(Elf*	elf_handle,
+			      size_t&	ht_section_index,
+			      size_t&	symtab_section_index);
+
+Elf_Scn*
+find_text_section(Elf* elf_handle);
+
+Elf_Scn*
+find_bss_section(Elf* elf_handle);
+
+Elf_Scn*
+find_rodata_section(Elf* elf_handle);
+
+Elf_Scn*
+find_data_section(Elf* elf_handle);
+
+Elf_Scn*
+find_data1_section(Elf* elf_handle);
+
 } // end namespace elf_helpers
 } // end namespace abigail