* [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
* 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
* [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, §ion_header_string_index) < 0)
- return 0;
-
- Elf_Scn* section = 0;
- GElf_Shdr header_mem, *header;
- while ((section = elf_nextscn(elf_handle, section)) != 0)
- {
- header = gelf_getshdr(section, &header_mem);
- if (header == NULL || 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, §ion_header_string_index) < 0)
+ return 0;
+
+ Elf_Scn* section = 0;
+ GElf_Shdr header_mem, *header;
+ while ((section = elf_nextscn(elf_handle, section)) != 0)
+ {
+ header = gelf_getshdr(section, &header_mem);
+ if (header == NULL || 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 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, §ion_header_string_index) < 0)
> - return 0;
> -
> - Elf_Scn* section = 0;
> - GElf_Shdr header_mem, *header;
> - while ((section = elf_nextscn(elf_handle, section)) != 0)
> - {
> - header = gelf_getshdr(section, &header_mem);
> - if (header == NULL || 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, §ion_header_string_index) < 0)
> + return 0;
> +
> + Elf_Scn* section = 0;
> + GElf_Shdr header_mem, *header;
> + while ((section = elf_nextscn(elf_handle, section)) != 0)
> + {
> + header = gelf_getshdr(section, &header_mem);
> + if (header == NULL || 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
* 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
* [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
* 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 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
* [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
* 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
* [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
* 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 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
* 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
* [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
* 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
* [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, §ion_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, §ion_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
* [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
* 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
* [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, §ion_header_string_index) < 0)
- return 0;
-
- Elf_Scn* section = 0;
- GElf_Shdr header_mem, *header;
- while ((section = elf_nextscn(elf_handle, section)) != 0)
- {
- header = gelf_getshdr(section, &header_mem);
- if (header == NULL || 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, §ion_header_string_index) < 0)
+ return 0;
+
+ Elf_Scn* section = 0;
+ GElf_Shdr header_mem, *header;
+ while ((section = elf_nextscn(elf_handle, section)) != 0)
+ {
+ header = gelf_getshdr(section, &header_mem);
+ if (header == NULL || 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 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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, §ion_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, §ion_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 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