From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id C2A2A3850239 for ; Fri, 3 Jun 2022 15:48:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C2A2A3850239 Received: from mail-pf1-f198.google.com (mail-pf1-f198.google.com [209.85.210.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-460-yKdKbo65NJmeZCXz2R0GFw-1; Fri, 03 Jun 2022 11:48:45 -0400 X-MC-Unique: yKdKbo65NJmeZCXz2R0GFw-1 Received: by mail-pf1-f198.google.com with SMTP id t1-20020a62ea01000000b0051be221a3ebso1012776pfh.17 for ; Fri, 03 Jun 2022 08:48:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=TE0ZTe2L1X3d5yq+f8nsRtQi6xLtv+fskzGMbMG2C0A=; b=rPltiv/S5lzlp1IHgpR/vzDboJkXAJ+m2Py2y2Qstym89P5dcr2/NJh5v1t6Z1FR3O NPqIW7QyvUaV0qXmkxUmumdUM4pkFtayXa7VDUTyrsCtiRoO/AUeoHGQ5ga8ljVkXjDx r8rt/OIarZV7TEVKdC7GOyJjCotWbuhf68Awd2HNrDZTfOMCvf8Di2Sq7MyFEsK5ZsVo zeV8wS/qMvSydOsfAEkcOSthOI2eGdxb7o2rZgm11vshxsk7eZYdqy+aZg+2o0Dt50OT ehucgABgM3CbWtPeSZBbisbIt9wgAxVS8eY3LYooMre8a09lOaqrsTz4Ow/IqFfuz9dD 549g== X-Gm-Message-State: AOAM532glzvIilepei7FlVjVd+9vF5Jr5s0BJ5H+S1vD68K0wptsggix ulN1/Zada194nwKbCb82k3AAQS7GpiCkoFnnJhbjXdsuAdZc1Ots+nrS/QrMAp3axAYwigrt2Ch JWJETP8C6eHA759LIA+kmakKmsgnKCe9M0y6NcYTsWCdzUXUCw23E++CafCfTzGy8b5yCiF8= X-Received: by 2002:a17:902:7c0e:b0:162:1aa9:f550 with SMTP id x14-20020a1709027c0e00b001621aa9f550mr10539475pll.159.1654271324060; Fri, 03 Jun 2022 08:48:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz8kCf5afHH2MoTPacKufrOEdrMozhM/ohGOMJXSU3ycEGh8X2XOME7IKPDcDKQBEN8dXHEoQ== X-Received: by 2002:a17:902:7c0e:b0:162:1aa9:f550 with SMTP id x14-20020a1709027c0e00b001621aa9f550mr10539442pll.159.1654271323477; Fri, 03 Jun 2022 08:48:43 -0700 (PDT) Received: from alien.localdomain ([47.208.199.57]) by smtp.gmail.com with ESMTPSA id b82-20020a621b55000000b0051ba8b742e4sm5676296pfb.69.2022.06.03.08.48.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Jun 2022 08:48:42 -0700 (PDT) From: Ben Woodard To: libabigail@sourceware.org Subject: [PATCH] Give abicompat the ability to read CTF and abixml Date: Fri, 3 Jun 2022 08:47:51 -0700 Message-Id: <20220603154750.318114-1-woodard@redhat.com> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libabigail@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list of the Libabigail project List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 03 Jun 2022 15:48:49 -0000 While abidw generates abidw and abidiff can consume that abidw abicompat could only read from ELF objects with DWARF. To bring it in line with the capabilities of abidiff, this patch adds the ability for abicompat to read both abixml and CTF. The reason why being able to handle abixml as well as an ELF file with DWARF is that it allows someone to archive the abixml for an object and use it in place of having to keep the entire object when doing abi compatibility studies. The ability to handle CTF was also in the code that I copied over from abidiff and so I brought it over at the same time. This should be tested more extensively. The make check works and a trivial test using the same object seems to work but I do not have any CTF other binaries around to test against. Also a feature that I asked for a long time ago was to fail if the binaries don't have debug infomation which is needed for proper comparison. This was added to abidiff but it didn't get added to abicompat. Since the code was in the same area, I copied it over from abidiff at the same time. I do not think it makes sense to try to split these three features apart because they are just replicating pre-existing code in a different tool. * tools/abicompat.cc - add abixml and ctf handling, add fail on no debug info option. * doc/manuals/abicompat.rst - add documentation for new options Signed-off-by: Ben Woodard --- doc/manuals/abicompat.rst | 12 +++ tools/abicompat.cc | 171 ++++++++++++++++++++++++++++++-------- 2 files changed, 148 insertions(+), 35 deletions(-) diff --git a/doc/manuals/abicompat.rst b/doc/manuals/abicompat.rst index 6bc56388..e88a05a8 100644 --- a/doc/manuals/abicompat.rst +++ b/doc/manuals/abicompat.rst @@ -77,6 +77,18 @@ Options Do not show information about where in the *second shared library* the respective type was changed. + * ``--ctf`` + + When comparing binaries, extract ABI information from CTF debug + information, if present. + + * ``--fail-no-debug-info`` + + If no debug info was found, then this option makes the program to + fail. Otherwise, without this option, the program will attempt to + compare properties of the binaries that are not related to debug + info, like pure ELF properties. + * ``--ignore-soname`` Ignore differences in the SONAME when doing a comparison diff --git a/tools/abicompat.cc b/tools/abicompat.cc index f4bc384d..8cbce3a1 100644 --- a/tools/abicompat.cc +++ b/tools/abicompat.cc @@ -37,7 +37,9 @@ #include "abg-config.h" #include "abg-tools-utils.h" #include "abg-corpus.h" +#include "abg-reader.h" #include "abg-dwarf-reader.h" +#include "abg-ctf-reader.h" #include "abg-comparison.h" #include "abg-suppression.h" @@ -74,7 +76,11 @@ public: bool redundant_opt_set; bool no_redundant_opt_set; bool show_locs; + bool fail_no_debug_info; bool ignore_soname; +#ifdef WITH_CTF + bool use_ctf; +#endif options(const char* program_name) :prog_name(program_name), @@ -87,7 +93,12 @@ public: redundant_opt_set(), no_redundant_opt_set(), show_locs(true), + fail_no_debug_info(), ignore_soname(false) +#ifdef WITH_CTF + , + use_ctf() +#endif {} }; // end struct options @@ -115,9 +126,13 @@ display_usage(const string& prog_name, ostream& out) << " --no-redundant do not display redundant changes\n" << " --no-show-locs do now show location information\n" << " --ignore-soname do not take the SONAMEs into account\n" + << " --fail-no-debug-info bail out if no debug info was found\n" << " --redundant display redundant changes (this is the default)\n" << " --weak-mode check compatibility between the application and " "just one version of the library.\n" +#ifdef WITH_CTF + << " --ctf use CTF instead of DWARF in ELF files\n" +#endif ; } @@ -211,6 +226,8 @@ parse_command_line(int argc, char* argv[], options& opts) opts.show_locs = false; else if (!strcmp(argv[i], "--ignore-soname")) opts.ignore_soname=true; + else if (!strcmp(argv[i], "--fail-no-debug-info")) + opts.fail_no_debug_info = true; else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) { @@ -219,6 +236,10 @@ parse_command_line(int argc, char* argv[], options& opts) } else if (!strcmp(argv[i], "--weak-mode")) opts.weak_mode = true; +#ifdef WITH_CTF + else if (!strcmp(argv[i], "--ctf")) + opts.use_ctf = true; +#endif else { opts.unknow_option = argv[i]; @@ -251,7 +272,7 @@ using abigail::ir::type_base_sptr; using abigail::ir::function_type_sptr; using abigail::ir::function_decl; using abigail::ir::var_decl; -using abigail::elf_reader::status; +using namespace abigail::elf_reader; using abigail::dwarf_reader::read_corpus_from_elf; using abigail::comparison::diff_context_sptr; using abigail::comparison::diff_context; @@ -617,6 +638,71 @@ perform_compat_check_in_weak_mode(options& opts, return status; } +static corpus_sptr read_corpus(char *exename, bool use_ctf, bool weak_mode, + status &status, const vector di_roots, + const environment_sptr &env, const string &path){ + corpus_sptr retval=NULL; + abigail::tools_utils::file_type type = + abigail::tools_utils::guess_file_type(path); + switch (type) + { + case abigail::tools_utils::FILE_TYPE_UNKNOWN: + emit_prefix(exename, cerr) + << "Unknown content type for file " << path << "\n"; + break; + case abigail::tools_utils::FILE_TYPE_ELF: + { +#ifdef WITH_CTF + if (use_ctf) + { + abigail::ctf_reader::read_context_sptr r_ctxt + = abigail::ctf_reader::create_read_context(path, + env.get()); + ABG_ASSERT(r_ctxt); + + retval = abigail::ctf_reader::read_corpus(r_ctxt.get(), status); + } + else +#endif + { + abigail::dwarf_reader::read_context_sptr r_ctxt = + abigail::dwarf_reader::create_read_context + (path, di_roots, + env.get(), /*read_all_types=*/weak_mode, + false); + assert(r_ctxt); + + // abigail::dwarf_reader::set_show_stats(*r_ctxt, opts.show_stats); + // set_suppressions(*r_ctxt, opts); + // abigail::dwarf_reader::set_do_log(*r_ctxt, opts.do_log); + retval = abigail::dwarf_reader::read_corpus_from_elf(*r_ctxt, status); + } + } + break; + case abigail::tools_utils::FILE_TYPE_XML_CORPUS: + { + abigail::xml_reader::read_context_sptr r_ctxt = + abigail::xml_reader::create_native_xml_read_context(path, env.get()); + assert(r_ctxt); + // set_suppressions(*r_ctxt, opts); + // set_native_xml_reader_options(*r_ctxt, opts); + retval = abigail::xml_reader::read_corpus_from_input(*r_ctxt); + } + break; + case abigail::tools_utils::FILE_TYPE_AR: + case abigail::tools_utils::FILE_TYPE_XML_CORPUS_GROUP: + case abigail::tools_utils::FILE_TYPE_RPM: + case abigail::tools_utils::FILE_TYPE_SRPM: + case abigail::tools_utils::FILE_TYPE_DEB: + case abigail::tools_utils::FILE_TYPE_DIR: + case abigail::tools_utils::FILE_TYPE_TAR: + case abigail::tools_utils::FILE_TYPE_NATIVE_BI: + break; + } + + return retval; +} + int main(int argc, char* argv[]) { @@ -674,15 +760,6 @@ main(int argc, char* argv[]) if (!abigail::tools_utils::check_file(opts.app_path, cerr, opts.prog_name)) return abigail::tools_utils::ABIDIFF_ERROR; - abigail::tools_utils::file_type type = - abigail::tools_utils::guess_file_type(opts.app_path); - if (type != abigail::tools_utils::FILE_TYPE_ELF) - { - emit_prefix(argv[0], cerr) - << opts.app_path << " is not an ELF file\n"; - return abigail::tools_utils::ABIDIFF_ERROR; - } - // Create the context of the diff diff_context_sptr ctxt = create_diff_context(opts); @@ -691,7 +768,7 @@ main(int argc, char* argv[]) suppressions_type& supprs = ctxt->suppressions(); bool files_suppressed = (file_is_suppressed(opts.app_path, supprs) || file_is_suppressed(opts.lib1_path, supprs) - ||file_is_suppressed(opts.lib2_path, supprs)); + || file_is_suppressed(opts.lib2_path, supprs)); if (files_suppressed) // We don't have to compare anything because a user @@ -705,12 +782,27 @@ main(int argc, char* argv[]) app_di_roots.push_back(&app_di_root); status status = abigail::elf_reader::STATUS_UNKNOWN; environment_sptr env(new environment); - corpus_sptr app_corpus= - read_corpus_from_elf(opts.app_path, - app_di_roots, env.get(), - /*load_all_types=*/opts.weak_mode, - status); + bool use_ctf=false; +#ifdef WITH_CTF + use_ctf=opts.use_ctf; +#endif + + corpus_sptr app_corpus=read_corpus(argv[0], use_ctf, opts.weak_mode, status, + app_di_roots, env, opts.app_path); + if (!app_corpus) + { + emit_prefix(argv[0], cerr) << opts.app_path + << " is not a supported file\n"; + return abigail::tools_utils::ABIDIFF_ERROR; + } + if (opts.fail_no_debug_info && (status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) + && (status & STATUS_DEBUG_INFO_NOT_FOUND)) + { + emit_prefix(argv[0], cerr) << opts.app_path + << " does not have debug symbols\n"; + return abigail::tools_utils::ABIDIFF_ERROR; + } if (status & abigail::elf_reader::STATUS_NO_SYMBOLS_FOUND) { emit_prefix(argv[0], cerr) @@ -746,26 +838,26 @@ main(int argc, char* argv[]) ABG_ASSERT(!opts.lib1_path.empty()); if (!abigail::tools_utils::check_file(opts.lib1_path, cerr, opts.prog_name)) return abigail::tools_utils::ABIDIFF_ERROR; - type = abigail::tools_utils::guess_file_type(opts.lib1_path); - if (type != abigail::tools_utils::FILE_TYPE_ELF) - { - emit_prefix(argv[0], cerr) << opts.lib1_path << " is not an ELF file\n"; - return abigail::tools_utils::ABIDIFF_ERROR; - } char * lib1_di_root = opts.lib1_di_root_path.get(); vector lib1_di_roots; lib1_di_roots.push_back(&lib1_di_root); - corpus_sptr lib1_corpus = read_corpus_from_elf(opts.lib1_path, - lib1_di_roots, env.get(), - /*load_all_types=*/false, - status); - if (status & abigail::elf_reader::STATUS_DEBUG_INFO_NOT_FOUND) + corpus_sptr lib1_corpus=read_corpus(argv[0], use_ctf, false, status, + lib1_di_roots, env, opts.lib1_path); + if (!lib1_corpus) + { + emit_prefix(argv[0], cerr) << opts.lib1_path + << " is not a supported file\n"; + return abigail::tools_utils::ABIDIFF_ERROR; + } + if (opts.fail_no_debug_info && (status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) + && (status & STATUS_DEBUG_INFO_NOT_FOUND)) emit_prefix(argv[0], cerr) << "could not read debug info for " << opts.lib1_path << "\n"; if (status & abigail::elf_reader::STATUS_NO_SYMBOLS_FOUND) { - cerr << "could not read symbols from " << opts.lib1_path << "\n"; + emit_prefix(argv[0], cerr) << "could not read symbols from " + << opts.lib1_path << "\n"; return abigail::tools_utils::ABIDIFF_ERROR; } if (!(status & abigail::elf_reader::STATUS_OK)) @@ -783,13 +875,22 @@ main(int argc, char* argv[]) char * lib2_di_root = opts.lib2_di_root_path.get(); vector lib2_di_roots; lib2_di_roots.push_back(&lib2_di_root); - lib2_corpus = read_corpus_from_elf(opts.lib2_path, - lib2_di_roots, env.get(), - /*load_all_types=*/false, - status); - if (status & abigail::elf_reader::STATUS_DEBUG_INFO_NOT_FOUND) - emit_prefix(argv[0], cerr) - << "could not read debug info for " << opts.lib2_path << "\n"; + lib2_corpus = read_corpus(argv[0], use_ctf, false, status, + lib2_di_roots, env, opts.lib2_path); + if (!lib2_corpus) + { + emit_prefix(argv[0], cerr) << opts.lib2_path + << " is not a supported file\n"; + return abigail::tools_utils::ABIDIFF_ERROR; + } + + if (opts.fail_no_debug_info && (status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) + && (status & STATUS_DEBUG_INFO_NOT_FOUND)) + { + emit_prefix(argv[0], cerr) + << "could not read debug info for " << opts.lib2_path << "\n"; + return abigail::tools_utils::ABIDIFF_ERROR; + } if (status & abigail::elf_reader::STATUS_NO_SYMBOLS_FOUND) { emit_prefix(argv[0], cerr) -- 2.36.1