Support alternate debug info sections

ABGBZ#17193
	* include/abg-dwarf-reader.h (class read_context)
	(typedef read_context_sptr, create_read_context)
	(has_alt_debug_info): Declare these.
	(read_corpus_from_elf): Declare new overload.
	* src/abg-dwarf-reader.cc (find_alt_debug_info)
	(is_die_attribute_resolved_through_gnu_ref_alt)
	(build_primary_die_parent_relations_under)
	(build_alternate_die_parent_relations_under):
	Define new static functions.
	(read_context::{alt_dwarf_,
	alt_debug_info_path_, alternate_die_decl_map_,
	alternate_die_parent_map_}): New data members.
	(read_context::{alt_dwarf, alt_debug_info_path,
	alternate_die_decl_map, associate_die_to_decl_primary,
	associate_die_to_decl_alternate, associate_die_to_decl,
	lookup_decl_from_die_offset_primary,
	lookup_decl_from_die_offset_alternate,
	lookup_decl_from_die_offset, alternate_die_parent_map}): New
	member functions.
	(read_context::load_debug_info): Painfully Get a handle on the
	alternate debug info section too.  We shouldn't have to do all
	this work; we could use the new dwarf_getalt() function from
	libdw, but we cannot as we want to support supports that predate
	that api.  When a version of elfutils gets released with that api
	though, we should conditionally use that instead.
	(build_ir_node_from_die, get_parent_die, get_scope_for_die)
	(build_namespace_decl_and_add_to_ir)
	(build_class_type_and_add_to_ir, build_qualified_type)
	(build_pointer_type_def, build_reference_type, build_typedef_type)
	(build_var_decl, build_function_decl): Take a new parameter that
	tells if the input DIE is from alternate debug info.  Adjust their
	code accordingly.
	(die_die_attribute): Take a new output parameter that tells if the
	resolved DIE is from alternate debug info.  Also take a new
	parameter that tells if the input DIE is from alternate debug info
	sections.
	(build_die_parent_relations_under): Take the DIE -> parent map to
	act upon.  Also, add a new overload that takes a flag saying if
	the DIE is from alternate debug info or not, and act upon that.
	(build_die_parent_maps): Renamed build_die_parent_map into this
	and make it build DIE -> parent DIE relationship for the alternate
	debug info file as well.
	(find_last_import_unit_point_before_die, ): Adjust to use the
	information about if the relevant DIEs are in alternate debug info
	or not.
	(build_translation_unit_and_add_to_ir): Clear the alternate DIE ->
	decl map, that is per TU just as the primary DIE -> decl map.
	Adjust to use the information about if the relevant DIEs are in
	alternate debug info or not.
	(read_debug_info_into_corpus): Build the two DIE -> DIE parent
	maps (one for the primary debug info and one for the alternate
	debug info).
	(create_read_context, has_alt_debug_info): Define new public entry
	points.
	(read_corpus_from_elf): New entry point overload that takes a
	read_context.
	* tools/bidw.cc (options::{check_alt_debug_info_path,
	show_base_name_alt_debug_info_path}): New data members.
	(display_usage): Update for the two new options
	--check-alternate-debug-info and
	check-alternate-debug-info-base-name.
	(parse_command_line): Parse the two options above.
	(main) Handle the two new options above.
	* tests/Makefile.am: Build the new runtestaltdwarf test.  Add the
	new data/test-alt-dwarf-file/* files to the build system.
	* tests/test-alt-dwarf-file.cc: New test driver.
	* tests/data/test-alt-dwarf-file/test0-common.cc: New test input
	files.
	* tests/data/test-alt-dwarf-file/libtest0-common.so: Likewise.
	* tests/data/test-alt-dwarf-file/test0.cc: Likewise.
	* tests/data/test-alt-dwarf-file/libtest0.so: Likewise.
	* tests/data/test-alt-dwarf-file/test0.h: Likewise.
	* tests/data/test-alt-dwarf-file/test0-common-dwz.debug: Likewise.
	* tests/data/test-alt-dwarf-file/test0-debug-dir/.build-id/16/7088580c513b439c9ed95fe6a8b29496495f26.debug:
	Likewise.
	* tests/data/test-alt-dwarf-file/test0-debug-dir/test0-common-dwz.debug:
	Likewise.
	* tests/data/test-read-dwarf/test1.abi: Adjust. bidw doesn't emit
	an abstract constructor/destructor anymore. It emits just the
	functions matching the cdtor symbols found in the binary.
	* tests/data/test-read-dwarf/test2.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2014-08-15 18:11:49 +02:00
parent 9742eb07ba
commit 7b126c03a0
16 changed files with 1167 additions and 165 deletions

View File

@ -52,10 +52,23 @@ enum status
STATUS_NO_SYMBOLS_FOUND,
};
class read_context;
/// A convenience typedef for a smart pointer to a
/// dwarf_reader::read_context.
typedef shared_ptr<read_context> read_context_sptr;
read_context_sptr
create_read_context(const std::string& elf_path,
char** debug_info_root_path);
status
read_corpus_from_elf(read_context& ctxt,
corpus_sptr& resulting_corp);
status
read_corpus_from_elf(const std::string& elf_path,
char** debug_info_root_path,
corpus_sptr& resulting_corp);
char** debug_info_root_path,
corpus_sptr& resulting_corp);
bool
lookup_symbol_from_elf(const string& elf_path,
@ -68,6 +81,17 @@ lookup_public_function_symbol_from_elf(const string& path,
const string& symname,
vector<elf_symbol>& func_syms);
status
has_alt_debug_info(read_context& elf_path,
bool& has_alt_di,
string& alt_debug_info_path);
status
has_alt_debug_info(const string& elf_path,
char** debug_info_root_path,
bool& has_alt_di,
string& alt_debug_info_path);
}// end namespace dwarf_reader
}// end namespace abigail

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@ runtestreadwrite \
runtestwritereadarchive \
runtestreaddwarf \
runtestlookupsyms \
runtestaltdwarf \
runtestcorediff \
runtestbidiff \
runtestdiffdwarf \
@ -41,6 +42,9 @@ runtestreaddwarf_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
runtestlookupsyms_SOURCES=test-lookup-syms.cc
runtestlookupsyms_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
runtestaltdwarf_SOURCES=test-alt-dwarf-file.cc
runtestaltdwarf_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
runtestcorediff_SOURCES=test-core-diff.cc
runtestcorediff_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
@ -277,7 +281,16 @@ data/test-lookup-syms/test1.version-script \
data/test-lookup-syms/test1.so \
data/test-lookup-syms/test1-1-report.txt \
data/test-lookup-syms/test1-2-report.txt \
data/test-lookup-syms/test1-3-report.txt
data/test-lookup-syms/test1-3-report.txt \
\
data/test-alt-dwarf-file/test0.cc \
data/test-alt-dwarf-file/libtest0.so \
data/test-alt-dwarf-file/test0-common.cc \
data/test-alt-dwarf-file/libtest0-common.so \
data/test-alt-dwarf-file/test0-report.txt \
data/test-alt-dwarf-file/test0-debug-dir/test0-common-dwz.debug \
data/test-alt-dwarf-file/test0-debug-dir/.build-id/16/7088580c513b439c9ed95fe6a8b29496495f26.debug
clean-local: clean-local-check
.PHONY: clean-local-check

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,17 @@
// To compile this type:
//
// g++ -shared -g -Wall -o libtest0-common.so test0-common.cc
#include "test0.h"
S::S()
:m0(0), m1(0), m2(0)
{}
int
S::get_m0() const
{return m0;}
char
S::get_m1() const
{return m1;}

View File

@ -0,0 +1 @@
/home/dodji/git/libabigail/fixes/tests/data/test-alt-dwarf-file/test0-common-dwz.debug

View File

@ -0,0 +1 @@
../test0-common-dwz.debug

View File

@ -0,0 +1 @@
found the alternate debug info file 'test0-common-dwz.debug'

View File

@ -0,0 +1,36 @@
// To compile this, type:
// g++ -shared -fPIC -g -Wall -L. -ltest0-common -o libtest0.so test0.cc
//
// Once the libtest0-common.so as been generated as well (from the
// test0-common.cc file), please geneate the common debug info file
// using the 'dwz' tool by doing:
//
// dwz -m test0-common-dwz.debug -r libtest0-common.so libtest0.so.
//
// Then, create a build-id subdirectory my doing:
//
// mkdir -p test0-debug-dir/.build-id/<first-two-chars-of-ascii-repr-of-build-id-of-test0-common-dwz.debug>
// Then ln -s `pwd`/test0-common-dwz.debug `pwd`/test0-debug-dir/.build-id/<build-id-of-test0-common-dwz.debug>.debug
#include "test0.h"
S global_s;
unsigned
S::get_m2() const
{return m2;}
void
foo(S& s)
{
S a = s;
char c = a.get_m1();
int i = c + a.get_m0();
i += (int) a.get_m2();
}
S*
bar()
{
return &global_s;
}

View File

@ -0,0 +1,17 @@
struct S
{
int m0;
char m1;
unsigned m2;
S();
int
get_m0() const;
char
get_m1() const;
unsigned
get_m2() const;
};

View File

@ -65,24 +65,6 @@
<data-member access='public' layout-offset-in-bits='96'>
<var-decl name='m1' type-id='type-id-9' visibility='default' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='19' column='1'/>
</data-member>
<member-function access='public' constructor='yes'>
<function-decl name='s0' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='21' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-11' is-artificial='yes'/>
<parameter type-id='type-id-8' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public' destructor='yes'>
<function-decl name='~s0' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='27' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-11' is-artificial='yes'/>
<parameter type-id='type-id-8' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public'>
<function-decl name='mem_fun' mangled-name='_ZN2s07mem_funEv' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='36' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN2s07mem_funEv'>
<parameter type-id='type-id-11' is-artificial='yes'/>
<return type-id='type-id-7'/>
</function-decl>
</member-function>
<member-function access='public' constructor='yes'>
<function-decl name='s0' mangled-name='_ZN2s0C1Ev' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='21' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN2s0C1Ev'>
<parameter type-id='type-id-11' is-artificial='yes'/>
@ -95,6 +77,12 @@
<parameter type-id='type-id-8' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public'>
<function-decl name='mem_fun' mangled-name='_ZN2s07mem_funEv' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='36' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN2s07mem_funEv'>
<parameter type-id='type-id-11' is-artificial='yes'/>
<return type-id='type-id-7'/>
</function-decl>
</member-function>
</class-decl>
<type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-8'/>
<type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='type-id-10'/>

View File

@ -17,11 +17,6 @@
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='member1' type-id='type-id-3' visibility='default' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='7' column='1'/>
</data-member>
<member-function access='public' constructor='yes'>
<function-decl name='first_type' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='9' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-4' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public' constructor='yes'>
<function-decl name='first_type' mangled-name='_ZN10first_typeC1Ev' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='9' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN10first_typeC1Ev'>
<parameter type-id='type-id-4' is-artificial='yes'/>
@ -47,11 +42,6 @@
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='member1' type-id='type-id-9' visibility='default' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='15' column='1'/>
</data-member>
<member-function access='public' constructor='yes'>
<function-decl name='second_type' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='17' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-10' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public' constructor='yes'>
<function-decl name='second_type' mangled-name='_ZN11second_typeC1Ev' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='17' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN11second_typeC1Ev'>
<parameter type-id='type-id-10' is-artificial='yes'/>

View File

@ -0,0 +1,115 @@
// -*- Mode: C++ -*-
//
// Copyright (C) 2013-2014 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
///
/// This program tests that libabigail can handle alternate debug info
/// files as specified by http://www.dwarfstd.org/ShowIssue.php?issue=120604.1.
#include <iostream>
#include <cstdlib>
#include "abg-tools-utils.h"
#include "test-utils.h"
using std::cerr;
using std::string;
struct InOutSpec
{
const char* in_elf_path;
const char* debug_info_dir_path;
const char* bidw_options;
const char* in_report_path;
const char* out_report_path;
};
InOutSpec in_out_specs[] =
{
{
"data/test-alt-dwarf-file/libtest0.so",
"data/test-alt-dwarf-file/test0-debug-dir",
"--check-alternate-debug-info-base-name",
"data/test-alt-dwarf-file/test0-report.txt",
"output/test-alt-dwarf-file/test0-report.txt"
},
{
"data/test-alt-dwarf-file/libtest0-common.so",
"data/test-alt-dwarf-file/test0-debug-dir",
"--check-alternate-debug-info-base-name",
"data/test-alt-dwarf-file/test0-report.txt",
"output/test-alt-dwarf-file/test0-report.txt"
},
// This should always be the last entry
{NULL, NULL, NULL, NULL, NULL}
};
int
main()
{
using abigail::tests::get_src_dir;
using abigail::tests::get_build_dir;
using abigail::tools::ensure_parent_dir_created;
bool is_ok = true;
string in_elf_path, ref_report_path, out_report_path, debug_info_dir;
string bidw, bidw_options;
bidw = get_build_dir() + "/tools/bidw";
for (InOutSpec* s = in_out_specs; s->in_elf_path; ++s)
{
bidw_options = s->bidw_options;
in_elf_path = get_src_dir() + "/tests/" + s->in_elf_path;
debug_info_dir = get_src_dir() + "/tests/" + s->debug_info_dir_path;
ref_report_path = get_src_dir() + "/tests/" + s->in_report_path;
out_report_path = get_build_dir() + "/tests/" + s->out_report_path;
if (!ensure_parent_dir_created(out_report_path))
{
cerr << "could not create parent directory for "
<< out_report_path;
is_ok = false;
continue;
}
string cmd = bidw + " --debug-info-dir " + debug_info_dir
+ " " + bidw_options + " " + in_elf_path + " > " + out_report_path;
bool bidw_ok = true;
if (system(cmd.c_str()))
bidw_ok = false;
if (bidw_ok)
{
cmd = "diff -u " + ref_report_path + " " + out_report_path;
if (system(cmd.c_str()))
is_ok &=false;
}
else
{
cerr << "command failed: " << cmd << "\n";
is_ok &= false;
}
}
return !is_ok;
}

View File

@ -52,8 +52,12 @@ struct options
string in_file_path;
string out_file_path;
shared_ptr<char> di_root_path;
bool check_alt_debug_info_path;
bool show_base_name_alt_debug_info_path;
options()
: check_alt_debug_info_path(false),
show_base_name_alt_debug_info_path(false)
{}
};
@ -64,7 +68,12 @@ display_usage(const string& prog_name, ostream& out)
<< " where options can be: \n"
<< " --help display this message\n"
<< " --debug-info-dir <dir-path> look for debug info under 'dir-path'\n"
<< " --out-file <file-path> write the output to 'file-path'\n";
<< " --out-file <file-path> write the output to 'file-path'\n"
<< " --check-alternate-debug-info <elf-path> check alternate debug info "
"of <elf-path>\n"
<< " --check-alternate-debug-info-base-name <elf-path> check alternate "
"debug info of <elf-path>, and show its base name\n"
;
}
static bool
@ -103,6 +112,19 @@ parse_command_line(int argc, char* argv[], options& opts)
opts.out_file_path = argv[i + 1];
++i;
}
else if (!strcmp(argv[i], "--check-alternate-debug-info")
|| !strcmp(argv[i], "--check-alternate-debug-info-base-name"))
{
if (argc <= i + 1
|| argv[i + 1][0] == '-'
|| !opts.in_file_path.empty())
return false;
if (!strcmp(argv[i], "--check-alternate-debug-info-base-name"))
opts.show_base_name_alt_debug_info_path = true;
opts.check_alt_debug_info_path = true;
opts.in_file_path = argv[i + 1];
++i;
}
else if (!strcmp(argv[i], "--help"))
return false;
else
@ -139,13 +161,47 @@ main(int argc, char* argv[])
using abigail::corpus;
using abigail::corpus_sptr;
using abigail::translation_units;
using abigail::dwarf_reader::read_context_sptr;
using abigail::dwarf_reader::read_context;
using abigail::dwarf_reader::read_corpus_from_elf;
using abigail::dwarf_reader::create_read_context;
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);
read_context_sptr c = create_read_context(opts.in_file_path, &p);
read_context& ctxt = *c;
if (opts.check_alt_debug_info_path)
{
bool has_alt_di = false;
string alt_di_path;
abigail::dwarf_reader::status status =
abigail::dwarf_reader::has_alt_debug_info(ctxt,
has_alt_di, alt_di_path);
if (status == abigail::dwarf_reader::STATUS_OK)
{
if (alt_di_path.empty())
;
else
{
if (opts.show_base_name_alt_debug_info_path)
tools::base_name(alt_di_path, alt_di_path);
cout << "found the alternate debug info file '"
<< alt_di_path
<< "'\n";
}
return 0;
}
else
{
cerr << "could not find alternate debug info file\n";
return 1;
}
}
dwarf_reader::status s = read_corpus_from_elf(ctxt, corp);
if (!corp)
{
if (s == dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND)
@ -174,8 +230,8 @@ main(int argc, char* argv[])
return 1;
}
abigail::xml_writer::write_corpus_to_native_xml(corp, 0, cout);
else
abigail::xml_writer::write_corpus_to_native_xml(corp, 0, cout);
return 0;
}