mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-23 02:02:15 +00:00
e2d450176b
* include/abg-corpus.h (corpus::{g,s}et_{fun,var}_symbol_map{_sptr}): Declare new accessors. (corpus::lookup_{variable,function}_symbol): Declare new member functions. * src/abg-corpus.cc (corpus::{g,s}et_{fun,var}_symbol_map{_sptr}): Define new accessors. (corpus::lookup_{variable,function}_symbol): Define new member functions. * include/abg-ir.h (string_elf_symbol_sptr_map_type) (string_elf_symbol_sptr_map_sptr, elf_symbols) (string_elf_symbols_map_type, string_elf_symbols_map_sptr): New convenience typedefs. (elf_symbol::{get_main_symbol, is_main_symbol, get_next_alias, has_aliases, add_alias, get_id_string, get_name_and_version_from_id, operator=}): Declare new member functions. * src/abg-ir.cc (elf_symbol::{get_main_symbol, is_main_symbol, get_next_alias, has_aliases, add_alias, get_id_string, get_name_and_version_from_id, operator=}): Define new member functions. * include/abg-reader.h (read_corpus_from_file): Take a shared pointer to corpus. * src/abg-reader.cc (read_context::{g,s}et_corpus): Define these. (build_elf_symbol_db, build_elf_symbol_from_reference) (read_symbol_db_from_input): Define new functions. (read_corpus_from_input): Adjust. Make it read symbol databases. (build_elf_symbol): Harden this. (build_{var,function}_decl): Read the symbol reference. Do not read the local symbol serialization anymore. (read_corpus_from_archive): Adjust. (read_corpus_from_file): Take a reference to a shared pointer to corpus, rather than a reference to the corpus. (read_corpus_from_native_xml): Only keep the overload that returns a corpus. Set the current context with the corpus. * src/abg-dwarf-reader.cc (addr_elf_symbol_sptr_map_type) (addr_elf_symbol_sptr_map_sptr): New convenience typedefs. (read_context::{fun_sym_addr_sym_index_map_, var_sym_addr_sym_index_map_): Remove. (read_context::{fun,var}_addr_sym_map_): New. Replace the above that got removed. (read_context::{var,fun}_syms_): New. (read_context::lookup_elf_{fn,var}_symbol_from_address): Adjust. (read_context::{fun,var}_addr_sym_map{_sptr}): New. (read_context::{fun,var}_syms{_sptr}): New. (read_context::load_symbol_maps): Replace read_context::load_symbol_addr_to_index_maps. Adjust to load all the new maps. (read_context::maybe_load_symbol_maps): New. (read_debug_info_into_corpus): Renamed build_corpus into this. Update to load symbol maps and set it to the corpus. * src/abg-writer.cc (write_context::get_fun_symbol_map): New accessor. (write_elf_symbol_aliases, write_elf_symbol_reference) (write_elf_symbols_table): Define new static functions. (write_var_decl): Write the reference to the underlying symbol of the variable. Do not write the full symbol here anymore. (write_function_decl): Likewise, write the reference to the underlying symbol of the function. Do not write the full symbol here anymore. (write_corpus_to_native_xml): Write the symbol databases at the beginning of the corpus document. * src/abg-comparison.cc (corpus_diff::priv::ensure_lookup_tables_populated): Now that the corpus has symbols, check if a the symbol of an allegedly deleted function (resp. variable) is deleted; if not, then do not report the function (resp. variable) as deleted. Similarly, check if the symbol of an allegedly added function (resp. variable) is added. if not, the do not report the function (resp. variable) as added. * tests/test-write-read-archive.cc (main): Adjust. * tools/biar.cc (extract_tus_from_archive): Likewise. * tests/data/test-diff-filter/test9-report.txt: Adjust. * tests/data/test-read-dwarf/test0.abi: Likewise. * tests/data/test-read-dwarf/test1.abi: Likewise. * tests/data/test-read-dwarf/test2.so.abi: Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
334 lines
8.7 KiB
C++
334 lines
8.7 KiB
C++
// -*- Mode: C++ -*-
|
|
//
|
|
// Copyright (C) 2013 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/>.
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>// The two above is for 'stat'
|
|
#include <cstring> // for 'strcmp'
|
|
#include <cstdlib> // for 'system'
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <list>
|
|
#include "abg-corpus.h"
|
|
#include "abg-reader.h"
|
|
#include "abg-writer.h"
|
|
#include "abg-tools-utils.h"
|
|
|
|
using std::cerr;
|
|
using std::cout;
|
|
using std::string;
|
|
using std::list;
|
|
|
|
struct options
|
|
{
|
|
bool list_content;
|
|
string extract_dest;
|
|
string archive;
|
|
list<string> in_files;
|
|
string out_dir;
|
|
|
|
options()
|
|
: list_content(false)
|
|
{
|
|
}
|
|
|
|
};//end options
|
|
|
|
/// Display a message explaining the usage of the program on stdout.
|
|
static void
|
|
display_usage()
|
|
{
|
|
cout << "usage: biar [options] [archive-file-path]\n"
|
|
<< " where options are: \n"
|
|
<< "--help|-h display this usage message\n"
|
|
<< "--list|l <archive> list the archive content\n"
|
|
<< "--add|-a <files-to-add> <archive> add files to an archive\n"
|
|
<< "--extract|x [dest-dir] <archive> extract archive content\n"
|
|
;
|
|
}
|
|
|
|
/// Parse the command line arguments and populate an instance of \a
|
|
/// options as a result.
|
|
///
|
|
/// @param argc the number of words on the command line, including the
|
|
/// program name.
|
|
///
|
|
/// @param argv an array of words representing the command line. This
|
|
/// is the thing that is parsed.
|
|
///
|
|
/// @param opts the options that are set as a result of parsing the
|
|
/// command line. This output parameter is set iff the function
|
|
/// returs true.
|
|
///
|
|
/// @return true if the function could make sense of the command line
|
|
/// and parsed it correctly. Otherwise, return false. If this
|
|
/// function returns false, the caller would be well inspired to call
|
|
/// display_usage() to remind the user how to properly invoke this
|
|
/// program so that its command line makes sense.
|
|
static bool
|
|
parse_args(int argc, char* argv[], options& opts)
|
|
{
|
|
if (argc < 2)
|
|
return false;
|
|
|
|
for (int i = 1; i < argc; ++i)
|
|
{
|
|
char* arg = argv[i];
|
|
|
|
if (! strcmp(arg, "--help")
|
|
||! strcmp(arg, "-h"))
|
|
return false;
|
|
|
|
if (arg[0] != '-')
|
|
opts.archive = arg;
|
|
else if (! strcmp(arg, "--list")
|
|
||! strcmp(arg, "-l"))
|
|
opts.list_content = true;
|
|
else if (! strcmp(arg, "--add")
|
|
|| ! strcmp(arg,"-a"))
|
|
{
|
|
int arg_index0, arg_index1;
|
|
char *f = 0;
|
|
for (arg_index0 = i + 1; arg_index0 < argc; ++arg_index0)
|
|
{
|
|
// --add must be followed by at N words that don't start
|
|
// by '-' (N > 1). The first N-1 words are the
|
|
// arguments of --add (the files to add to the archive)
|
|
// and the last one is the name of the archive to add
|
|
// the files to.
|
|
|
|
f = argv[arg_index0];
|
|
if (f[0] == '-')
|
|
break;
|
|
|
|
arg_index1 = arg_index0 + 1;
|
|
if (arg_index1 >= argc
|
|
|| argv[arg_index1][0] == '-')
|
|
break;
|
|
|
|
opts.in_files.push_back(f);
|
|
}
|
|
if (opts.in_files.empty())
|
|
return false;
|
|
}
|
|
else if (! strcmp(arg, "--extract")
|
|
|| ! strcmp(arg, "-x"))
|
|
{
|
|
int arg_index = i + 1, arch_index = arg_index + 1;
|
|
if (arg_index < argc
|
|
&& argv[arg_index][0] != '-'
|
|
&& arch_index < argc
|
|
&& argv[arch_index][0] != '-')
|
|
opts.extract_dest = argv[arg_index];
|
|
else if (arg_index < argc
|
|
&& argv[arg_index][0] != '-')
|
|
// No destination directory argument was given for the
|
|
// --extract option, so consider it to be the current
|
|
// directory
|
|
opts.extract_dest = ".";
|
|
else
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
using abigail::corpus;
|
|
using abigail::corpus_sptr;
|
|
using abigail::translation_unit;
|
|
using abigail::translation_unit_sptr;
|
|
using abigail::translation_units;
|
|
using abigail::xml_reader::read_corpus_from_file;
|
|
using abigail::xml_writer::write_corpus_to_archive;
|
|
|
|
/// List the content of a given archive. The names of the files of
|
|
/// the archive are then displayed on stdout.
|
|
///
|
|
/// @param archive_path a path to the file containing the archive file
|
|
/// to list the content of.
|
|
///
|
|
/// @return true upon successful completion, false otherwise.
|
|
static bool
|
|
list_content(const string& archive_path)
|
|
{
|
|
if (archive_path.empty())
|
|
{
|
|
cerr << "Empty archive path\n";
|
|
return false;
|
|
}
|
|
|
|
corpus_sptr archive = read_corpus_from_file(archive_path);
|
|
if (!archive)
|
|
{
|
|
cerr << "Could not read archive at '" << archive_path << "'\n";
|
|
return false;
|
|
}
|
|
|
|
for (translation_units::const_iterator i =
|
|
archive->get_translation_units().begin();
|
|
i != archive->get_translation_units().end();
|
|
++i)
|
|
cout << (*i)->get_path() << "\n";
|
|
|
|
return true;
|
|
}
|
|
|
|
/// Add a translation unit to an archive -- or create one for that
|
|
/// matter.
|
|
///
|
|
/// @param tu_paths a list of paths to add to the archive.
|
|
///
|
|
/// @param archive_path the path of the archive to either open or
|
|
/// create. The specified in \tu_paths are then added to this
|
|
/// archive. Note that this function creates the entire directory
|
|
/// tree needed up to \a archive_path, if needed.
|
|
///
|
|
/// @return true upon successful completion, false otherwise.
|
|
static bool
|
|
add_tus_to_archive(const list<string>& tu_paths,
|
|
const string& archive_path)
|
|
{
|
|
translation_units tus;
|
|
corpus corp(archive_path);
|
|
|
|
bool added_some_tus = false;
|
|
for (list<string>::const_iterator i = tu_paths.begin();
|
|
i != tu_paths.end();
|
|
++i)
|
|
{
|
|
translation_unit_sptr tu =
|
|
abigail::xml_reader::read_translation_unit_from_file(*i);
|
|
if (!tu)
|
|
{
|
|
cerr << "could not read binary instrumentation file '"
|
|
<< *i
|
|
<< "'\n";
|
|
continue;
|
|
}
|
|
corp.add(tu);
|
|
added_some_tus = true;
|
|
}
|
|
|
|
if (added_some_tus)
|
|
{
|
|
if (!write_corpus_to_archive(corp))
|
|
{
|
|
cerr << "could not write archive file '"
|
|
<< corp.get_path()
|
|
<< "'\n";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// Extract translation units from a given archive.
|
|
///
|
|
/// @param dest_path the path of the destination directory which the
|
|
/// elements of the archive are to be extracted under.
|
|
///
|
|
/// @param archive_path the path to the archive to extract. The
|
|
/// archive must exist and be accessible with read privileges.
|
|
///
|
|
/// @return true upon successful completion, false otherwise.
|
|
static bool
|
|
extract_tus_from_archive(const string& dest_path,
|
|
const string& archive_path)
|
|
{
|
|
if (dest_path.empty())
|
|
{
|
|
cerr << "empty file directory\n";
|
|
return false;
|
|
}
|
|
|
|
corpus_sptr archive(new corpus(archive_path));
|
|
|
|
if (read_corpus_from_file(archive) < 1)
|
|
{
|
|
cerr << "could not read archive at '"
|
|
<< archive_path
|
|
<< "'\n;";
|
|
return false;
|
|
}
|
|
|
|
string cmd = "mkdir -p " + dest_path;
|
|
if (system(cmd.c_str()))
|
|
{
|
|
cerr << "could not create file directory '"
|
|
<< dest_path
|
|
<< "'\n";
|
|
return false;
|
|
}
|
|
|
|
for (translation_units::const_iterator i =
|
|
archive->get_translation_units().begin();
|
|
i != archive->get_translation_units().end();
|
|
++i)
|
|
{
|
|
string dest = dest_path + "/" + (*i)->get_path();
|
|
if (!abigail::tools::ensure_parent_dir_created(dest))
|
|
{
|
|
cerr << "could not create parent director for '" << dest << "'\n";
|
|
return false;
|
|
}
|
|
|
|
if (!abigail::xml_writer::write_translation_unit(**i, /*indent=*/0, dest))
|
|
{
|
|
cerr << "could not write binary instrumentation file to '"
|
|
<< dest
|
|
<< "'\n";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// Parse the command line and perform the archive-related operations
|
|
/// asked by the user, if the command line makes sense; otherwise,
|
|
/// display a usage help message and bail out.
|
|
int
|
|
main(int argc, char* argv[])
|
|
{
|
|
options opts;
|
|
|
|
if (!parse_args(argc, argv, opts)
|
|
|| opts.archive.empty())
|
|
{
|
|
display_usage();
|
|
return -1;
|
|
}
|
|
|
|
if (opts.list_content)
|
|
return !list_content(opts.archive);
|
|
else if (!opts.in_files.empty())
|
|
return !add_tus_to_archive(opts.in_files, opts.archive);
|
|
else if (!opts.extract_dest.empty())
|
|
return !extract_tus_from_archive(opts.extract_dest, opts.archive);
|
|
else
|
|
{
|
|
display_usage();
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|