mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-14 05:54:50 +00:00
Add support for BTF
This adds support for the BTF debug information format. It provides a new BTF front-end which can be instantiated by the function tools::create_best_elf_based_reader(). For now, the BTF front-end supports the basic types (integers, pointers, qualified types, typedefs, struct and unions and function pointers) for functions and variables as emitted for the C language by GCC. It seems to be able to support the BTF debug information emitted for the vmlinux kernel by the pahole tool as well. When configured with the --enable-btf option, the WITH_BTF pre-processor macro is defined, enabling the BTF support. That option is turned on by default if the /usr/include/bpf/btf.h header is found on the system. To disable this, one can use the --disable-btf option. The abidw and abidiff programs have been adapted to use the BTF front-end when provided with the '--btf' option, or if BTF debug information is the only one present in the binary. * configure.ac: If the header /usr/include/bpf/btf.h exists, then define the WITH_BTF pre-processor macro, unless --disable-btf was provided. * doc/manuals/abidiff.rst: Document the new --btf option. * doc/manuals/abidw.rst: Likewise. * doc/manuals/kmidiff.rst: Likewise. * doc/manuals/abipkgdiff.rst: Likewise. * include/abg-btf-reader.h: New header file. Contains the declaration of the new btf::reader class. * src/abg-btf-reader.cc: New source file. Contains the definitions of the new btf::reader class. * include/Makefile.am: Add the new include/abg-btf-reader.h header file to source distribution. * include/abg-corpus.h (enum origin): Add a new BTF_ORIGIN enumerator. * include/abg-tools-utils.h (file_has_btf_debug_info): Declare new function. * src/abg-tools-utils.cc (file_has_btf_debug_info): Define new function. (create_best_elf_based_reader): Adapt to support BTF input. If the user requested the BTF front-end, instantiate it. Otherwise, if the input file has only BTF debug info, instantiate the BTF front end. * include/abg-elf-reader.h (elf::reader::find_btf_section): Declare new member function. (elf::reader::{function, variable}_symbol_is_exported): Add new overloads. * src/abg-elf-reader.cc (reader::priv::btf_section): New data member. (reader::find_btf_section): Define new member function. * src/Makefile.am: Add the new abg-ctf-reader.cc file to source distribution. * tools/abidw.cc (options::use_btf): New data member. (display_usage): Add a help string for the new --btf option. (parse_command_line): Support the new --btf option. (load_corpus_and_write_abixml): If the user asked to use the btf front-end then use that one. * tools/abidiff.cc (options::use_btf): New data member. (options::options): Initialize it. (display_usage):: Add a help string to the new --btf options. (parse_command_line): Support the new --btf options. (main): If the user asked to use the btf front-end, then use that one. * tools/abidw.cc (options::use_btf): New data member. (options::options): Initialize it. (parse_command_line): Add a help string to the new --btf options. (load_corpus_and_write_abixml): If the user asked to use the btf front-end, then use that one. * tools/kmidiff.cc (options::use_btf): New data member. (options::options): Initialize it. (display_usage): Add a help string to the new --btf options. (parse_command_line): Add a help string to the new --btf options. (main): If the user asked to use the btf front-end, then use that one. * tools/abipkgdiff.cc (options::use_btf): New data member. (options::options): Initialize it. (display_usage): Add a help string to the new --btf options. (parse_command_line): Add a help string to the new --btf options. (compare, compare_to_self) (compare_prepared_linux_kernel_packages): If the user asked to use the btf front-end, then use that one. * tests/data/test-read-btf/test{0,1}.o: New binary test input file. * tests/data/test-read-btf/test{0,1}.c: Source code of the binary input file above. * tests/data/test-read-btf/test{0,1}.o.abi: Reference ABIXML output. * tests/data/test-abidiff-exit/btf/test0-report-{1,2}.txt: New test reference output. * tests/data/test-abidiff-exit/btf/test0-v{0,1}.o: New binary test input. * tests/data/test-abidiff-exit/btf/test0-v{0,1}.c: The source files of the binary inputs above. * tests/test-read-btf.cc: New test file to run the btf/abixml tests. * tests/Makefile.am: Add the new test files to the source distribution. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
5d97da9755
commit
12641b1130
81
configure.ac
81
configure.ac
@ -201,6 +201,12 @@ AC_ARG_ENABLE(ctf,
|
||||
ENABLE_CTF=$enableval,
|
||||
ENABLE_CTF=auto)
|
||||
|
||||
dnl check if user has enabled BTF code
|
||||
AC_ARG_ENABLE(btf,
|
||||
AS_HELP_STRING([--enable-btf=yes|no],
|
||||
[disable support of btf files)]),
|
||||
ENABLE_BTF=$enableval,
|
||||
ENABLE_BTF=auto)
|
||||
dnl *************************************************
|
||||
dnl check for dependencies
|
||||
dnl *************************************************
|
||||
@ -339,6 +345,77 @@ if test x$ENABLE_CTF != xno; then
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl configure BTF usage
|
||||
BPF_LIBS=
|
||||
if test x$ENABLE_BTF != xno; then
|
||||
AC_CHECK_HEADER([bpf/btf.h],
|
||||
[ENABLE_BTF=yes],
|
||||
[AC_MSG_NOTICE([could not find bpf/btf.h])])
|
||||
if test x$ENABLE_BTF = xyes; then
|
||||
AC_MSG_NOTICE([enable BTF support])
|
||||
ENABLE_BTF=yes
|
||||
AC_DEFINE([WITH_BTF], 1,
|
||||
[Defined if user enabled BTF usage])
|
||||
BPF_LIBS=-lbpf
|
||||
else
|
||||
AC_MSG_NOTICE([BTF support was disabled])
|
||||
ENABLE_BTF=no
|
||||
fi
|
||||
|
||||
dnl Test if various functions and structs are present.
|
||||
|
||||
if test x$ENABLE_BTF = xyes; then
|
||||
dnl Test if struct btf_enum64 is present.
|
||||
AC_CHECK_TYPE([struct btf_enum64],
|
||||
[HAVE_BTF_ENUM64=yes],
|
||||
[HAVE_BTF_ENUM64=no],
|
||||
[#include <bpf/btf.h>])
|
||||
|
||||
if test x$HAVE_BTF_ENUM64 = xyes; then
|
||||
AC_DEFINE([WITH_BTF_ENUM64], 1, [struct btf_enum64 is present])
|
||||
fi
|
||||
|
||||
dnl Test if btf__get_nr_types is present
|
||||
AC_CHECK_DECL([btf__get_nr_types],
|
||||
[HAVE_BTF__GET_NR_TYPES=yes],
|
||||
[HAVE_BTF__GET_NR_TYPES=no],
|
||||
[#include <bpf/btf.h>])
|
||||
|
||||
if test x$HAVE_BTF__GET_NR_TYPES = xyes; then
|
||||
AC_DEFINE(WITH_BTF__GET_NR_TYPES, 1, [The function btf__get_nr_types is present])
|
||||
fi
|
||||
|
||||
dnl Test if btf__type_cnt is present
|
||||
AC_CHECK_DECL([btf__type_cnt],
|
||||
[HAVE_BTF__TYPE_CNT=yes],
|
||||
[HAVE_BTF__TYPE_CNT=no],
|
||||
[#include <bpf/btf.h>])
|
||||
if test x$HAVE_BTF__TYPE_CNT = xyes; then
|
||||
AC_DEFINE(WITH_BTF__TYPE_CNT, 1, [The function btf__type_cnt is present])
|
||||
fi
|
||||
|
||||
dnl Test if BTF_KIND_TYPE_TAG exists
|
||||
AC_CHECK_DECL([int kind = BTF_KIND_TYPE_TAG],
|
||||
[HAVE_BTF_KIND_TYPE_TAG=yes],
|
||||
[HAVE_BTF_KIND_TYPE_TAG=no],
|
||||
[#include <bpf/btf.h>])
|
||||
if test x$HAVE_BTF_KIND_TYPE_TAG = xyes; then
|
||||
AC_DEFINE([WITH_BTF_KIND_TYPE_TAG], 1,
|
||||
[The BTF_KIND_TYPE_TAG enumerator is present])
|
||||
fi
|
||||
|
||||
dnl Test if BTF_KIND_DECL_TAG exists
|
||||
AC_CHECK_DECL([int kind = BTF_KIND_DECL_TAG],
|
||||
[HAVE_BTF_KIND_DECL_TAG=yes],
|
||||
[HAVE_BTF_KIND_DECL_TAG=no],
|
||||
[#include <bpf/btf.h>])
|
||||
if test x$HAVE_BTF_KIND_DECL_TAG = xyes; then
|
||||
AC_DEFINE([WITH_BTF_KIND_DECL_TAG], 1,
|
||||
[The BTF_KIND_DECL_TAG enumerator is present])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Check for dependency: libxml
|
||||
LIBXML2_VERSION=2.6.22
|
||||
PKG_CHECK_MODULES(XML, libxml-2.0 >= $LIBXML2_VERSION)
|
||||
@ -741,7 +818,7 @@ AX_VALGRIND_CHECK
|
||||
|
||||
dnl Set the list of libraries libabigail depends on
|
||||
|
||||
DEPS_LIBS="$XML_LIBS $ELF_LIBS $DW_LIBS $CTF_LIBS"
|
||||
DEPS_LIBS="$XML_LIBS $ELF_LIBS $DW_LIBS $CTF_LIBS $BPF_LIBS"
|
||||
AC_SUBST(DEPS_LIBS)
|
||||
|
||||
if test x$ABIGAIL_DEVEL != x; then
|
||||
@ -782,6 +859,7 @@ fi
|
||||
dnl Set a few Automake conditionals
|
||||
|
||||
AM_CONDITIONAL([CTF_READER],[test "x$ENABLE_CTF" = "xyes"])
|
||||
AM_CONDITIONAL([BTF_READER],[test "x$ENABLE_BTF" = "xyes"])
|
||||
|
||||
dnl Set the level of C++ standard we use.
|
||||
CXXFLAGS="$CXXFLAGS -std=$CXX_STANDARD"
|
||||
@ -1092,6 +1170,7 @@ AC_MSG_NOTICE([
|
||||
Enable fedabipkgdiff : ${ENABLE_FEDABIPKGDIFF}
|
||||
Enable python 3 : ${ENABLE_PYTHON3}
|
||||
Enable CTF front-end : ${ENABLE_CTF}
|
||||
Enable BTF front-end : ${ENABLE_BTF}
|
||||
Enable running tests under Valgrind : ${enable_valgrind}
|
||||
Enable build with -fsanitize=address : ${ENABLE_ASAN}
|
||||
Enable build with -fsanitize=memory : ${ENABLE_MSAN}
|
||||
|
@ -16,8 +16,9 @@ For a comprehensive ABI change report between two input shared
|
||||
libraries that includes changes about function and variable sub-types,
|
||||
``abidiff`` uses by default, debug information in `DWARF`_ format, if
|
||||
present, otherwise it compares interfaces using debug information in
|
||||
`CTF`_ format, if present, finally, if neither is found, it uses only
|
||||
`ELF`_ symbols to report which of them were added or removed.
|
||||
`CTF`_ or `BTF`_ formats, if present. Finally, if no debug info in
|
||||
these formats is found, it only considers `ELF`_ symbols and report
|
||||
about their addition or removal.
|
||||
|
||||
.. include:: tools-use-libabigail.txt
|
||||
|
||||
@ -605,6 +606,11 @@ Options
|
||||
When comparing binaries, extract ABI information from `CTF`_ debug
|
||||
information, if present.
|
||||
|
||||
* ``--btf``
|
||||
|
||||
When comparing binaries, extract ABI information from `BTF`_ debug
|
||||
information, if present.
|
||||
|
||||
* ``--stats``
|
||||
|
||||
Emit statistics about various internal things.
|
||||
@ -830,6 +836,7 @@ Usage examples
|
||||
.. _ELF: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
.. _DWARF: http://www.dwarfstd.org
|
||||
.. _CTF: https://raw.githubusercontent.com/wiki/oracle/binutils-gdb/files/ctf-spec.pdf
|
||||
.. _BTF: https://docs.kernel.org/bpf/btf.html
|
||||
.. _ODR: https://en.wikipedia.org/wiki/One_Definition_Rule
|
||||
.. _One Definition Rule: https://en.wikipedia.org/wiki/One_Definition_Rule
|
||||
.. _DWZ: https://sourceware.org/dwz
|
||||
|
@ -21,10 +21,10 @@ functions and variables, along with a complete representation of their
|
||||
types.
|
||||
|
||||
To generate either ABI or KMI representation, by default ``abidw``
|
||||
uses debug information in `DWARF`_ format, if present, otherwise it
|
||||
looks for debug information in `CTF`_ format, if present, finally, if
|
||||
neither is found, it uses only `ELF`_ symbols to report which of them
|
||||
were added or removed.
|
||||
uses debug information in the `DWARF`_ format, if present, otherwise
|
||||
it looks for debug information in `CTF`_ or `BTF`_formats, if present.
|
||||
Finally, if no debug info in these formats is found, it only considers
|
||||
`ELF`_ symbols and report about their addition or removal.
|
||||
|
||||
.. include:: tools-use-libabigail.txt
|
||||
|
||||
@ -389,6 +389,7 @@ standard `here
|
||||
.. _GNU: http://www.gnu.org
|
||||
.. _Linux Kernel: https://kernel.org/
|
||||
.. _CTF: https://raw.githubusercontent.com/wiki/oracle/binutils-gdb/files/ctf-spec.pdf
|
||||
.. _BTF: https://docs.kernel.org/bpf/btf.html
|
||||
.. _ODR: https://en.wikipedia.org/wiki/One_Definition_Rule
|
||||
.. _One Definition Rule: https://en.wikipedia.org/wiki/One_Definition_Rule
|
||||
.. _DWZ: https://sourceware.org/dwz
|
||||
|
@ -13,17 +13,17 @@ binaries.
|
||||
For a comprehensive ABI change report that includes changes about
|
||||
function and variable sub-types, the two input packages must be
|
||||
accompanied with their debug information packages that contain debug
|
||||
information either in `DWARF`_ or in `CTF`_ formats. Please note
|
||||
however that some packages contain binaries that embed the debug
|
||||
information either in `DWARF`_, `CTF`_ or in `BTF`_ formats. Please
|
||||
note however that some packages contain binaries that embed the debug
|
||||
information directly in a section of said binaries. In those cases,
|
||||
obviously, no separate debug information package is needed as the tool
|
||||
will find the debug information inside the binaries.
|
||||
|
||||
By default, ``abipkgdiff`` uses debug information in `DWARF`_ format,
|
||||
if present, otherwise it compares binaries interfaces using debug
|
||||
information in `CTF`_ format, if present, finally, if neither is
|
||||
found, it uses only `ELF`_ symbols to report which of them were added
|
||||
or removed.
|
||||
information in `CTF`_ or in `BTF`_ formats, if present. Finally, if no
|
||||
debug info in these formats is found, it only considers `ELF`_ symbols
|
||||
and report about their addition or removal.
|
||||
|
||||
.. include:: tools-use-libabigail.txt
|
||||
|
||||
@ -554,6 +554,11 @@ Options
|
||||
This is used to compare packages with `CTF`_ debug information,
|
||||
if present.
|
||||
|
||||
* ``--btf``
|
||||
|
||||
This is used to compare packages with `BTF`_ debug information,
|
||||
if present.
|
||||
|
||||
.. _abipkgdiff_return_value_label:
|
||||
|
||||
Return value
|
||||
@ -573,6 +578,7 @@ In the later case, the value of the exit code is the same as for the
|
||||
.. _tar: https://en.wikipedia.org/wiki/Tar_%28computing%29
|
||||
.. _DWARF: http://www.dwarfstd.org
|
||||
.. _CTF: https://raw.githubusercontent.com/wiki/oracle/binutils-gdb/files/ctf-spec.pdf
|
||||
.. _BTF: https://docs.kernel.org/bpf/btf.html
|
||||
.. _Development Package: https://fedoraproject.org/wiki/Packaging:Guidelines?rd=Packaging/Guidelines#Devel_Packages
|
||||
.. _ODR: https://en.wikipedia.org/wiki/One_Definition_Rule
|
||||
.. _One Definition Rule: https://en.wikipedia.org/wiki/One_Definition_Rule
|
||||
|
@ -74,10 +74,11 @@ functions and variables) between the Kernel and its modules. In
|
||||
practice, though, some users might want to compare a subset of the
|
||||
those interfaces.
|
||||
|
||||
By default, ``kmidiff`` uses debug information in `DWARF`_ format,
|
||||
if present, otherwise it compares interfaces using debug information
|
||||
in `CTF`_ format, if present, finally, if neither is found, it uses
|
||||
only `ELF`_ symbols to report which were added or removed.
|
||||
By default, ``kmidiff`` uses debug information in the `DWARF`_ debug
|
||||
info format, if present, otherwise it compares interfaces using `CTF`_
|
||||
or `BTF`_ debug info formats, if present. Finally, if no debug info
|
||||
in these formats is found, it only considers `ELF`_ symbols and report
|
||||
about their addition or removal.
|
||||
|
||||
Users can then define a "white list" of the interfaces to compare.
|
||||
Such a white list is a just a file in the "INI" format that looks
|
||||
@ -179,8 +180,13 @@ Options
|
||||
|
||||
* ``--ctf``
|
||||
|
||||
Extract ABI information from `CTF`_ debug information, if present in
|
||||
the Kernel and Modules.
|
||||
Extract ABI information from `CTF`_ debug information, if present,
|
||||
in the Kernel and Modules.
|
||||
|
||||
* ``--btf``
|
||||
|
||||
Extract ABI information from `BTF`_ debug information, if present,
|
||||
in the Kernel and Modules.
|
||||
|
||||
* ``--impacted-interfaces | -i``
|
||||
|
||||
@ -249,3 +255,4 @@ Options
|
||||
.. _Linux Kernel: https://kernel.org
|
||||
.. _DWARF: http://www.dwarfstd.org
|
||||
.. _CTF: https://raw.githubusercontent.com/wiki/oracle/binutils-gdb/files/ctf-spec.pdf
|
||||
.. _BTF: https://docs.kernel.org/bpf/btf.html
|
||||
|
@ -34,4 +34,8 @@ if CTF_READER
|
||||
pkginclude_HEADERS += abg-ctf-reader.h
|
||||
endif
|
||||
|
||||
if BTF_READER
|
||||
pkginclude_HEADERS += abg-btf-reader.h
|
||||
endif
|
||||
|
||||
EXTRA_DIST = abg-version.h.in
|
||||
|
34
include/abg-btf-reader.h
Normal file
34
include/abg-btf-reader.h
Normal file
@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// -*- Mode: C++ -*-
|
||||
//
|
||||
// Copyright (C) 2022 Red Hat, Inc.
|
||||
//
|
||||
// Author: Dodji Seketeli
|
||||
|
||||
/// @file
|
||||
///
|
||||
/// This file contains the declarations of the front-end to analyze the
|
||||
/// BTF information contained in an ELF file.
|
||||
|
||||
#ifndef __ABG_BTF_READER_H__
|
||||
#define __ABG_BTF_READER_H__
|
||||
|
||||
#include "abg-elf-based-reader.h"
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
|
||||
namespace btf
|
||||
{
|
||||
|
||||
elf_based_reader_sptr
|
||||
create_reader(const std::string& elf_path,
|
||||
const vector<char**>& debug_info_root_paths,
|
||||
environment& env,
|
||||
bool load_all_types = false,
|
||||
bool linux_kernel_mode = false);
|
||||
|
||||
}//end namespace btf
|
||||
}//end namespace abigail
|
||||
|
||||
#endif //__ABG_BTF_READER_H__
|
@ -48,7 +48,8 @@ public:
|
||||
ELF_ORIGIN = 1 << 1,
|
||||
DWARF_ORIGIN = 1 << 2,
|
||||
CTF_ORIGIN = 1 << 3,
|
||||
LINUX_KERNEL_BINARY_ORIGIN = 1 << 4
|
||||
BTF_ORIGIN = 1 << 4,
|
||||
LINUX_KERNEL_BINARY_ORIGIN = 1 << 5
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -97,6 +97,9 @@ class reader : public fe_iface
|
||||
bool
|
||||
has_ctf_debug_info() const;
|
||||
|
||||
bool
|
||||
has_btf_debug_info() const;
|
||||
|
||||
const Dwarf*
|
||||
alternate_dwarf_debug_info() const;
|
||||
|
||||
@ -118,6 +121,9 @@ class reader : public fe_iface
|
||||
const Elf_Scn*
|
||||
find_alternate_ctf_section() const;
|
||||
|
||||
const Elf_Scn*
|
||||
find_btf_section() const;
|
||||
|
||||
const vector<string>&
|
||||
dt_needed()const;
|
||||
|
||||
|
@ -41,6 +41,8 @@ bool file_has_dwarf_debug_info(const string& elf_file_path,
|
||||
const vector<char**>& debug_info_root_paths);
|
||||
bool file_has_ctf_debug_info(const string& elf_file_path,
|
||||
const vector<char**>& debug_info_root_paths);
|
||||
bool file_has_btf_debug_info(const string& elf_file_path,
|
||||
const vector<char**>& debug_info_root_paths);
|
||||
bool is_dir(const string&);
|
||||
bool dir_exists(const string&);
|
||||
bool dir_is_empty(const string &);
|
||||
|
@ -48,6 +48,10 @@ if CTF_READER
|
||||
libabigail_la_SOURCES += abg-ctf-reader.cc
|
||||
endif
|
||||
|
||||
if BTF_READER
|
||||
libabigail_la_SOURCES += abg-btf-reader.cc
|
||||
endif
|
||||
|
||||
libabigail_la_LIBADD = $(DEPS_LIBS) $(FTS_LIBS)
|
||||
libabigail_la_LDFLAGS = -lpthread -Wl,--as-needed -no-undefined -version-info $(LIBABIGAIL_SO_CURRENT):$(LIBABIGAIL_SO_REVISION):$(LIBABIGAIL_SO_AGE)
|
||||
|
||||
|
1102
src/abg-btf-reader.cc
Normal file
1102
src/abg-btf-reader.cc
Normal file
File diff suppressed because it is too large
Load Diff
@ -274,6 +274,7 @@ struct reader::priv
|
||||
int alt_ctf_fd = 0;
|
||||
Elf* alt_ctf_handle = nullptr;
|
||||
Elf_Scn* alt_ctf_section = nullptr;
|
||||
Elf_Scn* btf_section = nullptr;
|
||||
|
||||
priv(reader& reeder, const std::string& elf_path,
|
||||
const vector<char**>& debug_info_roots)
|
||||
@ -602,6 +603,13 @@ bool
|
||||
reader::has_ctf_debug_info() const
|
||||
{return (priv_->ctf_section != nullptr);}
|
||||
|
||||
/// Test if the binary has BTF debug info.
|
||||
///
|
||||
/// @return true iff the binary has BTF debug info
|
||||
bool
|
||||
reader::has_btf_debug_info() const
|
||||
{return (priv_->btf_section != nullptr);}
|
||||
|
||||
/// Getter of the handle use to access DWARF information from the
|
||||
/// alternate split DWARF information.
|
||||
///
|
||||
@ -697,6 +705,20 @@ reader::find_alternate_ctf_section() const
|
||||
return priv_->alt_ctf_section;
|
||||
}
|
||||
|
||||
/// Find and return a pointer to the BTF section of the current ELF
|
||||
/// file.
|
||||
///
|
||||
/// @return a pointer to the BTF section of the current ELF file.
|
||||
const Elf_Scn*
|
||||
reader::find_btf_section() const
|
||||
{
|
||||
if (priv_->btf_section == nullptr)
|
||||
priv_->btf_section =
|
||||
elf_helpers::find_section(priv_->elf_handle,
|
||||
".BTF", SHT_PROGBITS);
|
||||
return priv_->btf_section;
|
||||
}
|
||||
|
||||
/// Get the value of the DT_NEEDED property of the current ELF file.
|
||||
///
|
||||
/// @return the value of the DT_NEEDED property.
|
||||
|
@ -47,6 +47,9 @@
|
||||
#ifdef WITH_CTF
|
||||
#include "abg-ctf-reader.h"
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
#include "abg-btf-reader.h"
|
||||
#endif
|
||||
#include "abg-internal.h"
|
||||
#include "abg-regex.h"
|
||||
|
||||
@ -504,6 +507,34 @@ file_has_ctf_debug_info(const string& elf_file_path,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Test if an ELF file has BTFG debug info.
|
||||
///
|
||||
/// @param elf_file_path the path to the ELF file to consider.
|
||||
///
|
||||
/// @param debug_info_root a vector of pointer to directory to look
|
||||
/// for debug info, in case the file is associated to split debug
|
||||
/// info. If there is no split debug info then this vector can be
|
||||
/// empty. Note that convert_char_stars_to_char_star_stars() can be
|
||||
/// used to ease the construction of this vector.
|
||||
///
|
||||
/// @return true iff the ELF file at @elf_file_path is an ELF file
|
||||
/// that contains debug info.
|
||||
bool
|
||||
file_has_btf_debug_info(const string& elf_file_path,
|
||||
const vector<char**>& debug_info_root_paths)
|
||||
{
|
||||
if (guess_file_type(elf_file_path) != FILE_TYPE_ELF)
|
||||
return false;
|
||||
|
||||
environment env;
|
||||
elf::reader r(elf_file_path, debug_info_root_paths, env);
|
||||
|
||||
if (r.find_btf_section())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Tests if a given path is a directory or a symbolic link to a
|
||||
/// directory.
|
||||
///
|
||||
@ -2850,6 +2881,13 @@ create_best_elf_based_reader(const string& elf_file_path,
|
||||
#ifdef WITH_CTF
|
||||
if (file_has_ctf_debug_info(elf_file_path, debug_info_root_paths))
|
||||
result = ctf::create_reader(elf_file_path, debug_info_root_paths, env);
|
||||
#endif
|
||||
}
|
||||
else if (requested_fe_kind & corpus::BTF_ORIGIN)
|
||||
{
|
||||
#ifdef WITH_BTF
|
||||
if (file_has_btf_debug_info(elf_file_path, debug_info_root_paths))
|
||||
result = btf::create_reader(elf_file_path, debug_info_root_paths, env);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@ -2862,6 +2900,14 @@ create_best_elf_based_reader(const string& elf_file_path,
|
||||
// front end even if it wasn't formally requested by the user.
|
||||
result = ctf::create_reader(elf_file_path, debug_info_root_paths, env);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BTF
|
||||
if (!file_has_dwarf_debug_info(elf_file_path, debug_info_root_paths)
|
||||
&& file_has_btf_debug_info(elf_file_path, debug_info_root_paths))
|
||||
// The file has BTF debug info and no BTF, let's use the BTF
|
||||
// front-end even if it wasn't formally requested by the user.
|
||||
result = btf::create_reader(elf_file_path, debug_info_root_paths, env);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!result)
|
||||
|
@ -30,6 +30,10 @@ if CTF_READER
|
||||
TESTS += runtestreadctf
|
||||
endif
|
||||
|
||||
if BTF_READER
|
||||
TESTS += runtestreadbtf
|
||||
endif
|
||||
|
||||
# rather cheap tests
|
||||
TESTS+= \
|
||||
runtestabicompat \
|
||||
@ -111,6 +115,13 @@ runtestreadctf_LDADD=libtestreadcommon.la libtestutils.la \
|
||||
runtestreadctf_LDFLAGS=-pthread
|
||||
endif
|
||||
|
||||
if BTF_READER
|
||||
runtestreadbtf_SOURCES=test-read-btf.cc
|
||||
runtestreadbtf_LDADD=libtestreadcommon.la libtestutils.la \
|
||||
$(top_builddir)/src/libabigail.la
|
||||
runtestreadbtf_LDFLAGS=-pthread
|
||||
endif
|
||||
|
||||
runtestannotate_SOURCES=test-annotate.cc
|
||||
runtestannotate_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
|
||||
|
||||
|
@ -242,6 +242,12 @@ test-abidiff-exit/test-rhbz2114909-v0.o \
|
||||
test-abidiff-exit/test-rhbz2114909-v1.cc \
|
||||
test-abidiff-exit/test-rhbz2114909-v1.o \
|
||||
test-abidiff-exit/test-rhbz2114909-report-1.txt \
|
||||
test-abidiff-exit/btf/test0-report-1.txt \
|
||||
test-abidiff-exit/btf/test0-report-2.txt \
|
||||
test-abidiff-exit/btf/test0-v0.c \
|
||||
test-abidiff-exit/btf/test0-v0.o \
|
||||
test-abidiff-exit/btf/test0-v1.c \
|
||||
test-abidiff-exit/btf/test0-v1.o \
|
||||
\
|
||||
test-diff-dwarf/test0-v0.cc \
|
||||
test-diff-dwarf/test0-v0.o \
|
||||
@ -721,6 +727,13 @@ test-read-ctf/test-array-size.abi \
|
||||
test-read-ctf/test-array-size.c \
|
||||
test-read-ctf/test-array-size.o \
|
||||
\
|
||||
test-read-btf/test0.c \
|
||||
test-read-btf/test0.o \
|
||||
test-read-btf/test0.o.abi \
|
||||
test-read-btf/test1.c \
|
||||
test-read-btf/test1.o \
|
||||
test-read-btf/test1.o.abi \
|
||||
\
|
||||
test-annotate/test0.abi \
|
||||
test-annotate/test1.abi \
|
||||
test-annotate/test2.so.abi \
|
||||
|
16
tests/data/test-abidiff-exit/btf/test0-report-1.txt
Normal file
16
tests/data/test-abidiff-exit/btf/test0-report-1.txt
Normal file
@ -0,0 +1,16 @@
|
||||
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
|
||||
Variables changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added variable
|
||||
|
||||
1 function with some indirect sub-type change:
|
||||
|
||||
[C] 'function void fn0(const foo_type*)' has some indirect sub-type changes:
|
||||
return type changed:
|
||||
type name changed from 'void' to 'int'
|
||||
type size changed from 0 to 32 (in bits)
|
||||
mangled name changed from '' to int
|
||||
parameter 1 of type 'const foo_type*' changed:
|
||||
in pointed to type 'const foo_type':
|
||||
entity changed from 'const foo_type' to 'typedef foo_type'
|
||||
type size hasn't changed
|
||||
parameter 2 of type 'int' was added
|
||||
|
53
tests/data/test-abidiff-exit/btf/test0-report-2.txt
Normal file
53
tests/data/test-abidiff-exit/btf/test0-report-2.txt
Normal file
@ -0,0 +1,53 @@
|
||||
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
|
||||
Variables changes summary: 0 Removed, 1 Changed, 0 Added variable
|
||||
|
||||
1 function with some indirect sub-type change:
|
||||
|
||||
[C] 'function void fn0(const foo_type*)' has some indirect sub-type changes:
|
||||
return type changed:
|
||||
type name changed from 'void' to 'int'
|
||||
type size changed from 0 to 32 (in bits)
|
||||
mangled name changed from '' to int
|
||||
parameter 1 of type 'const foo_type*' changed:
|
||||
in pointed to type 'const foo_type':
|
||||
entity changed from 'const foo_type' to 'typedef foo_type'
|
||||
type size hasn't changed
|
||||
parameter 2 of type 'int' was added
|
||||
|
||||
1 Changed variable:
|
||||
|
||||
[C] 'foo_type foos[2]' was changed:
|
||||
type of variable changed:
|
||||
array element type 'struct foo_type' changed:
|
||||
type size hasn't changed
|
||||
2 data member changes:
|
||||
type of 'const int* m0' changed:
|
||||
in pointed to type 'const int':
|
||||
entity changed from 'const int' to 'int'
|
||||
type size hasn't changed
|
||||
type of 'volatile const u_type* m5' changed:
|
||||
in pointed to type 'volatile const u_type':
|
||||
in unqualified underlying type 'typedef u_type':
|
||||
underlying type 'union u_type' changed:
|
||||
type size hasn't changed
|
||||
1 data member insertion:
|
||||
'char* m2'
|
||||
2 data member changes:
|
||||
type of 'ENUM_TYPE* m0' changed:
|
||||
in pointed to type 'typedef ENUM_TYPE':
|
||||
underlying type 'enum ENUM_TYPE' changed:
|
||||
type size hasn't changed
|
||||
1 enumerator insertion:
|
||||
'ENUM_TYPE::E2_ENUM_TYPE' value '2'
|
||||
type of 'ANOTHER_ENUM_TYPE* m1' changed:
|
||||
in pointed to type 'typedef ANOTHER_ENUM_TYPE':
|
||||
underlying type 'enum ANOTHER_ENUM_TYPE' changed:
|
||||
type size hasn't changed
|
||||
1 enumerator insertion:
|
||||
'ANOTHER_ENUM_TYPE::E2_ANOTHER_ENUM_TYPE' value '2'
|
||||
type changed from:
|
||||
union u_type{ENUM_TYPE* m0; ANOTHER_ENUM_TYPE* m1;}
|
||||
to:
|
||||
union u_type{ENUM_TYPE* m0; ANOTHER_ENUM_TYPE* m1; char* m2;}
|
||||
type size hasn't changed
|
||||
|
40
tests/data/test-abidiff-exit/btf/test0-v0.c
Normal file
40
tests/data/test-abidiff-exit/btf/test0-v0.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Compile this to emit BTF debug info with:
|
||||
*
|
||||
* gcc -c -gbtf test0.c
|
||||
*/
|
||||
|
||||
typedef enum ENUM_TYPE
|
||||
{
|
||||
E0_ENUM_TYPE = 0,
|
||||
E1_ENUM_TYPE= 1
|
||||
} ENUM_TYPE;
|
||||
|
||||
typedef enum ANOTHER_ENUM_TYPE
|
||||
{
|
||||
E0_ANOTHER_ENUM_TYPE = 0,
|
||||
E1_ANOTHER_ENUM_TYPE= 1
|
||||
} ANOTHER_ENUM_TYPE;
|
||||
|
||||
typedef union u_type
|
||||
{
|
||||
ENUM_TYPE *m0;
|
||||
ANOTHER_ENUM_TYPE *m1;
|
||||
} u_type;
|
||||
|
||||
typedef struct foo_type
|
||||
{
|
||||
const int *m0;
|
||||
volatile char *m1;
|
||||
unsigned *m2;
|
||||
const volatile unsigned char *m3;
|
||||
float m4[10];
|
||||
volatile const u_type *m5;
|
||||
} foo_type;
|
||||
|
||||
void
|
||||
fn0(const foo_type* p __attribute__((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
struct foo_type foos[2] = {0};
|
BIN
tests/data/test-abidiff-exit/btf/test0-v0.o
Normal file
BIN
tests/data/test-abidiff-exit/btf/test0-v0.o
Normal file
Binary file not shown.
45
tests/data/test-abidiff-exit/btf/test0-v1.c
Normal file
45
tests/data/test-abidiff-exit/btf/test0-v1.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Compile this to emit BTF debug info with:
|
||||
*
|
||||
* gcc -c -gbtf test0.c
|
||||
*/
|
||||
|
||||
typedef enum ENUM_TYPE
|
||||
{
|
||||
E0_ENUM_TYPE = 0,
|
||||
E1_ENUM_TYPE= 1,
|
||||
E2_ENUM_TYPE= 2
|
||||
} ENUM_TYPE;
|
||||
|
||||
typedef enum ANOTHER_ENUM_TYPE
|
||||
{
|
||||
E0_ANOTHER_ENUM_TYPE = 0,
|
||||
E1_ANOTHER_ENUM_TYPE= 1,
|
||||
E2_ANOTHER_ENUM_TYPE= 2
|
||||
} ANOTHER_ENUM_TYPE;
|
||||
|
||||
typedef union u_type
|
||||
{
|
||||
ENUM_TYPE *m0;
|
||||
ANOTHER_ENUM_TYPE *m1;
|
||||
char *m2;
|
||||
} u_type;
|
||||
|
||||
typedef struct foo_type
|
||||
{
|
||||
int *m0;
|
||||
volatile char *m1;
|
||||
unsigned *m2;
|
||||
const volatile unsigned char *m3;
|
||||
float m4[10];
|
||||
volatile const u_type *m5;
|
||||
} foo_type;
|
||||
|
||||
int
|
||||
fn0(foo_type* p, int a)
|
||||
{
|
||||
*p->m0 = a;
|
||||
return a;
|
||||
}
|
||||
|
||||
struct foo_type foos[2] = {0};
|
BIN
tests/data/test-abidiff-exit/btf/test0-v1.o
Normal file
BIN
tests/data/test-abidiff-exit/btf/test0-v1.o
Normal file
Binary file not shown.
40
tests/data/test-read-btf/test0.c
Normal file
40
tests/data/test-read-btf/test0.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Compile this to emit BTF debug info with:
|
||||
*
|
||||
* gcc -c -gbtf test0.c
|
||||
*/
|
||||
|
||||
typedef enum ENUM_TYPE
|
||||
{
|
||||
E0_ENUM_TYPE = 0,
|
||||
E1_ENUM_TYPE= 1
|
||||
} ENUM_TYPE;
|
||||
|
||||
typedef enum ANOTHER_ENUM_TYPE
|
||||
{
|
||||
E0_ANOTHER_ENUM_TYPE = 0,
|
||||
E1_ANOTHER_ENUM_TYPE= 1
|
||||
} ANOTHER_ENUM_TYPE;
|
||||
|
||||
typedef union u_type
|
||||
{
|
||||
ENUM_TYPE *m0;
|
||||
ANOTHER_ENUM_TYPE *m1;
|
||||
} u_type;
|
||||
|
||||
typedef struct foo_type
|
||||
{
|
||||
const int *m0;
|
||||
volatile char *m1;
|
||||
unsigned *m2;
|
||||
const volatile unsigned char *m3;
|
||||
float m4[10];
|
||||
volatile const u_type *m5;
|
||||
} foo_type;
|
||||
|
||||
void
|
||||
fn0(const foo_type* p __attribute__((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
struct foo_type foos[2] = {0};
|
BIN
tests/data/test-read-btf/test0.o
Normal file
BIN
tests/data/test-read-btf/test0.o
Normal file
Binary file not shown.
90
tests/data/test-read-btf/test0.o.abi
Normal file
90
tests/data/test-read-btf/test0.o.abi
Normal file
@ -0,0 +1,90 @@
|
||||
<abi-corpus version='2.1' path='data/test-read-btf/test0.o'>
|
||||
<elf-function-symbols>
|
||||
<elf-symbol name='fn0' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
</elf-function-symbols>
|
||||
<elf-variable-symbols>
|
||||
<elf-symbol name='foos' size='160' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
</elf-variable-symbols>
|
||||
<abi-instr address-size='64'>
|
||||
<type-decl name='char' size-in-bits='8' id='type-id-1'/>
|
||||
<enum-decl name='ANOTHER_ENUM_TYPE' linkage-name='ANOTHER_ENUM_TYPE' id='type-id-2'>
|
||||
<underlying-type type-id='type-id-3'/>
|
||||
<enumerator name='E0_ANOTHER_ENUM_TYPE' value='0'/>
|
||||
<enumerator name='E1_ANOTHER_ENUM_TYPE' value='1'/>
|
||||
</enum-decl>
|
||||
<enum-decl name='ENUM_TYPE' linkage-name='ENUM_TYPE' id='type-id-4'>
|
||||
<underlying-type type-id='type-id-5'/>
|
||||
<enumerator name='E0_ENUM_TYPE' value='0'/>
|
||||
<enumerator name='E1_ENUM_TYPE' value='1'/>
|
||||
</enum-decl>
|
||||
<type-decl name='enum-ANOTHER_ENUM_TYPE-underlying-type-32' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
|
||||
<type-decl name='enum-ENUM_TYPE-underlying-type-32' size-in-bits='32' alignment-in-bits='32' id='type-id-5'/>
|
||||
<type-decl name='float' size-in-bits='32' id='type-id-6'/>
|
||||
<array-type-def dimensions='1' type-id='type-id-6' size-in-bits='320' id='type-id-7'>
|
||||
<subrange length='10' id='type-id-8'/>
|
||||
</array-type-def>
|
||||
<array-type-def dimensions='1' type-id='type-id-9' size-in-bits='1280' id='type-id-10'>
|
||||
<subrange length='2' id='type-id-11'/>
|
||||
</array-type-def>
|
||||
<type-decl name='int' size-in-bits='32' id='type-id-12'/>
|
||||
<class-decl name='foo_type' size-in-bits='640' is-struct='yes' visibility='default' id='type-id-9'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='m0' type-id='type-id-13' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='m1' type-id='type-id-14' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='m2' type-id='type-id-15' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='m3' type-id='type-id-16' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='m4' type-id='type-id-7' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='576'>
|
||||
<var-decl name='m5' type-id='type-id-17' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='ANOTHER_ENUM_TYPE' type-id='type-id-2' id='type-id-18'/>
|
||||
<typedef-decl name='ENUM_TYPE' type-id='type-id-4' id='type-id-19'/>
|
||||
<typedef-decl name='foo_type' type-id='type-id-9' id='type-id-20'/>
|
||||
<typedef-decl name='u_type' type-id='type-id-21' id='type-id-22'/>
|
||||
<union-decl name='u_type' size-in-bits='64' visibility='default' id='type-id-21'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='m0' type-id='type-id-23' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public'>
|
||||
<var-decl name='m1' type-id='type-id-24' visibility='default'/>
|
||||
</data-member>
|
||||
</union-decl>
|
||||
<type-decl name='unsigned char' size-in-bits='8' id='type-id-25'/>
|
||||
<type-decl name='unsigned int' size-in-bits='32' id='type-id-26'/>
|
||||
<pointer-type-def type-id='type-id-18' size-in-bits='64' id='type-id-24'/>
|
||||
<pointer-type-def type-id='type-id-19' size-in-bits='64' id='type-id-23'/>
|
||||
<qualified-type-def type-id='type-id-20' const='yes' id='type-id-27'/>
|
||||
<pointer-type-def type-id='type-id-27' size-in-bits='64' id='type-id-28'/>
|
||||
<qualified-type-def type-id='type-id-12' const='yes' id='type-id-29'/>
|
||||
<pointer-type-def type-id='type-id-29' size-in-bits='64' id='type-id-13'/>
|
||||
<qualified-type-def type-id='type-id-22' const='yes' id='type-id-30'/>
|
||||
<qualified-type-def type-id='type-id-25' const='yes' id='type-id-31'/>
|
||||
<pointer-type-def type-id='type-id-26' size-in-bits='64' id='type-id-15'/>
|
||||
<qualified-type-def type-id='type-id-1' volatile='yes' id='type-id-32'/>
|
||||
<pointer-type-def type-id='type-id-32' size-in-bits='64' id='type-id-14'/>
|
||||
<qualified-type-def type-id='type-id-30' volatile='yes' id='type-id-33'/>
|
||||
<pointer-type-def type-id='type-id-33' size-in-bits='64' id='type-id-17'/>
|
||||
<qualified-type-def type-id='type-id-31' volatile='yes' id='type-id-34'/>
|
||||
<pointer-type-def type-id='type-id-34' size-in-bits='64' id='type-id-16'/>
|
||||
<var-decl name='foos' type-id='type-id-10' mangled-name='foos' visibility='default' elf-symbol-id='foos'/>
|
||||
<function-decl name='fn0' mangled-name='fn0' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fn0'>
|
||||
<parameter type-id='type-id-28' name='p'/>
|
||||
<return type-id='type-id-35'/>
|
||||
</function-decl>
|
||||
<type-decl name='void' id='type-id-35'/>
|
||||
<function-type size-in-bits='64' id='type-id-36'>
|
||||
<parameter type-id='type-id-28' name='p'/>
|
||||
<return type-id='type-id-35'/>
|
||||
</function-type>
|
||||
</abi-instr>
|
||||
</abi-corpus>
|
20
tests/data/test-read-btf/test1.c
Normal file
20
tests/data/test-read-btf/test1.c
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Compile this to emit BTF debug info with:
|
||||
*
|
||||
* gcc -c -gbtf test0.c
|
||||
*/
|
||||
|
||||
struct S;
|
||||
typedef struct S S;
|
||||
|
||||
union U;
|
||||
typedef union U U;
|
||||
|
||||
S*
|
||||
fn0(S* p, U* u)
|
||||
{
|
||||
if (u)
|
||||
;
|
||||
|
||||
return p;
|
||||
}
|
BIN
tests/data/test-read-btf/test1.o
Normal file
BIN
tests/data/test-read-btf/test1.o
Normal file
Binary file not shown.
23
tests/data/test-read-btf/test1.o.abi
Normal file
23
tests/data/test-read-btf/test1.o.abi
Normal file
@ -0,0 +1,23 @@
|
||||
<abi-corpus version='2.1' path='data/test-read-btf/test1.o'>
|
||||
<elf-function-symbols>
|
||||
<elf-symbol name='fn0' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
</elf-function-symbols>
|
||||
<abi-instr address-size='64'>
|
||||
<typedef-decl name='S' type-id='type-id-1' id='type-id-2'/>
|
||||
<typedef-decl name='U' type-id='type-id-3' id='type-id-4'/>
|
||||
<pointer-type-def type-id='type-id-2' size-in-bits='64' id='type-id-5'/>
|
||||
<pointer-type-def type-id='type-id-4' size-in-bits='64' id='type-id-6'/>
|
||||
<function-decl name='fn0' mangled-name='fn0' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fn0'>
|
||||
<parameter type-id='type-id-5' name='p'/>
|
||||
<parameter type-id='type-id-6' name='u'/>
|
||||
<return type-id='type-id-5'/>
|
||||
</function-decl>
|
||||
<class-decl name='S' size-in-bits='48' is-struct='yes' visibility='default' is-declaration-only='yes' id='type-id-1'/>
|
||||
<union-decl name='U' visibility='default' is-declaration-only='yes' id='type-id-3'/>
|
||||
<function-type size-in-bits='64' id='type-id-7'>
|
||||
<parameter type-id='type-id-5' name='p'/>
|
||||
<parameter type-id='type-id-6' name='u'/>
|
||||
<return type-id='type-id-5'/>
|
||||
</function-type>
|
||||
</abi-instr>
|
||||
</abi-corpus>
|
@ -471,6 +471,30 @@ InOutSpec in_out_specs[] =
|
||||
"data/test-abidiff-exit/test-rhbz2114909-report-1.txt",
|
||||
"output/test-abidiff-exit/test-rhbz2114909-report-1.txt"
|
||||
},
|
||||
#ifdef WITH_BTF
|
||||
{
|
||||
"data/test-abidiff-exit/btf/test0-v0.o",
|
||||
"data/test-abidiff-exit/btf/test0-v1.o",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"--no-default-suppression --btf",
|
||||
abigail::tools_utils::ABIDIFF_ABI_CHANGE,
|
||||
"data/test-abidiff-exit/btf/test0-report-1.txt",
|
||||
"output/test-abidiff-exit/btf/test0-report-1.txt"
|
||||
},
|
||||
{
|
||||
"data/test-abidiff-exit/btf/test0-v0.o",
|
||||
"data/test-abidiff-exit/btf/test0-v1.o",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"--no-default-suppression --harmless --btf",
|
||||
abigail::tools_utils::ABIDIFF_ABI_CHANGE,
|
||||
"data/test-abidiff-exit/btf/test0-report-2.txt",
|
||||
"output/test-abidiff-exit/btf/test0-report-2.txt"
|
||||
},
|
||||
#endif
|
||||
{0, 0, 0 ,0, 0, 0, abigail::tools_utils::ABIDIFF_OK, 0, 0}
|
||||
};
|
||||
|
||||
|
188
tests/test-read-btf.cc
Normal file
188
tests/test-read-btf.cc
Normal file
@ -0,0 +1,188 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// -*- Mode: C++ -*-
|
||||
//
|
||||
// Copyright (C) 2022 Red Hat, Inc.
|
||||
//
|
||||
// Author: Dodji Seketeli
|
||||
|
||||
/// @file
|
||||
///
|
||||
/// This file is part of the BTF testsuite. It reads ELF binaries
|
||||
/// containing BTF, save them in XML corpus files and diff the
|
||||
/// corpus files against reference XML corpus files.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "abg-btf-reader.h"
|
||||
#include "test-read-common.h"
|
||||
|
||||
using std::string;
|
||||
using std::cerr;
|
||||
using std::vector;
|
||||
|
||||
using abigail::tests::read_common::InOutSpec;
|
||||
using abigail::tests::read_common::test_task;
|
||||
using abigail::tests::read_common::display_usage;
|
||||
using abigail::tests::read_common::options;
|
||||
|
||||
using abigail::btf::create_reader;
|
||||
using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE;
|
||||
using abigail::xml_writer::HASH_TYPE_ID_STYLE;
|
||||
using abigail::tools_utils::emit_prefix;
|
||||
|
||||
static InOutSpec in_out_specs[] =
|
||||
{
|
||||
{
|
||||
"data/test-read-btf/test0.o",
|
||||
"",
|
||||
"",
|
||||
SEQUENCE_TYPE_ID_STYLE,
|
||||
"data/test-read-btf/test0.o.abi",
|
||||
"output/test-read-btf/test0.o.abi",
|
||||
"--btf",
|
||||
},
|
||||
{
|
||||
"data/test-read-btf/test1.o",
|
||||
"",
|
||||
"",
|
||||
SEQUENCE_TYPE_ID_STYLE,
|
||||
"data/test-read-btf/test1.o.abi",
|
||||
"output/test-read-btf/test1.o.abi",
|
||||
"--btf",
|
||||
},
|
||||
// This should be the last entry.
|
||||
{NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/// Task specialization to perform BTF tests.
|
||||
struct test_task_btf : public test_task
|
||||
{
|
||||
test_task_btf(const InOutSpec &s,
|
||||
string& a_out_abi_base,
|
||||
string& a_in_elf_base,
|
||||
string& a_in_abi_base);
|
||||
virtual void
|
||||
perform();
|
||||
|
||||
virtual
|
||||
~test_task_btf()
|
||||
{}
|
||||
}; // end struct test_task_btf
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// Task to be executed for each BTF test entry in @ref
|
||||
/// abigail::tests::read_common::InOutSpec.
|
||||
/// @param InOutSpec the array containing set of tests.
|
||||
///
|
||||
/// @param a_out_abi_base the output base directory for abixml files.
|
||||
///
|
||||
/// @param a_in_elf_base the input base directory for object files.
|
||||
///
|
||||
/// @param a_in_elf_base the input base directory for expected
|
||||
/// abixml files.
|
||||
test_task_btf::test_task_btf(const InOutSpec &s,
|
||||
string& a_out_abi_base,
|
||||
string& a_in_elf_base,
|
||||
string& a_in_abi_base)
|
||||
: test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
|
||||
{}
|
||||
|
||||
/// The thread function to execute each BTF test entry in @ref
|
||||
/// abigail::tests::read_common::InOutSpec.
|
||||
///
|
||||
/// This reads the corpus into memory, saves it to disk, loads it
|
||||
/// again and compares the new in-memory representation against the
|
||||
void
|
||||
test_task_btf::perform()
|
||||
{
|
||||
abigail::ir::environment env;
|
||||
|
||||
set_in_elf_path();
|
||||
set_in_suppr_spec_path();
|
||||
|
||||
abigail::fe_iface::status status =
|
||||
abigail::fe_iface::STATUS_UNKNOWN;
|
||||
vector<char**> di_roots;
|
||||
ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path));
|
||||
|
||||
abigail::elf_based_reader_sptr rdr = abigail::btf::create_reader(in_elf_path,
|
||||
di_roots, env);
|
||||
ABG_ASSERT(rdr);
|
||||
|
||||
corpus_sptr corp = rdr->read_corpus(status);
|
||||
|
||||
// if there is no output and no input, assume that we do not care about the
|
||||
// actual read result, just that it succeeded.
|
||||
if (!spec.in_abi_path && !spec.out_abi_path)
|
||||
{
|
||||
// Phew! we made it here and we did not crash! yay!
|
||||
return;
|
||||
}
|
||||
if (!corp)
|
||||
{
|
||||
error_message = string("failed to read ") + in_elf_path + "\n";
|
||||
is_ok = false;
|
||||
return;
|
||||
}
|
||||
corp->set_path(spec.in_elf_path);
|
||||
// Do not take architecture names in comparison so that these
|
||||
// test input binaries can come from whatever arch the
|
||||
// programmer likes.
|
||||
corp->set_architecture_name("");
|
||||
|
||||
if (!(is_ok = set_out_abi_path()))
|
||||
return;
|
||||
|
||||
if (!(is_ok = serialize_corpus(out_abi_path, corp)))
|
||||
return;
|
||||
|
||||
if (!(is_ok = run_abidw("--btf ")))
|
||||
return;
|
||||
|
||||
if (!(is_ok = run_diff()))
|
||||
return;
|
||||
}
|
||||
|
||||
/// Create a new BTF instance for task to be execute by the testsuite.
|
||||
///
|
||||
/// @param s the @ref abigail::tests::read_common::InOutSpec
|
||||
/// tests container.
|
||||
///
|
||||
/// @param a_out_abi_base the output base directory for abixml files.
|
||||
///
|
||||
/// @param a_in_elf_base the input base directory for object files.
|
||||
///
|
||||
/// @param a_in_abi_base the input base directory for abixml files.
|
||||
///
|
||||
/// @return abigail::tests::read_common::test_task instance.
|
||||
static test_task*
|
||||
new_task(const InOutSpec* s, string& a_out_abi_base,
|
||||
string& a_in_elf_base, string& a_in_abi_base)
|
||||
{
|
||||
return new test_task_btf(*s, a_out_abi_base,
|
||||
a_in_elf_base, a_in_abi_base);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
options opts;
|
||||
if (!parse_command_line(argc, argv, opts))
|
||||
{
|
||||
if (!opts.wrong_option.empty())
|
||||
emit_prefix(argv[0], cerr)
|
||||
<< "unrecognized option: " << opts.wrong_option << "\n";
|
||||
display_usage(argv[0], cerr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// compute number of tests to be executed.
|
||||
const size_t num_tests = sizeof(in_out_specs) / sizeof(InOutSpec) - 1;
|
||||
|
||||
return run_tests(num_tests, in_out_specs, opts, new_task);
|
||||
}
|
@ -23,6 +23,10 @@
|
||||
#include "abg-ctf-reader.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BTF
|
||||
#include "abg-btf-reader.h"
|
||||
#endif
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::ostream;
|
||||
@ -121,6 +125,9 @@ struct options
|
||||
#endif
|
||||
#ifdef WITH_CTF
|
||||
bool use_ctf;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
bool use_btf;
|
||||
#endif
|
||||
vector<char*> di_root_paths1;
|
||||
vector<char*> di_root_paths2;
|
||||
@ -170,6 +177,10 @@ struct options
|
||||
,
|
||||
use_ctf()
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
,
|
||||
use_btf()
|
||||
#endif
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
,
|
||||
do_debug_self_comparison()
|
||||
@ -273,6 +284,9 @@ display_usage(const string& prog_name, ostream& out)
|
||||
#ifdef WITH_CTF
|
||||
<< " --ctf use CTF instead of DWARF in ELF files\n"
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
<< " --btf use BTF instead of DWARF in ELF files\n"
|
||||
#endif
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
<< " --debug-self-comparison debug the process of comparing "
|
||||
"an ABI corpus against itself"
|
||||
@ -639,6 +653,10 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
else if (!strcmp(argv[i], "--ctf"))
|
||||
opts.use_ctf = true;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
else if (!strcmp(argv[i], "--btf"))
|
||||
opts.use_btf = true;
|
||||
#endif
|
||||
#ifdef WITH_DEBUG_SELF_COMPARISON
|
||||
else if (!strcmp(argv[i], "--debug-self-comparison"))
|
||||
opts.do_debug_self_comparison = true;
|
||||
@ -1232,6 +1250,10 @@ main(int argc, char* argv[])
|
||||
#ifdef WITH_CTF
|
||||
if (opts.use_ctf)
|
||||
requested_fe_kind = corpus::CTF_ORIGIN;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
requested_fe_kind = corpus::BTF_ORIGIN;
|
||||
#endif
|
||||
abigail::elf_based_reader_sptr rdr =
|
||||
create_best_elf_based_reader(opts.file1,
|
||||
@ -1305,6 +1327,10 @@ main(int argc, char* argv[])
|
||||
#ifdef WITH_CTF
|
||||
if (opts.use_ctf)
|
||||
requested_fe_kind = corpus::CTF_ORIGIN;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
requested_fe_kind = corpus::BTF_ORIGIN;
|
||||
#endif
|
||||
abigail::elf_based_reader_sptr rdr =
|
||||
create_best_elf_based_reader(opts.file2,
|
||||
|
@ -29,6 +29,9 @@
|
||||
#ifdef WITH_CTF
|
||||
#include "abg-ctf-reader.h"
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
#include "abg-btf-reader.h"
|
||||
#endif
|
||||
#include "abg-writer.h"
|
||||
#include "abg-reader.h"
|
||||
#include "abg-comparison.h"
|
||||
@ -103,6 +106,9 @@ struct options
|
||||
bool noout;
|
||||
#ifdef WITH_CTF
|
||||
bool use_ctf;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
bool use_btf;
|
||||
#endif
|
||||
bool show_locs;
|
||||
bool abidiff;
|
||||
@ -144,6 +150,9 @@ struct options
|
||||
noout(),
|
||||
#ifdef WITH_CTF
|
||||
use_ctf(false),
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
use_btf(false),
|
||||
#endif
|
||||
show_locs(true),
|
||||
abidiff(),
|
||||
@ -234,6 +243,9 @@ display_usage(const string& prog_name, ostream& out)
|
||||
"speed-up the analysis of the binary\n"
|
||||
<< " --no-assume-odr-for-cplusplus do not assume the ODR to speed-up the "
|
||||
"analysis of the binary\n"
|
||||
#ifdef WITH_BTF
|
||||
<< " --btf use BTF instead of DWARF in ELF files\n"
|
||||
#endif
|
||||
<< " --annotate annotate the ABI artifacts emitted in the output\n"
|
||||
<< " --stats show statistics about various internal stuff\n"
|
||||
<< " --verbose show verbose messages about internal stuff\n";
|
||||
@ -335,6 +347,10 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
#ifdef WITH_CTF
|
||||
else if (!strcmp(argv[i], "--ctf"))
|
||||
opts.use_ctf = true;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
else if (!strcmp(argv[i], "--btf"))
|
||||
opts.use_btf = true;
|
||||
#endif
|
||||
else if (!strcmp(argv[i], "--no-architecture"))
|
||||
opts.write_architecture = false;
|
||||
@ -588,6 +604,10 @@ load_corpus_and_write_abixml(char* argv[],
|
||||
if (opts.use_ctf)
|
||||
requested_fe_kind = corpus::CTF_ORIGIN;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
requested_fe_kind = corpus::BTF_ORIGIN;
|
||||
#endif
|
||||
|
||||
// First of all, create a reader to read the ABI from the file
|
||||
// specfied in opts ...
|
||||
|
@ -93,6 +93,9 @@
|
||||
#ifdef WITH_CTF
|
||||
#include "abg-ctf-reader.h"
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
#include "abg-btf-reader.h"
|
||||
#endif
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
@ -212,6 +215,9 @@ public:
|
||||
#ifdef WITH_CTF
|
||||
bool use_ctf;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
bool use_btf;
|
||||
#endif
|
||||
|
||||
vector<string> kabi_whitelist_packages;
|
||||
vector<string> suppression_paths;
|
||||
@ -256,6 +262,10 @@ public:
|
||||
#ifdef WITH_CTF
|
||||
,
|
||||
use_ctf()
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
,
|
||||
use_btf()
|
||||
#endif
|
||||
{
|
||||
// set num_workers to the default number of threads of the
|
||||
@ -905,6 +915,9 @@ display_usage(const string& prog_name, ostream& out)
|
||||
"binaries inside the input package against their ABIXML representation\n"
|
||||
#ifdef WITH_CTF
|
||||
<< " --ctf use CTF instead of DWARF in ELF files\n"
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
<< " --btf use BTF instead of DWARF in ELF files\n"
|
||||
#endif
|
||||
<< " --help|-h display this help message\n"
|
||||
<< " --version|-v display program version information"
|
||||
@ -1353,6 +1366,10 @@ compare(const elf_file& elf1,
|
||||
#ifdef WITH_CTF
|
||||
if (opts.use_ctf)
|
||||
requested_fe_kind = corpus::CTF_ORIGIN;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
requested_fe_kind = corpus::BTF_ORIGIN;
|
||||
#endif
|
||||
abigail::elf_based_reader_sptr reader =
|
||||
create_best_elf_based_reader(elf1.path,
|
||||
@ -1414,6 +1431,11 @@ compare(const elf_file& elf1,
|
||||
if (opts.use_ctf)
|
||||
;
|
||||
else
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
;
|
||||
else
|
||||
#endif
|
||||
reader->refers_to_alt_debug_info(alt_di_path);
|
||||
if (!alt_di_path.empty())
|
||||
@ -1449,10 +1471,16 @@ compare(const elf_file& elf1,
|
||||
corpus_sptr corpus2;
|
||||
{
|
||||
corpus::origin requested_fe_kind = corpus::DWARF_ORIGIN;
|
||||
|
||||
#ifdef WITH_CTF
|
||||
if (opts.use_ctf)
|
||||
requested_fe_kind = corpus::CTF_ORIGIN;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
requested_fe_kind = corpus::BTF_ORIGIN;
|
||||
#endif
|
||||
|
||||
abigail::elf_based_reader_sptr reader =
|
||||
create_best_elf_based_reader(elf2.path,
|
||||
di_dirs2,
|
||||
@ -1513,6 +1541,11 @@ compare(const elf_file& elf1,
|
||||
if (opts.use_ctf)
|
||||
;
|
||||
else
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
;
|
||||
else
|
||||
#endif
|
||||
reader->refers_to_alt_debug_info(alt_di_path);
|
||||
if (!alt_di_path.empty())
|
||||
@ -1617,6 +1650,10 @@ compare_to_self(const elf_file& elf,
|
||||
#ifdef WITH_CTF
|
||||
if (opts.use_ctf)
|
||||
requested_fe_kind = corpus::CTF_ORIGIN;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
requested_fe_kind = corpus::BTF_ORIGIN;
|
||||
#endif
|
||||
abigail::elf_based_reader_sptr reader =
|
||||
create_best_elf_based_reader(elf.path,
|
||||
@ -3044,14 +3081,24 @@ compare_prepared_linux_kernel_packages(package& first_package,
|
||||
|
||||
suppressions_type supprs;
|
||||
corpus_group_sptr corpus1, corpus2;
|
||||
|
||||
corpus::origin requested_fe_kind = corpus::DWARF_ORIGIN;
|
||||
#ifdef WITH_CTF
|
||||
if (opts.use_ctf)
|
||||
requested_fe_kind = corpus::CTF_ORIGIN;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
requested_fe_kind = corpus::BTF_ORIGIN;
|
||||
#endif
|
||||
|
||||
corpus1 = build_corpus_group_from_kernel_dist_under(dist_root1,
|
||||
debug_dir1,
|
||||
vmlinux_path1,
|
||||
opts.suppression_paths,
|
||||
opts.kabi_whitelist_paths,
|
||||
supprs,
|
||||
opts.verbose,
|
||||
env);
|
||||
supprs, opts.verbose,
|
||||
env, requested_fe_kind);
|
||||
|
||||
if (!corpus1)
|
||||
return abigail::tools_utils::ABIDIFF_ERROR;
|
||||
@ -3061,9 +3108,8 @@ compare_prepared_linux_kernel_packages(package& first_package,
|
||||
vmlinux_path2,
|
||||
opts.suppression_paths,
|
||||
opts.kabi_whitelist_paths,
|
||||
supprs,
|
||||
opts.verbose,
|
||||
env);
|
||||
supprs, opts.verbose,
|
||||
env, requested_fe_kind);
|
||||
|
||||
if (!corpus2)
|
||||
return abigail::tools_utils::ABIDIFF_ERROR;
|
||||
@ -3434,6 +3480,10 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
#ifdef WITH_CTF
|
||||
else if (!strcmp(argv[i], "--ctf"))
|
||||
opts.use_ctf = true;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
else if (!strcmp(argv[i], "--btf"))
|
||||
opts.use_btf = true;
|
||||
#endif
|
||||
else if (!strcmp(argv[i], "--help")
|
||||
|| !strcmp(argv[i], "-h"))
|
||||
|
@ -63,6 +63,9 @@ struct options
|
||||
optional<bool> exported_interfaces_only;
|
||||
#ifdef WITH_CTF
|
||||
bool use_ctf;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
bool use_btf;
|
||||
#endif
|
||||
string wrong_option;
|
||||
string kernel_dist_root1;
|
||||
@ -88,6 +91,10 @@ struct options
|
||||
#ifdef WITH_CTF
|
||||
,
|
||||
use_ctf(false)
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
,
|
||||
use_btf(false)
|
||||
#endif
|
||||
{}
|
||||
}; // end struct options.
|
||||
@ -117,6 +124,9 @@ display_usage(const string& prog_name, ostream& out)
|
||||
"whitelist\n"
|
||||
#ifdef WITH_CTF
|
||||
<< " --ctf use CTF instead of DWARF in ELF files\n"
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
<< " --btf use BTF instead of DWARF in ELF files\n"
|
||||
#endif
|
||||
<< " --impacted-interfaces|-i show interfaces impacted by ABI changes\n"
|
||||
<< " --full-impact|-f show the full impact of changes on top-most "
|
||||
@ -259,6 +269,10 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
#ifdef WITH_CTF
|
||||
else if (!strcmp(argv[i], "--ctf"))
|
||||
opts.use_ctf = true;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
else if (!strcmp(argv[i], "--btf"))
|
||||
opts.use_btf = true;
|
||||
#endif
|
||||
else if (!strcmp(argv[i], "--impacted-interfaces")
|
||||
|| !strcmp(argv[i], "-i"))
|
||||
@ -421,11 +435,15 @@ main(int argc, char* argv[])
|
||||
|
||||
corpus_group_sptr group1, group2;
|
||||
string debug_info_root_dir;
|
||||
corpus::origin requested_fe_kind =
|
||||
corpus::origin requested_fe_kind = corpus::DWARF_ORIGIN;
|
||||
#ifdef WITH_CTF
|
||||
opts.use_ctf ? corpus::CTF_ORIGIN :
|
||||
if (opts.use_ctf)
|
||||
requested_fe_kind = corpus::CTF_ORIGIN;
|
||||
#endif
|
||||
#ifdef WITH_BTF
|
||||
if (opts.use_btf)
|
||||
requested_fe_kind = corpus::BTF_ORIGIN;
|
||||
#endif
|
||||
corpus::DWARF_ORIGIN;
|
||||
|
||||
if (!opts.kernel_dist_root1.empty())
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user