mirror of
git://sourceware.org/git/libabigail.git
synced 2025-03-03 13:17:35 +00:00
Harden debug info path management & better error reporting
* include/abg-dwarf-reader.h (enum status): New enum. (read_corpus_from_elf): Return an instance of status above, and return the corpus by parameter. * src/abg-dwarf-reader.cc (create_default_dwfl): Add a comment about elfutils wanting the Dwfl_Callbacks::debuginfo_path to be an absolute path. (read_corpus_from_elf): Return an instance of status above, and return the corpus by parameter. * tools/abg-tools-utils.h (make_path_absolute): Declare new function. * tools/abg-tools-utils.cc (make_path_absolute): New implementation. * tools/bidiff.cc (options::di_root_path[12]): Make these be shared pointers. (parse_command_line): ensure the debug info root paths are absolute. (main): Adjust. Give meaningful errors when the debug info or symbol files couldn't be read. * tools/bidw.cc (options::di_root_path): Make this be a shared pointer. (parse_command_line): Ensure the debug info root path is absolute. (main): Adjust. Give meaningful errors when the debug info or symbol files couldn't be read. * tools/bilint.cc (options::di_root_path): Make this be a shared pointer. (parse_command_line): Ensure the debug info root path is absolute. (main): Adjust. Give meaningful errors when the debug info or symbol file couldn't be read. * tests/test-diff-dwarf.cc (main): Adjust. * tests/test-read-dwarf.cc (main): Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
3153f4c83a
commit
c4e7f9792d
@ -38,9 +38,24 @@ namespace abigail
|
||||
namespace dwarf_reader
|
||||
{
|
||||
|
||||
corpus_sptr
|
||||
/// The status of the @ref read_corpus_from_elf() call.
|
||||
enum status
|
||||
{
|
||||
/// This status is for when the call went OK.
|
||||
STATUS_OK,
|
||||
|
||||
/// This satus is for when the debug info could not be read.
|
||||
STATUS_DEBUG_INFO_NOT_FOUND,
|
||||
|
||||
/// This status is for when the symbols of the ELF binaries could
|
||||
/// not be read.
|
||||
STATUS_NO_SYMBOLS_FOUND,
|
||||
};
|
||||
|
||||
status
|
||||
read_corpus_from_elf(const std::string& elf_path,
|
||||
char** debug_info_root_path);
|
||||
char** debug_info_root_path,
|
||||
corpus_sptr& resulting_corp);
|
||||
|
||||
bool
|
||||
lookup_symbol_from_elf(const string& elf_path,
|
||||
|
@ -1986,7 +1986,9 @@ build_function_decl(read_context& ctxt,
|
||||
/// compatible systems, this root path is usually /usr/lib/debug by
|
||||
/// default. If this argument is set to NULL, then "./debug" and
|
||||
/// /usr/lib/debug will be searched for sub-directories containing the
|
||||
/// debug info file.
|
||||
/// debug info file. Note that for now, elfutils wants this path to
|
||||
/// be absolute otherwise things just don't work and the debug info is
|
||||
/// not found.
|
||||
///
|
||||
/// @return the constructed Dwfl handle.
|
||||
static Dwfl*
|
||||
@ -5370,10 +5372,13 @@ build_ir_node_from_die(read_context& ctxt,
|
||||
/// /usr/lib/debug will be searched for sub-directories containing the
|
||||
/// debug info file.
|
||||
///
|
||||
/// @return a pointer to the resulting @ref abigail::corpus.
|
||||
corpus_sptr
|
||||
/// @param resulting_corp a pointer to the resulting abigail::corpus.
|
||||
///
|
||||
/// @return the resulting status.
|
||||
status
|
||||
read_corpus_from_elf(const std::string& elf_path,
|
||||
char** debug_info_root_path)
|
||||
char** debug_info_root_path,
|
||||
corpus_sptr& resulting_corp)
|
||||
{
|
||||
// Create a DWARF Front End Library handle to be used by functions
|
||||
// of that library.
|
||||
@ -5383,11 +5388,11 @@ read_corpus_from_elf(const std::string& elf_path,
|
||||
|
||||
// Load debug info from the elf path.
|
||||
if (!ctxt.load_debug_info())
|
||||
return corpus_sptr();
|
||||
return STATUS_DEBUG_INFO_NOT_FOUND;
|
||||
|
||||
// First read the symbols for publicly defined decls
|
||||
if (!ctxt.load_symbol_maps())
|
||||
return corpus_sptr();
|
||||
return STATUS_NO_SYMBOLS_FOUND;
|
||||
|
||||
// Now, read an ABI corpus proper from the debug info we have
|
||||
// through the dwfl handle.
|
||||
@ -5398,7 +5403,9 @@ read_corpus_from_elf(const std::string& elf_path,
|
||||
corp->set_fun_symbol_map(ctxt.fun_syms_sptr());
|
||||
corp->set_var_symbol_map(ctxt.var_syms_sptr());
|
||||
|
||||
return corp;
|
||||
resulting_corp = corp;
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
/// Look into the symbol tables of a given elf file and see if we find
|
||||
|
@ -149,10 +149,12 @@ main()
|
||||
continue;
|
||||
}
|
||||
|
||||
corp0 = read_corpus_from_elf(in_elfv0_path,
|
||||
/*debug_info_root_path=*/0);
|
||||
corp1 = read_corpus_from_elf(in_elfv1_path,
|
||||
/*debug_info_root_path=*/0);
|
||||
read_corpus_from_elf(in_elfv0_path,
|
||||
/*debug_info_root_path=*/0,
|
||||
corp0);
|
||||
read_corpus_from_elf(in_elfv1_path,
|
||||
/*debug_info_root_path=*/0,
|
||||
corp1);
|
||||
|
||||
if (!corp0)
|
||||
{
|
||||
|
@ -81,9 +81,9 @@ main()
|
||||
for (InOutSpec* s = in_out_specs; s->in_elf_path; ++s)
|
||||
{
|
||||
in_elf_path = abigail::tests::get_src_dir() + "/tests/" + s->in_elf_path;
|
||||
corp =
|
||||
abigail::dwarf_reader::read_corpus_from_elf(in_elf_path,
|
||||
/*debug_info_root_path=*/0);
|
||||
abigail::dwarf_reader::read_corpus_from_elf(in_elf_path,
|
||||
/*debug_info_root_path=*/0,
|
||||
corp);
|
||||
if (!corp)
|
||||
{
|
||||
cerr << "failed to read " << in_elf_path << "\n";
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
///@file
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <cstdlib>
|
||||
@ -304,6 +305,44 @@ guess_file_type(const std::string& file_path)
|
||||
return r;
|
||||
}
|
||||
|
||||
struct malloced_char_star_deleter
|
||||
{
|
||||
void
|
||||
operator()(char* ptr)
|
||||
{free(ptr);}
|
||||
};
|
||||
|
||||
/// Return a copy of the path given in argument, turning it into an
|
||||
/// absolute path by prefixing it with the concatenation of the result
|
||||
/// of get_current_dir_name() and the '/' character.
|
||||
///
|
||||
/// The result being an shared_ptr to char*, it should manage its
|
||||
/// memory by itself and the user shouldn't need to wory too much for
|
||||
/// that.
|
||||
///
|
||||
/// @param p the path to turn into an absolute path.
|
||||
///
|
||||
/// @return a shared pointer to the resulting absolute path.
|
||||
std::tr1::shared_ptr<char>
|
||||
make_path_absolute(const char*p)
|
||||
{
|
||||
using std::tr1::shared_ptr;
|
||||
|
||||
shared_ptr<char> result;
|
||||
|
||||
if (p && p[0] != '/')
|
||||
{
|
||||
shared_ptr<char> pwd(get_current_dir_name(),
|
||||
malloced_char_star_deleter());
|
||||
string s = string(pwd.get()) + "/" + p;
|
||||
result.reset(strdup(s.c_str()), malloced_char_star_deleter());
|
||||
}
|
||||
else
|
||||
result.reset(strdup(p), malloced_char_star_deleter());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}//end namespace tools
|
||||
|
||||
using abigail::function_decl;
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
///@file
|
||||
|
||||
#include <tr1/memory>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
@ -64,5 +65,8 @@ enum file_type
|
||||
file_type guess_file_type(std::istream& in);
|
||||
file_type guess_file_type(const std::string& file_path);
|
||||
|
||||
std::tr1::shared_ptr<char>
|
||||
make_path_absolute(const char*p);
|
||||
|
||||
}// end namespace tools
|
||||
}//end namespace abigail
|
||||
|
@ -36,12 +36,14 @@ using std::string;
|
||||
using std::ostream;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::tr1::shared_ptr;
|
||||
using abigail::translation_unit;
|
||||
using abigail::translation_unit_sptr;
|
||||
using abigail::corpus_sptr;
|
||||
using abigail::comparison::translation_unit_diff_sptr;
|
||||
using abigail::comparison::corpus_diff_sptr;
|
||||
using abigail::comparison::compute_diff;
|
||||
using namespace abigail::dwarf_reader;
|
||||
using abigail::tools::check_file;
|
||||
using abigail::tools::guess_file_type;
|
||||
|
||||
@ -66,8 +68,8 @@ struct options
|
||||
bool show_linkage_names;
|
||||
bool show_harmful_changes;
|
||||
bool show_harmless_changes;
|
||||
char** di_root_path1;
|
||||
char** di_root_path2;
|
||||
shared_ptr<char> di_root_path1;
|
||||
shared_ptr<char> di_root_path2;
|
||||
|
||||
options()
|
||||
: show_stats_only(false),
|
||||
@ -82,9 +84,7 @@ struct options
|
||||
show_all_vars(true),
|
||||
show_linkage_names(true),
|
||||
show_harmful_changes(true),
|
||||
show_harmless_changes(false),
|
||||
di_root_path1(0),
|
||||
di_root_path2(0)
|
||||
show_harmless_changes(false)
|
||||
{}
|
||||
};//end struct options;
|
||||
|
||||
@ -150,7 +150,9 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
int j = i + 1;
|
||||
if (j >= argc)
|
||||
return false;
|
||||
opts.di_root_path1 = &argv[j];
|
||||
// elfutils wants the root path to the debug info to be
|
||||
// absolute.
|
||||
opts.di_root_path1 = abigail::tools::make_path_absolute(argv[j]);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--debug-info-dir2"))
|
||||
@ -158,7 +160,9 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
int j = i + 1;
|
||||
if (j >= argc)
|
||||
return false;
|
||||
opts.di_root_path2 = &argv[j];
|
||||
// elfutils wants the root path to the debug info to be
|
||||
// absolute.
|
||||
opts.di_root_path2 = abigail::tools::make_path_absolute(argv[j]);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--stat"))
|
||||
@ -407,7 +411,11 @@ main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
translation_unit_sptr t1, t2;
|
||||
abigail::dwarf_reader::status c1_status =
|
||||
abigail::dwarf_reader::STATUS_OK,
|
||||
c2_status = abigail::dwarf_reader::STATUS_OK;
|
||||
corpus_sptr c1, c2;
|
||||
char *di_dir1 = 0, *di_dir2 = 0;
|
||||
|
||||
switch (t1_type)
|
||||
{
|
||||
@ -420,8 +428,9 @@ main(int argc, char* argv[])
|
||||
break;
|
||||
case abigail::tools::FILE_TYPE_ELF:
|
||||
case abigail::tools::FILE_TYPE_AR:
|
||||
c1 = abigail::dwarf_reader::read_corpus_from_elf(opts.file1,
|
||||
opts.di_root_path1);
|
||||
di_dir1 = opts.di_root_path1.get();
|
||||
c1_status = abigail::dwarf_reader::read_corpus_from_elf(opts.file1,
|
||||
&di_dir1, c1);
|
||||
break;
|
||||
case abigail::tools::FILE_TYPE_XML_CORPUS:
|
||||
c1 =
|
||||
@ -443,8 +452,9 @@ main(int argc, char* argv[])
|
||||
break;
|
||||
case abigail::tools::FILE_TYPE_ELF:
|
||||
case abigail::tools::FILE_TYPE_AR:
|
||||
c2 = abigail::dwarf_reader::read_corpus_from_elf(opts.file2,
|
||||
opts.di_root_path2);
|
||||
di_dir2 = opts.di_root_path2.get();
|
||||
c2_status = abigail::dwarf_reader::read_corpus_from_elf(opts.file2,
|
||||
&di_dir2, c2);
|
||||
break;
|
||||
case abigail::tools::FILE_TYPE_XML_CORPUS:
|
||||
c2 =
|
||||
@ -458,13 +468,64 @@ main(int argc, char* argv[])
|
||||
if (!t1 && !c1)
|
||||
{
|
||||
cerr << "failed to read input file " << opts.file1 << "\n";
|
||||
return true;
|
||||
if (c1_status != abigail::dwarf_reader::STATUS_OK)
|
||||
{
|
||||
switch (c1_status)
|
||||
{
|
||||
case abigail::dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND:
|
||||
cerr << "could not find the debug info";
|
||||
if(di_dir1 == 0)
|
||||
cerr << " Maybe you should consider using the "
|
||||
"--debug-info-dir1 option to tell me about the "
|
||||
"root directory of the debuginfo? "
|
||||
"(e.g, --debug-info-dir1 /usr/lib/debug)\n";
|
||||
else
|
||||
cerr << "Maybe the root path to the debug information '"
|
||||
<< di_dir1 << "' is wrong?\n";
|
||||
break;
|
||||
case abigail::dwarf_reader::STATUS_NO_SYMBOLS_FOUND:
|
||||
cerr << "could not find the ELF symbols in the file '"
|
||||
<< opts.file1
|
||||
<< "'\n";
|
||||
break;
|
||||
case abigail::dwarf_reader::STATUS_OK:
|
||||
// This cannot be!
|
||||
abort();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!t2 && !c2)
|
||||
{
|
||||
cerr << "failed to read input file" << opts.file2 << "\n";
|
||||
return true;
|
||||
if (c2_status != abigail::dwarf_reader::STATUS_OK)
|
||||
{
|
||||
switch (c2_status)
|
||||
{
|
||||
case abigail::dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND:
|
||||
cerr << "could not find the debug info";
|
||||
if(di_dir2 == 0)
|
||||
cerr << " Maybe you should consider using the "
|
||||
"--debug-info-dir1 option to tell me about the "
|
||||
"root directory of the debuginfo? "
|
||||
"(e.g, --debug-info-dir1 /usr/lib/debug)\n";
|
||||
else
|
||||
cerr << "Maybe the root path to the debug information '"
|
||||
<< di_dir2
|
||||
<< "' is wrong?\n";
|
||||
break;
|
||||
case abigail::dwarf_reader::STATUS_NO_SYMBOLS_FOUND:
|
||||
cerr << "could not find the ELF symbols in the file '"
|
||||
<< opts.file2
|
||||
<< "'\n";
|
||||
break;
|
||||
case abigail::dwarf_reader::STATUS_OK:
|
||||
// This cannot be!
|
||||
abort();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!!c1 != !!c2
|
||||
|
@ -26,6 +26,7 @@
|
||||
/// DWARF format) and emit it back in a set of "text sections" in native
|
||||
/// libabigail XML format.
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
@ -33,6 +34,7 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <tr1/memory>
|
||||
#include "abg-tools-utils.h"
|
||||
#include "abg-corpus.h"
|
||||
#include "abg-dwarf-reader.h"
|
||||
@ -43,15 +45,15 @@ using std::cerr;
|
||||
using std::cout;
|
||||
using std::ostream;
|
||||
using std::ofstream;
|
||||
using std::tr1::shared_ptr;
|
||||
|
||||
struct options
|
||||
{
|
||||
string in_file_path;
|
||||
string out_file_path;
|
||||
char** di_root_path;
|
||||
string in_file_path;
|
||||
string out_file_path;
|
||||
shared_ptr<char> di_root_path;
|
||||
|
||||
options()
|
||||
: di_root_path(0)
|
||||
{}
|
||||
};
|
||||
|
||||
@ -86,8 +88,9 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
|| argv[i + 1][0] == '-'
|
||||
|| !opts.out_file_path.empty())
|
||||
return false;
|
||||
|
||||
opts.di_root_path = &argv[i + 1];
|
||||
// elfutils wants the root path to the debug info to be
|
||||
// absolute.
|
||||
opts.di_root_path = abigail::tools::make_path_absolute(argv[i + 1]);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--out-file"))
|
||||
@ -137,27 +140,38 @@ main(int argc, char* argv[])
|
||||
using abigail::corpus_sptr;
|
||||
using abigail::translation_units;
|
||||
using abigail::dwarf_reader::read_corpus_from_elf;
|
||||
using namespace abigail;
|
||||
|
||||
char* p = opts.di_root_path.get();
|
||||
corpus_sptr corp;
|
||||
dwarf_reader::status s = read_corpus_from_elf(opts.in_file_path, &p, corp);
|
||||
|
||||
corpus_sptr corp = read_corpus_from_elf(opts.in_file_path,
|
||||
opts.di_root_path);
|
||||
if (!corp)
|
||||
{
|
||||
if (opts.di_root_path == 0)
|
||||
if (s == dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND)
|
||||
{
|
||||
cerr <<
|
||||
"Could not read debug info from "
|
||||
<< opts.in_file_path << "\n";
|
||||
if (p == 0)
|
||||
{
|
||||
cerr <<
|
||||
"Could not read debug info from "
|
||||
<< opts.in_file_path << "\n";
|
||||
|
||||
cerr << "You might want to supply the root directory where "
|
||||
"to search debug info from, using the "
|
||||
"--debug-info-dir option\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Could not read debug info for " << opts.in_file_path
|
||||
<< " from debug info root directory " << *opts.di_root_path
|
||||
<< "\n";
|
||||
cerr << "You might want to supply the root directory where "
|
||||
"to search debug info from, using the "
|
||||
"--debug-info-dir option "
|
||||
"(e.g --debug-info-dir /usr/lib/debug)\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Could not read debug info for '" << opts.in_file_path
|
||||
<< "' from debug info root directory '" << p
|
||||
<< "'\n";
|
||||
}
|
||||
}
|
||||
else if (s == dwarf_reader::STATUS_NO_SYMBOLS_FOUND)
|
||||
cerr << "Could not read ELF symbol information from "
|
||||
<< opts.in_file_path << "\n";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -64,21 +64,20 @@ using abigail::xml_writer::write_corpus_to_archive;
|
||||
|
||||
struct options
|
||||
{
|
||||
string file_path;
|
||||
bool read_from_stdin;
|
||||
bool read_tu;
|
||||
bool diff;
|
||||
bool bidiff;
|
||||
bool noout;
|
||||
char** di_root_path;
|
||||
string file_path;
|
||||
bool read_from_stdin;
|
||||
bool read_tu;
|
||||
bool diff;
|
||||
bool bidiff;
|
||||
bool noout;
|
||||
std::tr1::shared_ptr<char> di_root_path;
|
||||
|
||||
options()
|
||||
: read_from_stdin(false),
|
||||
read_tu(false),
|
||||
diff(false),
|
||||
bidiff(false),
|
||||
noout(false),
|
||||
di_root_path(0)
|
||||
noout(false)
|
||||
{}
|
||||
};//end struct options;
|
||||
|
||||
@ -124,8 +123,9 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
if (argc <= i + 1
|
||||
|| argv[i + 1][0] == '-')
|
||||
return false;
|
||||
|
||||
opts.di_root_path = &argv[i + 1];
|
||||
// elfutils wants the root path to the debug info to be
|
||||
// absolute.
|
||||
opts.di_root_path = abigail::tools::make_path_absolute(argv[i + 1]);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--stdin"))
|
||||
@ -194,6 +194,8 @@ main(int argc, char* argv[])
|
||||
|
||||
abigail::translation_unit_sptr tu;
|
||||
abigail::corpus_sptr corp;
|
||||
abigail::dwarf_reader::status s = abigail::dwarf_reader::STATUS_OK;
|
||||
char* di_root_path = 0;
|
||||
file_type type = guess_file_type(opts.file_path);
|
||||
|
||||
switch (type)
|
||||
@ -206,8 +208,10 @@ main(int argc, char* argv[])
|
||||
break;
|
||||
case abigail::tools::FILE_TYPE_ELF:
|
||||
case abigail::tools::FILE_TYPE_AR:
|
||||
corp = read_corpus_from_elf(opts.file_path,
|
||||
opts.di_root_path);
|
||||
di_root_path = opts.di_root_path.get();
|
||||
s= read_corpus_from_elf(opts.file_path,
|
||||
&di_root_path,
|
||||
corp);
|
||||
break;
|
||||
case abigail::tools::FILE_TYPE_XML_CORPUS:
|
||||
corp = read_corpus_from_native_xml_file(opts.file_path);
|
||||
@ -220,6 +224,31 @@ main(int argc, char* argv[])
|
||||
if (!tu && !corp)
|
||||
{
|
||||
cerr << "failed to read " << opts.file_path << "\n";
|
||||
if (s != abigail::dwarf_reader::STATUS_OK)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case abigail::dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND:
|
||||
cerr << "could not find the debug info";
|
||||
if(di_root_path == 0)
|
||||
cerr << " Maybe you should consider using the "
|
||||
"--debug-info-dir1 option to tell me about the "
|
||||
"root directory of the debuginfo? "
|
||||
"(e.g, --debug-info-dir1 /usr/lib/debug)\n";
|
||||
else
|
||||
cerr << "Maybe the root path to the debug "
|
||||
"information is wrong?\n";
|
||||
break;
|
||||
case abigail::dwarf_reader::STATUS_NO_SYMBOLS_FOUND:
|
||||
cerr << "could not find the ELF symbols in the file "
|
||||
<< opts.file_path
|
||||
<< "\n";
|
||||
break;
|
||||
case abigail::dwarf_reader::STATUS_OK:
|
||||
// This cannot be!
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user