mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-29 21:32:08 +00:00
48801d23e4
It turns out that, in DWARF, there can be function template instantiations foo<int>(int) and foo<TypedefOfInt>(TypedefOfInt) which have the same symbol name, if TypedefOfInt is a typedef of int. An ABI corpus retains only one function declaration per symbol name. So in the example of the bug the input DWARF has the two instantiations, but libabigail is just keeping one of the two; so the abixml only has one of the two template instantiations. This patch changes the ABI corpus model so that it represents the fact that there can be several function declarations for a given symbol. The patch then adjust the comparison engine to make it know about this new model. * include/abg-corpus.h (corpus::exported_decls_builder::str_{fn,var}_ptr_map_type): Remove these typedefs from here as they only used internally in abg-corpus.cc. So we move them there instead. * src/abg-corpus.cc (str_fn_ptrs_map_type): New typedef. (str_var_ptr_map_type): Moved the typedef that was in corpus::exported_decls_builder here. (corpus::exported_decls_builder::id_fns_map_): Rename the fns_ data member into this. Make it have a str_fn_ptrs_map_type as a type. (corpus::exported_decls_builder::id_fns_map): Renamed the fns_map() accessor into this one. (corpus::exported_decls_builder::{fn_id_is_in_id_fns_map, fn_is_in_fns}): New member functions. (corpus::exported_decls_builder::fn_is_in_id_fns_map): Rename fn_is_in_map into this. (corpus::exported_decls_builder::add_fn_to_id_fns_map): Rename add_fn_to_map into this. (corpus::exported_decls_builder::add_fn_to_exported): Adjust. (corpus::exported_decls_builder::maybe_add_fn_to_exported_fns): Adjust. * src/abg-comparison.cc (function_decl_diff::report): Emit reports about function name changes (for a given function ID) only if there are sub-type changes to be reported for the function. In that case, do not forget to emit the sub-type changes after the name changes have been reported. (corpus_diff::priv::ensure_lookup_tables_populated): Several functions of the same ID can be removed or added from/to the corpus. * tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so: New test input binary. * tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi: New test output reference. * tests/data/Makefile.am: Add the new test materials to the source distribution. * tests/test-read-dwarf.cc (in_out_specs): Adjust to add the new test inputs above. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
246 lines
6.9 KiB
C++
246 lines
6.9 KiB
C++
// -*- Mode: C++ -*-
|
|
//
|
|
// Copyright (C) 2013-2015 Red Hat, 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: Dodji Seketeli
|
|
|
|
/// @file read ELF binaries containing DWARF, save them in XML corpus
|
|
/// files and diff the corpus files against reference XML corpus
|
|
/// files.
|
|
|
|
#include <string>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
#include "abg-ir.h"
|
|
#include "abg-dwarf-reader.h"
|
|
#include "abg-writer.h"
|
|
#include "abg-tools-utils.h"
|
|
#include "test-utils.h"
|
|
|
|
using std::string;
|
|
using std::ofstream;
|
|
using std::cerr;
|
|
using abigail::tests::get_build_dir;
|
|
|
|
/// This is an aggregate that specifies where a test shall get its
|
|
/// input from, and where it shall write its ouput to.
|
|
struct InOutSpec
|
|
{
|
|
const char* in_elf_path;
|
|
const char* in_abi_path;
|
|
const char* out_abi_path;
|
|
};// end struct InOutSpec
|
|
|
|
|
|
InOutSpec in_out_specs[] =
|
|
{
|
|
{
|
|
"data/test-read-dwarf/test0",
|
|
"data/test-read-dwarf/test0.abi",
|
|
"output/test-read-dwarf/test0.abi"
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test1",
|
|
"data/test-read-dwarf/test1.abi",
|
|
"output/test-read-dwarf/test1.abi"
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test2.so",
|
|
"data/test-read-dwarf/test2.so.abi",
|
|
"output/test-read-dwarf/test2.so.abi"
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test3.so",
|
|
"data/test-read-dwarf/test3.so.abi",
|
|
"output/test-read-dwarf/test3.so.abi"
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test4.so",
|
|
"data/test-read-dwarf/test4.so.abi",
|
|
"output/test-read-dwarf/test4.so.abi"
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test5.o",
|
|
"data/test-read-dwarf/test5.o.abi",
|
|
"output/test-read-dwarf/test5.o.abi"
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test6.so",
|
|
"data/test-read-dwarf/test6.so.abi",
|
|
"output/test-read-dwarf/test6.so.abi"
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test7.so",
|
|
"data/test-read-dwarf/test7.so.abi",
|
|
"output/test-read-dwarf/test7.so.abi"
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test8-qualified-this-pointer.so",
|
|
"data/test-read-dwarf/test8-qualified-this-pointer.so.abi",
|
|
"output/test-read-dwarf/test8-qualified-this-pointer.so.abi"
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test9-pr18818-clang.so",
|
|
"data/test-read-dwarf/test9-pr18818-clang.so.abi",
|
|
"output/test-read-dwarf/test9-pr18818-clang.so.abi",
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test10-pr18818-gcc.so",
|
|
"data/test-read-dwarf/test10-pr18818-gcc.so.abi",
|
|
"output/test-read-dwarf/test10-pr18818-gcc.so.abi",
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test11-pr18828.so",
|
|
"data/test-read-dwarf/test11-pr18828.so.abi",
|
|
"output/test-read-dwarf/test11-pr18828.so.abi",
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test12-pr18844.so",
|
|
"data/test-read-dwarf/test12-pr18844.so.abi",
|
|
"output/test-read-dwarf/test12-pr18844.so.abi",
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test13-pr18894.so",
|
|
"data/test-read-dwarf/test13-pr18894.so.abi",
|
|
"output/test-read-dwarf/test13-pr18894.so.abi",
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test14-pr18893.so",
|
|
"data/test-read-dwarf/test14-pr18893.so.abi",
|
|
"output/test-read-dwarf/test14-pr18893.so.abi",
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test15-pr18892.so",
|
|
"data/test-read-dwarf/test15-pr18892.so.abi",
|
|
"output/test-read-dwarf/test15-pr18892.so.abi",
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test16-pr18904.so",
|
|
"data/test-read-dwarf/test16-pr18904.so.abi",
|
|
"output/test-read-dwarf/test16-pr18904.so.abi",
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test17-pr19027.so",
|
|
"data/test-read-dwarf/test17-pr19027.so.abi",
|
|
"output/test-read-dwarf/test17-pr19027.so.abi",
|
|
},
|
|
{
|
|
"data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so",
|
|
"data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi",
|
|
"output/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi",
|
|
},
|
|
// This should be the last entry.
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
int
|
|
main()
|
|
{
|
|
using abigail::dwarf_reader::read_corpus_from_elf;
|
|
unsigned result = 1;
|
|
|
|
bool is_ok = true;
|
|
string in_elf_path, in_abi_path, out_abi_path;
|
|
abigail::ir::environment_sptr env;
|
|
abigail::corpus_sptr corp;
|
|
|
|
for (InOutSpec* s = in_out_specs; s->in_elf_path; ++s)
|
|
{
|
|
in_elf_path = abigail::tests::get_src_dir() + "/tests/" + s->in_elf_path;
|
|
env.reset(new abigail::ir::environment);
|
|
abigail::dwarf_reader::status status =
|
|
abigail::dwarf_reader::STATUS_UNKNOWN;
|
|
corp = read_corpus_from_elf(in_elf_path,
|
|
/*debug_info_root_path=*/0,
|
|
env.get(),
|
|
/*load_all_types=*/false,
|
|
status);
|
|
if (!corp)
|
|
{
|
|
cerr << "failed to read " << in_elf_path << "\n";
|
|
is_ok = false;
|
|
continue;
|
|
}
|
|
corp->set_path(s->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("");
|
|
|
|
out_abi_path = get_build_dir() + "/tests/" + s->out_abi_path;
|
|
if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
|
|
{
|
|
cerr << "Could not create parent director for " << out_abi_path;
|
|
is_ok = false;
|
|
return result;
|
|
}
|
|
|
|
ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
|
|
if (!of.is_open())
|
|
{
|
|
cerr << "failed to read " << out_abi_path << "\n";
|
|
is_ok = false;
|
|
continue;
|
|
}
|
|
|
|
bool r =
|
|
abigail::xml_writer::write_corpus_to_native_xml(corp,
|
|
/*indent=*/0,
|
|
of);
|
|
is_ok = (is_ok && r);
|
|
of.close();
|
|
|
|
string abilint = get_build_dir() + "/tools/abilint";
|
|
abilint += " --noout";
|
|
string cmd = abilint + " " + out_abi_path;
|
|
if (system(cmd.c_str()))
|
|
{
|
|
cerr << "output file doesn't pass abilint: " << out_abi_path << "\n";
|
|
r = false;
|
|
}
|
|
is_ok = (is_ok && r);
|
|
|
|
|
|
in_elf_path = abigail::tests::get_src_dir() + "/tests/" + s->in_elf_path;
|
|
string abidiff = get_build_dir() + "/tools/abidiff";
|
|
cmd = abidiff + " --no-architecture " + in_elf_path + " " + out_abi_path;
|
|
r = true;
|
|
if (system(cmd.c_str()))
|
|
{
|
|
cerr << "ABIs differ:\n"
|
|
<< in_elf_path
|
|
<< "\nand:\n"
|
|
<< out_abi_path
|
|
<< "\n";
|
|
r = false;
|
|
}
|
|
is_ok = (is_ok && r);
|
|
|
|
in_abi_path = abigail::tests::get_src_dir() + "/tests/" + s->in_abi_path;
|
|
cmd = "diff -u " + in_abi_path + " " + out_abi_path;
|
|
r = true;
|
|
if (system(cmd.c_str()))
|
|
r = false;
|
|
is_ok = (is_ok && r);
|
|
}
|
|
|
|
return !is_ok;
|
|
}
|