public inbox for libabigail@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers
@ 2020-04-20 11:08 Matthias Maennich
  2020-04-20 11:08 ` [PATCH 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
                   ` (8 more replies)
  0 siblings, 9 replies; 37+ messages in thread
From: Matthias Maennich @ 2020-04-20 11:08 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

The abg-dwarf-reader.cc has grown into a large compilation unit with a lot of
responsibilities. This does not only affect the compilation time, but also
readability of the various implementation details. Hence it makes sense to
attempt a refactoring of parts of it.

To overcome the above and as a preparation for my future work on the symtab
reading part, this splits out functionality from the dwarf reader into a new
set of source files: src/elf-helpers.{h,cc} along with a test that so far only
serves the purpose of ensuring that the header file can be compiled on its own.

The elf-helpers, sensibly not named elf-utils, contain functionality like
looking up sections, converting values or deducting information and properties
in some way from an Elf* handle. They are not exposed to libabigail users as
they are an implementation detail of libabigail.

This set of changes is only a refactoring with minor cleanups and renames and
any change to the functionality would be unintentional.

Cheers,
Matthias

Matthias Maennich (8):
  abg-dwarf-reader split: create abg-elf-helpers.{h,cc} and test case
  abg-elf-helpers: move some elf helpers from abg-dwarf-reader
  abg-elf-helpers: move some versioning helpers from abg-dwarf-reader
  abg-elf-helpers: move some kernel helpers from abg-dwarf-reader
  abg-elf-helpers: consolidate the is_linux_kernel* helpers
  abg-dwarf-reader: migrate more ELF helpers to elf-helpers
  abg-elf-helpers: migrate more elf helpers (architecture specific
    helpers)
  abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr

 src/Makefile.am           |    2 +
 src/abg-dwarf-reader.cc   | 1209 ++-----------------------------------
 src/abg-elf-helpers.cc    | 1031 +++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h     |  183 ++++++
 tests/.gitignore          |    1 +
 tests/Makefile.am         |    6 +-
 tests/test-elf-helpers.cc |   30 +
 7 files changed, 1295 insertions(+), 1167 deletions(-)
 create mode 100644 src/abg-elf-helpers.cc
 create mode 100644 src/abg-elf-helpers.h
 create mode 100644 tests/test-elf-helpers.cc

-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case
  2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
@ 2020-04-20 11:08 ` Matthias Maennich
  2020-04-20 15:35   ` Giuliano Procida
  2020-04-20 11:08 ` [PATCH 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader Matthias Maennich
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-20 11:08 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

abg-elf-helpers.{h,cc} shall contain the ELF related parts of the
abg-dwarf-reader. Create the stub files, an empty unit test and hook
everything up in the make system.

    * src/Makefile.am: Add new source files abg-elf-helpers.{h,cc}.
    * src/abg-elf-helpers.cc: New source file.
    * src/abg-elf-helpers.h: New header file.
    * tests/.gitignore: Exclude runtestelfhelpers from being committed.
    * tests/Makefile.am: Add new test case runtestelfhelpers.
    * tests/test-elf-helpers.cc: New test source file.

Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/Makefile.am           |  2 ++
 src/abg-elf-helpers.cc    | 34 ++++++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h     | 37 +++++++++++++++++++++++++++++++++++++
 tests/.gitignore          |  1 +
 tests/Makefile.am         |  6 +++++-
 tests/test-elf-helpers.cc | 30 ++++++++++++++++++++++++++++++
 6 files changed, 109 insertions(+), 1 deletion(-)
 create mode 100644 src/abg-elf-helpers.cc
 create mode 100644 src/abg-elf-helpers.h
 create mode 100644 tests/test-elf-helpers.cc

diff --git a/src/Makefile.am b/src/Makefile.am
index 1d0e2dcecdee..fafab853b520 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,6 +39,8 @@ abg-config.cc				\
 abg-ini.cc				\
 abg-workers.cc				\
 abg-tools-utils.cc			\
+abg-elf-helpers.h			\
+abg-elf-helpers.cc			\
 $(CXX11_SOURCES)
 
 libabigail_la_LIBADD = $(DEPS_LIBS)
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
new file mode 100644
index 000000000000..e99fe4a5c306
--- /dev/null
+++ b/src/abg-elf-helpers.cc
@@ -0,0 +1,34 @@
+// -*- Mode: C++ -*-
+//
+// Copyright (C) 2020 Google, Inc.
+//
+// This file is part of the GNU Application Binary Interface Generic
+// Analysis and Instrumentation Library (libabigail).  This library is
+// free software; you can redistribute it and/or modify it under the
+// terms of the GNU Lesser General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option) any
+// later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; see the file COPYING-LGPLV3.  If
+// not, see <http://www.gnu.org/licenses/>.
+
+/// @file
+///
+/// This contains the definitions of the ELF utilities for the dwarf reader.
+
+#include "abg-elf-helpers.h"
+
+namespace abigail
+{
+
+namespace elf_helpers
+{
+
+} // end namespace elf_helpers
+} // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
new file mode 100644
index 000000000000..bffa46cc3c2d
--- /dev/null
+++ b/src/abg-elf-helpers.h
@@ -0,0 +1,37 @@
+// -*- Mode: C++ -*-
+//
+// Copyright (C) 2020 Google, Inc.
+//
+// This file is part of the GNU Application Binary Interface Generic
+// Analysis and Instrumentation Library (libabigail).  This library is
+// free software; you can redistribute it and/or modify it under the
+// terms of the GNU Lesser General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option) any
+// later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; see the file COPYING-LGPLV3.  If
+// not, see <http://www.gnu.org/licenses/>.
+
+/// @file
+///
+/// This contains a set of ELF utilities used by the dwarf reader.
+
+#ifndef __ABG_ELF_HELPERS_H__
+#define __ABG_ELF_HELPERS_H__
+
+namespace abigail
+{
+
+namespace elf_helpers
+{
+
+} // end namespace elf_helpers
+} // end namespace abigail
+
+#endif // __ABG_ELF_HELPERS_H__
diff --git a/tests/.gitignore b/tests/.gitignore
index f05e295db260..ebe7b9cc9e13 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -22,6 +22,7 @@ runtestdiffdwarfabixml
 runtestdifffilter
 runtestdiffpkg
 runtestdiffsuppr
+runtestelfhelpers
 runtestini
 runtestkmiwhitelist
 runtestlookupsyms
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 823e0db50c37..c1b187051377 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -46,6 +46,7 @@ runtestabidiffexit		\
 runtestini			\
 runtesttoolsutils		\
 runtestkmiwhitelist		\
+runtestelfhelpers		\
 $(CXX11_TESTS)
 
 if ENABLE_RUNNING_TESTS_WITH_PY3
@@ -142,6 +143,9 @@ runtesttoolsutils_LDADD = libtestutils.la $(top_builddir)/src/libabigail.la
 runtestkmiwhitelist_SOURCES = test-kmi-whitelist.cc
 runtestkmiwhitelist_LDADD = libtestutils.la libcatch.la $(top_builddir)/src/libabigail.la
 
+runtestelfhelpers_SOURCES = test-elf-helpers.cc
+runtestelfhelpers_LDADD = libcatch.la $(top_builddir)/src/libabigail.la
+
 runtestsvg_SOURCES=test-svg.cc
 runtestsvg_LDADD=$(top_builddir)/src/libabigail.la
 
@@ -172,7 +176,7 @@ runtestfedabipkgdiffpy3.sh$(EXEEXT):
 runtestdefaultsupprspy3_sh_SOURCES =
 runtestdefaultsupprspy3.sh$(EXEEXT):
 
-AM_CPPFLAGS=-I${abs_top_srcdir}/include \
+AM_CPPFLAGS=-I${abs_top_srcdir}/include -I${abs_top_srcdir}/src \
 -I${abs_top_builddir}/include -I${abs_top_srcdir}/tools -fPIC
 
 clean-local: clean-local-check
diff --git a/tests/test-elf-helpers.cc b/tests/test-elf-helpers.cc
new file mode 100644
index 000000000000..1b36ee2f122a
--- /dev/null
+++ b/tests/test-elf-helpers.cc
@@ -0,0 +1,30 @@
+// -*- Mode: C++ -*-
+//
+// Copyright (C) 2020 Google, Inc.
+//
+// This file is part of the GNU Application Binary Interface Generic
+// Analysis and Instrumentation Library (libabigail).  This library is
+// free software; you can redistribute it and/or modify it under the
+// terms of the GNU Lesser General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option) any
+// later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; see the file COPYING-LGPLV3.  If
+// not, see <http://www.gnu.org/licenses/>.
+
+// Author: Matthias Maennich
+
+/// @file
+///
+/// This program tests libabigail's ELF helpers.
+
+#include "lib/catch.hpp"
+
+#include "abg-elf-helpers.h"
+
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader
  2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
  2020-04-20 11:08 ` [PATCH 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
@ 2020-04-20 11:08 ` Matthias Maennich
  2020-04-20 15:34   ` Giuliano Procida
  2020-04-20 11:08 ` [PATCH 3/8] abg-elf-helpers: move some versioning " Matthias Maennich
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-20 11:08 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

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(-)

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


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 3/8] abg-elf-helpers: move some versioning helpers from abg-dwarf-reader
  2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
  2020-04-20 11:08 ` [PATCH 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
  2020-04-20 11:08 ` [PATCH 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader Matthias Maennich
@ 2020-04-20 11:08 ` Matthias Maennich
  2020-04-20 15:33   ` Giuliano Procida
  2020-04-20 11:08 ` [PATCH 4/8] abg-elf-helpers: move some kernel " Matthias Maennich
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-20 11:08 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

Move some definitions from abg-dwarf-reader to abg-elf-helpers that are
strictly only related to ELF.

        * abg-dwarf-reader.cc(get_symbol_versionning_sections): Move function out.
        (get_version_definition_for_versym): Likewise.
        (get_version_needed_for_versym): Likewise.
        (get_version_for_symbol): Likewise.
        * abg-elf-helpers.cc(get_symbol_versionning_sections): Move function in.
        (get_version_definition_for_versym): Likewise.
        (get_version_needed_for_versym): Likewise.
        (get_version_for_symbol): Likewise.
        * abg-elf-helpers.cc(get_symbol_versionning_sections): Add declaration.
        (get_version_definition_for_versym): Likewise.
        (get_version_needed_for_versym): Likewise.
        (get_version_for_symbol): Likewise.

Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 256 ----------------------------------------
 src/abg-elf-helpers.cc  | 251 +++++++++++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h   |  28 +++++
 3 files changed, 279 insertions(+), 256 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 6ec7e4b6e968..303c1f8df4c2 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -294,12 +294,6 @@ static void
 add_symbol_to_map(const elf_symbol_sptr& sym,
 		  string_elf_symbols_map_type& map);
 
-static bool
-get_symbol_versionning_sections(Elf*		elf_handle,
-				Elf_Scn*&	versym_section,
-				Elf_Scn*&	verdef_section,
-				Elf_Scn*&	verneed_section);
-
 static bool
 get_parent_die(const read_context&	ctxt,
 	       const Dwarf_Die*	die,
@@ -867,256 +861,6 @@ compare_symbol_name(const string& symbol_name,
   return symbol_name == name;
 }
 
-/// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
-/// sections that are involved in symbol versionning.
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @param versym_section the SHT_GNU_versym section found.  If the
-/// section wasn't found, this is set to nil.
-///
-/// @param verdef_section the SHT_GNU_verdef section found.  If the
-/// section wasn't found, this is set to nil.
-///
-/// @param verneed_section the SHT_GNU_verneed section found.  If the
-/// section wasn't found, this is set to nil.
-///
-/// @return true iff at least one of the sections where found.
-static bool
-get_symbol_versionning_sections(Elf*		elf_handle,
-				Elf_Scn*&	versym_section,
-				Elf_Scn*&	verdef_section,
-				Elf_Scn*&	verneed_section)
-{
-  Elf_Scn* section = NULL;
-  GElf_Shdr mem;
-  Elf_Scn* versym = NULL, *verdef = NULL, *verneed = NULL;
-
-  while ((section = elf_nextscn(elf_handle, section)) != NULL)
-    {
-      GElf_Shdr* h = gelf_getshdr(section, &mem);
-      if (h->sh_type == SHT_GNU_versym)
-	versym = section;
-      else if (h->sh_type == SHT_GNU_verdef)
-	verdef = section;
-      else if (h->sh_type == SHT_GNU_verneed)
-	verneed = section;
-    }
-
-  if (versym || verdef || verneed)
-    {
-      // At least one the versionning sections was found.  Return it.
-      versym_section = versym;
-      verdef_section = verdef;
-      verneed_section = verneed;
-      return true;
-    }
-
-  return false;
-}
-
-/// Get the version definition (from the SHT_GNU_verdef section) of a
-/// given symbol represented by a pointer to GElf_Versym.
-///
-/// @param elf_hande the elf handle to use.
-///
-/// @param versym the symbol to get the version definition for.
-///
-/// @param verdef_section the SHT_GNU_verdef section.
-///
-/// @param version the resulting version definition.  This is set iff
-/// the function returns true.
-///
-/// @return true upon successful completion, false otherwise.
-static bool
-get_version_definition_for_versym(Elf*			 elf_handle,
-				  GElf_Versym*		 versym,
-				  Elf_Scn*		 verdef_section,
-				  elf_symbol::version&	 version)
-{
-  Elf_Data* verdef_data = elf_getdata(verdef_section, NULL);
-  GElf_Verdef verdef_mem;
-  GElf_Verdef* verdef = gelf_getverdef(verdef_data, 0, &verdef_mem);
-  size_t vd_offset = 0;
-
-  for (;; vd_offset += verdef->vd_next)
-    {
-      for (;verdef != 0;)
-	{
-	  if (verdef->vd_ndx == (*versym & 0x7fff))
-	    // Found the version of the symbol.
-	    break;
-	  vd_offset += verdef->vd_next;
-	  verdef = (verdef->vd_next == 0
-		    ? 0
-		    : gelf_getverdef(verdef_data, vd_offset, &verdef_mem));
-	}
-
-      if (verdef != 0)
-	{
-	  GElf_Verdaux verdaux_mem;
-	  GElf_Verdaux *verdaux = gelf_getverdaux(verdef_data,
-						  vd_offset + verdef->vd_aux,
-						  &verdaux_mem);
-	  GElf_Shdr header_mem;
-	  GElf_Shdr* verdef_section_header = gelf_getshdr(verdef_section,
-							  &header_mem);
-	  size_t verdef_stridx = verdef_section_header->sh_link;
-	  version.str(elf_strptr(elf_handle, verdef_stridx, verdaux->vda_name));
-	  if (*versym & 0x8000)
-	    version.is_default(false);
-	  else
-	    version.is_default(true);
-	  return true;
-	}
-      if (!verdef || verdef->vd_next == 0)
-	break;
-    }
-  return false;
-}
-
-/// Get the version needed (from the SHT_GNU_verneed section) to
-/// resolve an undefined symbol represented by a pointer to
-/// GElf_Versym.
-///
-/// @param elf_hande the elf handle to use.
-///
-/// @param versym the symbol to get the version definition for.
-///
-/// @param verneed_section the SHT_GNU_verneed section.
-///
-/// @param version the resulting version definition.  This is set iff
-/// the function returns true.
-///
-/// @return true upon successful completion, false otherwise.
-static bool
-get_version_needed_for_versym(Elf*			elf_handle,
-			      GElf_Versym*		versym,
-			      Elf_Scn*			verneed_section,
-			      elf_symbol::version&	version)
-{
-  if (versym == 0 || elf_handle == 0 || verneed_section == 0)
-    return false;
-
-  size_t vn_offset = 0;
-  Elf_Data* verneed_data = elf_getdata(verneed_section, NULL);
-  GElf_Verneed verneed_mem;
-  GElf_Verneed* verneed = gelf_getverneed(verneed_data, 0, &verneed_mem);
-
-  for (;verneed; vn_offset += verneed->vn_next)
-    {
-      size_t vna_offset = vn_offset;
-      GElf_Vernaux vernaux_mem;
-      GElf_Vernaux *vernaux = gelf_getvernaux(verneed_data,
-					      vn_offset + verneed->vn_aux,
-					      &vernaux_mem);
-      for (;vernaux != 0 && verneed;)
-	{
-	  if (vernaux->vna_other == *versym)
-	    // Found the version of the symbol.
-	    break;
-	  vna_offset += verneed->vn_next;
-	  verneed = (verneed->vn_next == 0
-		     ? 0
-		     : gelf_getverneed(verneed_data, vna_offset, &verneed_mem));
-	}
-
-      if (verneed != 0 && vernaux != 0 && vernaux->vna_other == *versym)
-	{
-	  GElf_Shdr header_mem;
-	  GElf_Shdr* verneed_section_header = gelf_getshdr(verneed_section,
-							   &header_mem);
-	  size_t verneed_stridx = verneed_section_header->sh_link;
-	  version.str(elf_strptr(elf_handle,
-				 verneed_stridx,
-				 vernaux->vna_name));
-	  if (*versym & 0x8000)
-	    version.is_default(false);
-	  else
-	    version.is_default(true);
-	  return true;
-	}
-
-      if (!verneed || verneed->vn_next == 0)
-	break;
-    }
-  return false;
-}
-
-/// Return the version for a symbol that is at a given index in its
-/// SHT_SYMTAB section.
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @param symbol_index the index of the symbol to consider.
-///
-/// @param get_def_version if this is true, it means that that we want
-/// the version for a defined symbol; in that case, the version is
-/// looked for in a section of type SHT_GNU_verdef.  Otherwise, if
-/// this parameter is false, this means that we want the version for
-/// an undefined symbol; in that case, the version is the needed one
-/// for the symbol to be resolved; so the version is looked fo in a
-/// section of type SHT_GNU_verneed.
-///
-/// @param version the version found for symbol at @p symbol_index.
-///
-/// @return true iff a version was found for symbol at index @p
-/// symbol_index.
-static bool
-get_version_for_symbol(Elf*			elf_handle,
-		       size_t			symbol_index,
-		       bool			get_def_version,
-		       elf_symbol::version&	version)
-{
-  Elf_Scn *versym_section = NULL,
-    *verdef_section = NULL,
-    *verneed_section = NULL;
-
-  if (!get_symbol_versionning_sections(elf_handle,
-				       versym_section,
-				       verdef_section,
-				       verneed_section))
-    return false;
-
-  GElf_Versym versym_mem;
-  Elf_Data* versym_data = (versym_section)
-    ? elf_getdata(versym_section, NULL)
-    : NULL;
-  GElf_Versym* versym = (versym_data)
-    ? gelf_getversym(versym_data, symbol_index, &versym_mem)
-    : NULL;
-
-  if (versym == 0 || *versym <= 1)
-    // I got these value from the code of readelf.c in elfutils.
-    // Apparently, if the symbol version entry has these values, the
-    // symbol must be discarded. This is not documented in the
-    // official specification.
-    return false;
-
-  if (get_def_version)
-    {
-      if (*versym == 0x8001)
-	// I got this value from the code of readelf.c in elfutils
-	// too.  It's not really documented in the official
-	// specification.
-	return false;
-
-      if (verdef_section
-	  && get_version_definition_for_versym(elf_handle, versym,
-					       verdef_section, version))
-	return true;
-    }
-  else
-    {
-      if (verneed_section
-	  && get_version_needed_for_versym(elf_handle, versym,
-					   verneed_section, version))
-	return true;
-    }
-
-  return false;
-}
-
 /// Lookup a symbol using the SysV ELF hash table.
 ///
 /// Note that this function hasn't been tested.  So it hasn't been
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index b0113a4efd2c..b7b868a332ec 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -500,6 +500,257 @@ Elf_Scn*
 find_data1_section(Elf* elf_handle)
 {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
 
+/// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
+/// sections that are involved in symbol versionning.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @param versym_section the SHT_GNU_versym section found.  If the
+/// section wasn't found, this is set to nil.
+///
+/// @param verdef_section the SHT_GNU_verdef section found.  If the
+/// section wasn't found, this is set to nil.
+///
+/// @param verneed_section the SHT_GNU_verneed section found.  If the
+/// section wasn't found, this is set to nil.
+///
+/// @return true iff at least one of the sections where found.
+bool
+get_symbol_versionning_sections(Elf*		elf_handle,
+				Elf_Scn*&	versym_section,
+				Elf_Scn*&	verdef_section,
+				Elf_Scn*&	verneed_section)
+{
+  Elf_Scn* section = NULL;
+  GElf_Shdr mem;
+  Elf_Scn* versym = NULL, *verdef = NULL, *verneed = NULL;
+
+  while ((section = elf_nextscn(elf_handle, section)) != NULL)
+    {
+      GElf_Shdr* h = gelf_getshdr(section, &mem);
+      if (h->sh_type == SHT_GNU_versym)
+	versym = section;
+      else if (h->sh_type == SHT_GNU_verdef)
+	verdef = section;
+      else if (h->sh_type == SHT_GNU_verneed)
+	verneed = section;
+    }
+
+  if (versym || verdef || verneed)
+    {
+      // At least one the versionning sections was found.  Return it.
+      versym_section = versym;
+      verdef_section = verdef;
+      verneed_section = verneed;
+      return true;
+    }
+
+  return false;
+}
+
+/// Get the version definition (from the SHT_GNU_verdef section) of a
+/// given symbol represented by a pointer to GElf_Versym.
+///
+/// @param elf_hande the elf handle to use.
+///
+/// @param versym the symbol to get the version definition for.
+///
+/// @param verdef_section the SHT_GNU_verdef section.
+///
+/// @param version the resulting version definition.  This is set iff
+/// the function returns true.
+///
+/// @return true upon successful completion, false otherwise.
+bool
+get_version_definition_for_versym(Elf*			 elf_handle,
+				  GElf_Versym*		 versym,
+				  Elf_Scn*		 verdef_section,
+				  elf_symbol::version&	 version)
+{
+  Elf_Data* verdef_data = elf_getdata(verdef_section, NULL);
+  GElf_Verdef verdef_mem;
+  GElf_Verdef* verdef = gelf_getverdef(verdef_data, 0, &verdef_mem);
+  size_t vd_offset = 0;
+
+  for (;; vd_offset += verdef->vd_next)
+    {
+      for (;verdef != 0;)
+	{
+	  if (verdef->vd_ndx == (*versym & 0x7fff))
+	    // Found the version of the symbol.
+	    break;
+	  vd_offset += verdef->vd_next;
+	  verdef = (verdef->vd_next == 0
+		    ? 0
+		    : gelf_getverdef(verdef_data, vd_offset, &verdef_mem));
+	}
+
+      if (verdef != 0)
+	{
+	  GElf_Verdaux verdaux_mem;
+	  GElf_Verdaux *verdaux = gelf_getverdaux(verdef_data,
+						  vd_offset + verdef->vd_aux,
+						  &verdaux_mem);
+	  GElf_Shdr header_mem;
+	  GElf_Shdr* verdef_section_header = gelf_getshdr(verdef_section,
+							  &header_mem);
+	  size_t verdef_stridx = verdef_section_header->sh_link;
+	  version.str(elf_strptr(elf_handle, verdef_stridx, verdaux->vda_name));
+	  if (*versym & 0x8000)
+	    version.is_default(false);
+	  else
+	    version.is_default(true);
+	  return true;
+	}
+      if (!verdef || verdef->vd_next == 0)
+	break;
+    }
+  return false;
+}
+
+/// Get the version needed (from the SHT_GNU_verneed section) to
+/// resolve an undefined symbol represented by a pointer to
+/// GElf_Versym.
+///
+/// @param elf_hande the elf handle to use.
+///
+/// @param versym the symbol to get the version definition for.
+///
+/// @param verneed_section the SHT_GNU_verneed section.
+///
+/// @param version the resulting version definition.  This is set iff
+/// the function returns true.
+///
+/// @return true upon successful completion, false otherwise.
+bool
+get_version_needed_for_versym(Elf*			elf_handle,
+			      GElf_Versym*		versym,
+			      Elf_Scn*			verneed_section,
+			      elf_symbol::version&	version)
+{
+  if (versym == 0 || elf_handle == 0 || verneed_section == 0)
+    return false;
+
+  size_t vn_offset = 0;
+  Elf_Data* verneed_data = elf_getdata(verneed_section, NULL);
+  GElf_Verneed verneed_mem;
+  GElf_Verneed* verneed = gelf_getverneed(verneed_data, 0, &verneed_mem);
+
+  for (;verneed; vn_offset += verneed->vn_next)
+    {
+      size_t vna_offset = vn_offset;
+      GElf_Vernaux vernaux_mem;
+      GElf_Vernaux *vernaux = gelf_getvernaux(verneed_data,
+					      vn_offset + verneed->vn_aux,
+					      &vernaux_mem);
+      for (;vernaux != 0 && verneed;)
+	{
+	  if (vernaux->vna_other == *versym)
+	    // Found the version of the symbol.
+	    break;
+	  vna_offset += verneed->vn_next;
+	  verneed = (verneed->vn_next == 0
+		     ? 0
+		     : gelf_getverneed(verneed_data, vna_offset, &verneed_mem));
+	}
+
+      if (verneed != 0 && vernaux != 0 && vernaux->vna_other == *versym)
+	{
+	  GElf_Shdr header_mem;
+	  GElf_Shdr* verneed_section_header = gelf_getshdr(verneed_section,
+							   &header_mem);
+	  size_t verneed_stridx = verneed_section_header->sh_link;
+	  version.str(elf_strptr(elf_handle,
+				 verneed_stridx,
+				 vernaux->vna_name));
+	  if (*versym & 0x8000)
+	    version.is_default(false);
+	  else
+	    version.is_default(true);
+	  return true;
+	}
+
+      if (!verneed || verneed->vn_next == 0)
+	break;
+    }
+  return false;
+}
+
+/// Return the version for a symbol that is at a given index in its
+/// SHT_SYMTAB section.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @param symbol_index the index of the symbol to consider.
+///
+/// @param get_def_version if this is true, it means that that we want
+/// the version for a defined symbol; in that case, the version is
+/// looked for in a section of type SHT_GNU_verdef.  Otherwise, if
+/// this parameter is false, this means that we want the version for
+/// an undefined symbol; in that case, the version is the needed one
+/// for the symbol to be resolved; so the version is looked fo in a
+/// section of type SHT_GNU_verneed.
+///
+/// @param version the version found for symbol at @p symbol_index.
+///
+/// @return true iff a version was found for symbol at index @p
+/// symbol_index.
+bool
+get_version_for_symbol(Elf*			elf_handle,
+		       size_t			symbol_index,
+		       bool			get_def_version,
+		       elf_symbol::version&	version)
+{
+  Elf_Scn *versym_section = NULL,
+    *verdef_section = NULL,
+    *verneed_section = NULL;
+
+  if (!get_symbol_versionning_sections(elf_handle,
+				       versym_section,
+				       verdef_section,
+				       verneed_section))
+    return false;
+
+  GElf_Versym versym_mem;
+  Elf_Data* versym_data = (versym_section)
+    ? elf_getdata(versym_section, NULL)
+    : NULL;
+  GElf_Versym* versym = (versym_data)
+    ? gelf_getversym(versym_data, symbol_index, &versym_mem)
+    : NULL;
+
+  if (versym == 0 || *versym <= 1)
+    // I got these value from the code of readelf.c in elfutils.
+    // Apparently, if the symbol version entry has these values, the
+    // symbol must be discarded. This is not documented in the
+    // official specification.
+    return false;
+
+  if (get_def_version)
+    {
+      if (*versym == 0x8001)
+	// I got this value from the code of readelf.c in elfutils
+	// too.  It's not really documented in the official
+	// specification.
+	return false;
+
+      if (verdef_section
+	  && get_version_definition_for_versym(elf_handle, versym,
+					       verdef_section, version))
+	return true;
+    }
+  else
+    {
+      if (verneed_section
+	  && get_version_needed_for_versym(elf_handle, versym,
+					   verneed_section, version))
+	return true;
+    }
+
+  return false;
+}
+
+
 
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 58720da0fa9e..7e1c231ccc4e 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -96,6 +96,34 @@ find_data_section(Elf* elf_handle);
 Elf_Scn*
 find_data1_section(Elf* elf_handle);
 
+bool
+get_symbol_versionning_sections(Elf*		elf_handle,
+				Elf_Scn*&	versym_section,
+				Elf_Scn*&	verdef_section,
+				Elf_Scn*&	verneed_section);
+
+//
+// Helpers for symbol versioning
+//
+
+bool
+get_version_definition_for_versym(Elf*			 elf_handle,
+				  GElf_Versym*		 versym,
+				  Elf_Scn*		 verdef_section,
+				  elf_symbol::version&	 version);
+
+bool
+get_version_needed_for_versym(Elf*			elf_handle,
+			      GElf_Versym*		versym,
+			      Elf_Scn*			verneed_section,
+			      elf_symbol::version&	version);
+
+bool
+get_version_for_symbol(Elf*			elf_handle,
+		       size_t			symbol_index,
+		       bool			get_def_version,
+		       elf_symbol::version&	version);
+
 } // end namespace elf_helpers
 } // end namespace abigail
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 4/8] abg-elf-helpers: move some kernel helpers from abg-dwarf-reader
  2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                   ` (2 preceding siblings ...)
  2020-04-20 11:08 ` [PATCH 3/8] abg-elf-helpers: move some versioning " Matthias Maennich
@ 2020-04-20 11:08 ` Matthias Maennich
  2020-04-20 14:32   ` Giuliano Procida
  2020-04-20 11:08 ` [PATCH 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers Matthias Maennich
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-20 11:08 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

Move some definitions from abg-dwarf-reader to abg-elf-helpers that are
strictly only related to ELF.

        * abg-dwarf-reader.cc(binary_is_linux_kernel): Move function out.
	(binary_is_linux_kernel_module): Likewise.
	(find_ksymtab_strings_section): Likewise.
        * abg-elf-helpers.cc(binary_is_linux_kernel): Move function in.
	(binary_is_linux_kernel_module): Likewise.
	(find_ksymtab_strings_section): Likewise.
        * abg-elf-helpers.cc(binary_is_linux_kernel): Add declaration.
	(binary_is_linux_kernel_module): Likewise.
	(find_ksymtab_strings_section): Likewise.

Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 46 -----------------------------------------
 src/abg-elf-helpers.cc  | 45 ++++++++++++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h   | 14 +++++++++++++
 3 files changed, 59 insertions(+), 46 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 303c1f8df4c2..3adb978b784b 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -542,52 +542,6 @@ compare_dies(const read_context& ctxt,
 	     bool update_canonical_dies_on_the_fly);
 
 
-/// Test if the ELF binary denoted by a given ELF handle is a Linux
-/// Kernel Module.
-///
-/// @param elf_handle the ELF handle to consider.
-///
-/// @return true iff the binary denoted by @p elf_handle is a Linux
-/// kernel module.
-static bool
-binary_is_linux_kernel_module(Elf *elf_handle)
-{
-  return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
-	  && find_section(elf_handle,
-			  ".gnu.linkonce.this_module",
-			  SHT_PROGBITS));
-}
-
-/// Test if the ELF binary denoted by a given ELF handle is a Linux
-/// Kernel binary (either vmlinux or a kernel module).
-///
-/// @param elf_handle the ELF handle to consider.
-///
-/// @return true iff the binary denoted by @p elf_handle is a Linux
-/// kernel binary
-static bool
-binary_is_linux_kernel(Elf *elf_handle)
-{
-  return (find_section(elf_handle,
-		       "__ksymtab_strings",
-		       SHT_PROGBITS)
-	  || binary_is_linux_kernel_module(elf_handle));
-}
-
-/// Find the __ksymtab_strings section of a Linux kernel binary.
-///
-///
-/// @return the find_ksymtab_strings_section of the linux kernel
-/// binary denoted by @p elf_handle, or nil if such a section could
-/// not be found.
-static Elf_Scn*
-find_ksymtab_strings_section(Elf *elf_handle)
-{
-  if (binary_is_linux_kernel(elf_handle))
-    return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
-  return 0;
-}
-
 /// Get the address at which a given binary is loaded in memory⋅
 ///
 /// @param elf_handle the elf handle for the binary to consider.
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index b7b868a332ec..ff0941dc6536 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -548,6 +548,21 @@ get_symbol_versionning_sections(Elf*		elf_handle,
   return false;
 }
 
+/// Find the __ksymtab_strings section of a Linux kernel binary.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @return the find_ksymtab_strings_section of the linux kernel
+/// binary denoted by @p elf_handle, or nil if such a section could
+/// not be found.
+Elf_Scn*
+find_ksymtab_strings_section(Elf *elf_handle)
+{
+  if (binary_is_linux_kernel(elf_handle))
+    return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
+  return 0;
+}
+
 /// Get the version definition (from the SHT_GNU_verdef section) of a
 /// given symbol represented by a pointer to GElf_Versym.
 ///
@@ -750,7 +765,37 @@ get_version_for_symbol(Elf*			elf_handle,
   return false;
 }
 
+/// Test if the ELF binary denoted by a given ELF handle is a Linux
+/// Kernel Module.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the binary denoted by @p elf_handle is a Linux
+/// kernel module.
+bool
+binary_is_linux_kernel_module(Elf *elf_handle)
+{
+  return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
+	  && find_section(elf_handle,
+			  ".gnu.linkonce.this_module",
+			  SHT_PROGBITS));
+}
 
+/// Test if the ELF binary denoted by a given ELF handle is a Linux
+/// Kernel binary (either vmlinux or a kernel module).
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the binary denoted by @p elf_handle is a Linux
+/// kernel binary
+bool
+binary_is_linux_kernel(Elf *elf_handle)
+{
+  return (find_section(elf_handle,
+		       "__ksymtab_strings",
+		       SHT_PROGBITS)
+	  || binary_is_linux_kernel_module(elf_handle));
+}
 
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 7e1c231ccc4e..33348126028c 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -102,6 +102,9 @@ get_symbol_versionning_sections(Elf*		elf_handle,
 				Elf_Scn*&	verdef_section,
 				Elf_Scn*&	verneed_section);
 
+Elf_Scn*
+find_ksymtab_strings_section(Elf *elf_handle);
+
 //
 // Helpers for symbol versioning
 //
@@ -124,6 +127,17 @@ get_version_for_symbol(Elf*			elf_handle,
 		       bool			get_def_version,
 		       elf_symbol::version&	version);
 
+//
+// Helpers for Linux Kernel Binaries
+//
+
+bool
+binary_is_linux_kernel_module(Elf *elf_handle);
+
+bool
+binary_is_linux_kernel(Elf *elf_handle);
+
+
 } // end namespace elf_helpers
 } // end namespace abigail
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers
  2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                   ` (3 preceding siblings ...)
  2020-04-20 11:08 ` [PATCH 4/8] abg-elf-helpers: move some kernel " Matthias Maennich
@ 2020-04-20 11:08 ` Matthias Maennich
  2020-04-20 15:29   ` Giuliano Procida
  2020-04-20 11:08 ` [PATCH 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers Matthias Maennich
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-20 11:08 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

This consistently names the is_linux_kernel* helpers and keeps only the
copy in the elf-helpers. All users are adjusted.

	* src/abg-dwarf-reader.cc
	(read_context::function_symbol_is_exported): use is_linux_kernel
	from elf_helpers.
	(read_context::variable_is_exported): Likewise.
	(read_context::get_symtab_format): Likewise.
	(read_context::load_symbol_maps): Likewise.
	(read_debug_info_into_corpus): Likewise.
	(read_context::is_linux_kernel_binary): Drop function.
	(read_context::is_linux_kernel_module): Drop function.
	* src/abg-elf-helpers.cc (binary_is_linux_kernel): rename to
	is_linux_kernel
	(binary_is_linux_kernel_module): rename to is_linux_kernel_module
	(find_ksymtab_strings_section): Adjust to function renames.
	* src/abg-elf-helpers.h (binary_is_linux_kernel): rename to
	is_linux_kernel
	(binary_is_linux_kernel_module): rename to is_linux_kernel_module

Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 37 +++++++------------------------------
 src/abg-elf-helpers.cc  |  8 ++++----
 src/abg-elf-helpers.h   |  4 ++--
 3 files changed, 13 insertions(+), 36 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 3adb978b784b..ec1f9f3fe8f3 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -5939,7 +5939,7 @@ public:
 
     address_set_sptr set;
     bool looking_at_linux_kernel_binary =
-      load_in_linux_kernel_mode() && is_linux_kernel_binary();
+      load_in_linux_kernel_mode() && is_linux_kernel(elf_handle());
 
     if (looking_at_linux_kernel_binary)
       {
@@ -5979,7 +5979,7 @@ public:
 
     address_set_sptr set;
     bool looking_at_linux_kernel_binary =
-      load_in_linux_kernel_mode() && is_linux_kernel_binary();
+      load_in_linux_kernel_mode() && is_linux_kernel(elf_handle());
 
     if (looking_at_linux_kernel_binary)
       {
@@ -6920,7 +6920,7 @@ public:
 	  {
 	    // Since Linux kernel modules are relocatable, we can first try
 	    // using a heuristic based on relocations to guess the ksymtab format.
-	    if (is_linux_kernel_module())
+	    if (is_linux_kernel_module(elf_handle()))
 	     {
 	       ksymtab_format_ = get_ksymtab_format_module();
 	       if (ksymtab_format_ != UNDEFINED_KSYMTAB_FORMAT)
@@ -7467,7 +7467,7 @@ public:
 						 load_undefined_fun_map,
 						 load_undefined_var_map))
 	  {
-	    if (load_in_linux_kernel_mode() && is_linux_kernel_binary())
+	    if (load_in_linux_kernel_mode() && is_linux_kernel(elf_handle()))
 	      return load_linux_specific_exported_symbol_maps();
 	    return true;
 	  }
@@ -8166,30 +8166,6 @@ public:
   load_in_linux_kernel_mode(bool f)
   {options_.load_in_linux_kernel_mode = f;}
 
-  /// Guess if the current binary is a Linux Kernel or a Linux Kernel module.
-  ///
-  /// To guess that, the function looks for the presence of the
-  /// special "__ksymtab_strings" section in the binary.
-  ///
-  bool
-  is_linux_kernel_binary() const
-  {
-    return find_section(elf_handle(), "__ksymtab_strings", SHT_PROGBITS)
-	   || is_linux_kernel_module();
-  }
-
-  /// Guess if the current binary is a Linux Kernel module.
-  ///
-  /// To guess that, the function looks for the presence of the special
-  /// ".modinfo" and ".gnu.linkonce.this_module" sections in the binary.
-  ///
-  bool
-  is_linux_kernel_module() const
-  {
-    return find_section(elf_handle(), ".modinfo", SHT_PROGBITS)
-	   && find_section(elf_handle(), ".gnu.linkonce.this_module", SHT_PROGBITS);
-  }
-
   /// Getter of the "show_stats" flag.
   ///
   /// This flag tells if we should emit statistics about various
@@ -16322,7 +16298,7 @@ read_debug_info_into_corpus(read_context& ctxt)
   // First set some mundane properties of the corpus gathered from
   // ELF.
   ctxt.current_corpus()->set_path(ctxt.elf_path());
-  if (ctxt.is_linux_kernel_binary())
+  if (is_linux_kernel(ctxt.elf_handle()))
     ctxt.current_corpus()->set_origin(corpus::LINUX_KERNEL_BINARY_ORIGIN);
   else
     ctxt.current_corpus()->set_origin(corpus::DWARF_ORIGIN);
@@ -16335,7 +16311,8 @@ read_debug_info_into_corpus(read_context& ctxt)
   // Set symbols information to the corpus.
   if (!get_ignore_symbol_table(ctxt))
     {
-      if (ctxt.load_in_linux_kernel_mode() && ctxt.is_linux_kernel_binary())
+      if (ctxt.load_in_linux_kernel_mode()
+	  && is_linux_kernel(ctxt.elf_handle()))
 	{
 	  string_elf_symbols_map_sptr exported_fn_symbols_map
 	    (new string_elf_symbols_map_type);
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index ff0941dc6536..ede191014369 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -558,7 +558,7 @@ get_symbol_versionning_sections(Elf*		elf_handle,
 Elf_Scn*
 find_ksymtab_strings_section(Elf *elf_handle)
 {
-  if (binary_is_linux_kernel(elf_handle))
+  if (is_linux_kernel(elf_handle))
     return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
   return 0;
 }
@@ -773,7 +773,7 @@ get_version_for_symbol(Elf*			elf_handle,
 /// @return true iff the binary denoted by @p elf_handle is a Linux
 /// kernel module.
 bool
-binary_is_linux_kernel_module(Elf *elf_handle)
+is_linux_kernel_module(Elf *elf_handle)
 {
   return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
 	  && find_section(elf_handle,
@@ -789,12 +789,12 @@ binary_is_linux_kernel_module(Elf *elf_handle)
 /// @return true iff the binary denoted by @p elf_handle is a Linux
 /// kernel binary
 bool
-binary_is_linux_kernel(Elf *elf_handle)
+is_linux_kernel(Elf *elf_handle)
 {
   return (find_section(elf_handle,
 		       "__ksymtab_strings",
 		       SHT_PROGBITS)
-	  || binary_is_linux_kernel_module(elf_handle));
+	  || is_linux_kernel_module(elf_handle));
 }
 
 } // end namespace elf_helpers
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 33348126028c..7ddd887de959 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -132,10 +132,10 @@ get_version_for_symbol(Elf*			elf_handle,
 //
 
 bool
-binary_is_linux_kernel_module(Elf *elf_handle);
+is_linux_kernel_module(Elf *elf_handle);
 
 bool
-binary_is_linux_kernel(Elf *elf_handle);
+is_linux_kernel(Elf *elf_handle);
 
 
 } // end namespace elf_helpers
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers
  2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                   ` (4 preceding siblings ...)
  2020-04-20 11:08 ` [PATCH 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers Matthias Maennich
@ 2020-04-20 11:08 ` Matthias Maennich
  2020-04-20 15:24   ` Giuliano Procida
  2020-04-20 11:08 ` [PATCH 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers) Matthias Maennich
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-20 11:08 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

This change migrates all ELF helpers related to section lookup to
abg-elf-helpers.{cc,h}. It also homogenizes the interface of those to
always return Elf_Scn* and NULL in case that section can't be found.
Though this smells like a functional change, this latter change is
purely cosmetic.

	* src/abg-dwarf-reader.cc (read_context::find_symbol_table_section):
	adjust to new interface of elf_helpers::find_symbol_table_section.
	(find_opd_section): use elf_helpers::find_opd_section for lookup.
	(find_ksymtab_section): use elf_helpers::find_ksymtab_section.
	(find_ksymtab_gpl_section): use elf_helpers::find_ksymtab_gpl_section.
	(find_relocation_section): Move out function.
	(get_binary_load_address): Move out function.
	(find_ksymtab_reloc_section): use elf_helpers::find_relocation_section
	(find_ksymtab_gpl_reloc_section): use elf_helpers::find_relocation_section
	* src/elf-helpers.cc (find_symbol_table_section): change
	interface to match other find_*_section functions.
	(find_symbol_table_section_index): Adjust for the new interface
	of find_symbol_table_section.
	(find_opd_section): New function.
	(find_ksymtab_section): New function.
	(find_ksymtab_gpl_section): New function.
	(find_relocation_section): New function.
	(get_binary_load_address): New function.
	* src/elf-helpers.h (find_symbol_table_section): Change declaration.
	(find_opd_section): New function declation.
	(find_ksymtab_section): New function declation.
	(find_ksymtab_gpl_section): New function declation.
	(find_relocation_section): New function declation.
	(get_binary_load_address): New function declation.

Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 112 ++++++----------------------------
 src/abg-elf-helpers.cc  | 129 +++++++++++++++++++++++++++++++++++++---
 src/abg-elf-helpers.h   |  22 ++++++-
 3 files changed, 157 insertions(+), 106 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index ec1f9f3fe8f3..56da03a60940 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -542,53 +542,6 @@ compare_dies(const read_context& ctxt,
 	     bool update_canonical_dies_on_the_fly);
 
 
-/// Get the address at which a given binary is loaded in memory⋅
-///
-/// @param elf_handle the elf handle for the binary to consider.
-///
-/// @param load_address the address where the binary is loaded.  This
-/// is set by the function iff it returns true.
-///
-/// @return true if the function could get the binary load address
-/// and assign @p load_address to it.
-static bool
-get_binary_load_address(Elf *elf_handle,
-			GElf_Addr &load_address)
-{
-  GElf_Ehdr eh_mem;
-  GElf_Ehdr *elf_header = gelf_getehdr(elf_handle, &eh_mem);
-  size_t num_segments = elf_header->e_phnum;
-  GElf_Phdr *program_header = 0;
-  GElf_Addr result;
-  bool found_loaded_segment = false;
-  GElf_Phdr ph_mem;
-
-  for (unsigned i = 0; i < num_segments; ++i)
-    {
-      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
-      if (program_header && program_header->p_type == PT_LOAD)
-	{
-	  if (!found_loaded_segment)
-	    {
-	      result = program_header->p_vaddr;
-	      found_loaded_segment = true;
-	    }
-
-	  if (program_header->p_vaddr < result)
-	    // The resulting load address we want is the lowest
-	    // load address of all the loaded segments.
-	    result = program_header->p_vaddr;
-	}
-    }
-
-  if (found_loaded_segment)
-    {
-      load_address = result;
-      return true;
-    }
-  return false;
-}
-
 /// Find the file name of the alternate debug info file.
 ///
 /// @param elf_module the elf module to consider.
@@ -5282,8 +5235,8 @@ public:
   find_symbol_table_section() const
   {
     if (!symtab_section_)
-      dwarf_reader::find_symbol_table_section(elf_handle(),
-					      const_cast<read_context*>(this)->symtab_section_);
+      const_cast<read_context*>(this)->symtab_section_ =
+	  elf_helpers::find_symbol_table_section(elf_handle());
     return symtab_section_;
   }
 
@@ -5296,8 +5249,8 @@ public:
   find_opd_section() const
   {
     if (!opd_section_)
-      const_cast<read_context*>(this)->opd_section_=
-	find_section(elf_handle(), ".opd", SHT_PROGBITS);
+      const_cast<read_context*>(this)->opd_section_ =
+	  elf_helpers::find_opd_section(elf_handle());
     return opd_section_;
   }
 
@@ -5310,39 +5263,21 @@ public:
   {
     if (!ksymtab_section_)
       const_cast<read_context*>(this)->ksymtab_section_ =
-	find_section(elf_handle(), "__ksymtab", SHT_PROGBITS);
+	  elf_helpers::find_ksymtab_section(elf_handle());
     return ksymtab_section_;
   }
 
-  /// Return the .rel{a,} section corresponding to a given section.
-  ///
-  /// @param target_section the section to search the relocation section for
+  /// Return the __ksymtab_gpl section of a linux kernel ELF file
+  /// (either a vmlinux binary or a kernel module).
   ///
-  /// @return the .rel{a,} section if found, null otherwise.
+  /// @return the __ksymtab_gpl section if found, nil otherwise.
   Elf_Scn*
-  find_relocation_section(Elf_Scn* target_section) const
+  find_ksymtab_gpl_section() const
   {
-    if (target_section)
-      {
-	// the relo section we are searching for has this index as sh_info
-	size_t target_index = elf_ndxscn(target_section);
-
-	// now iterate over all the sections, look for relocation sections and
-	// find the one that points to the section we are searching for
-	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 != SHT_RELA && header->sh_type != SHT_REL))
-	      continue;
-
-	    if (header->sh_info == target_index)
-	      return section;
-	  }
-      }
-    return NULL;
+    if (!ksymtab_gpl_section_)
+      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
+	  elf_helpers::find_ksymtab_gpl_section(elf_handle());
+    return ksymtab_gpl_section_;
   }
 
   /// Return the .rel{a,}__ksymtab section of a linux kernel ELF file (either
@@ -5354,25 +5289,12 @@ public:
   {
     if (!ksymtab_reloc_section_)
       {
-	const_cast<read_context*>(this)->ksymtab_reloc_section_
-	    = find_relocation_section(find_ksymtab_section());
+	const_cast<read_context*>(this)->ksymtab_reloc_section_ =
+	    find_relocation_section(elf_handle(), find_ksymtab_section());
       }
     return ksymtab_reloc_section_;
   }
 
-  /// Return the __ksymtab_gpl section of a linux kernel ELF file
-  /// (either a vmlinux binary or a kernel module).
-  ///
-  /// @return the __ksymtab_gpl section if found, nil otherwise.
-  Elf_Scn*
-  find_ksymtab_gpl_section() const
-  {
-    if (!ksymtab_gpl_section_)
-      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
-	find_section(elf_handle(), "__ksymtab_gpl", SHT_PROGBITS);
-    return ksymtab_gpl_section_;
-  }
-
   /// Return the .rel{a,}__ksymtab_gpl section of a linux kernel ELF file
   /// (either a vmlinux binary or a kernel module).
   ///
@@ -5382,8 +5304,8 @@ public:
   {
     if (!ksymtab_gpl_reloc_section_)
       {
-	const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_
-	    = find_relocation_section(find_ksymtab_gpl_section());
+	const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_ =
+	    find_relocation_section(elf_handle(), find_ksymtab_gpl_section());
       }
     return ksymtab_gpl_reloc_section_;
   }
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index ede191014369..b77440206fb0 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -357,9 +357,9 @@ find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
 ///
 /// @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)
+/// @return the symbol table section
+Elf_Scn*
+find_symbol_table_section(Elf* elf_handle)
 {
   Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0;
   while ((section = elf_nextscn(elf_handle, section)) != 0)
@@ -378,12 +378,11 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
       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;
+	return sym_tab ? sym_tab : dynsym;
       else
-	symtab = dynsym ? dynsym : sym_tab;
-      return true;
+	return dynsym ? dynsym : sym_tab;
     }
-  return false;
+  return NULL;
 }
 
 /// Find the index (in the section headers table) of the symbol table
@@ -402,8 +401,9 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
 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))
+  Elf_Scn* section = find_symbol_table_section(elf_handle);
+
+  if (!section)
     return false;
 
   symtab_index = elf_ndxscn(section);
@@ -500,6 +500,17 @@ Elf_Scn*
 find_data1_section(Elf* elf_handle)
 {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
 
+/// Return the "Official Procedure descriptors section."  This
+/// section is named .opd, and is usually present only on PPC64
+/// ELFv1 binaries.
+///
+/// @param elf_handle the elf handle to consider.
+///
+/// @return the .opd section, if found.  Return nil otherwise.
+Elf_Scn*
+find_opd_section(Elf* elf_handle)
+{return find_section(elf_handle, ".opd", SHT_PROGBITS);}
+
 /// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
 /// sections that are involved in symbol versionning.
 ///
@@ -548,6 +559,26 @@ get_symbol_versionning_sections(Elf*		elf_handle,
   return false;
 }
 
+/// Return the __ksymtab section of a linux kernel ELF file (either
+/// a vmlinux binary or a kernel module).
+///
+/// @param elf_handle the elf handle to consider.
+///
+/// @return the __ksymtab section if found, nil otherwise.
+Elf_Scn*
+find_ksymtab_section(Elf* elf_handle)
+{return find_section(elf_handle, "__ksymtab", SHT_PROGBITS);}
+
+/// Return the __ksymtab_gpl section of a linux kernel ELF file (either
+/// a vmlinux binary or a kernel module).
+///
+/// @param elf_handle the elf handle to consider.
+///
+/// @return the __ksymtab section if found, nil otherwise.
+Elf_Scn*
+find_ksymtab_gpl_section(Elf* elf_handle)
+{return find_section(elf_handle, "__ksymtab_gpl", SHT_PROGBITS);}
+
 /// Find the __ksymtab_strings section of a Linux kernel binary.
 ///
 /// @param elf_handle the elf handle to use.
@@ -563,6 +594,39 @@ find_ksymtab_strings_section(Elf *elf_handle)
   return 0;
 }
 
+/// Return the .rel{a,} section corresponding to a given section.
+///
+/// @param elf_handle the elf handle to consider.
+///
+/// @param target_section the section to search the relocation section for
+///
+/// @return the .rel{a,} section if found, null otherwise.
+Elf_Scn*
+find_relocation_section(Elf* elf_handle, Elf_Scn* target_section)
+{
+  if (target_section)
+    {
+      // the relo section we are searching for has this index as sh_info
+      size_t target_index = elf_ndxscn(target_section);
+
+      // now iterate over all the sections, look for relocation sections and
+      // find the one that points to the section we are searching for
+      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 != SHT_RELA && header->sh_type != SHT_REL))
+	    continue;
+
+	  if (header->sh_info == target_index)
+	    return section;
+	}
+    }
+  return NULL;
+}
+
 /// Get the version definition (from the SHT_GNU_verdef section) of a
 /// given symbol represented by a pointer to GElf_Versym.
 ///
@@ -797,5 +861,52 @@ is_linux_kernel(Elf *elf_handle)
 	  || is_linux_kernel_module(elf_handle));
 }
 
+/// Get the address at which a given binary is loaded in memory⋅
+///
+/// @param elf_handle the elf handle for the binary to consider.
+///
+/// @param load_address the address where the binary is loaded.  This
+/// is set by the function iff it returns true.
+///
+/// @return true if the function could get the binary load address
+/// and assign @p load_address to it.
+bool
+get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
+{
+  GElf_Ehdr elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+  size_t num_segments = elf_header.e_phnum;
+  GElf_Phdr *program_header = NULL;
+  GElf_Addr result;
+  bool found_loaded_segment = false;
+  GElf_Phdr ph_mem;
+
+  for (unsigned i = 0; i < num_segments; ++i)
+    {
+      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
+      if (program_header && program_header->p_type == PT_LOAD)
+	{
+	  if (!found_loaded_segment)
+	    {
+	      result = program_header->p_vaddr;
+	      found_loaded_segment = true;
+	    }
+
+	  if (program_header->p_vaddr < result)
+	    // The resulting load address we want is the lowest
+	    // load address of all the loaded segments.
+	    result = program_header->p_vaddr;
+	}
+    }
+
+  if (found_loaded_segment)
+    {
+      load_address = result;
+      return true;
+    }
+  return false;
+}
+
+
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 7ddd887de959..8a83bb4f2e95 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -63,8 +63,8 @@ find_section(Elf*		elf_handle,
 	     const std::string& name,
 	     Elf64_Word		section_type);
 
-bool
-find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab);
+Elf_Scn*
+find_symbol_table_section(Elf* elf_handle);
 
 bool
 find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index);
@@ -96,15 +96,27 @@ find_data_section(Elf* elf_handle);
 Elf_Scn*
 find_data1_section(Elf* elf_handle);
 
+Elf_Scn*
+find_opd_section(Elf* elf_handle);
+
 bool
 get_symbol_versionning_sections(Elf*		elf_handle,
 				Elf_Scn*&	versym_section,
 				Elf_Scn*&	verdef_section,
 				Elf_Scn*&	verneed_section);
 
+Elf_Scn*
+find_ksymtab_section(Elf* elf_handle);
+
+Elf_Scn*
+find_ksymtab_gpl_section(Elf* elf_handle);
+
 Elf_Scn*
 find_ksymtab_strings_section(Elf *elf_handle);
 
+Elf_Scn*
+find_relocation_section(Elf* elf_handle, Elf_Scn* target_section);
+
 //
 // Helpers for symbol versioning
 //
@@ -137,6 +149,12 @@ is_linux_kernel_module(Elf *elf_handle);
 bool
 is_linux_kernel(Elf *elf_handle);
 
+//
+// Misc Helpers
+//
+
+bool
+get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address);
 
 } // end namespace elf_helpers
 } // end namespace abigail
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers)
  2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                   ` (5 preceding siblings ...)
  2020-04-20 11:08 ` [PATCH 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers Matthias Maennich
@ 2020-04-20 11:08 ` Matthias Maennich
  2020-04-20 15:25   ` Giuliano Procida
  2020-04-20 11:08 ` [PATCH 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr Matthias Maennich
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-20 11:08 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

This migrates more architecture specific helpers over to the
elf-helpers. No functional change intended.

Signed-off-by: Matthias Maennich <maennich@google.com>
	* src/abg-dwarf-reader.cc(elf_architecture_is_ppc64): Move
	function out and adjust callers to call the migrated
	functions.
	(elf_architecture_is_big_endian): Likewise.
	(architecture_word_size): Likewise.
	(current_elf_file_is_executable): Likewise.
	(current_elf_file_is_dso): Likewise.
	* src/abg-elf-helpers.cc (architecture_is_ppc64): Add new function.
	(architecture_is_big_endian): Likewise.
	(get_architecture_word_size): Likewise.
	(is_executable): Likewise.
	(is_dso): Likewise.
	* src/abg-elf-helpers.h (architecture_is_ppc64): Add new declaration.
	(architecture_is_big_endian): Likewise.
	(get_architecture_word_size): Likewise.
	(is_executable): Likewise.
	(is_dso): Likewise.

Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 91 ++++-------------------------------------
 src/abg-elf-helpers.cc  | 79 +++++++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h   | 18 ++++++++
 3 files changed, 106 insertions(+), 82 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 56da03a60940..dc3332410b1e 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -5700,10 +5700,10 @@ public:
     if (!elf_handle())
       return fn_desc_address;
 
-    if (!elf_architecture_is_ppc64())
+    if (!architecture_is_ppc64(elf_handle()))
       return fn_desc_address;
 
-    bool is_big_endian = elf_architecture_is_big_endian();
+    bool is_big_endian = architecture_is_big_endian(elf_handle());
 
     Elf_Scn *opd_section = find_opd_section();
     if (!opd_section)
@@ -5979,7 +5979,7 @@ public:
   {
     if (!fun_entry_addr_sym_map_ && !fun_addr_sym_map_)
       maybe_load_symbol_maps();
-    if (elf_architecture_is_ppc64())
+    if (architecture_is_ppc64(elf_handle()))
       return fun_entry_addr_sym_map_;
     return fun_addr_sym_map_;
   }
@@ -6335,79 +6335,6 @@ public:
   elf_architecture() const
   {return elf_architecture_;}
 
-  /// Return the size of a word for the current architecture.
-  /// @return the size of a word.
-  unsigned char
-  architecture_word_size() const
-  {
-    unsigned char word_size = 0;
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-    if (elf_header->e_ident[EI_CLASS] == ELFCLASS32)
-      word_size = 4;
-    else if (elf_header->e_ident[EI_CLASS] == ELFCLASS64)
-      word_size = 8;
-    else
-      ABG_ASSERT_NOT_REACHED;
-    return word_size;
-  }
-
-  /// Test if the architecture of the current binary is ppc64.
-  ///
-  /// @return true iff the architecture of the current binary is ppc64.
-  bool
-  elf_architecture_is_ppc64() const
-  {
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-
-    return (elf_header && elf_header->e_machine == EM_PPC64);
-  }
-
-  /// Test if the endianness of the current binary is Big Endian.
-  ///
-  /// https://en.wikipedia.org/wiki/Endianness.
-  ///
-  /// @return true iff the current binary is Big Endian.
-  bool
-  elf_architecture_is_big_endian() const
-  {
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-
-    bool is_big_endian = (elf_header->e_ident[EI_DATA] == ELFDATA2MSB);
-
-    if (!is_big_endian)
-      ABG_ASSERT(elf_header->e_ident[EI_DATA] == ELFDATA2LSB);
-
-    return is_big_endian;
-  }
-
-  /// Test if the current elf file being read is an executable.
-  ///
-  /// @return true iff the current elf file being read is an
-  /// executable.
-  bool
-  current_elf_file_is_executable() const
-  {
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-    return elf_header->e_type == ET_EXEC;
-  }
-
-  /// Test if the current elf file being read is a dynamic shared
-  /// object.
-  ///
-  /// @return true iff the current elf file being read is a
-  /// dynamic shared object.
-  bool
-  current_elf_file_is_dso() const
-  {
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-    return elf_header->e_type == ET_DYN;
-  }
-
   /// Getter for the map of global variables symbol address -> global
   /// variable symbol index.
   ///
@@ -6471,7 +6398,7 @@ public:
     GElf_Ehdr elf_header;
     ABG_ASSERT(gelf_getehdr(elf_handle(), &elf_header));
 
-    bool is_ppc64 = elf_architecture_is_ppc64();
+    bool is_ppc64 = architecture_is_ppc64(elf_handle());
 
     for (size_t i = 0; i < nb_syms; ++i)
       {
@@ -6688,7 +6615,7 @@ public:
   {
     Elf_Data*	    elf_data = elf_rawdata(section, 0);
     uint8_t*	    bytes = reinterpret_cast<uint8_t*>(elf_data->d_buf);
-    bool	    is_big_endian = elf_architecture_is_big_endian();
+    bool	    is_big_endian = architecture_is_big_endian(elf_handle());
     elf_symbol_sptr symbol;
     GElf_Addr	    symbol_address = 0;
 
@@ -6696,7 +6623,7 @@ public:
     if (position_relative_relocations)
       symbol_value_size = sizeof(int32_t);
     else
-      symbol_value_size = architecture_word_size();
+      symbol_value_size = get_architecture_word_size(elf_handle());
 
     const int read_offset = (symbol_offset * symbol_value_size);
     bytes += read_offset;
@@ -6886,7 +6813,7 @@ public:
     if (format == UNDEFINED_KSYMTAB_FORMAT)
       ;
     else if (format == PRE_V4_19_KSYMTAB_FORMAT)
-      result = architecture_word_size();
+      result = get_architecture_word_size(elf_handle());
     else if (format == V4_19_KSYMTAB_FORMAT)
       result = 4;
     else
@@ -7065,7 +6992,7 @@ public:
     //
     // Lets thus walk the array of entries, and let's read just the
     // symbol address part of each entry.
-    bool is_big_endian = elf_architecture_is_big_endian();
+    bool is_big_endian = architecture_is_big_endian(elf_handle());
     elf_symbol_sptr symbol;
     unsigned char symbol_value_size = get_ksymtab_symbol_value_size();
 
@@ -7367,7 +7294,7 @@ public:
     if (!fun_addr_sym_map_)
       fun_addr_sym_map_.reset(new addr_elf_symbol_sptr_map_type);
 
-    if (!fun_entry_addr_sym_map_ && elf_architecture_is_ppc64())
+    if (!fun_entry_addr_sym_map_ && architecture_is_ppc64(elf_handle()))
       fun_entry_addr_sym_map_.reset(new addr_elf_symbol_sptr_map_type);
 
     if (!var_syms_)
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index b77440206fb0..895feb6f7768 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -829,6 +829,40 @@ get_version_for_symbol(Elf*			elf_handle,
   return false;
 }
 
+/// Test if the architecture of the current binary is ppc64.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the architecture of the current binary is ppc64.
+bool
+architecture_is_ppc64(Elf* elf_handle)
+{
+  GElf_Ehdr  eh_mem;
+  GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
+  return (elf_header && elf_header->e_machine == EM_PPC64);
+}
+
+/// Test if the endianness of the current binary is Big Endian.
+///
+/// https://en.wikipedia.org/wiki/Endianness.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the current binary is Big Endian.
+bool
+architecture_is_big_endian(Elf* elf_handle)
+{
+  GElf_Ehdr  elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+
+  bool is_big_endian = (elf_header.e_ident[EI_DATA] == ELFDATA2MSB);
+
+  if (!is_big_endian)
+    ABG_ASSERT(elf_header.e_ident[EI_DATA] == ELFDATA2LSB);
+
+  return is_big_endian;
+}
+
 /// Test if the ELF binary denoted by a given ELF handle is a Linux
 /// Kernel Module.
 ///
@@ -907,6 +941,51 @@ get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
   return false;
 }
 
+/// Return the size of a word for the current architecture.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return the size of a word.
+unsigned char
+get_architecture_word_size(Elf* elf_handle)
+{
+  unsigned char word_size = 0;
+  GElf_Ehdr	elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+  if (elf_header.e_ident[EI_CLASS] == ELFCLASS32)
+    word_size = 4;
+  else if (elf_header.e_ident[EI_CLASS] == ELFCLASS64)
+    word_size = 8;
+  else
+    ABG_ASSERT_NOT_REACHED;
+  return word_size;
+}
+
+/// Test if the elf file being read is an executable.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the elf file being read is an / executable.
+bool
+is_executable(Elf* elf_handle)
+{
+  GElf_Ehdr  elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+  return elf_header.e_type == ET_EXEC;
+}
+
+/// Test if the elf file being read is a dynamic shared / object.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the elf file being read is a / dynamic shared object.
+bool
+is_dso(Elf* elf_handle)
+{
+  GElf_Ehdr  elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+  return elf_header.e_type == ET_DYN;
+}
 
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 8a83bb4f2e95..6eff245a6a30 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -139,6 +139,15 @@ get_version_for_symbol(Elf*			elf_handle,
 		       bool			get_def_version,
 		       elf_symbol::version&	version);
 
+//
+// Architecture specific helpers
+//
+bool
+architecture_is_ppc64(Elf* elf_handle);
+
+bool
+architecture_is_big_endian(Elf* elf_handle);
+
 //
 // Helpers for Linux Kernel Binaries
 //
@@ -156,6 +165,15 @@ is_linux_kernel(Elf *elf_handle);
 bool
 get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address);
 
+unsigned char
+get_architecture_word_size(Elf* elf_handle);
+
+bool
+is_executable(Elf* elf_handle);
+
+bool
+is_dso(Elf* elf_handle);
+
 } // end namespace elf_helpers
 } // end namespace abigail
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr
  2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                   ` (6 preceding siblings ...)
  2020-04-20 11:08 ` [PATCH 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers) Matthias Maennich
@ 2020-04-20 11:08 ` Matthias Maennich
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
  8 siblings, 0 replies; 37+ messages in thread
From: Matthias Maennich @ 2020-04-20 11:08 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

Move maybe_adjust_et_rel_sym_addr_to_abs_addr to the elf-helpers
dropping the wrapping overload.

	* src/abg-dwarf-reader.cc(maybe_adjust_et_rel_sym_addr_to_abs_addr):
	Move out functions (drop the wrapped overload completely).
	* src/abg-elf-helpers.cc(maybe_adjust_et_rel_sym_addr_to_abs_addr):
	New function.
	* src/abg-elf-helpers.h(maybe_adjust_et_rel_sym_addr_to_abs_addr):
	New function declaration.

Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 73 ++++-------------------------------------
 src/abg-elf-helpers.cc  | 40 ++++++++++++++++++++++
 src/abg-elf-helpers.h   |  3 ++
 3 files changed, 49 insertions(+), 67 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index dc3332410b1e..c65c01776398 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -6425,7 +6425,8 @@ public:
 
 		{
 		  GElf_Addr symbol_value =
-		    maybe_adjust_et_rel_sym_addr_to_abs_addr(sym);
+		      maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle(),
+							       sym);
 
 		  addr_elf_symbol_sptr_map_type::const_iterator it =
 		    fun_addr_sym_map_->find(symbol_value);
@@ -6563,7 +6564,8 @@ public:
 		else
 		  {
 		    GElf_Addr symbol_value =
-		      maybe_adjust_et_rel_sym_addr_to_abs_addr(sym);
+			maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle(),
+								 sym);
 		    addr_elf_symbol_sptr_map_type::const_iterator it =
 		      var_addr_sym_map_->find(symbol_value);
 		    if (it == var_addr_sym_map_->end())
@@ -7147,8 +7149,8 @@ public:
 	// the symbol value of native_symbol is relative to the
 	// section that symbol is defined in.  We need to translate it
 	// into an absolute (okay, binary-relative, rather) address.
-	GElf_Addr symbol_address =
-	  maybe_adjust_et_rel_sym_addr_to_abs_addr (&native_symbol);
+	GElf_Addr symbol_address = maybe_adjust_et_rel_sym_addr_to_abs_addr(
+	    elf_handle(), &native_symbol);
 
 	address_set_sptr set;
 	if (symbol->is_function())
@@ -7523,69 +7525,6 @@ public:
     return addr;
   }
 
-  /// Translate a section-relative symbol address (i.e, symbol value)
-  /// into an absolute symbol address by adding the address of the
-  /// section the symbol belongs to, to the address value.
-  ///
-  /// This is useful when looking at symbol values coming from
-  /// relocatable files (of ET_REL kind).  If the binary is not
-  /// ET_REL, then the function does nothing and returns the input
-  /// address unchanged.
-  ///
-  /// @param addr the symbol address to possibly translate.
-  ///
-  /// @param section the section the symbol which value is @p addr
-  /// belongs to.
-  ///
-  /// @return the section-relative address, translated into an
-  /// absolute address, if @p section is an ET_REL binary.  Otherwise,
-  /// return @p addr, unchanged.
-  GElf_Addr
-  maybe_adjust_et_rel_sym_addr_to_abs_addr(GElf_Addr addr, Elf_Scn *section)
-  {
-    if (!section)
-      return addr;
-
-    Elf* elf = elf_handle();
-    GElf_Ehdr elf_header;
-
-    if (!gelf_getehdr(elf, &elf_header))
-      return addr;
-
-    if (elf_header.e_type != ET_REL)
-      return addr;
-
-    GElf_Shdr section_header;
-    if (!gelf_getshdr(section, &section_header))
-      return addr;
-
-    return addr + section_header.sh_addr;
-  }
-
-  /// Translate a section-relative symbol address (i.e, symbol value)
-  /// into an absolute symbol address by adding the address of the
-  /// section the symbol belongs to, to the address value.
-  ///
-  /// This is useful when looking at symbol values coming from
-  /// relocatable files (of ET_REL kind).  If the binary is not
-  /// ET_REL, then the function does nothing and returns the input
-  /// address unchanged.
-  ///
-  /// @param sym the symbol whose address to possibly needs to be
-  /// translated.
-  ///
-  /// @return the section-relative address, translated into an
-  /// absolute address, if @p sym is from an ET_REL binary.
-  /// Otherwise, return the address of @p sym, unchanged.
-  GElf_Addr
-  maybe_adjust_et_rel_sym_addr_to_abs_addr(GElf_Sym *sym)
-  {
-    Elf_Scn *symbol_section = elf_getscn(elf_handle(), sym->st_shndx);
-    GElf_Addr result = sym->st_value;
-    result = maybe_adjust_et_rel_sym_addr_to_abs_addr(result, symbol_section);
-    return result;
-  }
-
   /// Test if a given address is in a given section.
   ///
   /// @param addr the address to consider.
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index 895feb6f7768..02ecbcf250ed 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -987,5 +987,45 @@ is_dso(Elf* elf_handle)
   return elf_header.e_type == ET_DYN;
 }
 
+/// Translate a section-relative symbol address (i.e, symbol value)
+/// into an absolute symbol address by adding the address of the
+/// section the symbol belongs to, to the address value.
+///
+/// This is useful when looking at symbol values coming from
+/// relocatable files (of ET_REL kind).  If the binary is not
+/// ET_REL, then the function does nothing and returns the input
+/// address unchanged.
+///
+/// @param elf_handle the elf handle for the binary to consider.
+///
+/// @param sym the symbol whose address to possibly needs to be
+/// translated.
+///
+/// @return the section-relative address, translated into an
+/// absolute address, if @p sym is from an ET_REL binary.
+/// Otherwise, return the address of @p sym, unchanged.
+GElf_Addr
+maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf* elf_handle, GElf_Sym* sym)
+{
+  Elf_Scn*  symbol_section = elf_getscn(elf_handle, sym->st_shndx);
+  GElf_Addr addr = sym->st_value;
+
+  if (!symbol_section)
+    return addr;
+
+  GElf_Ehdr elf_header;
+  if (!gelf_getehdr(elf_handle, &elf_header))
+    return addr;
+
+  if (elf_header.e_type != ET_REL)
+    return addr;
+
+  GElf_Shdr section_header;
+  if (!gelf_getshdr(symbol_section, &section_header))
+    return addr;
+
+  return addr + section_header.sh_addr;
+}
+
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 6eff245a6a30..647c92703dfa 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -174,6 +174,9 @@ is_executable(Elf* elf_handle);
 bool
 is_dso(Elf* elf_handle);
 
+GElf_Addr
+maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf* elf_handle, GElf_Sym* sym);
+
 } // end namespace elf_helpers
 } // end namespace abigail
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 4/8] abg-elf-helpers: move some kernel helpers from abg-dwarf-reader
  2020-04-20 11:08 ` [PATCH 4/8] abg-elf-helpers: move some kernel " Matthias Maennich
@ 2020-04-20 14:32   ` Giuliano Procida
  2020-04-20 15:30     ` Giuliano Procida
  0 siblings, 1 reply; 37+ messages in thread
From: Giuliano Procida @ 2020-04-20 14:32 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

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(binary_is_linux_kernel): Move function out.
>         (binary_is_linux_kernel_module): Likewise.
>         (find_ksymtab_strings_section): Likewise.
>         * abg-elf-helpers.cc(binary_is_linux_kernel): Move function in.
>         (binary_is_linux_kernel_module): Likewise.
>         (find_ksymtab_strings_section): Likewise.

Next one should be .h.

>         * abg-elf-helpers.cc(binary_is_linux_kernel): Add declaration.
>         (binary_is_linux_kernel_module): Likewise.
>         (find_ksymtab_strings_section): Likewise.
>
> Signed-off-by: Matthias Maennich <maennich@google.com>
> ---
>  src/abg-dwarf-reader.cc | 46 -----------------------------------------
>  src/abg-elf-helpers.cc  | 45 ++++++++++++++++++++++++++++++++++++++++
>  src/abg-elf-helpers.h   | 14 +++++++++++++
>  3 files changed, 59 insertions(+), 46 deletions(-)
>
> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
> index 303c1f8df4c2..3adb978b784b 100644
> --- a/src/abg-dwarf-reader.cc
> +++ b/src/abg-dwarf-reader.cc
> @@ -542,52 +542,6 @@ compare_dies(const read_context& ctxt,
>              bool update_canonical_dies_on_the_fly);
>
>
> -/// Test if the ELF binary denoted by a given ELF handle is a Linux
> -/// Kernel Module.
> -///
> -/// @param elf_handle the ELF handle to consider.
> -///
> -/// @return true iff the binary denoted by @p elf_handle is a Linux
> -/// kernel module.
> -static bool
> -binary_is_linux_kernel_module(Elf *elf_handle)
> -{
> -  return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
> -         && find_section(elf_handle,
> -                         ".gnu.linkonce.this_module",
> -                         SHT_PROGBITS));
> -}
> -
> -/// Test if the ELF binary denoted by a given ELF handle is a Linux
> -/// Kernel binary (either vmlinux or a kernel module).
> -///
> -/// @param elf_handle the ELF handle to consider.
> -///
> -/// @return true iff the binary denoted by @p elf_handle is a Linux
> -/// kernel binary
> -static bool
> -binary_is_linux_kernel(Elf *elf_handle)
> -{
> -  return (find_section(elf_handle,
> -                      "__ksymtab_strings",
> -                      SHT_PROGBITS)
> -         || binary_is_linux_kernel_module(elf_handle));
> -}
> -
> -/// Find the __ksymtab_strings section of a Linux kernel binary.
> -///
> -///
> -/// @return the find_ksymtab_strings_section of the linux kernel
> -/// binary denoted by @p elf_handle, or nil if such a section could
> -/// not be found.
> -static Elf_Scn*
> -find_ksymtab_strings_section(Elf *elf_handle)
> -{
> -  if (binary_is_linux_kernel(elf_handle))
> -    return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
> -  return 0;
> -}
> -
>  /// Get the address at which a given binary is loaded in memory⋅
>  ///
>  /// @param elf_handle the elf handle for the binary to consider.
> diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
> index b7b868a332ec..ff0941dc6536 100644
> --- a/src/abg-elf-helpers.cc
> +++ b/src/abg-elf-helpers.cc
> @@ -548,6 +548,21 @@ get_symbol_versionning_sections(Elf*               elf_handle,
>    return false;
>  }
>
> +/// Find the __ksymtab_strings section of a Linux kernel binary.
> +///
> +/// @param elf_handle the elf handle to use.
> +///
> +/// @return the find_ksymtab_strings_section of the linux kernel
> +/// binary denoted by @p elf_handle, or nil if such a section could
> +/// not be found.
> +Elf_Scn*
> +find_ksymtab_strings_section(Elf *elf_handle)
> +{
> +  if (binary_is_linux_kernel(elf_handle))
> +    return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
> +  return 0;
> +}
> +
>  /// Get the version definition (from the SHT_GNU_verdef section) of a
>  /// given symbol represented by a pointer to GElf_Versym.
>  ///
> @@ -750,7 +765,37 @@ get_version_for_symbol(Elf*                        elf_handle,
>    return false;
>  }
>
> +/// Test if the ELF binary denoted by a given ELF handle is a Linux
> +/// Kernel Module.
> +///
> +/// @param elf_handle the ELF handle to consider.
> +///
> +/// @return true iff the binary denoted by @p elf_handle is a Linux
> +/// kernel module.
> +bool
> +binary_is_linux_kernel_module(Elf *elf_handle)
> +{
> +  return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
> +         && find_section(elf_handle,
> +                         ".gnu.linkonce.this_module",
> +                         SHT_PROGBITS));
> +}
>
> +/// Test if the ELF binary denoted by a given ELF handle is a Linux
> +/// Kernel binary (either vmlinux or a kernel module).
> +///
> +/// @param elf_handle the ELF handle to consider.
> +///
> +/// @return true iff the binary denoted by @p elf_handle is a Linux
> +/// kernel binary
> +bool
> +binary_is_linux_kernel(Elf *elf_handle)
> +{
> +  return (find_section(elf_handle,
> +                      "__ksymtab_strings",
> +                      SHT_PROGBITS)
> +         || binary_is_linux_kernel_module(elf_handle));
> +}
>
>  } // end namespace elf_helpers
>  } // end namespace abigail
> diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
> index 7e1c231ccc4e..33348126028c 100644
> --- a/src/abg-elf-helpers.h
> +++ b/src/abg-elf-helpers.h
> @@ -102,6 +102,9 @@ get_symbol_versionning_sections(Elf*                elf_handle,
>                                 Elf_Scn*&       verdef_section,
>                                 Elf_Scn*&       verneed_section);
>
> +Elf_Scn*
> +find_ksymtab_strings_section(Elf *elf_handle);
> +
>  //
>  // Helpers for symbol versioning
>  //
> @@ -124,6 +127,17 @@ get_version_for_symbol(Elf*                        elf_handle,
>                        bool                     get_def_version,
>                        elf_symbol::version&     version);
>
> +//
> +// Helpers for Linux Kernel Binaries
> +//
> +
> +bool
> +binary_is_linux_kernel_module(Elf *elf_handle);
> +
> +bool
> +binary_is_linux_kernel(Elf *elf_handle);
> +
> +
>  } // end namespace elf_helpers
>  } // end namespace abigail
>
> --
> 2.26.1.301.g55bc3eb7cb9-goog
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers
  2020-04-20 11:08 ` [PATCH 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers Matthias Maennich
@ 2020-04-20 15:24   ` Giuliano Procida
  2020-04-21  6:14     ` Matthias Maennich
  0 siblings, 1 reply; 37+ messages in thread
From: Giuliano Procida @ 2020-04-20 15:24 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 20 Apr 2020 at 12:09, Matthias Maennich <maennich@google.com> wrote:
>
> This change migrates all ELF helpers related to section lookup to
> abg-elf-helpers.{cc,h}. It also homogenizes the interface of those to
> always return Elf_Scn* and NULL in case that section can't be found.
> Though this smells like a functional change, this latter change is
> purely cosmetic.
>
>         * src/abg-dwarf-reader.cc (read_context::find_symbol_table_section):
>         adjust to new interface of elf_helpers::find_symbol_table_section.
>         (find_opd_section): use elf_helpers::find_opd_section for lookup.
>         (find_ksymtab_section): use elf_helpers::find_ksymtab_section.
>         (find_ksymtab_gpl_section): use elf_helpers::find_ksymtab_gpl_section.
>         (find_relocation_section): Move out function.
>         (get_binary_load_address): Move out function.
>         (find_ksymtab_reloc_section): use elf_helpers::find_relocation_section
>         (find_ksymtab_gpl_reloc_section): use elf_helpers::find_relocation_section
>         * src/elf-helpers.cc (find_symbol_table_section): change
>         interface to match other find_*_section functions.
>         (find_symbol_table_section_index): Adjust for the new interface
>         of find_symbol_table_section.
>         (find_opd_section): New function.
>         (find_ksymtab_section): New function.
>         (find_ksymtab_gpl_section): New function.
>         (find_relocation_section): New function.
>         (get_binary_load_address): New function.
>         * src/elf-helpers.h (find_symbol_table_section): Change declaration.
>         (find_opd_section): New function declation.
>         (find_ksymtab_section): New function declation.
>         (find_ksymtab_gpl_section): New function declation.
>         (find_relocation_section): New function declation.
>         (get_binary_load_address): New function declation.
>
> Signed-off-by: Matthias Maennich <maennich@google.com>
> ---
>  src/abg-dwarf-reader.cc | 112 ++++++----------------------------
>  src/abg-elf-helpers.cc  | 129 +++++++++++++++++++++++++++++++++++++---
>  src/abg-elf-helpers.h   |  22 ++++++-
>  3 files changed, 157 insertions(+), 106 deletions(-)
>
> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
> index ec1f9f3fe8f3..56da03a60940 100644
> --- a/src/abg-dwarf-reader.cc
> +++ b/src/abg-dwarf-reader.cc
> @@ -542,53 +542,6 @@ compare_dies(const read_context& ctxt,
>              bool update_canonical_dies_on_the_fly);
>
>
> -/// Get the address at which a given binary is loaded in memory⋅
> -///
> -/// @param elf_handle the elf handle for the binary to consider.
> -///
> -/// @param load_address the address where the binary is loaded.  This
> -/// is set by the function iff it returns true.
> -///
> -/// @return true if the function could get the binary load address
> -/// and assign @p load_address to it.
> -static bool
> -get_binary_load_address(Elf *elf_handle,
> -                       GElf_Addr &load_address)
> -{
> -  GElf_Ehdr eh_mem;
> -  GElf_Ehdr *elf_header = gelf_getehdr(elf_handle, &eh_mem);
> -  size_t num_segments = elf_header->e_phnum;
> -  GElf_Phdr *program_header = 0;
> -  GElf_Addr result;
> -  bool found_loaded_segment = false;
> -  GElf_Phdr ph_mem;
> -
> -  for (unsigned i = 0; i < num_segments; ++i)
> -    {
> -      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
> -      if (program_header && program_header->p_type == PT_LOAD)
> -       {
> -         if (!found_loaded_segment)
> -           {
> -             result = program_header->p_vaddr;
> -             found_loaded_segment = true;
> -           }
> -
> -         if (program_header->p_vaddr < result)
> -           // The resulting load address we want is the lowest
> -           // load address of all the loaded segments.
> -           result = program_header->p_vaddr;
> -       }
> -    }
> -
> -  if (found_loaded_segment)
> -    {
> -      load_address = result;
> -      return true;
> -    }
> -  return false;
> -}
> -
>  /// Find the file name of the alternate debug info file.
>  ///
>  /// @param elf_module the elf module to consider.
> @@ -5282,8 +5235,8 @@ public:
>    find_symbol_table_section() const
>    {
>      if (!symtab_section_)
> -      dwarf_reader::find_symbol_table_section(elf_handle(),
> -                                             const_cast<read_context*>(this)->symtab_section_);
> +      const_cast<read_context*>(this)->symtab_section_ =
> +         elf_helpers::find_symbol_table_section(elf_handle());
>      return symtab_section_;
>    }
>
> @@ -5296,8 +5249,8 @@ public:
>    find_opd_section() const
>    {
>      if (!opd_section_)
> -      const_cast<read_context*>(this)->opd_section_=
> -       find_section(elf_handle(), ".opd", SHT_PROGBITS);
> +      const_cast<read_context*>(this)->opd_section_ =
> +         elf_helpers::find_opd_section(elf_handle());
>      return opd_section_;
>    }
>
> @@ -5310,39 +5263,21 @@ public:
>    {
>      if (!ksymtab_section_)
>        const_cast<read_context*>(this)->ksymtab_section_ =
> -       find_section(elf_handle(), "__ksymtab", SHT_PROGBITS);
> +         elf_helpers::find_ksymtab_section(elf_handle());
>      return ksymtab_section_;
>    }
>
> -  /// Return the .rel{a,} section corresponding to a given section.
> -  ///
> -  /// @param target_section the section to search the relocation section for
> +  /// Return the __ksymtab_gpl section of a linux kernel ELF file
> +  /// (either a vmlinux binary or a kernel module).
>    ///
> -  /// @return the .rel{a,} section if found, null otherwise.
> +  /// @return the __ksymtab_gpl section if found, nil otherwise.
>    Elf_Scn*
> -  find_relocation_section(Elf_Scn* target_section) const
> +  find_ksymtab_gpl_section() const
>    {
> -    if (target_section)
> -      {
> -       // the relo section we are searching for has this index as sh_info
> -       size_t target_index = elf_ndxscn(target_section);
> -
> -       // now iterate over all the sections, look for relocation sections and
> -       // find the one that points to the section we are searching for
> -       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 != SHT_RELA && header->sh_type != SHT_REL))
> -             continue;
> -
> -           if (header->sh_info == target_index)
> -             return section;
> -         }
> -      }
> -    return NULL;
> +    if (!ksymtab_gpl_section_)
> +      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
> +         elf_helpers::find_ksymtab_gpl_section(elf_handle());
> +    return ksymtab_gpl_section_;
>    }
>
>    /// Return the .rel{a,}__ksymtab section of a linux kernel ELF file (either
> @@ -5354,25 +5289,12 @@ public:
>    {
>      if (!ksymtab_reloc_section_)
>        {
> -       const_cast<read_context*>(this)->ksymtab_reloc_section_
> -           = find_relocation_section(find_ksymtab_section());
> +       const_cast<read_context*>(this)->ksymtab_reloc_section_ =
> +           find_relocation_section(elf_handle(), find_ksymtab_section());
>        }
>      return ksymtab_reloc_section_;
>    }
>
> -  /// Return the __ksymtab_gpl section of a linux kernel ELF file
> -  /// (either a vmlinux binary or a kernel module).
> -  ///
> -  /// @return the __ksymtab_gpl section if found, nil otherwise.
> -  Elf_Scn*
> -  find_ksymtab_gpl_section() const
> -  {
> -    if (!ksymtab_gpl_section_)
> -      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
> -       find_section(elf_handle(), "__ksymtab_gpl", SHT_PROGBITS);
> -    return ksymtab_gpl_section_;
> -  }
> -
>    /// Return the .rel{a,}__ksymtab_gpl section of a linux kernel ELF file
>    /// (either a vmlinux binary or a kernel module).
>    ///
> @@ -5382,8 +5304,8 @@ public:
>    {
>      if (!ksymtab_gpl_reloc_section_)
>        {
> -       const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_
> -           = find_relocation_section(find_ksymtab_gpl_section());
> +       const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_ =
> +           find_relocation_section(elf_handle(), find_ksymtab_gpl_section());
>        }
>      return ksymtab_gpl_reloc_section_;
>    }
> diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
> index ede191014369..b77440206fb0 100644
> --- a/src/abg-elf-helpers.cc
> +++ b/src/abg-elf-helpers.cc
> @@ -357,9 +357,9 @@ find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
>  ///
>  /// @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)
> +/// @return the symbol table section
> +Elf_Scn*
> +find_symbol_table_section(Elf* elf_handle)
>  {
>    Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0;
>    while ((section = elf_nextscn(elf_handle, section)) != 0)
> @@ -378,12 +378,11 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
>        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;
> +       return sym_tab ? sym_tab : dynsym;
>        else
> -       symtab = dynsym ? dynsym : sym_tab;
> -      return true;
> +       return dynsym ? dynsym : sym_tab;
>      }
> -  return false;
> +  return NULL;
>  }
>
>  /// Find the index (in the section headers table) of the symbol table
> @@ -402,8 +401,9 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
>  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))
> +  Elf_Scn* section = find_symbol_table_section(elf_handle);
> +
> +  if (!section)
>      return false;
>
>    symtab_index = elf_ndxscn(section);
> @@ -500,6 +500,17 @@ Elf_Scn*
>  find_data1_section(Elf* elf_handle)
>  {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
>
> +/// Return the "Official Procedure descriptors section."  This
> +/// section is named .opd, and is usually present only on PPC64
> +/// ELFv1 binaries.
> +///
> +/// @param elf_handle the elf handle to consider.
> +///
> +/// @return the .opd section, if found.  Return nil otherwise.
> +Elf_Scn*
> +find_opd_section(Elf* elf_handle)
> +{return find_section(elf_handle, ".opd", SHT_PROGBITS);}
> +
>  /// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
>  /// sections that are involved in symbol versionning.
>  ///
> @@ -548,6 +559,26 @@ get_symbol_versionning_sections(Elf*               elf_handle,
>    return false;
>  }
>
> +/// Return the __ksymtab section of a linux kernel ELF file (either
> +/// a vmlinux binary or a kernel module).
> +///
> +/// @param elf_handle the elf handle to consider.
> +///
> +/// @return the __ksymtab section if found, nil otherwise.
> +Elf_Scn*
> +find_ksymtab_section(Elf* elf_handle)
> +{return find_section(elf_handle, "__ksymtab", SHT_PROGBITS);}
> +
> +/// Return the __ksymtab_gpl section of a linux kernel ELF file (either
> +/// a vmlinux binary or a kernel module).
> +///
> +/// @param elf_handle the elf handle to consider.
> +///
> +/// @return the __ksymtab section if found, nil otherwise.
> +Elf_Scn*
> +find_ksymtab_gpl_section(Elf* elf_handle)
> +{return find_section(elf_handle, "__ksymtab_gpl", SHT_PROGBITS);}
> +
>  /// Find the __ksymtab_strings section of a Linux kernel binary.
>  ///
>  /// @param elf_handle the elf handle to use.
> @@ -563,6 +594,39 @@ find_ksymtab_strings_section(Elf *elf_handle)
>    return 0;
>  }
>
> +/// Return the .rel{a,} section corresponding to a given section.
> +///
> +/// @param elf_handle the elf handle to consider.
> +///
> +/// @param target_section the section to search the relocation section for
> +///
> +/// @return the .rel{a,} section if found, null otherwise.
> +Elf_Scn*
> +find_relocation_section(Elf* elf_handle, Elf_Scn* target_section)
> +{
> +  if (target_section)
> +    {
> +      // the relo section we are searching for has this index as sh_info
> +      size_t target_index = elf_ndxscn(target_section);
> +
> +      // now iterate over all the sections, look for relocation sections and
> +      // find the one that points to the section we are searching for
> +      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 != SHT_RELA && header->sh_type != SHT_REL))
> +           continue;
> +
> +         if (header->sh_info == target_index)
> +           return section;
> +       }
> +    }
> +  return NULL;
> +}
> +
>  /// Get the version definition (from the SHT_GNU_verdef section) of a
>  /// given symbol represented by a pointer to GElf_Versym.
>  ///
> @@ -797,5 +861,52 @@ is_linux_kernel(Elf *elf_handle)
>           || is_linux_kernel_module(elf_handle));
>  }
>
> +/// Get the address at which a given binary is loaded in memory⋅
> +///
> +/// @param elf_handle the elf handle for the binary to consider.
> +///
> +/// @param load_address the address where the binary is loaded.  This
> +/// is set by the function iff it returns true.
> +///
> +/// @return true if the function could get the binary load address
> +/// and assign @p load_address to it.

Should be returning nullable load_address.


> +bool
> +get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
> +{
> +  GElf_Ehdr elf_header;
> +  gelf_getehdr(elf_handle, &elf_header);
> +  size_t num_segments = elf_header.e_phnum;
> +  GElf_Phdr *program_header = NULL;
> +  GElf_Addr result;
> +  bool found_loaded_segment = false;
> +  GElf_Phdr ph_mem;
> +
> +  for (unsigned i = 0; i < num_segments; ++i)
> +    {
> +      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
> +      if (program_header && program_header->p_type == PT_LOAD)
> +       {
> +         if (!found_loaded_segment)
> +           {
> +             result = program_header->p_vaddr;
> +             found_loaded_segment = true;
> +           }
> +
> +         if (program_header->p_vaddr < result)
> +           // The resulting load address we want is the lowest
> +           // load address of all the loaded segments.
> +           result = program_header->p_vaddr;
> +       }
> +    }
> +
> +  if (found_loaded_segment)
> +    {
> +      load_address = result;
> +      return true;
> +    }
> +  return false;
> +}
> +
> +
>  } // end namespace elf_helpers
>  } // end namespace abigail
> diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
> index 7ddd887de959..8a83bb4f2e95 100644
> --- a/src/abg-elf-helpers.h
> +++ b/src/abg-elf-helpers.h
> @@ -63,8 +63,8 @@ find_section(Elf*             elf_handle,
>              const std::string& name,
>              Elf64_Word         section_type);
>
> -bool
> -find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab);
> +Elf_Scn*
> +find_symbol_table_section(Elf* elf_handle);
>
>  bool
>  find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index);
> @@ -96,15 +96,27 @@ find_data_section(Elf* elf_handle);
>  Elf_Scn*
>  find_data1_section(Elf* elf_handle);
>
> +Elf_Scn*
> +find_opd_section(Elf* elf_handle);
> +
>  bool
>  get_symbol_versionning_sections(Elf*           elf_handle,
>                                 Elf_Scn*&       versym_section,
>                                 Elf_Scn*&       verdef_section,
>                                 Elf_Scn*&       verneed_section);
>
> +Elf_Scn*
> +find_ksymtab_section(Elf* elf_handle);
> +
> +Elf_Scn*
> +find_ksymtab_gpl_section(Elf* elf_handle);
> +
>  Elf_Scn*
>  find_ksymtab_strings_section(Elf *elf_handle);
>
> +Elf_Scn*
> +find_relocation_section(Elf* elf_handle, Elf_Scn* target_section);
> +
>  //
>  // Helpers for symbol versioning
>  //
> @@ -137,6 +149,12 @@ is_linux_kernel_module(Elf *elf_handle);
>  bool
>  is_linux_kernel(Elf *elf_handle);
>
> +//
> +// Misc Helpers
> +//
> +
> +bool
> +get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address);
>
>  } // end namespace elf_helpers
>  } // end namespace abigail
> --
> 2.26.1.301.g55bc3eb7cb9-goog
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers)
  2020-04-20 11:08 ` [PATCH 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers) Matthias Maennich
@ 2020-04-20 15:25   ` Giuliano Procida
  0 siblings, 0 replies; 37+ messages in thread
From: Giuliano Procida @ 2020-04-20 15:25 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 20 Apr 2020 at 12:09, Matthias Maennich <maennich@google.com> wrote:
>
> This migrates more architecture specific helpers over to the
> elf-helpers. No functional change intended.
>
> Signed-off-by: Matthias Maennich <maennich@google.com>

Stray line.

>         * src/abg-dwarf-reader.cc(elf_architecture_is_ppc64): Move
>         function out and adjust callers to call the migrated
>         functions.
>         (elf_architecture_is_big_endian): Likewise.
>         (architecture_word_size): Likewise.
>         (current_elf_file_is_executable): Likewise.
>         (current_elf_file_is_dso): Likewise.
>         * src/abg-elf-helpers.cc (architecture_is_ppc64): Add new function.
>         (architecture_is_big_endian): Likewise.
>         (get_architecture_word_size): Likewise.
>         (is_executable): Likewise.
>         (is_dso): Likewise.
>         * src/abg-elf-helpers.h (architecture_is_ppc64): Add new declaration.
>         (architecture_is_big_endian): Likewise.
>         (get_architecture_word_size): Likewise.
>         (is_executable): Likewise.
>         (is_dso): Likewise.

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


> Signed-off-by: Matthias Maennich <maennich@google.com>
> ---
>  src/abg-dwarf-reader.cc | 91 ++++-------------------------------------
>  src/abg-elf-helpers.cc  | 79 +++++++++++++++++++++++++++++++++++
>  src/abg-elf-helpers.h   | 18 ++++++++
>  3 files changed, 106 insertions(+), 82 deletions(-)
>
> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
> index 56da03a60940..dc3332410b1e 100644
> --- a/src/abg-dwarf-reader.cc
> +++ b/src/abg-dwarf-reader.cc
> @@ -5700,10 +5700,10 @@ public:
>      if (!elf_handle())
>        return fn_desc_address;
>
> -    if (!elf_architecture_is_ppc64())
> +    if (!architecture_is_ppc64(elf_handle()))
>        return fn_desc_address;
>
> -    bool is_big_endian = elf_architecture_is_big_endian();
> +    bool is_big_endian = architecture_is_big_endian(elf_handle());
>
>      Elf_Scn *opd_section = find_opd_section();
>      if (!opd_section)
> @@ -5979,7 +5979,7 @@ public:
>    {
>      if (!fun_entry_addr_sym_map_ && !fun_addr_sym_map_)
>        maybe_load_symbol_maps();
> -    if (elf_architecture_is_ppc64())
> +    if (architecture_is_ppc64(elf_handle()))
>        return fun_entry_addr_sym_map_;
>      return fun_addr_sym_map_;
>    }
> @@ -6335,79 +6335,6 @@ public:
>    elf_architecture() const
>    {return elf_architecture_;}
>
> -  /// Return the size of a word for the current architecture.
> -  /// @return the size of a word.
> -  unsigned char
> -  architecture_word_size() const
> -  {
> -    unsigned char word_size = 0;
> -    GElf_Ehdr eh_mem;
> -    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
> -    if (elf_header->e_ident[EI_CLASS] == ELFCLASS32)
> -      word_size = 4;
> -    else if (elf_header->e_ident[EI_CLASS] == ELFCLASS64)
> -      word_size = 8;
> -    else
> -      ABG_ASSERT_NOT_REACHED;
> -    return word_size;
> -  }
> -
> -  /// Test if the architecture of the current binary is ppc64.
> -  ///
> -  /// @return true iff the architecture of the current binary is ppc64.
> -  bool
> -  elf_architecture_is_ppc64() const
> -  {
> -    GElf_Ehdr eh_mem;
> -    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
> -
> -    return (elf_header && elf_header->e_machine == EM_PPC64);
> -  }
> -
> -  /// Test if the endianness of the current binary is Big Endian.
> -  ///
> -  /// https://en.wikipedia.org/wiki/Endianness.
> -  ///
> -  /// @return true iff the current binary is Big Endian.
> -  bool
> -  elf_architecture_is_big_endian() const
> -  {
> -    GElf_Ehdr eh_mem;
> -    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
> -
> -    bool is_big_endian = (elf_header->e_ident[EI_DATA] == ELFDATA2MSB);
> -
> -    if (!is_big_endian)
> -      ABG_ASSERT(elf_header->e_ident[EI_DATA] == ELFDATA2LSB);
> -
> -    return is_big_endian;
> -  }
> -
> -  /// Test if the current elf file being read is an executable.
> -  ///
> -  /// @return true iff the current elf file being read is an
> -  /// executable.
> -  bool
> -  current_elf_file_is_executable() const
> -  {
> -    GElf_Ehdr eh_mem;
> -    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
> -    return elf_header->e_type == ET_EXEC;
> -  }
> -
> -  /// Test if the current elf file being read is a dynamic shared
> -  /// object.
> -  ///
> -  /// @return true iff the current elf file being read is a
> -  /// dynamic shared object.
> -  bool
> -  current_elf_file_is_dso() const
> -  {
> -    GElf_Ehdr eh_mem;
> -    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
> -    return elf_header->e_type == ET_DYN;
> -  }
> -
>    /// Getter for the map of global variables symbol address -> global
>    /// variable symbol index.
>    ///
> @@ -6471,7 +6398,7 @@ public:
>      GElf_Ehdr elf_header;
>      ABG_ASSERT(gelf_getehdr(elf_handle(), &elf_header));
>
> -    bool is_ppc64 = elf_architecture_is_ppc64();
> +    bool is_ppc64 = architecture_is_ppc64(elf_handle());
>
>      for (size_t i = 0; i < nb_syms; ++i)
>        {
> @@ -6688,7 +6615,7 @@ public:
>    {
>      Elf_Data*      elf_data = elf_rawdata(section, 0);
>      uint8_t*       bytes = reinterpret_cast<uint8_t*>(elf_data->d_buf);
> -    bool           is_big_endian = elf_architecture_is_big_endian();
> +    bool           is_big_endian = architecture_is_big_endian(elf_handle());
>      elf_symbol_sptr symbol;
>      GElf_Addr      symbol_address = 0;
>
> @@ -6696,7 +6623,7 @@ public:
>      if (position_relative_relocations)
>        symbol_value_size = sizeof(int32_t);
>      else
> -      symbol_value_size = architecture_word_size();
> +      symbol_value_size = get_architecture_word_size(elf_handle());
>
>      const int read_offset = (symbol_offset * symbol_value_size);
>      bytes += read_offset;
> @@ -6886,7 +6813,7 @@ public:
>      if (format == UNDEFINED_KSYMTAB_FORMAT)
>        ;
>      else if (format == PRE_V4_19_KSYMTAB_FORMAT)
> -      result = architecture_word_size();
> +      result = get_architecture_word_size(elf_handle());
>      else if (format == V4_19_KSYMTAB_FORMAT)
>        result = 4;
>      else
> @@ -7065,7 +6992,7 @@ public:
>      //
>      // Lets thus walk the array of entries, and let's read just the
>      // symbol address part of each entry.
> -    bool is_big_endian = elf_architecture_is_big_endian();
> +    bool is_big_endian = architecture_is_big_endian(elf_handle());
>      elf_symbol_sptr symbol;
>      unsigned char symbol_value_size = get_ksymtab_symbol_value_size();
>
> @@ -7367,7 +7294,7 @@ public:
>      if (!fun_addr_sym_map_)
>        fun_addr_sym_map_.reset(new addr_elf_symbol_sptr_map_type);
>
> -    if (!fun_entry_addr_sym_map_ && elf_architecture_is_ppc64())
> +    if (!fun_entry_addr_sym_map_ && architecture_is_ppc64(elf_handle()))
>        fun_entry_addr_sym_map_.reset(new addr_elf_symbol_sptr_map_type);
>
>      if (!var_syms_)
> diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
> index b77440206fb0..895feb6f7768 100644
> --- a/src/abg-elf-helpers.cc
> +++ b/src/abg-elf-helpers.cc
> @@ -829,6 +829,40 @@ get_version_for_symbol(Elf*                        elf_handle,
>    return false;
>  }
>
> +/// Test if the architecture of the current binary is ppc64.
> +///
> +/// @param elf_handle the ELF handle to consider.
> +///
> +/// @return true iff the architecture of the current binary is ppc64.
> +bool
> +architecture_is_ppc64(Elf* elf_handle)
> +{
> +  GElf_Ehdr  eh_mem;
> +  GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
> +  return (elf_header && elf_header->e_machine == EM_PPC64);
> +}
> +
> +/// Test if the endianness of the current binary is Big Endian.
> +///
> +/// https://en.wikipedia.org/wiki/Endianness.
> +///
> +/// @param elf_handle the ELF handle to consider.
> +///
> +/// @return true iff the current binary is Big Endian.
> +bool
> +architecture_is_big_endian(Elf* elf_handle)
> +{
> +  GElf_Ehdr  elf_header;
> +  gelf_getehdr(elf_handle, &elf_header);
> +
> +  bool is_big_endian = (elf_header.e_ident[EI_DATA] == ELFDATA2MSB);
> +
> +  if (!is_big_endian)
> +    ABG_ASSERT(elf_header.e_ident[EI_DATA] == ELFDATA2LSB);
> +
> +  return is_big_endian;
> +}
> +
>  /// Test if the ELF binary denoted by a given ELF handle is a Linux
>  /// Kernel Module.
>  ///
> @@ -907,6 +941,51 @@ get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
>    return false;
>  }
>
> +/// Return the size of a word for the current architecture.
> +///
> +/// @param elf_handle the ELF handle to consider.
> +///
> +/// @return the size of a word.
> +unsigned char
> +get_architecture_word_size(Elf* elf_handle)
> +{
> +  unsigned char word_size = 0;
> +  GElf_Ehdr    elf_header;
> +  gelf_getehdr(elf_handle, &elf_header);
> +  if (elf_header.e_ident[EI_CLASS] == ELFCLASS32)
> +    word_size = 4;
> +  else if (elf_header.e_ident[EI_CLASS] == ELFCLASS64)
> +    word_size = 8;
> +  else
> +    ABG_ASSERT_NOT_REACHED;
> +  return word_size;
> +}
> +
> +/// Test if the elf file being read is an executable.
> +///
> +/// @param elf_handle the ELF handle to consider.
> +///
> +/// @return true iff the elf file being read is an / executable.
> +bool
> +is_executable(Elf* elf_handle)
> +{
> +  GElf_Ehdr  elf_header;
> +  gelf_getehdr(elf_handle, &elf_header);
> +  return elf_header.e_type == ET_EXEC;
> +}
> +
> +/// Test if the elf file being read is a dynamic shared / object.
> +///
> +/// @param elf_handle the ELF handle to consider.
> +///
> +/// @return true iff the elf file being read is a / dynamic shared object.
> +bool
> +is_dso(Elf* elf_handle)
> +{
> +  GElf_Ehdr  elf_header;
> +  gelf_getehdr(elf_handle, &elf_header);
> +  return elf_header.e_type == ET_DYN;
> +}
>
>  } // end namespace elf_helpers
>  } // end namespace abigail
> diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
> index 8a83bb4f2e95..6eff245a6a30 100644
> --- a/src/abg-elf-helpers.h
> +++ b/src/abg-elf-helpers.h
> @@ -139,6 +139,15 @@ get_version_for_symbol(Elf*                        elf_handle,
>                        bool                     get_def_version,
>                        elf_symbol::version&     version);
>
> +//
> +// Architecture specific helpers
> +//
> +bool
> +architecture_is_ppc64(Elf* elf_handle);
> +
> +bool
> +architecture_is_big_endian(Elf* elf_handle);
> +
>  //
>  // Helpers for Linux Kernel Binaries
>  //
> @@ -156,6 +165,15 @@ is_linux_kernel(Elf *elf_handle);
>  bool
>  get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address);
>
> +unsigned char
> +get_architecture_word_size(Elf* elf_handle);
> +
> +bool
> +is_executable(Elf* elf_handle);
> +
> +bool
> +is_dso(Elf* elf_handle);
> +
>  } // end namespace elf_helpers
>  } // end namespace abigail
>
> --
> 2.26.1.301.g55bc3eb7cb9-goog
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers
  2020-04-20 11:08 ` [PATCH 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers Matthias Maennich
@ 2020-04-20 15:29   ` Giuliano Procida
  0 siblings, 0 replies; 37+ messages in thread
From: Giuliano Procida @ 2020-04-20 15:29 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Looks good.

On Mon, 20 Apr 2020 at 12:09, Matthias Maennich <maennich@google.com> wrote:
>
> This consistently names the is_linux_kernel* helpers and keeps only the
> copy in the elf-helpers. All users are adjusted.
>
>         * src/abg-dwarf-reader.cc
>         (read_context::function_symbol_is_exported): use is_linux_kernel
>         from elf_helpers.
>         (read_context::variable_is_exported): Likewise.
>         (read_context::get_symtab_format): Likewise.
>         (read_context::load_symbol_maps): Likewise.
>         (read_debug_info_into_corpus): Likewise.
>         (read_context::is_linux_kernel_binary): Drop function.
>         (read_context::is_linux_kernel_module): Drop function.
>         * src/abg-elf-helpers.cc (binary_is_linux_kernel): rename to
>         is_linux_kernel
>         (binary_is_linux_kernel_module): rename to is_linux_kernel_module
>         (find_ksymtab_strings_section): Adjust to function renames.
>         * src/abg-elf-helpers.h (binary_is_linux_kernel): rename to
>         is_linux_kernel
>         (binary_is_linux_kernel_module): rename to is_linux_kernel_module

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

> Signed-off-by: Matthias Maennich <maennich@google.com>
> ---
>  src/abg-dwarf-reader.cc | 37 +++++++------------------------------
>  src/abg-elf-helpers.cc  |  8 ++++----
>  src/abg-elf-helpers.h   |  4 ++--
>  3 files changed, 13 insertions(+), 36 deletions(-)
>
> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
> index 3adb978b784b..ec1f9f3fe8f3 100644
> --- a/src/abg-dwarf-reader.cc
> +++ b/src/abg-dwarf-reader.cc
> @@ -5939,7 +5939,7 @@ public:
>
>      address_set_sptr set;
>      bool looking_at_linux_kernel_binary =
> -      load_in_linux_kernel_mode() && is_linux_kernel_binary();
> +      load_in_linux_kernel_mode() && is_linux_kernel(elf_handle());
>
>      if (looking_at_linux_kernel_binary)
>        {
> @@ -5979,7 +5979,7 @@ public:
>
>      address_set_sptr set;
>      bool looking_at_linux_kernel_binary =
> -      load_in_linux_kernel_mode() && is_linux_kernel_binary();
> +      load_in_linux_kernel_mode() && is_linux_kernel(elf_handle());
>
>      if (looking_at_linux_kernel_binary)
>        {
> @@ -6920,7 +6920,7 @@ public:
>           {
>             // Since Linux kernel modules are relocatable, we can first try
>             // using a heuristic based on relocations to guess the ksymtab format.
> -           if (is_linux_kernel_module())
> +           if (is_linux_kernel_module(elf_handle()))
>              {
>                ksymtab_format_ = get_ksymtab_format_module();
>                if (ksymtab_format_ != UNDEFINED_KSYMTAB_FORMAT)
> @@ -7467,7 +7467,7 @@ public:
>                                                  load_undefined_fun_map,
>                                                  load_undefined_var_map))
>           {
> -           if (load_in_linux_kernel_mode() && is_linux_kernel_binary())
> +           if (load_in_linux_kernel_mode() && is_linux_kernel(elf_handle()))
>               return load_linux_specific_exported_symbol_maps();
>             return true;
>           }
> @@ -8166,30 +8166,6 @@ public:
>    load_in_linux_kernel_mode(bool f)
>    {options_.load_in_linux_kernel_mode = f;}
>
> -  /// Guess if the current binary is a Linux Kernel or a Linux Kernel module.
> -  ///
> -  /// To guess that, the function looks for the presence of the
> -  /// special "__ksymtab_strings" section in the binary.
> -  ///
> -  bool
> -  is_linux_kernel_binary() const
> -  {
> -    return find_section(elf_handle(), "__ksymtab_strings", SHT_PROGBITS)
> -          || is_linux_kernel_module();
> -  }
> -
> -  /// Guess if the current binary is a Linux Kernel module.
> -  ///
> -  /// To guess that, the function looks for the presence of the special
> -  /// ".modinfo" and ".gnu.linkonce.this_module" sections in the binary.
> -  ///
> -  bool
> -  is_linux_kernel_module() const
> -  {
> -    return find_section(elf_handle(), ".modinfo", SHT_PROGBITS)
> -          && find_section(elf_handle(), ".gnu.linkonce.this_module", SHT_PROGBITS);
> -  }
> -
>    /// Getter of the "show_stats" flag.
>    ///
>    /// This flag tells if we should emit statistics about various
> @@ -16322,7 +16298,7 @@ read_debug_info_into_corpus(read_context& ctxt)
>    // First set some mundane properties of the corpus gathered from
>    // ELF.
>    ctxt.current_corpus()->set_path(ctxt.elf_path());
> -  if (ctxt.is_linux_kernel_binary())
> +  if (is_linux_kernel(ctxt.elf_handle()))
>      ctxt.current_corpus()->set_origin(corpus::LINUX_KERNEL_BINARY_ORIGIN);
>    else
>      ctxt.current_corpus()->set_origin(corpus::DWARF_ORIGIN);
> @@ -16335,7 +16311,8 @@ read_debug_info_into_corpus(read_context& ctxt)
>    // Set symbols information to the corpus.
>    if (!get_ignore_symbol_table(ctxt))
>      {
> -      if (ctxt.load_in_linux_kernel_mode() && ctxt.is_linux_kernel_binary())
> +      if (ctxt.load_in_linux_kernel_mode()
> +         && is_linux_kernel(ctxt.elf_handle()))
>         {
>           string_elf_symbols_map_sptr exported_fn_symbols_map
>             (new string_elf_symbols_map_type);
> diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
> index ff0941dc6536..ede191014369 100644
> --- a/src/abg-elf-helpers.cc
> +++ b/src/abg-elf-helpers.cc
> @@ -558,7 +558,7 @@ get_symbol_versionning_sections(Elf*                elf_handle,
>  Elf_Scn*
>  find_ksymtab_strings_section(Elf *elf_handle)
>  {
> -  if (binary_is_linux_kernel(elf_handle))
> +  if (is_linux_kernel(elf_handle))
>      return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
>    return 0;
>  }
> @@ -773,7 +773,7 @@ get_version_for_symbol(Elf*                 elf_handle,
>  /// @return true iff the binary denoted by @p elf_handle is a Linux
>  /// kernel module.
>  bool
> -binary_is_linux_kernel_module(Elf *elf_handle)
> +is_linux_kernel_module(Elf *elf_handle)
>  {
>    return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
>           && find_section(elf_handle,
> @@ -789,12 +789,12 @@ binary_is_linux_kernel_module(Elf *elf_handle)
>  /// @return true iff the binary denoted by @p elf_handle is a Linux
>  /// kernel binary
>  bool
> -binary_is_linux_kernel(Elf *elf_handle)
> +is_linux_kernel(Elf *elf_handle)
>  {
>    return (find_section(elf_handle,
>                        "__ksymtab_strings",
>                        SHT_PROGBITS)
> -         || binary_is_linux_kernel_module(elf_handle));
> +         || is_linux_kernel_module(elf_handle));
>  }
>
>  } // end namespace elf_helpers
> diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
> index 33348126028c..7ddd887de959 100644
> --- a/src/abg-elf-helpers.h
> +++ b/src/abg-elf-helpers.h
> @@ -132,10 +132,10 @@ get_version_for_symbol(Elf*                       elf_handle,
>  //
>
>  bool
> -binary_is_linux_kernel_module(Elf *elf_handle);
> +is_linux_kernel_module(Elf *elf_handle);
>
>  bool
> -binary_is_linux_kernel(Elf *elf_handle);
> +is_linux_kernel(Elf *elf_handle);
>
>
>  } // end namespace elf_helpers
> --
> 2.26.1.301.g55bc3eb7cb9-goog
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 4/8] abg-elf-helpers: move some kernel helpers from abg-dwarf-reader
  2020-04-20 14:32   ` Giuliano Procida
@ 2020-04-20 15:30     ` Giuliano Procida
  0 siblings, 0 replies; 37+ messages in thread
From: Giuliano Procida @ 2020-04-20 15:30 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Hi.

On Mon, 20 Apr 2020 at 15:32, Giuliano Procida <gprocida@google.com> wrote:
>
> 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(binary_is_linux_kernel): Move function out.
> >         (binary_is_linux_kernel_module): Likewise.
> >         (find_ksymtab_strings_section): Likewise.
> >         * abg-elf-helpers.cc(binary_is_linux_kernel): Move function in.
> >         (binary_is_linux_kernel_module): Likewise.
> >         (find_ksymtab_strings_section): Likewise.
>
> Next one should be .h.

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

> >         * abg-elf-helpers.cc(binary_is_linux_kernel): Add declaration.
> >         (binary_is_linux_kernel_module): Likewise.
> >         (find_ksymtab_strings_section): Likewise.
> >
> > Signed-off-by: Matthias Maennich <maennich@google.com>
> > ---
> >  src/abg-dwarf-reader.cc | 46 -----------------------------------------
> >  src/abg-elf-helpers.cc  | 45 ++++++++++++++++++++++++++++++++++++++++
> >  src/abg-elf-helpers.h   | 14 +++++++++++++
> >  3 files changed, 59 insertions(+), 46 deletions(-)
> >
> > diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
> > index 303c1f8df4c2..3adb978b784b 100644
> > --- a/src/abg-dwarf-reader.cc
> > +++ b/src/abg-dwarf-reader.cc
> > @@ -542,52 +542,6 @@ compare_dies(const read_context& ctxt,
> >              bool update_canonical_dies_on_the_fly);
> >
> >
> > -/// Test if the ELF binary denoted by a given ELF handle is a Linux
> > -/// Kernel Module.
> > -///
> > -/// @param elf_handle the ELF handle to consider.
> > -///
> > -/// @return true iff the binary denoted by @p elf_handle is a Linux
> > -/// kernel module.
> > -static bool
> > -binary_is_linux_kernel_module(Elf *elf_handle)
> > -{
> > -  return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
> > -         && find_section(elf_handle,
> > -                         ".gnu.linkonce.this_module",
> > -                         SHT_PROGBITS));
> > -}
> > -
> > -/// Test if the ELF binary denoted by a given ELF handle is a Linux
> > -/// Kernel binary (either vmlinux or a kernel module).
> > -///
> > -/// @param elf_handle the ELF handle to consider.
> > -///
> > -/// @return true iff the binary denoted by @p elf_handle is a Linux
> > -/// kernel binary
> > -static bool
> > -binary_is_linux_kernel(Elf *elf_handle)
> > -{
> > -  return (find_section(elf_handle,
> > -                      "__ksymtab_strings",
> > -                      SHT_PROGBITS)
> > -         || binary_is_linux_kernel_module(elf_handle));
> > -}
> > -
> > -/// Find the __ksymtab_strings section of a Linux kernel binary.
> > -///
> > -///
> > -/// @return the find_ksymtab_strings_section of the linux kernel
> > -/// binary denoted by @p elf_handle, or nil if such a section could
> > -/// not be found.
> > -static Elf_Scn*
> > -find_ksymtab_strings_section(Elf *elf_handle)
> > -{
> > -  if (binary_is_linux_kernel(elf_handle))
> > -    return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
> > -  return 0;
> > -}
> > -
> >  /// Get the address at which a given binary is loaded in memory⋅
> >  ///
> >  /// @param elf_handle the elf handle for the binary to consider.
> > diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
> > index b7b868a332ec..ff0941dc6536 100644
> > --- a/src/abg-elf-helpers.cc
> > +++ b/src/abg-elf-helpers.cc
> > @@ -548,6 +548,21 @@ get_symbol_versionning_sections(Elf*               elf_handle,
> >    return false;
> >  }
> >
> > +/// Find the __ksymtab_strings section of a Linux kernel binary.
> > +///
> > +/// @param elf_handle the elf handle to use.
> > +///
> > +/// @return the find_ksymtab_strings_section of the linux kernel
> > +/// binary denoted by @p elf_handle, or nil if such a section could
> > +/// not be found.
> > +Elf_Scn*
> > +find_ksymtab_strings_section(Elf *elf_handle)
> > +{
> > +  if (binary_is_linux_kernel(elf_handle))
> > +    return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
> > +  return 0;
> > +}
> > +
> >  /// Get the version definition (from the SHT_GNU_verdef section) of a
> >  /// given symbol represented by a pointer to GElf_Versym.
> >  ///
> > @@ -750,7 +765,37 @@ get_version_for_symbol(Elf*                        elf_handle,
> >    return false;
> >  }
> >
> > +/// Test if the ELF binary denoted by a given ELF handle is a Linux
> > +/// Kernel Module.
> > +///
> > +/// @param elf_handle the ELF handle to consider.
> > +///
> > +/// @return true iff the binary denoted by @p elf_handle is a Linux
> > +/// kernel module.
> > +bool
> > +binary_is_linux_kernel_module(Elf *elf_handle)
> > +{
> > +  return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
> > +         && find_section(elf_handle,
> > +                         ".gnu.linkonce.this_module",
> > +                         SHT_PROGBITS));
> > +}
> >
> > +/// Test if the ELF binary denoted by a given ELF handle is a Linux
> > +/// Kernel binary (either vmlinux or a kernel module).
> > +///
> > +/// @param elf_handle the ELF handle to consider.
> > +///
> > +/// @return true iff the binary denoted by @p elf_handle is a Linux
> > +/// kernel binary
> > +bool
> > +binary_is_linux_kernel(Elf *elf_handle)
> > +{
> > +  return (find_section(elf_handle,
> > +                      "__ksymtab_strings",
> > +                      SHT_PROGBITS)
> > +         || binary_is_linux_kernel_module(elf_handle));
> > +}
> >
> >  } // end namespace elf_helpers
> >  } // end namespace abigail
> > diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
> > index 7e1c231ccc4e..33348126028c 100644
> > --- a/src/abg-elf-helpers.h
> > +++ b/src/abg-elf-helpers.h
> > @@ -102,6 +102,9 @@ get_symbol_versionning_sections(Elf*                elf_handle,
> >                                 Elf_Scn*&       verdef_section,
> >                                 Elf_Scn*&       verneed_section);
> >
> > +Elf_Scn*
> > +find_ksymtab_strings_section(Elf *elf_handle);
> > +
> >  //
> >  // Helpers for symbol versioning
> >  //
> > @@ -124,6 +127,17 @@ get_version_for_symbol(Elf*                        elf_handle,
> >                        bool                     get_def_version,
> >                        elf_symbol::version&     version);
> >
> > +//
> > +// Helpers for Linux Kernel Binaries
> > +//
> > +
> > +bool
> > +binary_is_linux_kernel_module(Elf *elf_handle);
> > +
> > +bool
> > +binary_is_linux_kernel(Elf *elf_handle);
> > +
> > +
> >  } // end namespace elf_helpers
> >  } // end namespace abigail
> >
> > --
> > 2.26.1.301.g55bc3eb7cb9-goog
> >

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 3/8] abg-elf-helpers: move some versioning helpers from abg-dwarf-reader
  2020-04-20 11:08 ` [PATCH 3/8] abg-elf-helpers: move some versioning " Matthias Maennich
@ 2020-04-20 15:33   ` Giuliano Procida
  0 siblings, 0 replies; 37+ messages in thread
From: Giuliano Procida @ 2020-04-20 15:33 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

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(get_symbol_versionning_sections): Move function out.
>         (get_version_definition_for_versym): Likewise.
>         (get_version_needed_for_versym): Likewise.
>         (get_version_for_symbol): Likewise.
>         * abg-elf-helpers.cc(get_symbol_versionning_sections): Move function in.
>         (get_version_definition_for_versym): Likewise.
>         (get_version_needed_for_versym): Likewise.
>         (get_version_for_symbol): Likewise.
>         * abg-elf-helpers.cc(get_symbol_versionning_sections): Add declaration.
>         (get_version_definition_for_versym): Likewise.
>         (get_version_needed_for_versym): Likewise.
>         (get_version_for_symbol): Likewise.

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

> Signed-off-by: Matthias Maennich <maennich@google.com>
> ---
>  src/abg-dwarf-reader.cc | 256 ----------------------------------------
>  src/abg-elf-helpers.cc  | 251 +++++++++++++++++++++++++++++++++++++++
>  src/abg-elf-helpers.h   |  28 +++++
>  3 files changed, 279 insertions(+), 256 deletions(-)
>
> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
> index 6ec7e4b6e968..303c1f8df4c2 100644
> --- a/src/abg-dwarf-reader.cc
> +++ b/src/abg-dwarf-reader.cc
> @@ -294,12 +294,6 @@ static void
>  add_symbol_to_map(const elf_symbol_sptr& sym,
>                   string_elf_symbols_map_type& map);
>
> -static bool
> -get_symbol_versionning_sections(Elf*           elf_handle,
> -                               Elf_Scn*&       versym_section,
> -                               Elf_Scn*&       verdef_section,
> -                               Elf_Scn*&       verneed_section);
> -
>  static bool
>  get_parent_die(const read_context&     ctxt,
>                const Dwarf_Die* die,
> @@ -867,256 +861,6 @@ compare_symbol_name(const string& symbol_name,
>    return symbol_name == name;
>  }
>
> -/// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
> -/// sections that are involved in symbol versionning.
> -///
> -/// @param elf_handle the elf handle to use.
> -///
> -/// @param versym_section the SHT_GNU_versym section found.  If the
> -/// section wasn't found, this is set to nil.
> -///
> -/// @param verdef_section the SHT_GNU_verdef section found.  If the
> -/// section wasn't found, this is set to nil.
> -///
> -/// @param verneed_section the SHT_GNU_verneed section found.  If the
> -/// section wasn't found, this is set to nil.
> -///
> -/// @return true iff at least one of the sections where found.
> -static bool
> -get_symbol_versionning_sections(Elf*           elf_handle,
> -                               Elf_Scn*&       versym_section,
> -                               Elf_Scn*&       verdef_section,
> -                               Elf_Scn*&       verneed_section)
> -{
> -  Elf_Scn* section = NULL;
> -  GElf_Shdr mem;
> -  Elf_Scn* versym = NULL, *verdef = NULL, *verneed = NULL;
> -
> -  while ((section = elf_nextscn(elf_handle, section)) != NULL)
> -    {
> -      GElf_Shdr* h = gelf_getshdr(section, &mem);
> -      if (h->sh_type == SHT_GNU_versym)
> -       versym = section;
> -      else if (h->sh_type == SHT_GNU_verdef)
> -       verdef = section;
> -      else if (h->sh_type == SHT_GNU_verneed)
> -       verneed = section;
> -    }
> -
> -  if (versym || verdef || verneed)
> -    {
> -      // At least one the versionning sections was found.  Return it.
> -      versym_section = versym;
> -      verdef_section = verdef;
> -      verneed_section = verneed;
> -      return true;
> -    }
> -
> -  return false;
> -}
> -
> -/// Get the version definition (from the SHT_GNU_verdef section) of a
> -/// given symbol represented by a pointer to GElf_Versym.
> -///
> -/// @param elf_hande the elf handle to use.
> -///
> -/// @param versym the symbol to get the version definition for.
> -///
> -/// @param verdef_section the SHT_GNU_verdef section.
> -///
> -/// @param version the resulting version definition.  This is set iff
> -/// the function returns true.
> -///
> -/// @return true upon successful completion, false otherwise.
> -static bool
> -get_version_definition_for_versym(Elf*                  elf_handle,
> -                                 GElf_Versym*           versym,
> -                                 Elf_Scn*               verdef_section,
> -                                 elf_symbol::version&   version)
> -{
> -  Elf_Data* verdef_data = elf_getdata(verdef_section, NULL);
> -  GElf_Verdef verdef_mem;
> -  GElf_Verdef* verdef = gelf_getverdef(verdef_data, 0, &verdef_mem);
> -  size_t vd_offset = 0;
> -
> -  for (;; vd_offset += verdef->vd_next)
> -    {
> -      for (;verdef != 0;)
> -       {
> -         if (verdef->vd_ndx == (*versym & 0x7fff))
> -           // Found the version of the symbol.
> -           break;
> -         vd_offset += verdef->vd_next;
> -         verdef = (verdef->vd_next == 0
> -                   ? 0
> -                   : gelf_getverdef(verdef_data, vd_offset, &verdef_mem));
> -       }
> -
> -      if (verdef != 0)
> -       {
> -         GElf_Verdaux verdaux_mem;
> -         GElf_Verdaux *verdaux = gelf_getverdaux(verdef_data,
> -                                                 vd_offset + verdef->vd_aux,
> -                                                 &verdaux_mem);
> -         GElf_Shdr header_mem;
> -         GElf_Shdr* verdef_section_header = gelf_getshdr(verdef_section,
> -                                                         &header_mem);
> -         size_t verdef_stridx = verdef_section_header->sh_link;
> -         version.str(elf_strptr(elf_handle, verdef_stridx, verdaux->vda_name));
> -         if (*versym & 0x8000)
> -           version.is_default(false);
> -         else
> -           version.is_default(true);
> -         return true;
> -       }
> -      if (!verdef || verdef->vd_next == 0)
> -       break;
> -    }
> -  return false;
> -}
> -
> -/// Get the version needed (from the SHT_GNU_verneed section) to
> -/// resolve an undefined symbol represented by a pointer to
> -/// GElf_Versym.
> -///
> -/// @param elf_hande the elf handle to use.
> -///
> -/// @param versym the symbol to get the version definition for.
> -///
> -/// @param verneed_section the SHT_GNU_verneed section.
> -///
> -/// @param version the resulting version definition.  This is set iff
> -/// the function returns true.
> -///
> -/// @return true upon successful completion, false otherwise.
> -static bool
> -get_version_needed_for_versym(Elf*                     elf_handle,
> -                             GElf_Versym*              versym,
> -                             Elf_Scn*                  verneed_section,
> -                             elf_symbol::version&      version)
> -{
> -  if (versym == 0 || elf_handle == 0 || verneed_section == 0)
> -    return false;
> -
> -  size_t vn_offset = 0;
> -  Elf_Data* verneed_data = elf_getdata(verneed_section, NULL);
> -  GElf_Verneed verneed_mem;
> -  GElf_Verneed* verneed = gelf_getverneed(verneed_data, 0, &verneed_mem);
> -
> -  for (;verneed; vn_offset += verneed->vn_next)
> -    {
> -      size_t vna_offset = vn_offset;
> -      GElf_Vernaux vernaux_mem;
> -      GElf_Vernaux *vernaux = gelf_getvernaux(verneed_data,
> -                                             vn_offset + verneed->vn_aux,
> -                                             &vernaux_mem);
> -      for (;vernaux != 0 && verneed;)
> -       {
> -         if (vernaux->vna_other == *versym)
> -           // Found the version of the symbol.
> -           break;
> -         vna_offset += verneed->vn_next;
> -         verneed = (verneed->vn_next == 0
> -                    ? 0
> -                    : gelf_getverneed(verneed_data, vna_offset, &verneed_mem));
> -       }
> -
> -      if (verneed != 0 && vernaux != 0 && vernaux->vna_other == *versym)
> -       {
> -         GElf_Shdr header_mem;
> -         GElf_Shdr* verneed_section_header = gelf_getshdr(verneed_section,
> -                                                          &header_mem);
> -         size_t verneed_stridx = verneed_section_header->sh_link;
> -         version.str(elf_strptr(elf_handle,
> -                                verneed_stridx,
> -                                vernaux->vna_name));
> -         if (*versym & 0x8000)
> -           version.is_default(false);
> -         else
> -           version.is_default(true);
> -         return true;
> -       }
> -
> -      if (!verneed || verneed->vn_next == 0)
> -       break;
> -    }
> -  return false;
> -}
> -
> -/// Return the version for a symbol that is at a given index in its
> -/// SHT_SYMTAB section.
> -///
> -/// @param elf_handle the elf handle to use.
> -///
> -/// @param symbol_index the index of the symbol to consider.
> -///
> -/// @param get_def_version if this is true, it means that that we want
> -/// the version for a defined symbol; in that case, the version is
> -/// looked for in a section of type SHT_GNU_verdef.  Otherwise, if
> -/// this parameter is false, this means that we want the version for
> -/// an undefined symbol; in that case, the version is the needed one
> -/// for the symbol to be resolved; so the version is looked fo in a
> -/// section of type SHT_GNU_verneed.
> -///
> -/// @param version the version found for symbol at @p symbol_index.
> -///
> -/// @return true iff a version was found for symbol at index @p
> -/// symbol_index.
> -static bool
> -get_version_for_symbol(Elf*                    elf_handle,
> -                      size_t                   symbol_index,
> -                      bool                     get_def_version,
> -                      elf_symbol::version&     version)
> -{
> -  Elf_Scn *versym_section = NULL,
> -    *verdef_section = NULL,
> -    *verneed_section = NULL;
> -
> -  if (!get_symbol_versionning_sections(elf_handle,
> -                                      versym_section,
> -                                      verdef_section,
> -                                      verneed_section))
> -    return false;
> -
> -  GElf_Versym versym_mem;
> -  Elf_Data* versym_data = (versym_section)
> -    ? elf_getdata(versym_section, NULL)
> -    : NULL;
> -  GElf_Versym* versym = (versym_data)
> -    ? gelf_getversym(versym_data, symbol_index, &versym_mem)
> -    : NULL;
> -
> -  if (versym == 0 || *versym <= 1)
> -    // I got these value from the code of readelf.c in elfutils.
> -    // Apparently, if the symbol version entry has these values, the
> -    // symbol must be discarded. This is not documented in the
> -    // official specification.
> -    return false;
> -
> -  if (get_def_version)
> -    {
> -      if (*versym == 0x8001)
> -       // I got this value from the code of readelf.c in elfutils
> -       // too.  It's not really documented in the official
> -       // specification.
> -       return false;
> -
> -      if (verdef_section
> -         && get_version_definition_for_versym(elf_handle, versym,
> -                                              verdef_section, version))
> -       return true;
> -    }
> -  else
> -    {
> -      if (verneed_section
> -         && get_version_needed_for_versym(elf_handle, versym,
> -                                          verneed_section, version))
> -       return true;
> -    }
> -
> -  return false;
> -}
> -
>  /// Lookup a symbol using the SysV ELF hash table.
>  ///
>  /// Note that this function hasn't been tested.  So it hasn't been
> diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
> index b0113a4efd2c..b7b868a332ec 100644
> --- a/src/abg-elf-helpers.cc
> +++ b/src/abg-elf-helpers.cc
> @@ -500,6 +500,257 @@ Elf_Scn*
>  find_data1_section(Elf* elf_handle)
>  {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
>
> +/// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
> +/// sections that are involved in symbol versionning.
> +///
> +/// @param elf_handle the elf handle to use.
> +///
> +/// @param versym_section the SHT_GNU_versym section found.  If the
> +/// section wasn't found, this is set to nil.
> +///
> +/// @param verdef_section the SHT_GNU_verdef section found.  If the
> +/// section wasn't found, this is set to nil.
> +///
> +/// @param verneed_section the SHT_GNU_verneed section found.  If the
> +/// section wasn't found, this is set to nil.
> +///
> +/// @return true iff at least one of the sections where found.
> +bool
> +get_symbol_versionning_sections(Elf*           elf_handle,
> +                               Elf_Scn*&       versym_section,
> +                               Elf_Scn*&       verdef_section,
> +                               Elf_Scn*&       verneed_section)
> +{
> +  Elf_Scn* section = NULL;
> +  GElf_Shdr mem;
> +  Elf_Scn* versym = NULL, *verdef = NULL, *verneed = NULL;
> +
> +  while ((section = elf_nextscn(elf_handle, section)) != NULL)
> +    {
> +      GElf_Shdr* h = gelf_getshdr(section, &mem);
> +      if (h->sh_type == SHT_GNU_versym)
> +       versym = section;
> +      else if (h->sh_type == SHT_GNU_verdef)
> +       verdef = section;
> +      else if (h->sh_type == SHT_GNU_verneed)
> +       verneed = section;
> +    }
> +
> +  if (versym || verdef || verneed)
> +    {
> +      // At least one the versionning sections was found.  Return it.
> +      versym_section = versym;
> +      verdef_section = verdef;
> +      verneed_section = verneed;
> +      return true;
> +    }
> +
> +  return false;
> +}
> +
> +/// Get the version definition (from the SHT_GNU_verdef section) of a
> +/// given symbol represented by a pointer to GElf_Versym.
> +///
> +/// @param elf_hande the elf handle to use.
> +///
> +/// @param versym the symbol to get the version definition for.
> +///
> +/// @param verdef_section the SHT_GNU_verdef section.
> +///
> +/// @param version the resulting version definition.  This is set iff
> +/// the function returns true.
> +///
> +/// @return true upon successful completion, false otherwise.
> +bool
> +get_version_definition_for_versym(Elf*                  elf_handle,
> +                                 GElf_Versym*           versym,
> +                                 Elf_Scn*               verdef_section,
> +                                 elf_symbol::version&   version)
> +{
> +  Elf_Data* verdef_data = elf_getdata(verdef_section, NULL);
> +  GElf_Verdef verdef_mem;
> +  GElf_Verdef* verdef = gelf_getverdef(verdef_data, 0, &verdef_mem);
> +  size_t vd_offset = 0;
> +
> +  for (;; vd_offset += verdef->vd_next)
> +    {
> +      for (;verdef != 0;)
> +       {
> +         if (verdef->vd_ndx == (*versym & 0x7fff))
> +           // Found the version of the symbol.
> +           break;
> +         vd_offset += verdef->vd_next;
> +         verdef = (verdef->vd_next == 0
> +                   ? 0
> +                   : gelf_getverdef(verdef_data, vd_offset, &verdef_mem));
> +       }
> +
> +      if (verdef != 0)
> +       {
> +         GElf_Verdaux verdaux_mem;
> +         GElf_Verdaux *verdaux = gelf_getverdaux(verdef_data,
> +                                                 vd_offset + verdef->vd_aux,
> +                                                 &verdaux_mem);
> +         GElf_Shdr header_mem;
> +         GElf_Shdr* verdef_section_header = gelf_getshdr(verdef_section,
> +                                                         &header_mem);
> +         size_t verdef_stridx = verdef_section_header->sh_link;
> +         version.str(elf_strptr(elf_handle, verdef_stridx, verdaux->vda_name));
> +         if (*versym & 0x8000)
> +           version.is_default(false);
> +         else
> +           version.is_default(true);
> +         return true;
> +       }
> +      if (!verdef || verdef->vd_next == 0)
> +       break;
> +    }
> +  return false;
> +}
> +
> +/// Get the version needed (from the SHT_GNU_verneed section) to
> +/// resolve an undefined symbol represented by a pointer to
> +/// GElf_Versym.
> +///
> +/// @param elf_hande the elf handle to use.
> +///
> +/// @param versym the symbol to get the version definition for.
> +///
> +/// @param verneed_section the SHT_GNU_verneed section.
> +///
> +/// @param version the resulting version definition.  This is set iff
> +/// the function returns true.
> +///
> +/// @return true upon successful completion, false otherwise.
> +bool
> +get_version_needed_for_versym(Elf*                     elf_handle,
> +                             GElf_Versym*              versym,
> +                             Elf_Scn*                  verneed_section,
> +                             elf_symbol::version&      version)
> +{
> +  if (versym == 0 || elf_handle == 0 || verneed_section == 0)
> +    return false;
> +
> +  size_t vn_offset = 0;
> +  Elf_Data* verneed_data = elf_getdata(verneed_section, NULL);
> +  GElf_Verneed verneed_mem;
> +  GElf_Verneed* verneed = gelf_getverneed(verneed_data, 0, &verneed_mem);
> +
> +  for (;verneed; vn_offset += verneed->vn_next)
> +    {
> +      size_t vna_offset = vn_offset;
> +      GElf_Vernaux vernaux_mem;
> +      GElf_Vernaux *vernaux = gelf_getvernaux(verneed_data,
> +                                             vn_offset + verneed->vn_aux,
> +                                             &vernaux_mem);
> +      for (;vernaux != 0 && verneed;)
> +       {
> +         if (vernaux->vna_other == *versym)
> +           // Found the version of the symbol.
> +           break;
> +         vna_offset += verneed->vn_next;
> +         verneed = (verneed->vn_next == 0
> +                    ? 0
> +                    : gelf_getverneed(verneed_data, vna_offset, &verneed_mem));
> +       }
> +
> +      if (verneed != 0 && vernaux != 0 && vernaux->vna_other == *versym)
> +       {
> +         GElf_Shdr header_mem;
> +         GElf_Shdr* verneed_section_header = gelf_getshdr(verneed_section,
> +                                                          &header_mem);
> +         size_t verneed_stridx = verneed_section_header->sh_link;
> +         version.str(elf_strptr(elf_handle,
> +                                verneed_stridx,
> +                                vernaux->vna_name));
> +         if (*versym & 0x8000)
> +           version.is_default(false);
> +         else
> +           version.is_default(true);
> +         return true;
> +       }
> +
> +      if (!verneed || verneed->vn_next == 0)
> +       break;
> +    }
> +  return false;
> +}
> +
> +/// Return the version for a symbol that is at a given index in its
> +/// SHT_SYMTAB section.
> +///
> +/// @param elf_handle the elf handle to use.
> +///
> +/// @param symbol_index the index of the symbol to consider.
> +///
> +/// @param get_def_version if this is true, it means that that we want
> +/// the version for a defined symbol; in that case, the version is
> +/// looked for in a section of type SHT_GNU_verdef.  Otherwise, if
> +/// this parameter is false, this means that we want the version for
> +/// an undefined symbol; in that case, the version is the needed one
> +/// for the symbol to be resolved; so the version is looked fo in a
> +/// section of type SHT_GNU_verneed.
> +///
> +/// @param version the version found for symbol at @p symbol_index.
> +///
> +/// @return true iff a version was found for symbol at index @p
> +/// symbol_index.
> +bool
> +get_version_for_symbol(Elf*                    elf_handle,
> +                      size_t                   symbol_index,
> +                      bool                     get_def_version,
> +                      elf_symbol::version&     version)
> +{
> +  Elf_Scn *versym_section = NULL,
> +    *verdef_section = NULL,
> +    *verneed_section = NULL;
> +
> +  if (!get_symbol_versionning_sections(elf_handle,
> +                                      versym_section,
> +                                      verdef_section,
> +                                      verneed_section))
> +    return false;
> +
> +  GElf_Versym versym_mem;
> +  Elf_Data* versym_data = (versym_section)
> +    ? elf_getdata(versym_section, NULL)
> +    : NULL;
> +  GElf_Versym* versym = (versym_data)
> +    ? gelf_getversym(versym_data, symbol_index, &versym_mem)
> +    : NULL;
> +
> +  if (versym == 0 || *versym <= 1)
> +    // I got these value from the code of readelf.c in elfutils.
> +    // Apparently, if the symbol version entry has these values, the
> +    // symbol must be discarded. This is not documented in the
> +    // official specification.
> +    return false;
> +
> +  if (get_def_version)
> +    {
> +      if (*versym == 0x8001)
> +       // I got this value from the code of readelf.c in elfutils
> +       // too.  It's not really documented in the official
> +       // specification.
> +       return false;
> +
> +      if (verdef_section
> +         && get_version_definition_for_versym(elf_handle, versym,
> +                                              verdef_section, version))
> +       return true;
> +    }
> +  else
> +    {
> +      if (verneed_section
> +         && get_version_needed_for_versym(elf_handle, versym,
> +                                          verneed_section, version))
> +       return true;
> +    }
> +
> +  return false;
> +}
> +
> +
>
>  } // end namespace elf_helpers
>  } // end namespace abigail
> diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
> index 58720da0fa9e..7e1c231ccc4e 100644
> --- a/src/abg-elf-helpers.h
> +++ b/src/abg-elf-helpers.h
> @@ -96,6 +96,34 @@ find_data_section(Elf* elf_handle);
>  Elf_Scn*
>  find_data1_section(Elf* elf_handle);
>
> +bool
> +get_symbol_versionning_sections(Elf*           elf_handle,
> +                               Elf_Scn*&       versym_section,
> +                               Elf_Scn*&       verdef_section,
> +                               Elf_Scn*&       verneed_section);
> +
> +//
> +// Helpers for symbol versioning
> +//
> +
> +bool
> +get_version_definition_for_versym(Elf*                  elf_handle,
> +                                 GElf_Versym*           versym,
> +                                 Elf_Scn*               verdef_section,
> +                                 elf_symbol::version&   version);
> +
> +bool
> +get_version_needed_for_versym(Elf*                     elf_handle,
> +                             GElf_Versym*              versym,
> +                             Elf_Scn*                  verneed_section,
> +                             elf_symbol::version&      version);
> +
> +bool
> +get_version_for_symbol(Elf*                    elf_handle,
> +                      size_t                   symbol_index,
> +                      bool                     get_def_version,
> +                      elf_symbol::version&     version);
> +
>  } // end namespace elf_helpers
>  } // end namespace abigail
>
> --
> 2.26.1.301.g55bc3eb7cb9-goog
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader
  2020-04-20 11:08 ` [PATCH 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader Matthias Maennich
@ 2020-04-20 15:34   ` Giuliano Procida
  0 siblings, 0 replies; 37+ messages in thread
From: Giuliano Procida @ 2020-04-20 15:34 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

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
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case
  2020-04-20 11:08 ` [PATCH 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
@ 2020-04-20 15:35   ` Giuliano Procida
  0 siblings, 0 replies; 37+ messages in thread
From: Giuliano Procida @ 2020-04-20 15:35 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

Looks good.

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

On Mon, 20 Apr 2020 at 12:09, Matthias Maennich <maennich@google.com> wrote:
>
> abg-elf-helpers.{h,cc} shall contain the ELF related parts of the
> abg-dwarf-reader. Create the stub files, an empty unit test and hook
> everything up in the make system.
>
>     * src/Makefile.am: Add new source files abg-elf-helpers.{h,cc}.
>     * src/abg-elf-helpers.cc: New source file.
>     * src/abg-elf-helpers.h: New header file.
>     * tests/.gitignore: Exclude runtestelfhelpers from being committed.
>     * tests/Makefile.am: Add new test case runtestelfhelpers.
>     * tests/test-elf-helpers.cc: New test source file.
>
> Signed-off-by: Matthias Maennich <maennich@google.com>
> ---
>  src/Makefile.am           |  2 ++
>  src/abg-elf-helpers.cc    | 34 ++++++++++++++++++++++++++++++++++
>  src/abg-elf-helpers.h     | 37 +++++++++++++++++++++++++++++++++++++
>  tests/.gitignore          |  1 +
>  tests/Makefile.am         |  6 +++++-
>  tests/test-elf-helpers.cc | 30 ++++++++++++++++++++++++++++++
>  6 files changed, 109 insertions(+), 1 deletion(-)
>  create mode 100644 src/abg-elf-helpers.cc
>  create mode 100644 src/abg-elf-helpers.h
>  create mode 100644 tests/test-elf-helpers.cc
>
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 1d0e2dcecdee..fafab853b520 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -39,6 +39,8 @@ abg-config.cc                         \
>  abg-ini.cc                             \
>  abg-workers.cc                         \
>  abg-tools-utils.cc                     \
> +abg-elf-helpers.h                      \
> +abg-elf-helpers.cc                     \
>  $(CXX11_SOURCES)
>
>  libabigail_la_LIBADD = $(DEPS_LIBS)
> diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
> new file mode 100644
> index 000000000000..e99fe4a5c306
> --- /dev/null
> +++ b/src/abg-elf-helpers.cc
> @@ -0,0 +1,34 @@
> +// -*- Mode: C++ -*-
> +//
> +// Copyright (C) 2020 Google, Inc.
> +//
> +// This file is part of the GNU Application Binary Interface Generic
> +// Analysis and Instrumentation Library (libabigail).  This library is
> +// free software; you can redistribute it and/or modify it under the
> +// terms of the GNU Lesser General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option) any
> +// later version.
> +
> +// This library is distributed in the hope that it will be useful, but
> +// WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +// General Lesser Public License for more details.
> +
> +// You should have received a copy of the GNU Lesser General Public
> +// License along with this program; see the file COPYING-LGPLV3.  If
> +// not, see <http://www.gnu.org/licenses/>.
> +
> +/// @file
> +///
> +/// This contains the definitions of the ELF utilities for the dwarf reader.
> +
> +#include "abg-elf-helpers.h"
> +
> +namespace abigail
> +{
> +
> +namespace elf_helpers
> +{
> +
> +} // end namespace elf_helpers
> +} // end namespace abigail
> diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
> new file mode 100644
> index 000000000000..bffa46cc3c2d
> --- /dev/null
> +++ b/src/abg-elf-helpers.h
> @@ -0,0 +1,37 @@
> +// -*- Mode: C++ -*-
> +//
> +// Copyright (C) 2020 Google, Inc.
> +//
> +// This file is part of the GNU Application Binary Interface Generic
> +// Analysis and Instrumentation Library (libabigail).  This library is
> +// free software; you can redistribute it and/or modify it under the
> +// terms of the GNU Lesser General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option) any
> +// later version.
> +
> +// This library is distributed in the hope that it will be useful, but
> +// WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +// General Lesser Public License for more details.
> +
> +// You should have received a copy of the GNU Lesser General Public
> +// License along with this program; see the file COPYING-LGPLV3.  If
> +// not, see <http://www.gnu.org/licenses/>.
> +
> +/// @file
> +///
> +/// This contains a set of ELF utilities used by the dwarf reader.
> +
> +#ifndef __ABG_ELF_HELPERS_H__
> +#define __ABG_ELF_HELPERS_H__
> +
> +namespace abigail
> +{
> +
> +namespace elf_helpers
> +{
> +
> +} // end namespace elf_helpers
> +} // end namespace abigail
> +
> +#endif // __ABG_ELF_HELPERS_H__
> diff --git a/tests/.gitignore b/tests/.gitignore
> index f05e295db260..ebe7b9cc9e13 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -22,6 +22,7 @@ runtestdiffdwarfabixml
>  runtestdifffilter
>  runtestdiffpkg
>  runtestdiffsuppr
> +runtestelfhelpers
>  runtestini
>  runtestkmiwhitelist
>  runtestlookupsyms
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 823e0db50c37..c1b187051377 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -46,6 +46,7 @@ runtestabidiffexit            \
>  runtestini                     \
>  runtesttoolsutils              \
>  runtestkmiwhitelist            \
> +runtestelfhelpers              \
>  $(CXX11_TESTS)
>
>  if ENABLE_RUNNING_TESTS_WITH_PY3
> @@ -142,6 +143,9 @@ runtesttoolsutils_LDADD = libtestutils.la $(top_builddir)/src/libabigail.la
>  runtestkmiwhitelist_SOURCES = test-kmi-whitelist.cc
>  runtestkmiwhitelist_LDADD = libtestutils.la libcatch.la $(top_builddir)/src/libabigail.la
>
> +runtestelfhelpers_SOURCES = test-elf-helpers.cc
> +runtestelfhelpers_LDADD = libcatch.la $(top_builddir)/src/libabigail.la
> +
>  runtestsvg_SOURCES=test-svg.cc
>  runtestsvg_LDADD=$(top_builddir)/src/libabigail.la
>
> @@ -172,7 +176,7 @@ runtestfedabipkgdiffpy3.sh$(EXEEXT):
>  runtestdefaultsupprspy3_sh_SOURCES =
>  runtestdefaultsupprspy3.sh$(EXEEXT):
>
> -AM_CPPFLAGS=-I${abs_top_srcdir}/include \
> +AM_CPPFLAGS=-I${abs_top_srcdir}/include -I${abs_top_srcdir}/src \
>  -I${abs_top_builddir}/include -I${abs_top_srcdir}/tools -fPIC
>
>  clean-local: clean-local-check
> diff --git a/tests/test-elf-helpers.cc b/tests/test-elf-helpers.cc
> new file mode 100644
> index 000000000000..1b36ee2f122a
> --- /dev/null
> +++ b/tests/test-elf-helpers.cc
> @@ -0,0 +1,30 @@
> +// -*- Mode: C++ -*-
> +//
> +// Copyright (C) 2020 Google, Inc.
> +//
> +// This file is part of the GNU Application Binary Interface Generic
> +// Analysis and Instrumentation Library (libabigail).  This library is
> +// free software; you can redistribute it and/or modify it under the
> +// terms of the GNU Lesser General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option) any
> +// later version.
> +
> +// This library is distributed in the hope that it will be useful, but
> +// WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +// General Lesser Public License for more details.
> +
> +// You should have received a copy of the GNU Lesser General Public
> +// License along with this program; see the file COPYING-LGPLV3.  If
> +// not, see <http://www.gnu.org/licenses/>.
> +
> +// Author: Matthias Maennich
> +
> +/// @file
> +///
> +/// This program tests libabigail's ELF helpers.
> +
> +#include "lib/catch.hpp"
> +
> +#include "abg-elf-helpers.h"
> +
> --
> 2.26.1.301.g55bc3eb7cb9-goog
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers
  2020-04-20 15:24   ` Giuliano Procida
@ 2020-04-21  6:14     ` Matthias Maennich
  2020-04-21 11:02       ` Giuliano Procida
  0 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:14 UTC (permalink / raw)
  To: Giuliano Procida; +Cc: libabigail, Dodji Seketeli, kernel-team

On Mon, Apr 20, 2020 at 04:24:50PM +0100, Giuliano Procida wrote:
>Hi.
>
>On Mon, 20 Apr 2020 at 12:09, Matthias Maennich <maennich@google.com> wrote:
>>
>> This change migrates all ELF helpers related to section lookup to
>> abg-elf-helpers.{cc,h}. It also homogenizes the interface of those to
>> always return Elf_Scn* and NULL in case that section can't be found.
>> Though this smells like a functional change, this latter change is
>> purely cosmetic.
>>
>>         * src/abg-dwarf-reader.cc (read_context::find_symbol_table_section):
>>         adjust to new interface of elf_helpers::find_symbol_table_section.
>>         (find_opd_section): use elf_helpers::find_opd_section for lookup.
>>         (find_ksymtab_section): use elf_helpers::find_ksymtab_section.
>>         (find_ksymtab_gpl_section): use elf_helpers::find_ksymtab_gpl_section.
>>         (find_relocation_section): Move out function.
>>         (get_binary_load_address): Move out function.
>>         (find_ksymtab_reloc_section): use elf_helpers::find_relocation_section
>>         (find_ksymtab_gpl_reloc_section): use elf_helpers::find_relocation_section
>>         * src/elf-helpers.cc (find_symbol_table_section): change
>>         interface to match other find_*_section functions.
>>         (find_symbol_table_section_index): Adjust for the new interface
>>         of find_symbol_table_section.
>>         (find_opd_section): New function.
>>         (find_ksymtab_section): New function.
>>         (find_ksymtab_gpl_section): New function.
>>         (find_relocation_section): New function.
>>         (get_binary_load_address): New function.
>>         * src/elf-helpers.h (find_symbol_table_section): Change declaration.
>>         (find_opd_section): New function declation.
>>         (find_ksymtab_section): New function declation.
>>         (find_ksymtab_gpl_section): New function declation.
>>         (find_relocation_section): New function declation.
>>         (get_binary_load_address): New function declation.
>>
>> Signed-off-by: Matthias Maennich <maennich@google.com>
>> ---
>>  src/abg-dwarf-reader.cc | 112 ++++++----------------------------
>>  src/abg-elf-helpers.cc  | 129 +++++++++++++++++++++++++++++++++++++---
>>  src/abg-elf-helpers.h   |  22 ++++++-
>>  3 files changed, 157 insertions(+), 106 deletions(-)
>>
>> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
>> index ec1f9f3fe8f3..56da03a60940 100644
>> --- a/src/abg-dwarf-reader.cc
>> +++ b/src/abg-dwarf-reader.cc
>> @@ -542,53 +542,6 @@ compare_dies(const read_context& ctxt,
>>              bool update_canonical_dies_on_the_fly);
>>
>>
>> -/// Get the address at which a given binary is loaded in memory⋅
>> -///
>> -/// @param elf_handle the elf handle for the binary to consider.
>> -///
>> -/// @param load_address the address where the binary is loaded.  This
>> -/// is set by the function iff it returns true.
>> -///
>> -/// @return true if the function could get the binary load address
>> -/// and assign @p load_address to it.
>> -static bool
>> -get_binary_load_address(Elf *elf_handle,
>> -                       GElf_Addr &load_address)
>> -{
>> -  GElf_Ehdr eh_mem;
>> -  GElf_Ehdr *elf_header = gelf_getehdr(elf_handle, &eh_mem);
>> -  size_t num_segments = elf_header->e_phnum;
>> -  GElf_Phdr *program_header = 0;
>> -  GElf_Addr result;
>> -  bool found_loaded_segment = false;
>> -  GElf_Phdr ph_mem;
>> -
>> -  for (unsigned i = 0; i < num_segments; ++i)
>> -    {
>> -      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
>> -      if (program_header && program_header->p_type == PT_LOAD)
>> -       {
>> -         if (!found_loaded_segment)
>> -           {
>> -             result = program_header->p_vaddr;
>> -             found_loaded_segment = true;
>> -           }
>> -
>> -         if (program_header->p_vaddr < result)
>> -           // The resulting load address we want is the lowest
>> -           // load address of all the loaded segments.
>> -           result = program_header->p_vaddr;
>> -       }
>> -    }
>> -
>> -  if (found_loaded_segment)
>> -    {
>> -      load_address = result;
>> -      return true;
>> -    }
>> -  return false;
>> -}
>> -
>>  /// Find the file name of the alternate debug info file.
>>  ///
>>  /// @param elf_module the elf module to consider.
>> @@ -5282,8 +5235,8 @@ public:
>>    find_symbol_table_section() const
>>    {
>>      if (!symtab_section_)
>> -      dwarf_reader::find_symbol_table_section(elf_handle(),
>> -                                             const_cast<read_context*>(this)->symtab_section_);
>> +      const_cast<read_context*>(this)->symtab_section_ =
>> +         elf_helpers::find_symbol_table_section(elf_handle());
>>      return symtab_section_;
>>    }
>>
>> @@ -5296,8 +5249,8 @@ public:
>>    find_opd_section() const
>>    {
>>      if (!opd_section_)
>> -      const_cast<read_context*>(this)->opd_section_=
>> -       find_section(elf_handle(), ".opd", SHT_PROGBITS);
>> +      const_cast<read_context*>(this)->opd_section_ =
>> +         elf_helpers::find_opd_section(elf_handle());
>>      return opd_section_;
>>    }
>>
>> @@ -5310,39 +5263,21 @@ public:
>>    {
>>      if (!ksymtab_section_)
>>        const_cast<read_context*>(this)->ksymtab_section_ =
>> -       find_section(elf_handle(), "__ksymtab", SHT_PROGBITS);
>> +         elf_helpers::find_ksymtab_section(elf_handle());
>>      return ksymtab_section_;
>>    }
>>
>> -  /// Return the .rel{a,} section corresponding to a given section.
>> -  ///
>> -  /// @param target_section the section to search the relocation section for
>> +  /// Return the __ksymtab_gpl section of a linux kernel ELF file
>> +  /// (either a vmlinux binary or a kernel module).
>>    ///
>> -  /// @return the .rel{a,} section if found, null otherwise.
>> +  /// @return the __ksymtab_gpl section if found, nil otherwise.
>>    Elf_Scn*
>> -  find_relocation_section(Elf_Scn* target_section) const
>> +  find_ksymtab_gpl_section() const
>>    {
>> -    if (target_section)
>> -      {
>> -       // the relo section we are searching for has this index as sh_info
>> -       size_t target_index = elf_ndxscn(target_section);
>> -
>> -       // now iterate over all the sections, look for relocation sections and
>> -       // find the one that points to the section we are searching for
>> -       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 != SHT_RELA && header->sh_type != SHT_REL))
>> -             continue;
>> -
>> -           if (header->sh_info == target_index)
>> -             return section;
>> -         }
>> -      }
>> -    return NULL;
>> +    if (!ksymtab_gpl_section_)
>> +      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
>> +         elf_helpers::find_ksymtab_gpl_section(elf_handle());
>> +    return ksymtab_gpl_section_;
>>    }
>>
>>    /// Return the .rel{a,}__ksymtab section of a linux kernel ELF file (either
>> @@ -5354,25 +5289,12 @@ public:
>>    {
>>      if (!ksymtab_reloc_section_)
>>        {
>> -       const_cast<read_context*>(this)->ksymtab_reloc_section_
>> -           = find_relocation_section(find_ksymtab_section());
>> +       const_cast<read_context*>(this)->ksymtab_reloc_section_ =
>> +           find_relocation_section(elf_handle(), find_ksymtab_section());
>>        }
>>      return ksymtab_reloc_section_;
>>    }
>>
>> -  /// Return the __ksymtab_gpl section of a linux kernel ELF file
>> -  /// (either a vmlinux binary or a kernel module).
>> -  ///
>> -  /// @return the __ksymtab_gpl section if found, nil otherwise.
>> -  Elf_Scn*
>> -  find_ksymtab_gpl_section() const
>> -  {
>> -    if (!ksymtab_gpl_section_)
>> -      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
>> -       find_section(elf_handle(), "__ksymtab_gpl", SHT_PROGBITS);
>> -    return ksymtab_gpl_section_;
>> -  }
>> -
>>    /// Return the .rel{a,}__ksymtab_gpl section of a linux kernel ELF file
>>    /// (either a vmlinux binary or a kernel module).
>>    ///
>> @@ -5382,8 +5304,8 @@ public:
>>    {
>>      if (!ksymtab_gpl_reloc_section_)
>>        {
>> -       const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_
>> -           = find_relocation_section(find_ksymtab_gpl_section());
>> +       const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_ =
>> +           find_relocation_section(elf_handle(), find_ksymtab_gpl_section());
>>        }
>>      return ksymtab_gpl_reloc_section_;
>>    }
>> diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
>> index ede191014369..b77440206fb0 100644
>> --- a/src/abg-elf-helpers.cc
>> +++ b/src/abg-elf-helpers.cc
>> @@ -357,9 +357,9 @@ find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
>>  ///
>>  /// @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)
>> +/// @return the symbol table section
>> +Elf_Scn*
>> +find_symbol_table_section(Elf* elf_handle)
>>  {
>>    Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0;
>>    while ((section = elf_nextscn(elf_handle, section)) != 0)
>> @@ -378,12 +378,11 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
>>        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;
>> +       return sym_tab ? sym_tab : dynsym;
>>        else
>> -       symtab = dynsym ? dynsym : sym_tab;
>> -      return true;
>> +       return dynsym ? dynsym : sym_tab;
>>      }
>> -  return false;
>> +  return NULL;
>>  }
>>
>>  /// Find the index (in the section headers table) of the symbol table
>> @@ -402,8 +401,9 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
>>  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))
>> +  Elf_Scn* section = find_symbol_table_section(elf_handle);
>> +
>> +  if (!section)
>>      return false;
>>
>>    symtab_index = elf_ndxscn(section);
>> @@ -500,6 +500,17 @@ Elf_Scn*
>>  find_data1_section(Elf* elf_handle)
>>  {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
>>
>> +/// Return the "Official Procedure descriptors section."  This
>> +/// section is named .opd, and is usually present only on PPC64
>> +/// ELFv1 binaries.
>> +///
>> +/// @param elf_handle the elf handle to consider.
>> +///
>> +/// @return the .opd section, if found.  Return nil otherwise.
>> +Elf_Scn*
>> +find_opd_section(Elf* elf_handle)
>> +{return find_section(elf_handle, ".opd", SHT_PROGBITS);}
>> +
>>  /// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
>>  /// sections that are involved in symbol versionning.
>>  ///
>> @@ -548,6 +559,26 @@ get_symbol_versionning_sections(Elf*               elf_handle,
>>    return false;
>>  }
>>
>> +/// Return the __ksymtab section of a linux kernel ELF file (either
>> +/// a vmlinux binary or a kernel module).
>> +///
>> +/// @param elf_handle the elf handle to consider.
>> +///
>> +/// @return the __ksymtab section if found, nil otherwise.
>> +Elf_Scn*
>> +find_ksymtab_section(Elf* elf_handle)
>> +{return find_section(elf_handle, "__ksymtab", SHT_PROGBITS);}
>> +
>> +/// Return the __ksymtab_gpl section of a linux kernel ELF file (either
>> +/// a vmlinux binary or a kernel module).
>> +///
>> +/// @param elf_handle the elf handle to consider.
>> +///
>> +/// @return the __ksymtab section if found, nil otherwise.
>> +Elf_Scn*
>> +find_ksymtab_gpl_section(Elf* elf_handle)
>> +{return find_section(elf_handle, "__ksymtab_gpl", SHT_PROGBITS);}
>> +
>>  /// Find the __ksymtab_strings section of a Linux kernel binary.
>>  ///
>>  /// @param elf_handle the elf handle to use.
>> @@ -563,6 +594,39 @@ find_ksymtab_strings_section(Elf *elf_handle)
>>    return 0;
>>  }
>>
>> +/// Return the .rel{a,} section corresponding to a given section.
>> +///
>> +/// @param elf_handle the elf handle to consider.
>> +///
>> +/// @param target_section the section to search the relocation section for
>> +///
>> +/// @return the .rel{a,} section if found, null otherwise.
>> +Elf_Scn*
>> +find_relocation_section(Elf* elf_handle, Elf_Scn* target_section)
>> +{
>> +  if (target_section)
>> +    {
>> +      // the relo section we are searching for has this index as sh_info
>> +      size_t target_index = elf_ndxscn(target_section);
>> +
>> +      // now iterate over all the sections, look for relocation sections and
>> +      // find the one that points to the section we are searching for
>> +      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 != SHT_RELA && header->sh_type != SHT_REL))
>> +           continue;
>> +
>> +         if (header->sh_info == target_index)
>> +           return section;
>> +       }
>> +    }
>> +  return NULL;
>> +}
>> +
>>  /// Get the version definition (from the SHT_GNU_verdef section) of a
>>  /// given symbol represented by a pointer to GElf_Versym.
>>  ///
>> @@ -797,5 +861,52 @@ is_linux_kernel(Elf *elf_handle)
>>           || is_linux_kernel_module(elf_handle));
>>  }
>>
>> +/// Get the address at which a given binary is loaded in memory⋅
>> +///
>> +/// @param elf_handle the elf handle for the binary to consider.
>> +///
>> +/// @param load_address the address where the binary is loaded.  This
>> +/// is set by the function iff it returns true.
>> +///
>> +/// @return true if the function could get the binary load address
>> +/// and assign @p load_address to it.
>
>Should be returning nullable load_address.

I thought of that as well, but decided against. The return value is not
a pointer type where NULL would be indicative, 0 is a valid result for
this function and we do not have the facilities like std::optional
(yet). I would not want to burden the caller with freeing any memory
either. Hence I stuck to the original interface. Did I miss an obvious
other option?

Cheers,
Matthias

>
>
>> +bool
>> +get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
>> +{
>> +  GElf_Ehdr elf_header;
>> +  gelf_getehdr(elf_handle, &elf_header);
>> +  size_t num_segments = elf_header.e_phnum;
>> +  GElf_Phdr *program_header = NULL;
>> +  GElf_Addr result;
>> +  bool found_loaded_segment = false;
>> +  GElf_Phdr ph_mem;
>> +
>> +  for (unsigned i = 0; i < num_segments; ++i)
>> +    {
>> +      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
>> +      if (program_header && program_header->p_type == PT_LOAD)
>> +       {
>> +         if (!found_loaded_segment)
>> +           {
>> +             result = program_header->p_vaddr;
>> +             found_loaded_segment = true;
>> +           }
>> +
>> +         if (program_header->p_vaddr < result)
>> +           // The resulting load address we want is the lowest
>> +           // load address of all the loaded segments.
>> +           result = program_header->p_vaddr;
>> +       }
>> +    }
>> +
>> +  if (found_loaded_segment)
>> +    {
>> +      load_address = result;
>> +      return true;
>> +    }
>> +  return false;
>> +}
>> +
>> +
>>  } // end namespace elf_helpers
>>  } // end namespace abigail
>> diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
>> index 7ddd887de959..8a83bb4f2e95 100644
>> --- a/src/abg-elf-helpers.h
>> +++ b/src/abg-elf-helpers.h
>> @@ -63,8 +63,8 @@ find_section(Elf*             elf_handle,
>>              const std::string& name,
>>              Elf64_Word         section_type);
>>
>> -bool
>> -find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab);
>> +Elf_Scn*
>> +find_symbol_table_section(Elf* elf_handle);
>>
>>  bool
>>  find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index);
>> @@ -96,15 +96,27 @@ find_data_section(Elf* elf_handle);
>>  Elf_Scn*
>>  find_data1_section(Elf* elf_handle);
>>
>> +Elf_Scn*
>> +find_opd_section(Elf* elf_handle);
>> +
>>  bool
>>  get_symbol_versionning_sections(Elf*           elf_handle,
>>                                 Elf_Scn*&       versym_section,
>>                                 Elf_Scn*&       verdef_section,
>>                                 Elf_Scn*&       verneed_section);
>>
>> +Elf_Scn*
>> +find_ksymtab_section(Elf* elf_handle);
>> +
>> +Elf_Scn*
>> +find_ksymtab_gpl_section(Elf* elf_handle);
>> +
>>  Elf_Scn*
>>  find_ksymtab_strings_section(Elf *elf_handle);
>>
>> +Elf_Scn*
>> +find_relocation_section(Elf* elf_handle, Elf_Scn* target_section);
>> +
>>  //
>>  // Helpers for symbol versioning
>>  //
>> @@ -137,6 +149,12 @@ is_linux_kernel_module(Elf *elf_handle);
>>  bool
>>  is_linux_kernel(Elf *elf_handle);
>>
>> +//
>> +// Misc Helpers
>> +//
>> +
>> +bool
>> +get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address);
>>
>>  } // end namespace elf_helpers
>>  } // end namespace abigail
>> --
>> 2.26.1.301.g55bc3eb7cb9-goog
>>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers
  2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                   ` (7 preceding siblings ...)
  2020-04-20 11:08 ` [PATCH 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr Matthias Maennich
@ 2020-04-21  6:35 ` Matthias Maennich
  2020-04-21  6:35   ` [PATCH v2 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
                     ` (8 more replies)
  8 siblings, 9 replies; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:35 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

The abg-dwarf-reader.cc has grown into a large compilation unit with a lot of
responsibilities. This does not only affect the compilation time, but also
readability of the various implementation details. Hence it makes sense to
attempt a refactoring of parts of it.

To overcome the above and as a preparation for my future work on the symtab
reading part, this splits out functionality from the dwarf reader into a new
set of source files: src/elf-helpers.{h,cc} along with a test that so far only
serves the purpose of ensuring that the header file can be compiled on its own.

The elf-helpers, sensibly not named elf-utils, contain functionality like
looking up sections, converting values or deducting information and properties
in some way from an Elf* handle. They are not exposed to libabigail users as
they are an implementation detail of libabigail.

This set of changes is only a refactoring with minor cleanups and renames and
any change to the functionality would be unintentional.

Cheers,
Matthias

---

v2: Address Giuliano's comments. (Thanks!)
    Mostly reworking the commit messages.

Matthias Maennich (8):
  abg-dwarf-reader split: create abg-elf-helpers.{h,cc} and test case
  abg-elf-helpers: move some elf helpers from abg-dwarf-reader
  abg-elf-helpers: move some versioning helpers from abg-dwarf-reader
  abg-elf-helpers: move some kernel helpers from abg-dwarf-reader
  abg-elf-helpers: consolidate the is_linux_kernel* helpers
  abg-dwarf-reader: migrate more ELF helpers to elf-helpers
  abg-elf-helpers: migrate more elf helpers (architecture specific
    helpers)
  abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr

 src/Makefile.am           |    2 +
 src/abg-dwarf-reader.cc   | 1209 ++-----------------------------------
 src/abg-elf-helpers.cc    | 1031 +++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h     |  183 ++++++
 tests/.gitignore          |    1 +
 tests/Makefile.am         |    6 +-
 tests/test-elf-helpers.cc |   30 +
 7 files changed, 1295 insertions(+), 1167 deletions(-)
 create mode 100644 src/abg-elf-helpers.cc
 create mode 100644 src/abg-elf-helpers.h
 create mode 100644 tests/test-elf-helpers.cc

-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v2 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
@ 2020-04-21  6:35   ` Matthias Maennich
  2020-04-22  9:42     ` Dodji Seketeli
  2020-04-21  6:35   ` [PATCH v2 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader Matthias Maennich
                     ` (7 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:35 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

abg-elf-helpers.{h,cc} shall contain the ELF related parts of the
abg-dwarf-reader. Create the stub files, an empty unit test and hook
everything up in the make system.

    * src/Makefile.am: Add new source files abg-elf-helpers.{h,cc}.
    * src/abg-elf-helpers.cc: New source file.
    * src/abg-elf-helpers.h: New header file.
    * tests/.gitignore: Exclude runtestelfhelpers from being committed.
    * tests/Makefile.am: Add new test case runtestelfhelpers.
    * tests/test-elf-helpers.cc: New test source file.

Reviewed-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/Makefile.am           |  2 ++
 src/abg-elf-helpers.cc    | 34 ++++++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h     | 37 +++++++++++++++++++++++++++++++++++++
 tests/.gitignore          |  1 +
 tests/Makefile.am         |  6 +++++-
 tests/test-elf-helpers.cc | 30 ++++++++++++++++++++++++++++++
 6 files changed, 109 insertions(+), 1 deletion(-)
 create mode 100644 src/abg-elf-helpers.cc
 create mode 100644 src/abg-elf-helpers.h
 create mode 100644 tests/test-elf-helpers.cc

diff --git a/src/Makefile.am b/src/Makefile.am
index 1d0e2dcecdee..fafab853b520 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,6 +39,8 @@ abg-config.cc				\
 abg-ini.cc				\
 abg-workers.cc				\
 abg-tools-utils.cc			\
+abg-elf-helpers.h			\
+abg-elf-helpers.cc			\
 $(CXX11_SOURCES)
 
 libabigail_la_LIBADD = $(DEPS_LIBS)
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
new file mode 100644
index 000000000000..e99fe4a5c306
--- /dev/null
+++ b/src/abg-elf-helpers.cc
@@ -0,0 +1,34 @@
+// -*- Mode: C++ -*-
+//
+// Copyright (C) 2020 Google, Inc.
+//
+// This file is part of the GNU Application Binary Interface Generic
+// Analysis and Instrumentation Library (libabigail).  This library is
+// free software; you can redistribute it and/or modify it under the
+// terms of the GNU Lesser General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option) any
+// later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; see the file COPYING-LGPLV3.  If
+// not, see <http://www.gnu.org/licenses/>.
+
+/// @file
+///
+/// This contains the definitions of the ELF utilities for the dwarf reader.
+
+#include "abg-elf-helpers.h"
+
+namespace abigail
+{
+
+namespace elf_helpers
+{
+
+} // end namespace elf_helpers
+} // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
new file mode 100644
index 000000000000..bffa46cc3c2d
--- /dev/null
+++ b/src/abg-elf-helpers.h
@@ -0,0 +1,37 @@
+// -*- Mode: C++ -*-
+//
+// Copyright (C) 2020 Google, Inc.
+//
+// This file is part of the GNU Application Binary Interface Generic
+// Analysis and Instrumentation Library (libabigail).  This library is
+// free software; you can redistribute it and/or modify it under the
+// terms of the GNU Lesser General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option) any
+// later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; see the file COPYING-LGPLV3.  If
+// not, see <http://www.gnu.org/licenses/>.
+
+/// @file
+///
+/// This contains a set of ELF utilities used by the dwarf reader.
+
+#ifndef __ABG_ELF_HELPERS_H__
+#define __ABG_ELF_HELPERS_H__
+
+namespace abigail
+{
+
+namespace elf_helpers
+{
+
+} // end namespace elf_helpers
+} // end namespace abigail
+
+#endif // __ABG_ELF_HELPERS_H__
diff --git a/tests/.gitignore b/tests/.gitignore
index f05e295db260..ebe7b9cc9e13 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -22,6 +22,7 @@ runtestdiffdwarfabixml
 runtestdifffilter
 runtestdiffpkg
 runtestdiffsuppr
+runtestelfhelpers
 runtestini
 runtestkmiwhitelist
 runtestlookupsyms
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 823e0db50c37..c1b187051377 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -46,6 +46,7 @@ runtestabidiffexit		\
 runtestini			\
 runtesttoolsutils		\
 runtestkmiwhitelist		\
+runtestelfhelpers		\
 $(CXX11_TESTS)
 
 if ENABLE_RUNNING_TESTS_WITH_PY3
@@ -142,6 +143,9 @@ runtesttoolsutils_LDADD = libtestutils.la $(top_builddir)/src/libabigail.la
 runtestkmiwhitelist_SOURCES = test-kmi-whitelist.cc
 runtestkmiwhitelist_LDADD = libtestutils.la libcatch.la $(top_builddir)/src/libabigail.la
 
+runtestelfhelpers_SOURCES = test-elf-helpers.cc
+runtestelfhelpers_LDADD = libcatch.la $(top_builddir)/src/libabigail.la
+
 runtestsvg_SOURCES=test-svg.cc
 runtestsvg_LDADD=$(top_builddir)/src/libabigail.la
 
@@ -172,7 +176,7 @@ runtestfedabipkgdiffpy3.sh$(EXEEXT):
 runtestdefaultsupprspy3_sh_SOURCES =
 runtestdefaultsupprspy3.sh$(EXEEXT):
 
-AM_CPPFLAGS=-I${abs_top_srcdir}/include \
+AM_CPPFLAGS=-I${abs_top_srcdir}/include -I${abs_top_srcdir}/src \
 -I${abs_top_builddir}/include -I${abs_top_srcdir}/tools -fPIC
 
 clean-local: clean-local-check
diff --git a/tests/test-elf-helpers.cc b/tests/test-elf-helpers.cc
new file mode 100644
index 000000000000..1b36ee2f122a
--- /dev/null
+++ b/tests/test-elf-helpers.cc
@@ -0,0 +1,30 @@
+// -*- Mode: C++ -*-
+//
+// Copyright (C) 2020 Google, Inc.
+//
+// This file is part of the GNU Application Binary Interface Generic
+// Analysis and Instrumentation Library (libabigail).  This library is
+// free software; you can redistribute it and/or modify it under the
+// terms of the GNU Lesser General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option) any
+// later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; see the file COPYING-LGPLV3.  If
+// not, see <http://www.gnu.org/licenses/>.
+
+// Author: Matthias Maennich
+
+/// @file
+///
+/// This program tests libabigail's ELF helpers.
+
+#include "lib/catch.hpp"
+
+#include "abg-elf-helpers.h"
+
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v2 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
  2020-04-21  6:35   ` [PATCH v2 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
@ 2020-04-21  6:35   ` Matthias Maennich
  2020-04-22  9:44     ` Dodji Seketeli
  2020-04-21  6:35   ` [PATCH v2 3/8] abg-elf-helpers: move some versioning " Matthias Maennich
                     ` (6 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:35 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

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.h(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


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v2 3/8] abg-elf-helpers: move some versioning helpers from abg-dwarf-reader
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
  2020-04-21  6:35   ` [PATCH v2 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
  2020-04-21  6:35   ` [PATCH v2 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader Matthias Maennich
@ 2020-04-21  6:35   ` Matthias Maennich
  2020-04-22  9:46     ` Dodji Seketeli
  2020-04-21  6:35   ` [PATCH v2 4/8] abg-elf-helpers: move some kernel " Matthias Maennich
                     ` (5 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:35 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

Move some definitions from abg-dwarf-reader to abg-elf-helpers that are
strictly only related to ELF.

        * abg-dwarf-reader.cc(get_symbol_versionning_sections): Move function out.
        (get_version_definition_for_versym): Likewise.
        (get_version_needed_for_versym): Likewise.
        (get_version_for_symbol): Likewise.
        * abg-elf-helpers.cc(get_symbol_versionning_sections): Move function in.
        (get_version_definition_for_versym): Likewise.
        (get_version_needed_for_versym): Likewise.
        (get_version_for_symbol): Likewise.
        * abg-elf-helpers.cc(get_symbol_versionning_sections): Add declaration.
        (get_version_definition_for_versym): Likewise.
        (get_version_needed_for_versym): Likewise.
        (get_version_for_symbol): Likewise.

Reviewed-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 256 ----------------------------------------
 src/abg-elf-helpers.cc  | 251 +++++++++++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h   |  28 +++++
 3 files changed, 279 insertions(+), 256 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 6ec7e4b6e968..303c1f8df4c2 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -294,12 +294,6 @@ static void
 add_symbol_to_map(const elf_symbol_sptr& sym,
 		  string_elf_symbols_map_type& map);
 
-static bool
-get_symbol_versionning_sections(Elf*		elf_handle,
-				Elf_Scn*&	versym_section,
-				Elf_Scn*&	verdef_section,
-				Elf_Scn*&	verneed_section);
-
 static bool
 get_parent_die(const read_context&	ctxt,
 	       const Dwarf_Die*	die,
@@ -867,256 +861,6 @@ compare_symbol_name(const string& symbol_name,
   return symbol_name == name;
 }
 
-/// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
-/// sections that are involved in symbol versionning.
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @param versym_section the SHT_GNU_versym section found.  If the
-/// section wasn't found, this is set to nil.
-///
-/// @param verdef_section the SHT_GNU_verdef section found.  If the
-/// section wasn't found, this is set to nil.
-///
-/// @param verneed_section the SHT_GNU_verneed section found.  If the
-/// section wasn't found, this is set to nil.
-///
-/// @return true iff at least one of the sections where found.
-static bool
-get_symbol_versionning_sections(Elf*		elf_handle,
-				Elf_Scn*&	versym_section,
-				Elf_Scn*&	verdef_section,
-				Elf_Scn*&	verneed_section)
-{
-  Elf_Scn* section = NULL;
-  GElf_Shdr mem;
-  Elf_Scn* versym = NULL, *verdef = NULL, *verneed = NULL;
-
-  while ((section = elf_nextscn(elf_handle, section)) != NULL)
-    {
-      GElf_Shdr* h = gelf_getshdr(section, &mem);
-      if (h->sh_type == SHT_GNU_versym)
-	versym = section;
-      else if (h->sh_type == SHT_GNU_verdef)
-	verdef = section;
-      else if (h->sh_type == SHT_GNU_verneed)
-	verneed = section;
-    }
-
-  if (versym || verdef || verneed)
-    {
-      // At least one the versionning sections was found.  Return it.
-      versym_section = versym;
-      verdef_section = verdef;
-      verneed_section = verneed;
-      return true;
-    }
-
-  return false;
-}
-
-/// Get the version definition (from the SHT_GNU_verdef section) of a
-/// given symbol represented by a pointer to GElf_Versym.
-///
-/// @param elf_hande the elf handle to use.
-///
-/// @param versym the symbol to get the version definition for.
-///
-/// @param verdef_section the SHT_GNU_verdef section.
-///
-/// @param version the resulting version definition.  This is set iff
-/// the function returns true.
-///
-/// @return true upon successful completion, false otherwise.
-static bool
-get_version_definition_for_versym(Elf*			 elf_handle,
-				  GElf_Versym*		 versym,
-				  Elf_Scn*		 verdef_section,
-				  elf_symbol::version&	 version)
-{
-  Elf_Data* verdef_data = elf_getdata(verdef_section, NULL);
-  GElf_Verdef verdef_mem;
-  GElf_Verdef* verdef = gelf_getverdef(verdef_data, 0, &verdef_mem);
-  size_t vd_offset = 0;
-
-  for (;; vd_offset += verdef->vd_next)
-    {
-      for (;verdef != 0;)
-	{
-	  if (verdef->vd_ndx == (*versym & 0x7fff))
-	    // Found the version of the symbol.
-	    break;
-	  vd_offset += verdef->vd_next;
-	  verdef = (verdef->vd_next == 0
-		    ? 0
-		    : gelf_getverdef(verdef_data, vd_offset, &verdef_mem));
-	}
-
-      if (verdef != 0)
-	{
-	  GElf_Verdaux verdaux_mem;
-	  GElf_Verdaux *verdaux = gelf_getverdaux(verdef_data,
-						  vd_offset + verdef->vd_aux,
-						  &verdaux_mem);
-	  GElf_Shdr header_mem;
-	  GElf_Shdr* verdef_section_header = gelf_getshdr(verdef_section,
-							  &header_mem);
-	  size_t verdef_stridx = verdef_section_header->sh_link;
-	  version.str(elf_strptr(elf_handle, verdef_stridx, verdaux->vda_name));
-	  if (*versym & 0x8000)
-	    version.is_default(false);
-	  else
-	    version.is_default(true);
-	  return true;
-	}
-      if (!verdef || verdef->vd_next == 0)
-	break;
-    }
-  return false;
-}
-
-/// Get the version needed (from the SHT_GNU_verneed section) to
-/// resolve an undefined symbol represented by a pointer to
-/// GElf_Versym.
-///
-/// @param elf_hande the elf handle to use.
-///
-/// @param versym the symbol to get the version definition for.
-///
-/// @param verneed_section the SHT_GNU_verneed section.
-///
-/// @param version the resulting version definition.  This is set iff
-/// the function returns true.
-///
-/// @return true upon successful completion, false otherwise.
-static bool
-get_version_needed_for_versym(Elf*			elf_handle,
-			      GElf_Versym*		versym,
-			      Elf_Scn*			verneed_section,
-			      elf_symbol::version&	version)
-{
-  if (versym == 0 || elf_handle == 0 || verneed_section == 0)
-    return false;
-
-  size_t vn_offset = 0;
-  Elf_Data* verneed_data = elf_getdata(verneed_section, NULL);
-  GElf_Verneed verneed_mem;
-  GElf_Verneed* verneed = gelf_getverneed(verneed_data, 0, &verneed_mem);
-
-  for (;verneed; vn_offset += verneed->vn_next)
-    {
-      size_t vna_offset = vn_offset;
-      GElf_Vernaux vernaux_mem;
-      GElf_Vernaux *vernaux = gelf_getvernaux(verneed_data,
-					      vn_offset + verneed->vn_aux,
-					      &vernaux_mem);
-      for (;vernaux != 0 && verneed;)
-	{
-	  if (vernaux->vna_other == *versym)
-	    // Found the version of the symbol.
-	    break;
-	  vna_offset += verneed->vn_next;
-	  verneed = (verneed->vn_next == 0
-		     ? 0
-		     : gelf_getverneed(verneed_data, vna_offset, &verneed_mem));
-	}
-
-      if (verneed != 0 && vernaux != 0 && vernaux->vna_other == *versym)
-	{
-	  GElf_Shdr header_mem;
-	  GElf_Shdr* verneed_section_header = gelf_getshdr(verneed_section,
-							   &header_mem);
-	  size_t verneed_stridx = verneed_section_header->sh_link;
-	  version.str(elf_strptr(elf_handle,
-				 verneed_stridx,
-				 vernaux->vna_name));
-	  if (*versym & 0x8000)
-	    version.is_default(false);
-	  else
-	    version.is_default(true);
-	  return true;
-	}
-
-      if (!verneed || verneed->vn_next == 0)
-	break;
-    }
-  return false;
-}
-
-/// Return the version for a symbol that is at a given index in its
-/// SHT_SYMTAB section.
-///
-/// @param elf_handle the elf handle to use.
-///
-/// @param symbol_index the index of the symbol to consider.
-///
-/// @param get_def_version if this is true, it means that that we want
-/// the version for a defined symbol; in that case, the version is
-/// looked for in a section of type SHT_GNU_verdef.  Otherwise, if
-/// this parameter is false, this means that we want the version for
-/// an undefined symbol; in that case, the version is the needed one
-/// for the symbol to be resolved; so the version is looked fo in a
-/// section of type SHT_GNU_verneed.
-///
-/// @param version the version found for symbol at @p symbol_index.
-///
-/// @return true iff a version was found for symbol at index @p
-/// symbol_index.
-static bool
-get_version_for_symbol(Elf*			elf_handle,
-		       size_t			symbol_index,
-		       bool			get_def_version,
-		       elf_symbol::version&	version)
-{
-  Elf_Scn *versym_section = NULL,
-    *verdef_section = NULL,
-    *verneed_section = NULL;
-
-  if (!get_symbol_versionning_sections(elf_handle,
-				       versym_section,
-				       verdef_section,
-				       verneed_section))
-    return false;
-
-  GElf_Versym versym_mem;
-  Elf_Data* versym_data = (versym_section)
-    ? elf_getdata(versym_section, NULL)
-    : NULL;
-  GElf_Versym* versym = (versym_data)
-    ? gelf_getversym(versym_data, symbol_index, &versym_mem)
-    : NULL;
-
-  if (versym == 0 || *versym <= 1)
-    // I got these value from the code of readelf.c in elfutils.
-    // Apparently, if the symbol version entry has these values, the
-    // symbol must be discarded. This is not documented in the
-    // official specification.
-    return false;
-
-  if (get_def_version)
-    {
-      if (*versym == 0x8001)
-	// I got this value from the code of readelf.c in elfutils
-	// too.  It's not really documented in the official
-	// specification.
-	return false;
-
-      if (verdef_section
-	  && get_version_definition_for_versym(elf_handle, versym,
-					       verdef_section, version))
-	return true;
-    }
-  else
-    {
-      if (verneed_section
-	  && get_version_needed_for_versym(elf_handle, versym,
-					   verneed_section, version))
-	return true;
-    }
-
-  return false;
-}
-
 /// Lookup a symbol using the SysV ELF hash table.
 ///
 /// Note that this function hasn't been tested.  So it hasn't been
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index b0113a4efd2c..b7b868a332ec 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -500,6 +500,257 @@ Elf_Scn*
 find_data1_section(Elf* elf_handle)
 {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
 
+/// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
+/// sections that are involved in symbol versionning.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @param versym_section the SHT_GNU_versym section found.  If the
+/// section wasn't found, this is set to nil.
+///
+/// @param verdef_section the SHT_GNU_verdef section found.  If the
+/// section wasn't found, this is set to nil.
+///
+/// @param verneed_section the SHT_GNU_verneed section found.  If the
+/// section wasn't found, this is set to nil.
+///
+/// @return true iff at least one of the sections where found.
+bool
+get_symbol_versionning_sections(Elf*		elf_handle,
+				Elf_Scn*&	versym_section,
+				Elf_Scn*&	verdef_section,
+				Elf_Scn*&	verneed_section)
+{
+  Elf_Scn* section = NULL;
+  GElf_Shdr mem;
+  Elf_Scn* versym = NULL, *verdef = NULL, *verneed = NULL;
+
+  while ((section = elf_nextscn(elf_handle, section)) != NULL)
+    {
+      GElf_Shdr* h = gelf_getshdr(section, &mem);
+      if (h->sh_type == SHT_GNU_versym)
+	versym = section;
+      else if (h->sh_type == SHT_GNU_verdef)
+	verdef = section;
+      else if (h->sh_type == SHT_GNU_verneed)
+	verneed = section;
+    }
+
+  if (versym || verdef || verneed)
+    {
+      // At least one the versionning sections was found.  Return it.
+      versym_section = versym;
+      verdef_section = verdef;
+      verneed_section = verneed;
+      return true;
+    }
+
+  return false;
+}
+
+/// Get the version definition (from the SHT_GNU_verdef section) of a
+/// given symbol represented by a pointer to GElf_Versym.
+///
+/// @param elf_hande the elf handle to use.
+///
+/// @param versym the symbol to get the version definition for.
+///
+/// @param verdef_section the SHT_GNU_verdef section.
+///
+/// @param version the resulting version definition.  This is set iff
+/// the function returns true.
+///
+/// @return true upon successful completion, false otherwise.
+bool
+get_version_definition_for_versym(Elf*			 elf_handle,
+				  GElf_Versym*		 versym,
+				  Elf_Scn*		 verdef_section,
+				  elf_symbol::version&	 version)
+{
+  Elf_Data* verdef_data = elf_getdata(verdef_section, NULL);
+  GElf_Verdef verdef_mem;
+  GElf_Verdef* verdef = gelf_getverdef(verdef_data, 0, &verdef_mem);
+  size_t vd_offset = 0;
+
+  for (;; vd_offset += verdef->vd_next)
+    {
+      for (;verdef != 0;)
+	{
+	  if (verdef->vd_ndx == (*versym & 0x7fff))
+	    // Found the version of the symbol.
+	    break;
+	  vd_offset += verdef->vd_next;
+	  verdef = (verdef->vd_next == 0
+		    ? 0
+		    : gelf_getverdef(verdef_data, vd_offset, &verdef_mem));
+	}
+
+      if (verdef != 0)
+	{
+	  GElf_Verdaux verdaux_mem;
+	  GElf_Verdaux *verdaux = gelf_getverdaux(verdef_data,
+						  vd_offset + verdef->vd_aux,
+						  &verdaux_mem);
+	  GElf_Shdr header_mem;
+	  GElf_Shdr* verdef_section_header = gelf_getshdr(verdef_section,
+							  &header_mem);
+	  size_t verdef_stridx = verdef_section_header->sh_link;
+	  version.str(elf_strptr(elf_handle, verdef_stridx, verdaux->vda_name));
+	  if (*versym & 0x8000)
+	    version.is_default(false);
+	  else
+	    version.is_default(true);
+	  return true;
+	}
+      if (!verdef || verdef->vd_next == 0)
+	break;
+    }
+  return false;
+}
+
+/// Get the version needed (from the SHT_GNU_verneed section) to
+/// resolve an undefined symbol represented by a pointer to
+/// GElf_Versym.
+///
+/// @param elf_hande the elf handle to use.
+///
+/// @param versym the symbol to get the version definition for.
+///
+/// @param verneed_section the SHT_GNU_verneed section.
+///
+/// @param version the resulting version definition.  This is set iff
+/// the function returns true.
+///
+/// @return true upon successful completion, false otherwise.
+bool
+get_version_needed_for_versym(Elf*			elf_handle,
+			      GElf_Versym*		versym,
+			      Elf_Scn*			verneed_section,
+			      elf_symbol::version&	version)
+{
+  if (versym == 0 || elf_handle == 0 || verneed_section == 0)
+    return false;
+
+  size_t vn_offset = 0;
+  Elf_Data* verneed_data = elf_getdata(verneed_section, NULL);
+  GElf_Verneed verneed_mem;
+  GElf_Verneed* verneed = gelf_getverneed(verneed_data, 0, &verneed_mem);
+
+  for (;verneed; vn_offset += verneed->vn_next)
+    {
+      size_t vna_offset = vn_offset;
+      GElf_Vernaux vernaux_mem;
+      GElf_Vernaux *vernaux = gelf_getvernaux(verneed_data,
+					      vn_offset + verneed->vn_aux,
+					      &vernaux_mem);
+      for (;vernaux != 0 && verneed;)
+	{
+	  if (vernaux->vna_other == *versym)
+	    // Found the version of the symbol.
+	    break;
+	  vna_offset += verneed->vn_next;
+	  verneed = (verneed->vn_next == 0
+		     ? 0
+		     : gelf_getverneed(verneed_data, vna_offset, &verneed_mem));
+	}
+
+      if (verneed != 0 && vernaux != 0 && vernaux->vna_other == *versym)
+	{
+	  GElf_Shdr header_mem;
+	  GElf_Shdr* verneed_section_header = gelf_getshdr(verneed_section,
+							   &header_mem);
+	  size_t verneed_stridx = verneed_section_header->sh_link;
+	  version.str(elf_strptr(elf_handle,
+				 verneed_stridx,
+				 vernaux->vna_name));
+	  if (*versym & 0x8000)
+	    version.is_default(false);
+	  else
+	    version.is_default(true);
+	  return true;
+	}
+
+      if (!verneed || verneed->vn_next == 0)
+	break;
+    }
+  return false;
+}
+
+/// Return the version for a symbol that is at a given index in its
+/// SHT_SYMTAB section.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @param symbol_index the index of the symbol to consider.
+///
+/// @param get_def_version if this is true, it means that that we want
+/// the version for a defined symbol; in that case, the version is
+/// looked for in a section of type SHT_GNU_verdef.  Otherwise, if
+/// this parameter is false, this means that we want the version for
+/// an undefined symbol; in that case, the version is the needed one
+/// for the symbol to be resolved; so the version is looked fo in a
+/// section of type SHT_GNU_verneed.
+///
+/// @param version the version found for symbol at @p symbol_index.
+///
+/// @return true iff a version was found for symbol at index @p
+/// symbol_index.
+bool
+get_version_for_symbol(Elf*			elf_handle,
+		       size_t			symbol_index,
+		       bool			get_def_version,
+		       elf_symbol::version&	version)
+{
+  Elf_Scn *versym_section = NULL,
+    *verdef_section = NULL,
+    *verneed_section = NULL;
+
+  if (!get_symbol_versionning_sections(elf_handle,
+				       versym_section,
+				       verdef_section,
+				       verneed_section))
+    return false;
+
+  GElf_Versym versym_mem;
+  Elf_Data* versym_data = (versym_section)
+    ? elf_getdata(versym_section, NULL)
+    : NULL;
+  GElf_Versym* versym = (versym_data)
+    ? gelf_getversym(versym_data, symbol_index, &versym_mem)
+    : NULL;
+
+  if (versym == 0 || *versym <= 1)
+    // I got these value from the code of readelf.c in elfutils.
+    // Apparently, if the symbol version entry has these values, the
+    // symbol must be discarded. This is not documented in the
+    // official specification.
+    return false;
+
+  if (get_def_version)
+    {
+      if (*versym == 0x8001)
+	// I got this value from the code of readelf.c in elfutils
+	// too.  It's not really documented in the official
+	// specification.
+	return false;
+
+      if (verdef_section
+	  && get_version_definition_for_versym(elf_handle, versym,
+					       verdef_section, version))
+	return true;
+    }
+  else
+    {
+      if (verneed_section
+	  && get_version_needed_for_versym(elf_handle, versym,
+					   verneed_section, version))
+	return true;
+    }
+
+  return false;
+}
+
+
 
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 58720da0fa9e..7e1c231ccc4e 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -96,6 +96,34 @@ find_data_section(Elf* elf_handle);
 Elf_Scn*
 find_data1_section(Elf* elf_handle);
 
+bool
+get_symbol_versionning_sections(Elf*		elf_handle,
+				Elf_Scn*&	versym_section,
+				Elf_Scn*&	verdef_section,
+				Elf_Scn*&	verneed_section);
+
+//
+// Helpers for symbol versioning
+//
+
+bool
+get_version_definition_for_versym(Elf*			 elf_handle,
+				  GElf_Versym*		 versym,
+				  Elf_Scn*		 verdef_section,
+				  elf_symbol::version&	 version);
+
+bool
+get_version_needed_for_versym(Elf*			elf_handle,
+			      GElf_Versym*		versym,
+			      Elf_Scn*			verneed_section,
+			      elf_symbol::version&	version);
+
+bool
+get_version_for_symbol(Elf*			elf_handle,
+		       size_t			symbol_index,
+		       bool			get_def_version,
+		       elf_symbol::version&	version);
+
 } // end namespace elf_helpers
 } // end namespace abigail
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v2 4/8] abg-elf-helpers: move some kernel helpers from abg-dwarf-reader
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                     ` (2 preceding siblings ...)
  2020-04-21  6:35   ` [PATCH v2 3/8] abg-elf-helpers: move some versioning " Matthias Maennich
@ 2020-04-21  6:35   ` Matthias Maennich
  2020-04-22  9:47     ` Dodji Seketeli
  2020-04-21  6:35   ` [PATCH v2 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers Matthias Maennich
                     ` (4 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:35 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

Move some definitions from abg-dwarf-reader to abg-elf-helpers that are
strictly only related to ELF.

        * abg-dwarf-reader.cc(binary_is_linux_kernel): Move function out.
	(binary_is_linux_kernel_module): Likewise.
	(find_ksymtab_strings_section): Likewise.
        * abg-elf-helpers.cc(binary_is_linux_kernel): Move function in.
	(binary_is_linux_kernel_module): Likewise.
	(find_ksymtab_strings_section): Likewise.
        * abg-elf-helpers.h(binary_is_linux_kernel): Add declaration.
	(binary_is_linux_kernel_module): Likewise.
	(find_ksymtab_strings_section): Likewise.

Reviewed-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 46 -----------------------------------------
 src/abg-elf-helpers.cc  | 45 ++++++++++++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h   | 14 +++++++++++++
 3 files changed, 59 insertions(+), 46 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 303c1f8df4c2..3adb978b784b 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -542,52 +542,6 @@ compare_dies(const read_context& ctxt,
 	     bool update_canonical_dies_on_the_fly);
 
 
-/// Test if the ELF binary denoted by a given ELF handle is a Linux
-/// Kernel Module.
-///
-/// @param elf_handle the ELF handle to consider.
-///
-/// @return true iff the binary denoted by @p elf_handle is a Linux
-/// kernel module.
-static bool
-binary_is_linux_kernel_module(Elf *elf_handle)
-{
-  return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
-	  && find_section(elf_handle,
-			  ".gnu.linkonce.this_module",
-			  SHT_PROGBITS));
-}
-
-/// Test if the ELF binary denoted by a given ELF handle is a Linux
-/// Kernel binary (either vmlinux or a kernel module).
-///
-/// @param elf_handle the ELF handle to consider.
-///
-/// @return true iff the binary denoted by @p elf_handle is a Linux
-/// kernel binary
-static bool
-binary_is_linux_kernel(Elf *elf_handle)
-{
-  return (find_section(elf_handle,
-		       "__ksymtab_strings",
-		       SHT_PROGBITS)
-	  || binary_is_linux_kernel_module(elf_handle));
-}
-
-/// Find the __ksymtab_strings section of a Linux kernel binary.
-///
-///
-/// @return the find_ksymtab_strings_section of the linux kernel
-/// binary denoted by @p elf_handle, or nil if such a section could
-/// not be found.
-static Elf_Scn*
-find_ksymtab_strings_section(Elf *elf_handle)
-{
-  if (binary_is_linux_kernel(elf_handle))
-    return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
-  return 0;
-}
-
 /// Get the address at which a given binary is loaded in memory⋅
 ///
 /// @param elf_handle the elf handle for the binary to consider.
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index b7b868a332ec..ff0941dc6536 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -548,6 +548,21 @@ get_symbol_versionning_sections(Elf*		elf_handle,
   return false;
 }
 
+/// Find the __ksymtab_strings section of a Linux kernel binary.
+///
+/// @param elf_handle the elf handle to use.
+///
+/// @return the find_ksymtab_strings_section of the linux kernel
+/// binary denoted by @p elf_handle, or nil if such a section could
+/// not be found.
+Elf_Scn*
+find_ksymtab_strings_section(Elf *elf_handle)
+{
+  if (binary_is_linux_kernel(elf_handle))
+    return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
+  return 0;
+}
+
 /// Get the version definition (from the SHT_GNU_verdef section) of a
 /// given symbol represented by a pointer to GElf_Versym.
 ///
@@ -750,7 +765,37 @@ get_version_for_symbol(Elf*			elf_handle,
   return false;
 }
 
+/// Test if the ELF binary denoted by a given ELF handle is a Linux
+/// Kernel Module.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the binary denoted by @p elf_handle is a Linux
+/// kernel module.
+bool
+binary_is_linux_kernel_module(Elf *elf_handle)
+{
+  return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
+	  && find_section(elf_handle,
+			  ".gnu.linkonce.this_module",
+			  SHT_PROGBITS));
+}
 
+/// Test if the ELF binary denoted by a given ELF handle is a Linux
+/// Kernel binary (either vmlinux or a kernel module).
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the binary denoted by @p elf_handle is a Linux
+/// kernel binary
+bool
+binary_is_linux_kernel(Elf *elf_handle)
+{
+  return (find_section(elf_handle,
+		       "__ksymtab_strings",
+		       SHT_PROGBITS)
+	  || binary_is_linux_kernel_module(elf_handle));
+}
 
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 7e1c231ccc4e..33348126028c 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -102,6 +102,9 @@ get_symbol_versionning_sections(Elf*		elf_handle,
 				Elf_Scn*&	verdef_section,
 				Elf_Scn*&	verneed_section);
 
+Elf_Scn*
+find_ksymtab_strings_section(Elf *elf_handle);
+
 //
 // Helpers for symbol versioning
 //
@@ -124,6 +127,17 @@ get_version_for_symbol(Elf*			elf_handle,
 		       bool			get_def_version,
 		       elf_symbol::version&	version);
 
+//
+// Helpers for Linux Kernel Binaries
+//
+
+bool
+binary_is_linux_kernel_module(Elf *elf_handle);
+
+bool
+binary_is_linux_kernel(Elf *elf_handle);
+
+
 } // end namespace elf_helpers
 } // end namespace abigail
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v2 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                     ` (3 preceding siblings ...)
  2020-04-21  6:35   ` [PATCH v2 4/8] abg-elf-helpers: move some kernel " Matthias Maennich
@ 2020-04-21  6:35   ` Matthias Maennich
  2020-04-22  9:48     ` Dodji Seketeli
  2020-04-21  6:35   ` [PATCH v2 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers Matthias Maennich
                     ` (3 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:35 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

This consistently names the is_linux_kernel* helpers and keeps only the
copy in the elf-helpers. All users are adjusted.

	* src/abg-dwarf-reader.cc
	(read_context::function_symbol_is_exported): use is_linux_kernel
	from elf_helpers.
	(read_context::variable_is_exported): Likewise.
	(read_context::get_symtab_format): Likewise.
	(read_context::load_symbol_maps): Likewise.
	(read_debug_info_into_corpus): Likewise.
	(read_context::is_linux_kernel_binary): Drop function.
	(read_context::is_linux_kernel_module): Drop function.
	* src/abg-elf-helpers.cc (binary_is_linux_kernel): rename to
	is_linux_kernel
	(binary_is_linux_kernel_module): rename to is_linux_kernel_module
	(find_ksymtab_strings_section): Adjust to function renames.
	* src/abg-elf-helpers.h (binary_is_linux_kernel): rename to
	is_linux_kernel
	(binary_is_linux_kernel_module): rename to is_linux_kernel_module

Reviewed-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 37 +++++++------------------------------
 src/abg-elf-helpers.cc  |  8 ++++----
 src/abg-elf-helpers.h   |  4 ++--
 3 files changed, 13 insertions(+), 36 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 3adb978b784b..ec1f9f3fe8f3 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -5939,7 +5939,7 @@ public:
 
     address_set_sptr set;
     bool looking_at_linux_kernel_binary =
-      load_in_linux_kernel_mode() && is_linux_kernel_binary();
+      load_in_linux_kernel_mode() && is_linux_kernel(elf_handle());
 
     if (looking_at_linux_kernel_binary)
       {
@@ -5979,7 +5979,7 @@ public:
 
     address_set_sptr set;
     bool looking_at_linux_kernel_binary =
-      load_in_linux_kernel_mode() && is_linux_kernel_binary();
+      load_in_linux_kernel_mode() && is_linux_kernel(elf_handle());
 
     if (looking_at_linux_kernel_binary)
       {
@@ -6920,7 +6920,7 @@ public:
 	  {
 	    // Since Linux kernel modules are relocatable, we can first try
 	    // using a heuristic based on relocations to guess the ksymtab format.
-	    if (is_linux_kernel_module())
+	    if (is_linux_kernel_module(elf_handle()))
 	     {
 	       ksymtab_format_ = get_ksymtab_format_module();
 	       if (ksymtab_format_ != UNDEFINED_KSYMTAB_FORMAT)
@@ -7467,7 +7467,7 @@ public:
 						 load_undefined_fun_map,
 						 load_undefined_var_map))
 	  {
-	    if (load_in_linux_kernel_mode() && is_linux_kernel_binary())
+	    if (load_in_linux_kernel_mode() && is_linux_kernel(elf_handle()))
 	      return load_linux_specific_exported_symbol_maps();
 	    return true;
 	  }
@@ -8166,30 +8166,6 @@ public:
   load_in_linux_kernel_mode(bool f)
   {options_.load_in_linux_kernel_mode = f;}
 
-  /// Guess if the current binary is a Linux Kernel or a Linux Kernel module.
-  ///
-  /// To guess that, the function looks for the presence of the
-  /// special "__ksymtab_strings" section in the binary.
-  ///
-  bool
-  is_linux_kernel_binary() const
-  {
-    return find_section(elf_handle(), "__ksymtab_strings", SHT_PROGBITS)
-	   || is_linux_kernel_module();
-  }
-
-  /// Guess if the current binary is a Linux Kernel module.
-  ///
-  /// To guess that, the function looks for the presence of the special
-  /// ".modinfo" and ".gnu.linkonce.this_module" sections in the binary.
-  ///
-  bool
-  is_linux_kernel_module() const
-  {
-    return find_section(elf_handle(), ".modinfo", SHT_PROGBITS)
-	   && find_section(elf_handle(), ".gnu.linkonce.this_module", SHT_PROGBITS);
-  }
-
   /// Getter of the "show_stats" flag.
   ///
   /// This flag tells if we should emit statistics about various
@@ -16322,7 +16298,7 @@ read_debug_info_into_corpus(read_context& ctxt)
   // First set some mundane properties of the corpus gathered from
   // ELF.
   ctxt.current_corpus()->set_path(ctxt.elf_path());
-  if (ctxt.is_linux_kernel_binary())
+  if (is_linux_kernel(ctxt.elf_handle()))
     ctxt.current_corpus()->set_origin(corpus::LINUX_KERNEL_BINARY_ORIGIN);
   else
     ctxt.current_corpus()->set_origin(corpus::DWARF_ORIGIN);
@@ -16335,7 +16311,8 @@ read_debug_info_into_corpus(read_context& ctxt)
   // Set symbols information to the corpus.
   if (!get_ignore_symbol_table(ctxt))
     {
-      if (ctxt.load_in_linux_kernel_mode() && ctxt.is_linux_kernel_binary())
+      if (ctxt.load_in_linux_kernel_mode()
+	  && is_linux_kernel(ctxt.elf_handle()))
 	{
 	  string_elf_symbols_map_sptr exported_fn_symbols_map
 	    (new string_elf_symbols_map_type);
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index ff0941dc6536..ede191014369 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -558,7 +558,7 @@ get_symbol_versionning_sections(Elf*		elf_handle,
 Elf_Scn*
 find_ksymtab_strings_section(Elf *elf_handle)
 {
-  if (binary_is_linux_kernel(elf_handle))
+  if (is_linux_kernel(elf_handle))
     return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
   return 0;
 }
@@ -773,7 +773,7 @@ get_version_for_symbol(Elf*			elf_handle,
 /// @return true iff the binary denoted by @p elf_handle is a Linux
 /// kernel module.
 bool
-binary_is_linux_kernel_module(Elf *elf_handle)
+is_linux_kernel_module(Elf *elf_handle)
 {
   return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
 	  && find_section(elf_handle,
@@ -789,12 +789,12 @@ binary_is_linux_kernel_module(Elf *elf_handle)
 /// @return true iff the binary denoted by @p elf_handle is a Linux
 /// kernel binary
 bool
-binary_is_linux_kernel(Elf *elf_handle)
+is_linux_kernel(Elf *elf_handle)
 {
   return (find_section(elf_handle,
 		       "__ksymtab_strings",
 		       SHT_PROGBITS)
-	  || binary_is_linux_kernel_module(elf_handle));
+	  || is_linux_kernel_module(elf_handle));
 }
 
 } // end namespace elf_helpers
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 33348126028c..7ddd887de959 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -132,10 +132,10 @@ get_version_for_symbol(Elf*			elf_handle,
 //
 
 bool
-binary_is_linux_kernel_module(Elf *elf_handle);
+is_linux_kernel_module(Elf *elf_handle);
 
 bool
-binary_is_linux_kernel(Elf *elf_handle);
+is_linux_kernel(Elf *elf_handle);
 
 
 } // end namespace elf_helpers
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v2 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                     ` (4 preceding siblings ...)
  2020-04-21  6:35   ` [PATCH v2 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers Matthias Maennich
@ 2020-04-21  6:35   ` Matthias Maennich
  2020-04-22  9:53     ` Dodji Seketeli
  2020-04-21  6:35   ` [PATCH v2 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers) Matthias Maennich
                     ` (2 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:35 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

This change migrates all ELF helpers related to section lookup to
abg-elf-helpers.{cc,h}. It also homogenizes the interface of those to
always return Elf_Scn* and NULL in case that section can't be found.
Though this smells like a functional change, this latter change is
purely cosmetic.

	* src/abg-dwarf-reader.cc (read_context::find_symbol_table_section):
	adjust to new interface of elf_helpers::find_symbol_table_section.
	(find_opd_section): use elf_helpers::find_opd_section for lookup.
	(find_ksymtab_section): use elf_helpers::find_ksymtab_section.
	(find_ksymtab_gpl_section): use elf_helpers::find_ksymtab_gpl_section.
	(find_relocation_section): Move out function.
	(get_binary_load_address): Move out function.
	(find_ksymtab_reloc_section): use elf_helpers::find_relocation_section
	(find_ksymtab_gpl_reloc_section): use elf_helpers::find_relocation_section
	* src/elf-helpers.cc (find_symbol_table_section): change
	interface to match other find_*_section functions.
	(find_symbol_table_section_index): Adjust for the new interface
	of find_symbol_table_section.
	(find_opd_section): New function.
	(find_ksymtab_section): New function.
	(find_ksymtab_gpl_section): New function.
	(find_relocation_section): New function.
	(get_binary_load_address): New function.
	* src/elf-helpers.h (find_symbol_table_section): Change declaration.
	(find_opd_section): New function declation.
	(find_ksymtab_section): New function declation.
	(find_ksymtab_gpl_section): New function declation.
	(find_relocation_section): New function declation.
	(get_binary_load_address): New function declation.

Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 112 ++++++----------------------------
 src/abg-elf-helpers.cc  | 129 +++++++++++++++++++++++++++++++++++++---
 src/abg-elf-helpers.h   |  22 ++++++-
 3 files changed, 157 insertions(+), 106 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index ec1f9f3fe8f3..56da03a60940 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -542,53 +542,6 @@ compare_dies(const read_context& ctxt,
 	     bool update_canonical_dies_on_the_fly);
 
 
-/// Get the address at which a given binary is loaded in memory⋅
-///
-/// @param elf_handle the elf handle for the binary to consider.
-///
-/// @param load_address the address where the binary is loaded.  This
-/// is set by the function iff it returns true.
-///
-/// @return true if the function could get the binary load address
-/// and assign @p load_address to it.
-static bool
-get_binary_load_address(Elf *elf_handle,
-			GElf_Addr &load_address)
-{
-  GElf_Ehdr eh_mem;
-  GElf_Ehdr *elf_header = gelf_getehdr(elf_handle, &eh_mem);
-  size_t num_segments = elf_header->e_phnum;
-  GElf_Phdr *program_header = 0;
-  GElf_Addr result;
-  bool found_loaded_segment = false;
-  GElf_Phdr ph_mem;
-
-  for (unsigned i = 0; i < num_segments; ++i)
-    {
-      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
-      if (program_header && program_header->p_type == PT_LOAD)
-	{
-	  if (!found_loaded_segment)
-	    {
-	      result = program_header->p_vaddr;
-	      found_loaded_segment = true;
-	    }
-
-	  if (program_header->p_vaddr < result)
-	    // The resulting load address we want is the lowest
-	    // load address of all the loaded segments.
-	    result = program_header->p_vaddr;
-	}
-    }
-
-  if (found_loaded_segment)
-    {
-      load_address = result;
-      return true;
-    }
-  return false;
-}
-
 /// Find the file name of the alternate debug info file.
 ///
 /// @param elf_module the elf module to consider.
@@ -5282,8 +5235,8 @@ public:
   find_symbol_table_section() const
   {
     if (!symtab_section_)
-      dwarf_reader::find_symbol_table_section(elf_handle(),
-					      const_cast<read_context*>(this)->symtab_section_);
+      const_cast<read_context*>(this)->symtab_section_ =
+	  elf_helpers::find_symbol_table_section(elf_handle());
     return symtab_section_;
   }
 
@@ -5296,8 +5249,8 @@ public:
   find_opd_section() const
   {
     if (!opd_section_)
-      const_cast<read_context*>(this)->opd_section_=
-	find_section(elf_handle(), ".opd", SHT_PROGBITS);
+      const_cast<read_context*>(this)->opd_section_ =
+	  elf_helpers::find_opd_section(elf_handle());
     return opd_section_;
   }
 
@@ -5310,39 +5263,21 @@ public:
   {
     if (!ksymtab_section_)
       const_cast<read_context*>(this)->ksymtab_section_ =
-	find_section(elf_handle(), "__ksymtab", SHT_PROGBITS);
+	  elf_helpers::find_ksymtab_section(elf_handle());
     return ksymtab_section_;
   }
 
-  /// Return the .rel{a,} section corresponding to a given section.
-  ///
-  /// @param target_section the section to search the relocation section for
+  /// Return the __ksymtab_gpl section of a linux kernel ELF file
+  /// (either a vmlinux binary or a kernel module).
   ///
-  /// @return the .rel{a,} section if found, null otherwise.
+  /// @return the __ksymtab_gpl section if found, nil otherwise.
   Elf_Scn*
-  find_relocation_section(Elf_Scn* target_section) const
+  find_ksymtab_gpl_section() const
   {
-    if (target_section)
-      {
-	// the relo section we are searching for has this index as sh_info
-	size_t target_index = elf_ndxscn(target_section);
-
-	// now iterate over all the sections, look for relocation sections and
-	// find the one that points to the section we are searching for
-	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 != SHT_RELA && header->sh_type != SHT_REL))
-	      continue;
-
-	    if (header->sh_info == target_index)
-	      return section;
-	  }
-      }
-    return NULL;
+    if (!ksymtab_gpl_section_)
+      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
+	  elf_helpers::find_ksymtab_gpl_section(elf_handle());
+    return ksymtab_gpl_section_;
   }
 
   /// Return the .rel{a,}__ksymtab section of a linux kernel ELF file (either
@@ -5354,25 +5289,12 @@ public:
   {
     if (!ksymtab_reloc_section_)
       {
-	const_cast<read_context*>(this)->ksymtab_reloc_section_
-	    = find_relocation_section(find_ksymtab_section());
+	const_cast<read_context*>(this)->ksymtab_reloc_section_ =
+	    find_relocation_section(elf_handle(), find_ksymtab_section());
       }
     return ksymtab_reloc_section_;
   }
 
-  /// Return the __ksymtab_gpl section of a linux kernel ELF file
-  /// (either a vmlinux binary or a kernel module).
-  ///
-  /// @return the __ksymtab_gpl section if found, nil otherwise.
-  Elf_Scn*
-  find_ksymtab_gpl_section() const
-  {
-    if (!ksymtab_gpl_section_)
-      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
-	find_section(elf_handle(), "__ksymtab_gpl", SHT_PROGBITS);
-    return ksymtab_gpl_section_;
-  }
-
   /// Return the .rel{a,}__ksymtab_gpl section of a linux kernel ELF file
   /// (either a vmlinux binary or a kernel module).
   ///
@@ -5382,8 +5304,8 @@ public:
   {
     if (!ksymtab_gpl_reloc_section_)
       {
-	const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_
-	    = find_relocation_section(find_ksymtab_gpl_section());
+	const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_ =
+	    find_relocation_section(elf_handle(), find_ksymtab_gpl_section());
       }
     return ksymtab_gpl_reloc_section_;
   }
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index ede191014369..b77440206fb0 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -357,9 +357,9 @@ find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
 ///
 /// @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)
+/// @return the symbol table section
+Elf_Scn*
+find_symbol_table_section(Elf* elf_handle)
 {
   Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0;
   while ((section = elf_nextscn(elf_handle, section)) != 0)
@@ -378,12 +378,11 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
       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;
+	return sym_tab ? sym_tab : dynsym;
       else
-	symtab = dynsym ? dynsym : sym_tab;
-      return true;
+	return dynsym ? dynsym : sym_tab;
     }
-  return false;
+  return NULL;
 }
 
 /// Find the index (in the section headers table) of the symbol table
@@ -402,8 +401,9 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
 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))
+  Elf_Scn* section = find_symbol_table_section(elf_handle);
+
+  if (!section)
     return false;
 
   symtab_index = elf_ndxscn(section);
@@ -500,6 +500,17 @@ Elf_Scn*
 find_data1_section(Elf* elf_handle)
 {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
 
+/// Return the "Official Procedure descriptors section."  This
+/// section is named .opd, and is usually present only on PPC64
+/// ELFv1 binaries.
+///
+/// @param elf_handle the elf handle to consider.
+///
+/// @return the .opd section, if found.  Return nil otherwise.
+Elf_Scn*
+find_opd_section(Elf* elf_handle)
+{return find_section(elf_handle, ".opd", SHT_PROGBITS);}
+
 /// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
 /// sections that are involved in symbol versionning.
 ///
@@ -548,6 +559,26 @@ get_symbol_versionning_sections(Elf*		elf_handle,
   return false;
 }
 
+/// Return the __ksymtab section of a linux kernel ELF file (either
+/// a vmlinux binary or a kernel module).
+///
+/// @param elf_handle the elf handle to consider.
+///
+/// @return the __ksymtab section if found, nil otherwise.
+Elf_Scn*
+find_ksymtab_section(Elf* elf_handle)
+{return find_section(elf_handle, "__ksymtab", SHT_PROGBITS);}
+
+/// Return the __ksymtab_gpl section of a linux kernel ELF file (either
+/// a vmlinux binary or a kernel module).
+///
+/// @param elf_handle the elf handle to consider.
+///
+/// @return the __ksymtab section if found, nil otherwise.
+Elf_Scn*
+find_ksymtab_gpl_section(Elf* elf_handle)
+{return find_section(elf_handle, "__ksymtab_gpl", SHT_PROGBITS);}
+
 /// Find the __ksymtab_strings section of a Linux kernel binary.
 ///
 /// @param elf_handle the elf handle to use.
@@ -563,6 +594,39 @@ find_ksymtab_strings_section(Elf *elf_handle)
   return 0;
 }
 
+/// Return the .rel{a,} section corresponding to a given section.
+///
+/// @param elf_handle the elf handle to consider.
+///
+/// @param target_section the section to search the relocation section for
+///
+/// @return the .rel{a,} section if found, null otherwise.
+Elf_Scn*
+find_relocation_section(Elf* elf_handle, Elf_Scn* target_section)
+{
+  if (target_section)
+    {
+      // the relo section we are searching for has this index as sh_info
+      size_t target_index = elf_ndxscn(target_section);
+
+      // now iterate over all the sections, look for relocation sections and
+      // find the one that points to the section we are searching for
+      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 != SHT_RELA && header->sh_type != SHT_REL))
+	    continue;
+
+	  if (header->sh_info == target_index)
+	    return section;
+	}
+    }
+  return NULL;
+}
+
 /// Get the version definition (from the SHT_GNU_verdef section) of a
 /// given symbol represented by a pointer to GElf_Versym.
 ///
@@ -797,5 +861,52 @@ is_linux_kernel(Elf *elf_handle)
 	  || is_linux_kernel_module(elf_handle));
 }
 
+/// Get the address at which a given binary is loaded in memory⋅
+///
+/// @param elf_handle the elf handle for the binary to consider.
+///
+/// @param load_address the address where the binary is loaded.  This
+/// is set by the function iff it returns true.
+///
+/// @return true if the function could get the binary load address
+/// and assign @p load_address to it.
+bool
+get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
+{
+  GElf_Ehdr elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+  size_t num_segments = elf_header.e_phnum;
+  GElf_Phdr *program_header = NULL;
+  GElf_Addr result;
+  bool found_loaded_segment = false;
+  GElf_Phdr ph_mem;
+
+  for (unsigned i = 0; i < num_segments; ++i)
+    {
+      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
+      if (program_header && program_header->p_type == PT_LOAD)
+	{
+	  if (!found_loaded_segment)
+	    {
+	      result = program_header->p_vaddr;
+	      found_loaded_segment = true;
+	    }
+
+	  if (program_header->p_vaddr < result)
+	    // The resulting load address we want is the lowest
+	    // load address of all the loaded segments.
+	    result = program_header->p_vaddr;
+	}
+    }
+
+  if (found_loaded_segment)
+    {
+      load_address = result;
+      return true;
+    }
+  return false;
+}
+
+
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 7ddd887de959..8a83bb4f2e95 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -63,8 +63,8 @@ find_section(Elf*		elf_handle,
 	     const std::string& name,
 	     Elf64_Word		section_type);
 
-bool
-find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab);
+Elf_Scn*
+find_symbol_table_section(Elf* elf_handle);
 
 bool
 find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index);
@@ -96,15 +96,27 @@ find_data_section(Elf* elf_handle);
 Elf_Scn*
 find_data1_section(Elf* elf_handle);
 
+Elf_Scn*
+find_opd_section(Elf* elf_handle);
+
 bool
 get_symbol_versionning_sections(Elf*		elf_handle,
 				Elf_Scn*&	versym_section,
 				Elf_Scn*&	verdef_section,
 				Elf_Scn*&	verneed_section);
 
+Elf_Scn*
+find_ksymtab_section(Elf* elf_handle);
+
+Elf_Scn*
+find_ksymtab_gpl_section(Elf* elf_handle);
+
 Elf_Scn*
 find_ksymtab_strings_section(Elf *elf_handle);
 
+Elf_Scn*
+find_relocation_section(Elf* elf_handle, Elf_Scn* target_section);
+
 //
 // Helpers for symbol versioning
 //
@@ -137,6 +149,12 @@ is_linux_kernel_module(Elf *elf_handle);
 bool
 is_linux_kernel(Elf *elf_handle);
 
+//
+// Misc Helpers
+//
+
+bool
+get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address);
 
 } // end namespace elf_helpers
 } // end namespace abigail
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v2 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers)
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                     ` (5 preceding siblings ...)
  2020-04-21  6:35   ` [PATCH v2 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers Matthias Maennich
@ 2020-04-21  6:35   ` Matthias Maennich
  2020-04-22  9:55     ` Dodji Seketeli
  2020-04-21  6:35   ` [PATCH v2 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr Matthias Maennich
  2020-04-22  9:57   ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Dodji Seketeli
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:35 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

This migrates more architecture specific helpers over to the
elf-helpers. No functional change intended.

	* src/abg-dwarf-reader.cc(elf_architecture_is_ppc64): Move
	function out and adjust callers to call the migrated
	functions.
	(elf_architecture_is_big_endian): Likewise.
	(architecture_word_size): Likewise.
	(current_elf_file_is_executable): Likewise.
	(current_elf_file_is_dso): Likewise.
	* src/abg-elf-helpers.cc (architecture_is_ppc64): Add new function.
	(architecture_is_big_endian): Likewise.
	(get_architecture_word_size): Likewise.
	(is_executable): Likewise.
	(is_dso): Likewise.
	* src/abg-elf-helpers.h (architecture_is_ppc64): Add new declaration.
	(architecture_is_big_endian): Likewise.
	(get_architecture_word_size): Likewise.
	(is_executable): Likewise.
	(is_dso): Likewise.

Reviewed-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 91 ++++-------------------------------------
 src/abg-elf-helpers.cc  | 79 +++++++++++++++++++++++++++++++++++
 src/abg-elf-helpers.h   | 18 ++++++++
 3 files changed, 106 insertions(+), 82 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 56da03a60940..dc3332410b1e 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -5700,10 +5700,10 @@ public:
     if (!elf_handle())
       return fn_desc_address;
 
-    if (!elf_architecture_is_ppc64())
+    if (!architecture_is_ppc64(elf_handle()))
       return fn_desc_address;
 
-    bool is_big_endian = elf_architecture_is_big_endian();
+    bool is_big_endian = architecture_is_big_endian(elf_handle());
 
     Elf_Scn *opd_section = find_opd_section();
     if (!opd_section)
@@ -5979,7 +5979,7 @@ public:
   {
     if (!fun_entry_addr_sym_map_ && !fun_addr_sym_map_)
       maybe_load_symbol_maps();
-    if (elf_architecture_is_ppc64())
+    if (architecture_is_ppc64(elf_handle()))
       return fun_entry_addr_sym_map_;
     return fun_addr_sym_map_;
   }
@@ -6335,79 +6335,6 @@ public:
   elf_architecture() const
   {return elf_architecture_;}
 
-  /// Return the size of a word for the current architecture.
-  /// @return the size of a word.
-  unsigned char
-  architecture_word_size() const
-  {
-    unsigned char word_size = 0;
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-    if (elf_header->e_ident[EI_CLASS] == ELFCLASS32)
-      word_size = 4;
-    else if (elf_header->e_ident[EI_CLASS] == ELFCLASS64)
-      word_size = 8;
-    else
-      ABG_ASSERT_NOT_REACHED;
-    return word_size;
-  }
-
-  /// Test if the architecture of the current binary is ppc64.
-  ///
-  /// @return true iff the architecture of the current binary is ppc64.
-  bool
-  elf_architecture_is_ppc64() const
-  {
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-
-    return (elf_header && elf_header->e_machine == EM_PPC64);
-  }
-
-  /// Test if the endianness of the current binary is Big Endian.
-  ///
-  /// https://en.wikipedia.org/wiki/Endianness.
-  ///
-  /// @return true iff the current binary is Big Endian.
-  bool
-  elf_architecture_is_big_endian() const
-  {
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-
-    bool is_big_endian = (elf_header->e_ident[EI_DATA] == ELFDATA2MSB);
-
-    if (!is_big_endian)
-      ABG_ASSERT(elf_header->e_ident[EI_DATA] == ELFDATA2LSB);
-
-    return is_big_endian;
-  }
-
-  /// Test if the current elf file being read is an executable.
-  ///
-  /// @return true iff the current elf file being read is an
-  /// executable.
-  bool
-  current_elf_file_is_executable() const
-  {
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-    return elf_header->e_type == ET_EXEC;
-  }
-
-  /// Test if the current elf file being read is a dynamic shared
-  /// object.
-  ///
-  /// @return true iff the current elf file being read is a
-  /// dynamic shared object.
-  bool
-  current_elf_file_is_dso() const
-  {
-    GElf_Ehdr eh_mem;
-    GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
-    return elf_header->e_type == ET_DYN;
-  }
-
   /// Getter for the map of global variables symbol address -> global
   /// variable symbol index.
   ///
@@ -6471,7 +6398,7 @@ public:
     GElf_Ehdr elf_header;
     ABG_ASSERT(gelf_getehdr(elf_handle(), &elf_header));
 
-    bool is_ppc64 = elf_architecture_is_ppc64();
+    bool is_ppc64 = architecture_is_ppc64(elf_handle());
 
     for (size_t i = 0; i < nb_syms; ++i)
       {
@@ -6688,7 +6615,7 @@ public:
   {
     Elf_Data*	    elf_data = elf_rawdata(section, 0);
     uint8_t*	    bytes = reinterpret_cast<uint8_t*>(elf_data->d_buf);
-    bool	    is_big_endian = elf_architecture_is_big_endian();
+    bool	    is_big_endian = architecture_is_big_endian(elf_handle());
     elf_symbol_sptr symbol;
     GElf_Addr	    symbol_address = 0;
 
@@ -6696,7 +6623,7 @@ public:
     if (position_relative_relocations)
       symbol_value_size = sizeof(int32_t);
     else
-      symbol_value_size = architecture_word_size();
+      symbol_value_size = get_architecture_word_size(elf_handle());
 
     const int read_offset = (symbol_offset * symbol_value_size);
     bytes += read_offset;
@@ -6886,7 +6813,7 @@ public:
     if (format == UNDEFINED_KSYMTAB_FORMAT)
       ;
     else if (format == PRE_V4_19_KSYMTAB_FORMAT)
-      result = architecture_word_size();
+      result = get_architecture_word_size(elf_handle());
     else if (format == V4_19_KSYMTAB_FORMAT)
       result = 4;
     else
@@ -7065,7 +6992,7 @@ public:
     //
     // Lets thus walk the array of entries, and let's read just the
     // symbol address part of each entry.
-    bool is_big_endian = elf_architecture_is_big_endian();
+    bool is_big_endian = architecture_is_big_endian(elf_handle());
     elf_symbol_sptr symbol;
     unsigned char symbol_value_size = get_ksymtab_symbol_value_size();
 
@@ -7367,7 +7294,7 @@ public:
     if (!fun_addr_sym_map_)
       fun_addr_sym_map_.reset(new addr_elf_symbol_sptr_map_type);
 
-    if (!fun_entry_addr_sym_map_ && elf_architecture_is_ppc64())
+    if (!fun_entry_addr_sym_map_ && architecture_is_ppc64(elf_handle()))
       fun_entry_addr_sym_map_.reset(new addr_elf_symbol_sptr_map_type);
 
     if (!var_syms_)
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index b77440206fb0..895feb6f7768 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -829,6 +829,40 @@ get_version_for_symbol(Elf*			elf_handle,
   return false;
 }
 
+/// Test if the architecture of the current binary is ppc64.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the architecture of the current binary is ppc64.
+bool
+architecture_is_ppc64(Elf* elf_handle)
+{
+  GElf_Ehdr  eh_mem;
+  GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
+  return (elf_header && elf_header->e_machine == EM_PPC64);
+}
+
+/// Test if the endianness of the current binary is Big Endian.
+///
+/// https://en.wikipedia.org/wiki/Endianness.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the current binary is Big Endian.
+bool
+architecture_is_big_endian(Elf* elf_handle)
+{
+  GElf_Ehdr  elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+
+  bool is_big_endian = (elf_header.e_ident[EI_DATA] == ELFDATA2MSB);
+
+  if (!is_big_endian)
+    ABG_ASSERT(elf_header.e_ident[EI_DATA] == ELFDATA2LSB);
+
+  return is_big_endian;
+}
+
 /// Test if the ELF binary denoted by a given ELF handle is a Linux
 /// Kernel Module.
 ///
@@ -907,6 +941,51 @@ get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
   return false;
 }
 
+/// Return the size of a word for the current architecture.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return the size of a word.
+unsigned char
+get_architecture_word_size(Elf* elf_handle)
+{
+  unsigned char word_size = 0;
+  GElf_Ehdr	elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+  if (elf_header.e_ident[EI_CLASS] == ELFCLASS32)
+    word_size = 4;
+  else if (elf_header.e_ident[EI_CLASS] == ELFCLASS64)
+    word_size = 8;
+  else
+    ABG_ASSERT_NOT_REACHED;
+  return word_size;
+}
+
+/// Test if the elf file being read is an executable.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the elf file being read is an / executable.
+bool
+is_executable(Elf* elf_handle)
+{
+  GElf_Ehdr  elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+  return elf_header.e_type == ET_EXEC;
+}
+
+/// Test if the elf file being read is a dynamic shared / object.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the elf file being read is a / dynamic shared object.
+bool
+is_dso(Elf* elf_handle)
+{
+  GElf_Ehdr  elf_header;
+  gelf_getehdr(elf_handle, &elf_header);
+  return elf_header.e_type == ET_DYN;
+}
 
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 8a83bb4f2e95..6eff245a6a30 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -139,6 +139,15 @@ get_version_for_symbol(Elf*			elf_handle,
 		       bool			get_def_version,
 		       elf_symbol::version&	version);
 
+//
+// Architecture specific helpers
+//
+bool
+architecture_is_ppc64(Elf* elf_handle);
+
+bool
+architecture_is_big_endian(Elf* elf_handle);
+
 //
 // Helpers for Linux Kernel Binaries
 //
@@ -156,6 +165,15 @@ is_linux_kernel(Elf *elf_handle);
 bool
 get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address);
 
+unsigned char
+get_architecture_word_size(Elf* elf_handle);
+
+bool
+is_executable(Elf* elf_handle);
+
+bool
+is_dso(Elf* elf_handle);
+
 } // end namespace elf_helpers
 } // end namespace abigail
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v2 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                     ` (6 preceding siblings ...)
  2020-04-21  6:35   ` [PATCH v2 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers) Matthias Maennich
@ 2020-04-21  6:35   ` Matthias Maennich
  2020-04-22  9:56     ` Dodji Seketeli
  2020-04-22  9:57   ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Dodji Seketeli
  8 siblings, 1 reply; 37+ messages in thread
From: Matthias Maennich @ 2020-04-21  6:35 UTC (permalink / raw)
  To: libabigail; +Cc: dodji, gprocida, kernel-team, maennich

Move maybe_adjust_et_rel_sym_addr_to_abs_addr to the elf-helpers.

This function had two overloads

  GElf_Addr
  maybe_adjust_et_rel_sym_addr_to_abs_addr(GElf_Addr addr, Elf_Scn *section);

  GElf_Addr
  maybe_adjust_et_rel_sym_addr_to_abs_addr(GElf_Sym *sym);

The former one is only ever called by the latter. Hence consolidate them
into

  GElf_Addr
  maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf* elf_handle, GElf_Sym* sym);

to combine their functionality and preserve the outer interface. Just we
add the Elf* handle argument as usual as we are out of read_context now.

	* src/abg-dwarf-reader.cc(maybe_adjust_et_rel_sym_addr_to_abs_addr):
	Move out functions (drop the wrapped overload completely).
	* src/abg-elf-helpers.cc(maybe_adjust_et_rel_sym_addr_to_abs_addr):
	New function.
	* src/abg-elf-helpers.h(maybe_adjust_et_rel_sym_addr_to_abs_addr):
	New function declaration.

Reviewed-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-dwarf-reader.cc | 73 ++++-------------------------------------
 src/abg-elf-helpers.cc  | 40 ++++++++++++++++++++++
 src/abg-elf-helpers.h   |  3 ++
 3 files changed, 49 insertions(+), 67 deletions(-)

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index dc3332410b1e..c65c01776398 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -6425,7 +6425,8 @@ public:
 
 		{
 		  GElf_Addr symbol_value =
-		    maybe_adjust_et_rel_sym_addr_to_abs_addr(sym);
+		      maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle(),
+							       sym);
 
 		  addr_elf_symbol_sptr_map_type::const_iterator it =
 		    fun_addr_sym_map_->find(symbol_value);
@@ -6563,7 +6564,8 @@ public:
 		else
 		  {
 		    GElf_Addr symbol_value =
-		      maybe_adjust_et_rel_sym_addr_to_abs_addr(sym);
+			maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle(),
+								 sym);
 		    addr_elf_symbol_sptr_map_type::const_iterator it =
 		      var_addr_sym_map_->find(symbol_value);
 		    if (it == var_addr_sym_map_->end())
@@ -7147,8 +7149,8 @@ public:
 	// the symbol value of native_symbol is relative to the
 	// section that symbol is defined in.  We need to translate it
 	// into an absolute (okay, binary-relative, rather) address.
-	GElf_Addr symbol_address =
-	  maybe_adjust_et_rel_sym_addr_to_abs_addr (&native_symbol);
+	GElf_Addr symbol_address = maybe_adjust_et_rel_sym_addr_to_abs_addr(
+	    elf_handle(), &native_symbol);
 
 	address_set_sptr set;
 	if (symbol->is_function())
@@ -7523,69 +7525,6 @@ public:
     return addr;
   }
 
-  /// Translate a section-relative symbol address (i.e, symbol value)
-  /// into an absolute symbol address by adding the address of the
-  /// section the symbol belongs to, to the address value.
-  ///
-  /// This is useful when looking at symbol values coming from
-  /// relocatable files (of ET_REL kind).  If the binary is not
-  /// ET_REL, then the function does nothing and returns the input
-  /// address unchanged.
-  ///
-  /// @param addr the symbol address to possibly translate.
-  ///
-  /// @param section the section the symbol which value is @p addr
-  /// belongs to.
-  ///
-  /// @return the section-relative address, translated into an
-  /// absolute address, if @p section is an ET_REL binary.  Otherwise,
-  /// return @p addr, unchanged.
-  GElf_Addr
-  maybe_adjust_et_rel_sym_addr_to_abs_addr(GElf_Addr addr, Elf_Scn *section)
-  {
-    if (!section)
-      return addr;
-
-    Elf* elf = elf_handle();
-    GElf_Ehdr elf_header;
-
-    if (!gelf_getehdr(elf, &elf_header))
-      return addr;
-
-    if (elf_header.e_type != ET_REL)
-      return addr;
-
-    GElf_Shdr section_header;
-    if (!gelf_getshdr(section, &section_header))
-      return addr;
-
-    return addr + section_header.sh_addr;
-  }
-
-  /// Translate a section-relative symbol address (i.e, symbol value)
-  /// into an absolute symbol address by adding the address of the
-  /// section the symbol belongs to, to the address value.
-  ///
-  /// This is useful when looking at symbol values coming from
-  /// relocatable files (of ET_REL kind).  If the binary is not
-  /// ET_REL, then the function does nothing and returns the input
-  /// address unchanged.
-  ///
-  /// @param sym the symbol whose address to possibly needs to be
-  /// translated.
-  ///
-  /// @return the section-relative address, translated into an
-  /// absolute address, if @p sym is from an ET_REL binary.
-  /// Otherwise, return the address of @p sym, unchanged.
-  GElf_Addr
-  maybe_adjust_et_rel_sym_addr_to_abs_addr(GElf_Sym *sym)
-  {
-    Elf_Scn *symbol_section = elf_getscn(elf_handle(), sym->st_shndx);
-    GElf_Addr result = sym->st_value;
-    result = maybe_adjust_et_rel_sym_addr_to_abs_addr(result, symbol_section);
-    return result;
-  }
-
   /// Test if a given address is in a given section.
   ///
   /// @param addr the address to consider.
diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index 895feb6f7768..02ecbcf250ed 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -987,5 +987,45 @@ is_dso(Elf* elf_handle)
   return elf_header.e_type == ET_DYN;
 }
 
+/// Translate a section-relative symbol address (i.e, symbol value)
+/// into an absolute symbol address by adding the address of the
+/// section the symbol belongs to, to the address value.
+///
+/// This is useful when looking at symbol values coming from
+/// relocatable files (of ET_REL kind).  If the binary is not
+/// ET_REL, then the function does nothing and returns the input
+/// address unchanged.
+///
+/// @param elf_handle the elf handle for the binary to consider.
+///
+/// @param sym the symbol whose address to possibly needs to be
+/// translated.
+///
+/// @return the section-relative address, translated into an
+/// absolute address, if @p sym is from an ET_REL binary.
+/// Otherwise, return the address of @p sym, unchanged.
+GElf_Addr
+maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf* elf_handle, GElf_Sym* sym)
+{
+  Elf_Scn*  symbol_section = elf_getscn(elf_handle, sym->st_shndx);
+  GElf_Addr addr = sym->st_value;
+
+  if (!symbol_section)
+    return addr;
+
+  GElf_Ehdr elf_header;
+  if (!gelf_getehdr(elf_handle, &elf_header))
+    return addr;
+
+  if (elf_header.e_type != ET_REL)
+    return addr;
+
+  GElf_Shdr section_header;
+  if (!gelf_getshdr(symbol_section, &section_header))
+    return addr;
+
+  return addr + section_header.sh_addr;
+}
+
 } // end namespace elf_helpers
 } // end namespace abigail
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index 6eff245a6a30..647c92703dfa 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -174,6 +174,9 @@ is_executable(Elf* elf_handle);
 bool
 is_dso(Elf* elf_handle);
 
+GElf_Addr
+maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf* elf_handle, GElf_Sym* sym);
+
 } // end namespace elf_helpers
 } // end namespace abigail
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers
  2020-04-21  6:14     ` Matthias Maennich
@ 2020-04-21 11:02       ` Giuliano Procida
  0 siblings, 0 replies; 37+ messages in thread
From: Giuliano Procida @ 2020-04-21 11:02 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, Dodji Seketeli, kernel-team

So a zero load address is OK. That's fine then.

I didn't understand your comment about memory management. I see no
allocation, free or change of ownership.

Giuliano.

On Tue, 21 Apr 2020 at 07:14, 'Matthias Maennich' via kernel-team
<kernel-team@android.com> wrote:
>
> On Mon, Apr 20, 2020 at 04:24:50PM +0100, Giuliano Procida wrote:
> >Hi.
> >
> >On Mon, 20 Apr 2020 at 12:09, Matthias Maennich <maennich@google.com> wrote:
> >>
> >> This change migrates all ELF helpers related to section lookup to
> >> abg-elf-helpers.{cc,h}. It also homogenizes the interface of those to
> >> always return Elf_Scn* and NULL in case that section can't be found.
> >> Though this smells like a functional change, this latter change is
> >> purely cosmetic.
> >>
> >>         * src/abg-dwarf-reader.cc (read_context::find_symbol_table_section):
> >>         adjust to new interface of elf_helpers::find_symbol_table_section.
> >>         (find_opd_section): use elf_helpers::find_opd_section for lookup.
> >>         (find_ksymtab_section): use elf_helpers::find_ksymtab_section.
> >>         (find_ksymtab_gpl_section): use elf_helpers::find_ksymtab_gpl_section.
> >>         (find_relocation_section): Move out function.
> >>         (get_binary_load_address): Move out function.
> >>         (find_ksymtab_reloc_section): use elf_helpers::find_relocation_section
> >>         (find_ksymtab_gpl_reloc_section): use elf_helpers::find_relocation_section
> >>         * src/elf-helpers.cc (find_symbol_table_section): change
> >>         interface to match other find_*_section functions.
> >>         (find_symbol_table_section_index): Adjust for the new interface
> >>         of find_symbol_table_section.
> >>         (find_opd_section): New function.
> >>         (find_ksymtab_section): New function.
> >>         (find_ksymtab_gpl_section): New function.
> >>         (find_relocation_section): New function.
> >>         (get_binary_load_address): New function.
> >>         * src/elf-helpers.h (find_symbol_table_section): Change declaration.
> >>         (find_opd_section): New function declation.
> >>         (find_ksymtab_section): New function declation.
> >>         (find_ksymtab_gpl_section): New function declation.
> >>         (find_relocation_section): New function declation.
> >>         (get_binary_load_address): New function declation.
> >>
> >> Signed-off-by: Matthias Maennich <maennich@google.com>
> >> ---
> >>  src/abg-dwarf-reader.cc | 112 ++++++----------------------------
> >>  src/abg-elf-helpers.cc  | 129 +++++++++++++++++++++++++++++++++++++---
> >>  src/abg-elf-helpers.h   |  22 ++++++-
> >>  3 files changed, 157 insertions(+), 106 deletions(-)
> >>
> >> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
> >> index ec1f9f3fe8f3..56da03a60940 100644
> >> --- a/src/abg-dwarf-reader.cc
> >> +++ b/src/abg-dwarf-reader.cc
> >> @@ -542,53 +542,6 @@ compare_dies(const read_context& ctxt,
> >>              bool update_canonical_dies_on_the_fly);
> >>
> >>
> >> -/// Get the address at which a given binary is loaded in memory⋅
> >> -///
> >> -/// @param elf_handle the elf handle for the binary to consider.
> >> -///
> >> -/// @param load_address the address where the binary is loaded.  This
> >> -/// is set by the function iff it returns true.
> >> -///
> >> -/// @return true if the function could get the binary load address
> >> -/// and assign @p load_address to it.
> >> -static bool
> >> -get_binary_load_address(Elf *elf_handle,
> >> -                       GElf_Addr &load_address)
> >> -{
> >> -  GElf_Ehdr eh_mem;
> >> -  GElf_Ehdr *elf_header = gelf_getehdr(elf_handle, &eh_mem);
> >> -  size_t num_segments = elf_header->e_phnum;
> >> -  GElf_Phdr *program_header = 0;
> >> -  GElf_Addr result;
> >> -  bool found_loaded_segment = false;
> >> -  GElf_Phdr ph_mem;
> >> -
> >> -  for (unsigned i = 0; i < num_segments; ++i)
> >> -    {
> >> -      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
> >> -      if (program_header && program_header->p_type == PT_LOAD)
> >> -       {
> >> -         if (!found_loaded_segment)
> >> -           {
> >> -             result = program_header->p_vaddr;
> >> -             found_loaded_segment = true;
> >> -           }
> >> -
> >> -         if (program_header->p_vaddr < result)
> >> -           // The resulting load address we want is the lowest
> >> -           // load address of all the loaded segments.
> >> -           result = program_header->p_vaddr;
> >> -       }
> >> -    }
> >> -
> >> -  if (found_loaded_segment)
> >> -    {
> >> -      load_address = result;
> >> -      return true;
> >> -    }
> >> -  return false;
> >> -}
> >> -
> >>  /// Find the file name of the alternate debug info file.
> >>  ///
> >>  /// @param elf_module the elf module to consider.
> >> @@ -5282,8 +5235,8 @@ public:
> >>    find_symbol_table_section() const
> >>    {
> >>      if (!symtab_section_)
> >> -      dwarf_reader::find_symbol_table_section(elf_handle(),
> >> -                                             const_cast<read_context*>(this)->symtab_section_);
> >> +      const_cast<read_context*>(this)->symtab_section_ =
> >> +         elf_helpers::find_symbol_table_section(elf_handle());
> >>      return symtab_section_;
> >>    }
> >>
> >> @@ -5296,8 +5249,8 @@ public:
> >>    find_opd_section() const
> >>    {
> >>      if (!opd_section_)
> >> -      const_cast<read_context*>(this)->opd_section_=
> >> -       find_section(elf_handle(), ".opd", SHT_PROGBITS);
> >> +      const_cast<read_context*>(this)->opd_section_ =
> >> +         elf_helpers::find_opd_section(elf_handle());
> >>      return opd_section_;
> >>    }
> >>
> >> @@ -5310,39 +5263,21 @@ public:
> >>    {
> >>      if (!ksymtab_section_)
> >>        const_cast<read_context*>(this)->ksymtab_section_ =
> >> -       find_section(elf_handle(), "__ksymtab", SHT_PROGBITS);
> >> +         elf_helpers::find_ksymtab_section(elf_handle());
> >>      return ksymtab_section_;
> >>    }
> >>
> >> -  /// Return the .rel{a,} section corresponding to a given section.
> >> -  ///
> >> -  /// @param target_section the section to search the relocation section for
> >> +  /// Return the __ksymtab_gpl section of a linux kernel ELF file
> >> +  /// (either a vmlinux binary or a kernel module).
> >>    ///
> >> -  /// @return the .rel{a,} section if found, null otherwise.
> >> +  /// @return the __ksymtab_gpl section if found, nil otherwise.
> >>    Elf_Scn*
> >> -  find_relocation_section(Elf_Scn* target_section) const
> >> +  find_ksymtab_gpl_section() const
> >>    {
> >> -    if (target_section)
> >> -      {
> >> -       // the relo section we are searching for has this index as sh_info
> >> -       size_t target_index = elf_ndxscn(target_section);
> >> -
> >> -       // now iterate over all the sections, look for relocation sections and
> >> -       // find the one that points to the section we are searching for
> >> -       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 != SHT_RELA && header->sh_type != SHT_REL))
> >> -             continue;
> >> -
> >> -           if (header->sh_info == target_index)
> >> -             return section;
> >> -         }
> >> -      }
> >> -    return NULL;
> >> +    if (!ksymtab_gpl_section_)
> >> +      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
> >> +         elf_helpers::find_ksymtab_gpl_section(elf_handle());
> >> +    return ksymtab_gpl_section_;
> >>    }
> >>
> >>    /// Return the .rel{a,}__ksymtab section of a linux kernel ELF file (either
> >> @@ -5354,25 +5289,12 @@ public:
> >>    {
> >>      if (!ksymtab_reloc_section_)
> >>        {
> >> -       const_cast<read_context*>(this)->ksymtab_reloc_section_
> >> -           = find_relocation_section(find_ksymtab_section());
> >> +       const_cast<read_context*>(this)->ksymtab_reloc_section_ =
> >> +           find_relocation_section(elf_handle(), find_ksymtab_section());
> >>        }
> >>      return ksymtab_reloc_section_;
> >>    }
> >>
> >> -  /// Return the __ksymtab_gpl section of a linux kernel ELF file
> >> -  /// (either a vmlinux binary or a kernel module).
> >> -  ///
> >> -  /// @return the __ksymtab_gpl section if found, nil otherwise.
> >> -  Elf_Scn*
> >> -  find_ksymtab_gpl_section() const
> >> -  {
> >> -    if (!ksymtab_gpl_section_)
> >> -      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
> >> -       find_section(elf_handle(), "__ksymtab_gpl", SHT_PROGBITS);
> >> -    return ksymtab_gpl_section_;
> >> -  }
> >> -
> >>    /// Return the .rel{a,}__ksymtab_gpl section of a linux kernel ELF file
> >>    /// (either a vmlinux binary or a kernel module).
> >>    ///
> >> @@ -5382,8 +5304,8 @@ public:
> >>    {
> >>      if (!ksymtab_gpl_reloc_section_)
> >>        {
> >> -       const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_
> >> -           = find_relocation_section(find_ksymtab_gpl_section());
> >> +       const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_ =
> >> +           find_relocation_section(elf_handle(), find_ksymtab_gpl_section());
> >>        }
> >>      return ksymtab_gpl_reloc_section_;
> >>    }
> >> diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
> >> index ede191014369..b77440206fb0 100644
> >> --- a/src/abg-elf-helpers.cc
> >> +++ b/src/abg-elf-helpers.cc
> >> @@ -357,9 +357,9 @@ find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
> >>  ///
> >>  /// @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)
> >> +/// @return the symbol table section
> >> +Elf_Scn*
> >> +find_symbol_table_section(Elf* elf_handle)
> >>  {
> >>    Elf_Scn* section = 0, *dynsym = 0, *sym_tab = 0;
> >>    while ((section = elf_nextscn(elf_handle, section)) != 0)
> >> @@ -378,12 +378,11 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
> >>        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;
> >> +       return sym_tab ? sym_tab : dynsym;
> >>        else
> >> -       symtab = dynsym ? dynsym : sym_tab;
> >> -      return true;
> >> +       return dynsym ? dynsym : sym_tab;
> >>      }
> >> -  return false;
> >> +  return NULL;
> >>  }
> >>
> >>  /// Find the index (in the section headers table) of the symbol table
> >> @@ -402,8 +401,9 @@ find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab)
> >>  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))
> >> +  Elf_Scn* section = find_symbol_table_section(elf_handle);
> >> +
> >> +  if (!section)
> >>      return false;
> >>
> >>    symtab_index = elf_ndxscn(section);
> >> @@ -500,6 +500,17 @@ Elf_Scn*
> >>  find_data1_section(Elf* elf_handle)
> >>  {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
> >>
> >> +/// Return the "Official Procedure descriptors section."  This
> >> +/// section is named .opd, and is usually present only on PPC64
> >> +/// ELFv1 binaries.
> >> +///
> >> +/// @param elf_handle the elf handle to consider.
> >> +///
> >> +/// @return the .opd section, if found.  Return nil otherwise.
> >> +Elf_Scn*
> >> +find_opd_section(Elf* elf_handle)
> >> +{return find_section(elf_handle, ".opd", SHT_PROGBITS);}
> >> +
> >>  /// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
> >>  /// sections that are involved in symbol versionning.
> >>  ///
> >> @@ -548,6 +559,26 @@ get_symbol_versionning_sections(Elf*               elf_handle,
> >>    return false;
> >>  }
> >>
> >> +/// Return the __ksymtab section of a linux kernel ELF file (either
> >> +/// a vmlinux binary or a kernel module).
> >> +///
> >> +/// @param elf_handle the elf handle to consider.
> >> +///
> >> +/// @return the __ksymtab section if found, nil otherwise.
> >> +Elf_Scn*
> >> +find_ksymtab_section(Elf* elf_handle)
> >> +{return find_section(elf_handle, "__ksymtab", SHT_PROGBITS);}
> >> +
> >> +/// Return the __ksymtab_gpl section of a linux kernel ELF file (either
> >> +/// a vmlinux binary or a kernel module).
> >> +///
> >> +/// @param elf_handle the elf handle to consider.
> >> +///
> >> +/// @return the __ksymtab section if found, nil otherwise.
> >> +Elf_Scn*
> >> +find_ksymtab_gpl_section(Elf* elf_handle)
> >> +{return find_section(elf_handle, "__ksymtab_gpl", SHT_PROGBITS);}
> >> +
> >>  /// Find the __ksymtab_strings section of a Linux kernel binary.
> >>  ///
> >>  /// @param elf_handle the elf handle to use.
> >> @@ -563,6 +594,39 @@ find_ksymtab_strings_section(Elf *elf_handle)
> >>    return 0;
> >>  }
> >>
> >> +/// Return the .rel{a,} section corresponding to a given section.
> >> +///
> >> +/// @param elf_handle the elf handle to consider.
> >> +///
> >> +/// @param target_section the section to search the relocation section for
> >> +///
> >> +/// @return the .rel{a,} section if found, null otherwise.
> >> +Elf_Scn*
> >> +find_relocation_section(Elf* elf_handle, Elf_Scn* target_section)
> >> +{
> >> +  if (target_section)
> >> +    {
> >> +      // the relo section we are searching for has this index as sh_info
> >> +      size_t target_index = elf_ndxscn(target_section);
> >> +
> >> +      // now iterate over all the sections, look for relocation sections and
> >> +      // find the one that points to the section we are searching for
> >> +      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 != SHT_RELA && header->sh_type != SHT_REL))
> >> +           continue;
> >> +
> >> +         if (header->sh_info == target_index)
> >> +           return section;
> >> +       }
> >> +    }
> >> +  return NULL;
> >> +}
> >> +
> >>  /// Get the version definition (from the SHT_GNU_verdef section) of a
> >>  /// given symbol represented by a pointer to GElf_Versym.
> >>  ///
> >> @@ -797,5 +861,52 @@ is_linux_kernel(Elf *elf_handle)
> >>           || is_linux_kernel_module(elf_handle));
> >>  }
> >>
> >> +/// Get the address at which a given binary is loaded in memory⋅
> >> +///
> >> +/// @param elf_handle the elf handle for the binary to consider.
> >> +///
> >> +/// @param load_address the address where the binary is loaded.  This
> >> +/// is set by the function iff it returns true.
> >> +///
> >> +/// @return true if the function could get the binary load address
> >> +/// and assign @p load_address to it.
> >
> >Should be returning nullable load_address.
>
> I thought of that as well, but decided against. The return value is not
> a pointer type where NULL would be indicative, 0 is a valid result for
> this function and we do not have the facilities like std::optional
> (yet). I would not want to burden the caller with freeing any memory
> either. Hence I stuck to the original interface. Did I miss an obvious
> other option?
>
> Cheers,
> Matthias
>
> >
> >
> >> +bool
> >> +get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
> >> +{
> >> +  GElf_Ehdr elf_header;
> >> +  gelf_getehdr(elf_handle, &elf_header);
> >> +  size_t num_segments = elf_header.e_phnum;
> >> +  GElf_Phdr *program_header = NULL;
> >> +  GElf_Addr result;
> >> +  bool found_loaded_segment = false;
> >> +  GElf_Phdr ph_mem;
> >> +
> >> +  for (unsigned i = 0; i < num_segments; ++i)
> >> +    {
> >> +      program_header = gelf_getphdr(elf_handle, i, &ph_mem);
> >> +      if (program_header && program_header->p_type == PT_LOAD)
> >> +       {
> >> +         if (!found_loaded_segment)
> >> +           {
> >> +             result = program_header->p_vaddr;
> >> +             found_loaded_segment = true;
> >> +           }
> >> +
> >> +         if (program_header->p_vaddr < result)
> >> +           // The resulting load address we want is the lowest
> >> +           // load address of all the loaded segments.
> >> +           result = program_header->p_vaddr;
> >> +       }
> >> +    }
> >> +
> >> +  if (found_loaded_segment)
> >> +    {
> >> +      load_address = result;
> >> +      return true;
> >> +    }
> >> +  return false;
> >> +}
> >> +
> >> +
> >>  } // end namespace elf_helpers
> >>  } // end namespace abigail
> >> diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
> >> index 7ddd887de959..8a83bb4f2e95 100644
> >> --- a/src/abg-elf-helpers.h
> >> +++ b/src/abg-elf-helpers.h
> >> @@ -63,8 +63,8 @@ find_section(Elf*             elf_handle,
> >>              const std::string& name,
> >>              Elf64_Word         section_type);
> >>
> >> -bool
> >> -find_symbol_table_section(Elf* elf_handle, Elf_Scn*& symtab);
> >> +Elf_Scn*
> >> +find_symbol_table_section(Elf* elf_handle);
> >>
> >>  bool
> >>  find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index);
> >> @@ -96,15 +96,27 @@ find_data_section(Elf* elf_handle);
> >>  Elf_Scn*
> >>  find_data1_section(Elf* elf_handle);
> >>
> >> +Elf_Scn*
> >> +find_opd_section(Elf* elf_handle);
> >> +
> >>  bool
> >>  get_symbol_versionning_sections(Elf*           elf_handle,
> >>                                 Elf_Scn*&       versym_section,
> >>                                 Elf_Scn*&       verdef_section,
> >>                                 Elf_Scn*&       verneed_section);
> >>
> >> +Elf_Scn*
> >> +find_ksymtab_section(Elf* elf_handle);
> >> +
> >> +Elf_Scn*
> >> +find_ksymtab_gpl_section(Elf* elf_handle);
> >> +
> >>  Elf_Scn*
> >>  find_ksymtab_strings_section(Elf *elf_handle);
> >>
> >> +Elf_Scn*
> >> +find_relocation_section(Elf* elf_handle, Elf_Scn* target_section);
> >> +
> >>  //
> >>  // Helpers for symbol versioning
> >>  //
> >> @@ -137,6 +149,12 @@ is_linux_kernel_module(Elf *elf_handle);
> >>  bool
> >>  is_linux_kernel(Elf *elf_handle);
> >>
> >> +//
> >> +// Misc Helpers
> >> +//
> >> +
> >> +bool
> >> +get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address);
> >>
> >>  } // end namespace elf_helpers
> >>  } // end namespace abigail
> >> --
> >> 2.26.1.301.g55bc3eb7cb9-goog
> >>
>
> --
> To unsubscribe from this group and stop receiving emails from it, send an email to kernel-team+unsubscribe@android.com.
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v2 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case
  2020-04-21  6:35   ` [PATCH v2 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
@ 2020-04-22  9:42     ` Dodji Seketeli
  0 siblings, 0 replies; 37+ messages in thread
From: Dodji Seketeli @ 2020-04-22  9:42 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, gprocida, kernel-team

Hello Matthias,

Matthias Maennich <maennich@google.com> a écrit:

> abg-elf-helpers.{h,cc} shall contain the ELF related parts of the
> abg-dwarf-reader. Create the stub files, an empty unit test and hook
> everything up in the make system.
>
>     * src/Makefile.am: Add new source files abg-elf-helpers.{h,cc}.
>     * src/abg-elf-helpers.cc: New source file.
>     * src/abg-elf-helpers.h: New header file.
>     * tests/.gitignore: Exclude runtestelfhelpers from being committed.
>     * tests/Makefile.am: Add new test case runtestelfhelpers.
>     * tests/test-elf-helpers.cc: New test source file.

I have just re-indented the ChangeLog part of the message above to
tabify it.  Applying to master.  Thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v2 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader
  2020-04-21  6:35   ` [PATCH v2 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader Matthias Maennich
@ 2020-04-22  9:44     ` Dodji Seketeli
  0 siblings, 0 replies; 37+ messages in thread
From: Dodji Seketeli @ 2020-04-22  9:44 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, gprocida, kernel-team

Matthias Maennich <maennich@google.com> a écrit:

> 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.h(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.

I have just tabified this ChangeLog, added a white space in e.g:

>     * abg-dwarf-reader.cc(stt_to_elf_symbol_type): Move function out.

To make:

	* abg-dwarf-reader.cc (stt_to_elf_symbol_type): Move function out.

Applying to master.  Thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v2 3/8] abg-elf-helpers: move some versioning helpers from abg-dwarf-reader
  2020-04-21  6:35   ` [PATCH v2 3/8] abg-elf-helpers: move some versioning " Matthias Maennich
@ 2020-04-22  9:46     ` Dodji Seketeli
  0 siblings, 0 replies; 37+ messages in thread
From: Dodji Seketeli @ 2020-04-22  9:46 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, gprocida, kernel-team

Matthias Maennich <maennich@google.com> a écrit:

> Move some definitions from abg-dwarf-reader to abg-elf-helpers that are
> strictly only related to ELF.
>
>         * abg-dwarf-reader.cc(get_symbol_versionning_sections): Move function out.
>         (get_version_definition_for_versym): Likewise.
>         (get_version_needed_for_versym): Likewise.
>         (get_version_for_symbol): Likewise.
>         * abg-elf-helpers.cc(get_symbol_versionning_sections): Move function in.
>         (get_version_definition_for_versym): Likewise.
>         (get_version_needed_for_versym): Likewise.
>         (get_version_for_symbol): Likewise.
>         * abg-elf-helpers.cc(get_symbol_versionning_sections): Add declaration.
>         (get_version_definition_for_versym): Likewise.
>         (get_version_needed_for_versym): Likewise.
>         (get_version_for_symbol): Likewise.

Likewise, I am tabifying this and adding spaces between the file name
and the changed interface name.

Applying to master.  Thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v2 4/8] abg-elf-helpers: move some kernel helpers from abg-dwarf-reader
  2020-04-21  6:35   ` [PATCH v2 4/8] abg-elf-helpers: move some kernel " Matthias Maennich
@ 2020-04-22  9:47     ` Dodji Seketeli
  0 siblings, 0 replies; 37+ messages in thread
From: Dodji Seketeli @ 2020-04-22  9:47 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, gprocida, kernel-team

Matthias Maennich <maennich@google.com> a écrit:

> Move some definitions from abg-dwarf-reader to abg-elf-helpers that are
> strictly only related to ELF.
>
>         * abg-dwarf-reader.cc(binary_is_linux_kernel): Move function out.
> 	(binary_is_linux_kernel_module): Likewise.
> 	(find_ksymtab_strings_section): Likewise.
>         * abg-elf-helpers.cc(binary_is_linux_kernel): Move function in.
> 	(binary_is_linux_kernel_module): Likewise.
> 	(find_ksymtab_strings_section): Likewise.
>         * abg-elf-helpers.h(binary_is_linux_kernel): Add declaration.
> 	(binary_is_linux_kernel_module): Likewise.
> 	(find_ksymtab_strings_section): Likewise.

Likewise, re-indenting this and inserting a white space between the file
name and the changed interface name.

Applying to master.  Thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v2 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers
  2020-04-21  6:35   ` [PATCH v2 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers Matthias Maennich
@ 2020-04-22  9:48     ` Dodji Seketeli
  0 siblings, 0 replies; 37+ messages in thread
From: Dodji Seketeli @ 2020-04-22  9:48 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, gprocida, kernel-team

Matthias Maennich <maennich@google.com> a écrit:

> This consistently names the is_linux_kernel* helpers and keeps only the
> copy in the elf-helpers. All users are adjusted.
>
> 	* src/abg-dwarf-reader.cc
> 	(read_context::function_symbol_is_exported): use is_linux_kernel
> 	from elf_helpers.
> 	(read_context::variable_is_exported): Likewise.
> 	(read_context::get_symtab_format): Likewise.
> 	(read_context::load_symbol_maps): Likewise.
> 	(read_debug_info_into_corpus): Likewise.
> 	(read_context::is_linux_kernel_binary): Drop function.
> 	(read_context::is_linux_kernel_module): Drop function.
> 	* src/abg-elf-helpers.cc (binary_is_linux_kernel): rename to
> 	is_linux_kernel
> 	(binary_is_linux_kernel_module): rename to is_linux_kernel_module
> 	(find_ksymtab_strings_section): Adjust to function renames.
> 	* src/abg-elf-helpers.h (binary_is_linux_kernel): rename to
> 	is_linux_kernel
> 	(binary_is_linux_kernel_module): rename to
> 	is_linux_kernel_module

Applying to master, Thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v2 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers
  2020-04-21  6:35   ` [PATCH v2 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers Matthias Maennich
@ 2020-04-22  9:53     ` Dodji Seketeli
  0 siblings, 0 replies; 37+ messages in thread
From: Dodji Seketeli @ 2020-04-22  9:53 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, gprocida, kernel-team

Matthias Maennich <maennich@google.com> a écrit:

> This change migrates all ELF helpers related to section lookup to
> abg-elf-helpers.{cc,h}. It also homogenizes the interface of those to
> always return Elf_Scn* and NULL in case that section can't be found.
> Though this smells like a functional change, this latter change is
> purely cosmetic.
>
> 	* src/abg-dwarf-reader.cc (read_context::find_symbol_table_section):
> 	adjust to new interface of elf_helpers::find_symbol_table_section.
> 	(find_opd_section): use elf_helpers::find_opd_section for lookup.
> 	(find_ksymtab_section): use elf_helpers::find_ksymtab_section.
> 	(find_ksymtab_gpl_section): use elf_helpers::find_ksymtab_gpl_section.
> 	(find_relocation_section): Move out function.
> 	(get_binary_load_address): Move out function.
> 	(find_ksymtab_reloc_section): use elf_helpers::find_relocation_section
> 	(find_ksymtab_gpl_reloc_section): use elf_helpers::find_relocation_section
> 	* src/elf-helpers.cc (find_symbol_table_section): change
> 	interface to match other find_*_section functions.
> 	(find_symbol_table_section_index): Adjust for the new interface
> 	of find_symbol_table_section.
> 	(find_opd_section): New function.
> 	(find_ksymtab_section): New function.
> 	(find_ksymtab_gpl_section): New function.
> 	(find_relocation_section): New function.
> 	(get_binary_load_address): New function.
> 	* src/elf-helpers.h (find_symbol_table_section): Change declaration.
> 	(find_opd_section): New function declation.

I am correcting the typo in "declation" here.  Likewise for the
lines below, until ...

> 	(find_ksymtab_section): New function declation.
> 	(find_ksymtab_gpl_section): New function declation.
> 	(find_relocation_section): New function declation.
> 	(get_binary_load_address): New function declation.

... here.

[...]

> @@ -5282,8 +5235,8 @@ public:
>    find_symbol_table_section() const
>    {
>      if (!symtab_section_)
> -      dwarf_reader::find_symbol_table_section(elf_handle(),
> -					      const_cast<read_context*>(this)->symtab_section_);
> +      const_cast<read_context*>(this)->symtab_section_ =
> +	  elf_helpers::find_symbol_table_section(elf_handle());
>      return symtab_section_;
>    }

I am declaring the read_context::symtab_section_ as mutable to avoid the
const_cast here.

>  
> @@ -5296,8 +5249,8 @@ public:
>    find_opd_section() const
>    {
>      if (!opd_section_)
> -      const_cast<read_context*>(this)->opd_section_=
> -	find_section(elf_handle(), ".opd", SHT_PROGBITS);
> +      const_cast<read_context*>(this)->opd_section_ =
> +	  elf_helpers::find_opd_section(elf_handle());
>      return opd_section_;
>    }

Likewise.

>  
> @@ -5310,39 +5263,21 @@ public:
>    {
>      if (!ksymtab_section_)
>        const_cast<read_context*>(this)->ksymtab_section_ =
> -	find_section(elf_handle(), "__ksymtab", SHT_PROGBITS);
> +	  elf_helpers::find_ksymtab_section(elf_handle());
>      return ksymtab_section_;
>    }


Likewise.

[...]

>    Elf_Scn*
> -  find_relocation_section(Elf_Scn* target_section) const
> +  find_ksymtab_gpl_section() const
>    {

[...]

> -    return NULL;
> +    if (!ksymtab_gpl_section_)
> +      const_cast<read_context*>(this)->ksymtab_gpl_section_ =
> +	  elf_helpers::find_ksymtab_gpl_section(elf_handle());
> +    return ksymtab_gpl_section_;
>    }

Likewise.

>  
>    /// Return the .rel{a,}__ksymtab section of a linux kernel ELF file (either
> @@ -5354,25 +5289,12 @@ public:
>    {
>      if (!ksymtab_reloc_section_)
>        {
> -	const_cast<read_context*>(this)->ksymtab_reloc_section_
> -	    = find_relocation_section(find_ksymtab_section());
> +	const_cast<read_context*>(this)->ksymtab_reloc_section_ =
> +	    find_relocation_section(elf_handle(), find_ksymtab_section());
>        }
>      return ksymtab_reloc_section_;
>    }

Likewise.

[...]

> @@ -5382,8 +5304,8 @@ public:
>    {
>      if (!ksymtab_gpl_reloc_section_)
>        {
> -	const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_
> -	    = find_relocation_section(find_ksymtab_gpl_section());
> +	const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_ =
> +	    find_relocation_section(elf_handle(), find_ksymtab_gpl_section());
>        }

Likewise.

[...]

Applying to master with those changes, thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v2 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers)
  2020-04-21  6:35   ` [PATCH v2 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers) Matthias Maennich
@ 2020-04-22  9:55     ` Dodji Seketeli
  0 siblings, 0 replies; 37+ messages in thread
From: Dodji Seketeli @ 2020-04-22  9:55 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, gprocida, kernel-team

Matthias Maennich <maennich@google.com> a écrit:

> This migrates more architecture specific helpers over to the
> elf-helpers. No functional change intended.
>
> 	* src/abg-dwarf-reader.cc(elf_architecture_is_ppc64): Move

I am adding a space here --------^

> 	function out and adjust callers to call the migrated
> 	functions.
> 	(elf_architecture_is_big_endian): Likewise.
> 	(architecture_word_size): Likewise.
> 	(current_elf_file_is_executable): Likewise.
> 	(current_elf_file_is_dso): Likewise.
> 	* src/abg-elf-helpers.cc (architecture_is_ppc64): Add new function.
> 	(architecture_is_big_endian): Likewise.
> 	(get_architecture_word_size): Likewise.
> 	(is_executable): Likewise.
> 	(is_dso): Likewise.
> 	* src/abg-elf-helpers.h (architecture_is_ppc64): Add new declaration.
> 	(architecture_is_big_endian): Likewise.
> 	(get_architecture_word_size): Likewise.
> 	(is_executable): Likewise.
> 	(is_dso): Likewise.

Applying to master with that change.

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v2 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr
  2020-04-21  6:35   ` [PATCH v2 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr Matthias Maennich
@ 2020-04-22  9:56     ` Dodji Seketeli
  0 siblings, 0 replies; 37+ messages in thread
From: Dodji Seketeli @ 2020-04-22  9:56 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, gprocida, kernel-team

Matthias Maennich <maennich@google.com> a écrit:

[...]

> 	* src/abg-dwarf-reader.cc(maybe_adjust_et_rel_sym_addr_to_abs_addr):

Adding a space here -------------^

Likewise or the relevant lines below.

> 	Move out functions (drop the wrapped overload completely).
> 	* src/abg-elf-helpers.cc(maybe_adjust_et_rel_sym_addr_to_abs_addr):
> 	New function.
> 	* src/abg-elf-helpers.h(maybe_adjust_et_rel_sym_addr_to_abs_addr):
> 	New function declaration.

Applying to master with that change.  Thanks!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers
  2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
                     ` (7 preceding siblings ...)
  2020-04-21  6:35   ` [PATCH v2 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr Matthias Maennich
@ 2020-04-22  9:57   ` Dodji Seketeli
  8 siblings, 0 replies; 37+ messages in thread
From: Dodji Seketeli @ 2020-04-22  9:57 UTC (permalink / raw)
  To: Matthias Maennich; +Cc: libabigail, gprocida, kernel-team

Hello Matthias,

Matthias Maennich <maennich@google.com> a écrit:

> The abg-dwarf-reader.cc has grown into a large compilation unit with a lot of
> responsibilities. This does not only affect the compilation time, but also
> readability of the various implementation details. Hence it makes sense to
> attempt a refactoring of parts of it.
>
> To overcome the above and as a preparation for my future work on the symtab
> reading part, this splits out functionality from the dwarf reader into a new
> set of source files: src/elf-helpers.{h,cc} along with a test that so far only
> serves the purpose of ensuring that the header file can be compiled on its own.
>
> The elf-helpers, sensibly not named elf-utils, contain functionality like
> looking up sections, converting values or deducting information and properties
> in some way from an Elf* handle. They are not exposed to libabigail users as
> they are an implementation detail of libabigail.
>
> This set of changes is only a refactoring with minor cleanups and renames and
> any change to the functionality would be unintentional.

Thank you for doing this!

I have reviewed and applied the patchset to master.

Thanks again!

Cheers,

-- 
		Dodji

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2020-04-22  9:57 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-20 11:08 [PATCH 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
2020-04-20 11:08 ` [PATCH 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
2020-04-20 15:35   ` Giuliano Procida
2020-04-20 11:08 ` [PATCH 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader Matthias Maennich
2020-04-20 15:34   ` Giuliano Procida
2020-04-20 11:08 ` [PATCH 3/8] abg-elf-helpers: move some versioning " Matthias Maennich
2020-04-20 15:33   ` Giuliano Procida
2020-04-20 11:08 ` [PATCH 4/8] abg-elf-helpers: move some kernel " Matthias Maennich
2020-04-20 14:32   ` Giuliano Procida
2020-04-20 15:30     ` Giuliano Procida
2020-04-20 11:08 ` [PATCH 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers Matthias Maennich
2020-04-20 15:29   ` Giuliano Procida
2020-04-20 11:08 ` [PATCH 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers Matthias Maennich
2020-04-20 15:24   ` Giuliano Procida
2020-04-21  6:14     ` Matthias Maennich
2020-04-21 11:02       ` Giuliano Procida
2020-04-20 11:08 ` [PATCH 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers) Matthias Maennich
2020-04-20 15:25   ` Giuliano Procida
2020-04-20 11:08 ` [PATCH 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr Matthias Maennich
2020-04-21  6:35 ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Matthias Maennich
2020-04-21  6:35   ` [PATCH v2 1/8] abg-dwarf-reader split: create abg-elf-helpers.{h, cc} and test case Matthias Maennich
2020-04-22  9:42     ` Dodji Seketeli
2020-04-21  6:35   ` [PATCH v2 2/8] abg-elf-helpers: move some elf helpers from abg-dwarf-reader Matthias Maennich
2020-04-22  9:44     ` Dodji Seketeli
2020-04-21  6:35   ` [PATCH v2 3/8] abg-elf-helpers: move some versioning " Matthias Maennich
2020-04-22  9:46     ` Dodji Seketeli
2020-04-21  6:35   ` [PATCH v2 4/8] abg-elf-helpers: move some kernel " Matthias Maennich
2020-04-22  9:47     ` Dodji Seketeli
2020-04-21  6:35   ` [PATCH v2 5/8] abg-elf-helpers: consolidate the is_linux_kernel* helpers Matthias Maennich
2020-04-22  9:48     ` Dodji Seketeli
2020-04-21  6:35   ` [PATCH v2 6/8] abg-dwarf-reader: migrate more ELF helpers to elf-helpers Matthias Maennich
2020-04-22  9:53     ` Dodji Seketeli
2020-04-21  6:35   ` [PATCH v2 7/8] abg-elf-helpers: migrate more elf helpers (architecture specific helpers) Matthias Maennich
2020-04-22  9:55     ` Dodji Seketeli
2020-04-21  6:35   ` [PATCH v2 8/8] abg-elf-helpers: migrate maybe_adjust_et_rel_sym_addr_to_abs_addr Matthias Maennich
2020-04-22  9:56     ` Dodji Seketeli
2020-04-22  9:57   ` [PATCH v2 0/8] Refactor dwarf-reader: split out ELF helpers Dodji Seketeli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).