Ondrej Oprala [Mon, 5 Oct 2015 06:33:46 +0000 (08:33 +0200)]
Fix an "Unknown target name" error during make info.
* doc/manuals/libabigail-overview.rst: Fix the reference to
"ELF symbols".
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Ondrej Oprala [Mon, 5 Oct 2015 05:47:13 +0000 (07:47 +0200)]
Fix a path in doc/Makefile.am
* doc/Makefile.am: Prefix the path for DOXY_WEBSITE_SRC_CFG and
DOXY_WEBSITE_BLD_{CFG,DIR} with "/doc" to protect it against make
clean.
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Dodji Seketeli [Sun, 4 Oct 2015 11:35:19 +0000 (13:35 +0200)]
Misc style cleanups
* src/abg-reader.cc (read_is_struct): Fix comment.
(build_type_decl): Use type_decl_sptr rather than
shared_ptr<type_decl>.
(build_type_decl): Use typedef_decl_sptr rather than
shared_ptr<typedef_decl>.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sun, 4 Oct 2015 10:34:13 +0000 (12:34 +0200)]
Use the ODR to speed up type canonicalization
This is the last patch of the series of 11 patches that started at the
patch with the subject:
constify is_class_type()
And below starts the cover letter of this patch.
While analyzing some libraries like libmozjs.so[1] it appeared that
type canonicalization takes a significant time to comparing composite
types that are re-defined in each translation units again and again.
The One Definition Rule[2] says that two types with the same name
shall designate the same thing; so when a type T being canonicalized
has the same name of a canonical type C in the same ABI corpus, then
this patch considers C as being the canonical type of T, without
comparing T and C structurally. This saves us from comparing T and C.
Before this patch, `abidw --noout libmozjs.so` was taking
approximatively 5 minutes; with the patch, it takes 1 minutes and 30
seconds.
To do this, the patch changes ABI artifacts to carry a pointer to the
corpus it belongs to. Whenever an ABI artifact is added to a given
context, the corpus of that context is propagated to the artifact;
that is now possible as the artifact now carries the property of the
corpus it belongs to.
During type canonicalization the ODR-based optimization outlined above
is performed as we can now compare the corpus of a given type again
the one of another type; it's now possible to know if two types come
from the same corpus.
There are a few cases though were the optimization is not performed:
- anonymous struct; when a struct is anonymous (it has no name, as
described in the DWARF), the DWARF reader gives it a name
nonetheless, so that diagnostics can refer to that anonymous type.
But then all anonymous types in the system have the same name. So
when faced with two anonymous types (with the same name) from the
same corpus, it's wrong to consider that they name the same thing.
The patch added an "is_anonymous" property to types created by the
DWARF reader so that such anonymous types can be detected by the
type canonicalizer; they are thus not involved in this
optimization. Note that the abixml writer and reader have been
updated to emit and read this property.
- typedefs. I have seen in some boost code two typedefs of the same
name refer to different underlying types. I believe this is a
violation of ODR. I'll need to investigate on this later. And I
think we really need to detect these ODR violations as part of
this enhancement request:
https://sourceware.org/bugzilla/show_bug.cgi?id=18941.
- pointers, references, arrays and function types, as they can refer
to the two exceptions above.
This is the last patch of the series which aimed at speeding up type
canonicalization in the context of types being re-defined a lot in
translation units.
[1]: Instruction to build libmozjs.so from the mongodb sources:
- git clone https://github.com/mongodb/mongo.git
- cd mongo
- scons --link-model=dynamic build/opt/third_party/mozjs-38/libmozjs.so
[2] One Definition Rule: https://en.wikipedia.org/wiki/One_Definition_Rule
* include/abg-fwd.h (class corpus): Forward-declare this.
(is_anonymous_type): Declare this new function.
* include/abg-ir.h (corpus_sptr, corpus_wptr): Declare these
typedefs here too.
(translation_unit::{g,s}et_corpus): Declare new member functions.
(type_or_decl_base::{g,s}et_corpus): Likewise.
* src/abg-ir.cc (translation_unit::priv::corpus): New data member.
(translation_unit::priv::priv): Initialize it.
(translation_unit::{g,s}et_corpus): Define new accessors.
(translation_unit::get_global_scope): Propagate the corpus of the
translation unit to its newly created global scope.
(translation_unit::bind_function_type_life_time): Propagate the
corpus of the translation_unit to the added function type.
(type_or_decl_base::priv::corpus_): Add new data member.
(type_or_decl_base::priv::priv): Initialize it.
(type_or_decl_base::{g,s}et_corpus): Define new accessors.
(scope_decl::{add,insert}_member_decl): Propagate the context's
corpus to the member added to the context.
(decl_base::priv::is_anonymous_): Add new data member.
(decl_base::priv::priv): Initialize it.
(decl_base::{s,g}et_is_anonymous): Define accessors.
(is_anonymous_type): Define a new test function.
(decl_base::set_name): Update the "is_anonymous" property.
(type_base::get_canonical_type_for): Implement the ODR-based
optimization to type canonicalization.
* src/abg-corpus.cc (corpus::add): When a translation unit is
added to a corpus, set the corpus of the translation unit.
* src/abg-dwarf-reader.cc (build_enum_type)
(build_class_type_and_add_to_ir): Set the "is_anonymous" flag on
anonymous enums and classes.
* src/abg-reader.cc (read_is_anonymous): Define new static
function.
(build_type_decl, build_enum_type, build_class_decl): Call the new
read_is_anonymous function and set the "is_anonymous" property on
the built type declaration.
* src/abg-writer.cc (write_is_anonymous): Define new static
function.
(write_type_decl, write_enum_type_decl, write_class_decl): Write
the "is_anonymous" property.
* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt:
Adjust.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
* tests/data/test-read-dwarf/test17-pr19027.so.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sun, 4 Oct 2015 10:08:08 +0000 (12:08 +0200)]
Late canonicalize all types that reference classes when reading DWARF
Until now, the DWARF reader would late canonicalize typedefs to
classes, as well as classes. That is not enough. Let's also
late-canonicalize pointers, references and array of classes too. This
is because classes that might not be finished yet might be referenced
by those types, and so we want to wait until they are finished before
we canonicalize them.
* include/abg-fwd.h (peel_array_type): Declare new function.
* src/abg-ir.cc (peel_array_type): Define it.
(peel_typedef_pointer_or_reference_type): Peel arrays too, to get
the type of its element.
* src/abg-dwarf-reader.cc (maybe_canonicalize_type): If a pointer,
reference, array or typedef references a class, then do
late-canonicalize this type.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sun, 4 Oct 2015 09:30:57 +0000 (11:30 +0200)]
Fix infinite loop in peel_typedef_pointer_or_reference_type
* src/abg-ir.cc (peel_typedef_pointer_or_reference_type): Make
sure the variable tested in the condition is the one updated by
the loop.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 2 Oct 2015 17:57:33 +0000 (19:57 +0200)]
Try harder to hash_type_or_decl avoid the slow path
In hash_type_or_decl, when we encounter a declaration-only class
(those have no canonical type), we not trying to get the canonical
type of the definition, when the class had a definition. We were
instead going straight to the slow path of computing the recursive
hash of the type.
This patch tries to get the canonical type of the class definition,
when it exists.
* src/abg-ir.cc (hash_type_or_decl): When a declaration-only
class has a definition, then use the canonical type of that
definition as a hash value. If the class no definition, only
then, use the slow patfh of computing the recursive progressive
hash value of the type.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 2 Oct 2015 17:42:12 +0000 (19:42 +0200)]
Do not use recursive type hashing when writing out function types
When the abixml writer emits function types, it puts function
types that are referenced by pointers or references into a map on the
side. Unfortunately, that map hashes types by recursively calculating
a progressive hash value. That is dog slow and we avoid that
throughout the code base.
This patch changes that to use the numerical values of the canonical
type pointer of the function type as a hash, making abixml fast again,
again on big library as libmozjs.so.
* src/abg-writer.cc (typedef fn_shared_ptr_map): Remove.
(write_context::m_referenced_fntypes_map): Change the type of this
into type_ptr_map.
(write_context::{record_fntype_as_referenced,
fntype_is_referenced}): Use the pointer value of the canonical
type of the referenced type as key for the map.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 2 Oct 2015 16:27:34 +0000 (18:27 +0200)]
Prevent build_function_type from not canonicalizing certain types
I noticed that in some cases in build_function_type, when building the
sub-types of the function type, the construction of a function type
for the same DIE could be triggered. This happens frequently for
aggregate types that happen to be recursive. In those cases, we must
arrange for the construction of the function type for the same DIE to
return the same type that is being currently built by
build_function_type; otherwise, several types are going to be built
for the same DIE, and only one of them is going to be canonicalized.
build_function_type was just not prepared for this.
This patch fixes that.
Please note that the patch changes the test output
/home/dodji/git/libabigail.git/merge/build/tests/output/test-read-dwarf/test12-pr18844.so.abi
but it's a later patch that adjust that file because several patches
are going to require an update to that file. We are going to update
that patch in one go at the end of the patch series.
* src/abg-dwarf-reader.cc (build_function_type): Associate the
type being built with its DIE, before starting to build the
sub-types. The current type is then amended with the sub-types
that are built later.
(build_ir_node_from_die): In the case for DW_TAG_subroutine_type,
do not associate the type to the DIE here, as it's been done in
build_function_type.
* src/abg-ir.cc (function_type::set_parameters): Adjust the index
of the parameters being set to the function: they start at 1,
unless the first parameter is artificial, in which case its index
starts at zero. This is just like what is done when the function
type is constructed directly with the parameters passed as an
argument to the constructor.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 2 Oct 2015 16:21:43 +0000 (18:21 +0200)]
Fix detection of changes in pointer diff in the comparison engine
* src/abg-comparison.cc (pointer_diff::has_changes): Just
comparing the underlying type might not be enough. Let's just
compare the pointer itself. Now that we have canonical types,
comparing the pointer itself is not slower.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 2 Oct 2015 15:59:52 +0000 (17:59 +0200)]
Do not overly canonicalize types during typedef stripping
strip_typedef() canonicalizes the stripped typed, even if the input
type was not canonicalized. This can lead to early canonicalization
that is not warranted. For instance, is_compatible_with_class_type()
calls strip_typedef() and can be called during DWARF reading on types
that haven't been canonicalized yet; this was triggering a
canonicalization what was happening too early.
With this patch, strip_typedef() does not canonicalize a stripped type
if the input type wasn't itself canonicalized.
* src/abg-ir.cc (strip_typedef): Do not canonicalize the stripped
type if the input one is not canonicalized.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 2 Oct 2015 15:05:23 +0000 (17:05 +0200)]
Cleanup some IR type comparison operators
* include/abg-ir.h (operator==): In the overloads for type_decl,
enum and class_decl, turn the shared_ptr parameter into a const
reference to the shared_ptr.
* src/abg-ir.cc (operator==): Do the same in the definitions.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 2 Oct 2015 14:50:22 +0000 (16:50 +0200)]
Add missing deep equality operator for pointer and reference types
I noticed that abigail::ir::pointer_type_def_sptr and
abigail::ir::reference_type_def_sptr did not have any free form
operator '==' defined. So writing a == b with a and b being either
pointer_type_def_sptr or reference_type_def_sptr was using pointer
value comparison, as opposed to deeply comparing the pointer and
reference instances.
This patch adds those two missing operators.
* include/abg-ir.h (pointer_type_def::operator==): Add an overload
for pointer_type_def.
(reference_type_def::operator==) Add an overload for
reference_type_def.
(operator==): Add an overload for pointer_type_def_sptr and
reference_type_def_sptr.
* src/abg-ir.cc (pointer_type_def::operator==): Make the overload
for type_base& use the overload for decl_base&. Add a new
overload for pointer_type_def& and make is use the overload for
decl_base& too.
(operator==): Add free form overloads for pointer_type_def& and
reference_type_def&.
(reference_type_def::operator==): Add comments. Add an overload
for reference_type_def&.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 2 Oct 2015 18:08:27 +0000 (20:08 +0200)]
constify is_class_type()
This the first patch of a series of 11 patches which aims at speeding
up the time taken by "abidw --noout libmozjs.so". That shared library
is built among by the mongodb project, among others. And abidw is
taking around 5 minutes on my old Lenovo X220 laptop. After the
series of patches, the same command is taking one minute and a half.
The core of the optimization is to speed up type canonicalization that
happens at the end of DWARF reading, once libabigail has built the IR
or the ABI of the entire elf binary. The optimization comes from an
insight derived from the One Definition Rule of C++, as explained at
https://en.wikipedia.org/wiki/One_Definition_Rule.
But before being able to perform that optimization, several fixes and
code massaging were necessary. I have split those changes up in the
first 10 patches of the series. The last patch thus contains the crux
of the optimization. Its cover letter also contains instructions on
how to build libmozjs.so, from mongodb, for those who want to
replicate the results I have seen.
Note that some of the first 10 patches incur adjustment in the test
suite, but don't carry those necessary adjustments. All test suite
adjustments are carried by the last, 11Th patch.
The short description of the patches of the series are:
constify is_class_type()
Add missing deep equality operator for pointer and reference types
Cleanup some IR type comparison operators
Do not overly canonicalize types during typedef stripping
Fix detection of changes in pointer diff in the comparison engine
Prevent build_function_type from not canonicalizing certain types
Do not use recursive type hashing when writing out function types
Try harder to hash_type_or_decl avoid the slow path
Fix infinite loop in peel_typedef_pointer_or_reference_type
Late canonicalize all types that reference classes when reading DWARF
Use the ODR to speed up type canonicalization
And below is the ChangeLog of this first patch.
* include/abg-fwd.h (is_class_type): Take a pointer to const.
* src/abg-ir.cc (is_class_type): Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Ondrej Oprala [Thu, 1 Oct 2015 09:06:15 +0000 (11:06 +0200)]
Bug 19027 - ABI asymmetry with enums over INT_MAX
* src/abg-reader.cc (build_enum_type_decl): Use strtol
instead of atoi to parse the values and check for overflow.
* tests/data/Makefile.am: Add the new test material to the build
system.
* tests/data/test-read-dwarf/test17-pr19027.so: New test file.
* tests/data/test-read-dwarf/test17-pr19027.so.abi: Likewise.
* tests/test-read-dwarf.cc: Adjust to launch the new test.
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Dodji Seketeli [Thu, 1 Oct 2015 08:40:51 +0000 (10:40 +0200)]
Encourage people to use autoreconf -i
This lets autoreconf add stuff that might be missing, rather than just
bailing out.
* COMPILING: Mention autoreconf -i, rather than just autoreconf.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Ondrej Oprala [Wed, 23 Sep 2015 06:44:00 +0000 (08:44 +0200)]
Bug 17340 - Support pointers and references to functions
* include/abg-comparison.h (compute_diff_for_distinct_kinds): Take the
first two arguments of type const type_or_decl_base_sptr instead.
* include/abg-ir.h (translation_unit::get_function_types): Declare new
method.
(function_types): Declare new typedef.
* src/abg-comparison.cc (compute_diff_for_types): Take the first two
arguments of type const type_or_decl_base_sptr instead of a const
decl_base_sptr.
(try_to_diff): Likewise.
(try_to_diff<class_decl>): Likewise.
(try_to_diff_distinct_kinds): Likewise.
(compute_diff_for_distinct_kinds): Likewise. Also remove a variant
accepting arguments of type const type_base_sptr.
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): Skip
building a pointer if it points to the beginning of a vptr.
(build_pointer_type_def): Declare utype_decl of type
type_or_decl_base_sptr and adjust assignments to it accordingly.
(build_function_type): New function definition.
(build_function_decl): Call build_function_type instead of building
an ftype manually.
(build_ir_node_from_die): Amend case DW_TAG_subroutine_type with
appropriate calls to build a function type.
* src/abg-ir.cc (translation_unit::get_function_types): New method
definition.
({pointer,reference}_type_def::pointer_type_def): Expect that
pointed_to might not have an accompanying declaration and set a type's
name in this case as well.
({pointer,reference}_type_def::get_qualified_name): Generate a
qualified name even if the pointed-to type has no declaration.
* src/abg-reader.cc (build_function_type): New function definition.
(handle_element_node): Return a type_or_decl_base_sptr instead and
try calling handle_function_type in addition to others.
(handle_function_type): New function definition that calls
build_function_type.
(build_type): Try calling build_function_type as well.
* src/abg-writer.cc (fn_shared_ptr_map): Declare new typedef.
(write_context::{clear_referenced_fntypes_map,fntype_is_referenced,
record_fntype_as_referenced}): New member functions.
(write_translation_unit): Call the new clear_referenced_fntypes_map.
* tests/data/Makefile.am: Add the new test material to the build
system.
(write_translation_unit): Separately write function types that have
been recorded to emit by write_{pointer,reference}_type_def.
(write_{pointer,reference}_type_def): Record the type pointed to as
a type to be emitted if type == function type.
(write_function_type): Write the details of a function type in the
abixml format and unmark the type.
* tests/data/test-diff-dwarf/test32-fnptr-changes-report-0.txt: New
test reference report.
* tests/data/test-diff-dwarf/test32-fnptr-changes-v{0,1}.cc: New test
source files.
* tests/data/test-diff-dwarf/test32-fnptr-changes-v{0,1}.o: New binary
test inputs.
* tests/data/test-diff-dwarf/test33-fnref-changes-report-0.txt: New
test reference report.
* tests/data/test-diff-dwarf/test33-fnref-changes-v{0,1}.cc: New test
source files.
* tests/data/test-diff-dwarf/test33-fnref-changes-v{0,1}.o: New binary
test inputs.
* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt:
Adjust.
* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt:
Likewise.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
* tests/data/test-read-write/test27.xml: New test source file.
* tests/test-diff-dwarf.cc: Adjust to launch the new tests.
* tests/test-read-write.cc: Likewise.
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Ondrej Oprala [Wed, 9 Sep 2015 08:12:03 +0000 (10:12 +0200)]
Generalize some dwarf-reader functions to generate and return
instances of type_or_decl_base_stpr to be able to propagate
types occurring without an accompanying declaration.
* src/abg-dwarf-reader.cc (build_ir_node_from_die): Return
a type_or_decl_base_sptr instead.
(get_scope_for_die): Likewise.
(build_class_type_and_add_to_ir): Typecast the assignment from
build_ir_node_from_die properly.
(build_{qualified,reference,array,typedef}_type): Likewise.
(build_pointer_type_def): Likewise.
(build_{var,function}_decl): Likewise.
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Ondrej Oprala [Tue, 29 Sep 2015 09:05:51 +0000 (11:05 +0200)]
Move a constructor declaration
* include/abg-ir.h (decl_base): Change the decl_base() declaration's
visibility to private.
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Dodji Seketeli [Thu, 24 Sep 2015 09:00:12 +0000 (11:00 +0200)]
Bug 18535 - abidiff reports false positive ABI difference for libstdc++
When the DWARF reader of libabigail sees a data member for a given
class flagged as being a declaration, it considers the declaration as
being a definition. The reason why it doesn't strictly trust the
"is_declaration" flag of DWARF is that some DWARF producers sometimes
wrongly emit that flag.
But then, it turns out that a class declaration can have a *static*
data member without loosing its declaration-only property. This patch
thus changes the behaviour of the DWARF reader to make it consider the
class declaration as being a definition when the class has a
*non-static* data member; a static data member only is not enough to
make the class declaration become a definition.
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): The
presence of a data member shouldn't make a declaration-only class
loose its declaration-only-ness; the presence of a enon-static*
data member should.
* tests/data/test-read-dwarf/test15-pr18892.so.abi: Adjust.
* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
* tests/data/test-diff-filter/test31-pr18535-libstdc++-4.8.3.so:
New binary test input.
* tests/data/test-diff-filter/test31-pr18535-libstdc++-4.9.2.so:
Likewise.
* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt:
New test reference output.
* tests/data/Makefile.am: Add the new test material to the build
system.
* tests/test-diff-filter.cc (in_out_specs): Add the new test
inputs to the set of inputs to consider.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 21 Sep 2015 13:23:14 +0000 (15:23 +0200)]
Remove duplicated runtestreaddwarf test
* tests/Makefile.am: Remove one copy of the runtestreaddwarf test
that is present twice.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 21 Sep 2015 13:22:35 +0000 (15:22 +0200)]
Add a missing function declaration
* include/abg-tools-utils.h (dir_name): Add missing function
declaration.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 21 Sep 2015 13:20:10 +0000 (15:20 +0200)]
Remove some dead code in abilint
* tools/abilint.cc (options::bidiff): Remove.
(options::options): Adjust.
(display_usage): Remove usage string for --bidiff
(parse_command_line): Remove parsing of un-implemented option
--bidiff.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 21 Sep 2015 13:14:26 +0000 (15:14 +0200)]
Add a new --abidiff option to abidw
This is a debugging and sanity check option. It saves the abi of the
ELF binary to a temporary file, reads it back and compares the abis of
the temporary file against the abi of the input ELF binary.
* tools/abidw.cc (options::abidiff): New data member.
(options::options): Initialize it.
(display_usage): Add a usage string for the new --abidiff option.
(parse_command): Parse the new --abidiff options.
(main): Save the abi of the input elf in a temporary abixml file;
read it back and compare both.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 21 Sep 2015 12:49:29 +0000 (14:49 +0200)]
Misc style fixes
* src/abg-hash.cc (class_decl::hash::operator()): Use a temporary
variable to ease debugging.
* src/abg-reader.cc (read_context::is_wip_type): Make this
function const.
* src/abg-writer.cc (write_context): Move data members at the top.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 21 Sep 2015 11:51:31 +0000 (13:51 +0200)]
Speed up type canonicalization by avoiding recursive hashing
Recursive type hashing was showing up as the major hot spot of
performance profiles. After spending a few days on trying to speed it
up, I have officially declared recursive tree node hashing as a slow
process and I am giving up.
I have thus decided to not use that at type canonicalization time.
Rather, I am proposing a new type canonicalization routine where types
are first hashed by hashing their pretty representation string.
Basically, if T is the total number of types in the system and C the
number of classes of equivalences (or the number of canonical types),
the number of type comparisons done by a naive type canonicalization
routine is N x C. With the worse C being equal to N itself, that
worse number of comparisons is N*N.
By using a hash table to store the canonical types, keyed by a hash of
their pretty representation string, the number of type comparisons can
be brought down to N*P, where P is a the greater number of which
pretty representation string hash collide. That number P is usually
small; my measurements show that N usually goes from 1 to 3. And
moreover, computing the hash of the pretty representation string of
the function is way faster than using the recursive type hash!
As a result, running abidw on the libcilkrts.so library, from GCC goes
from 12 minutes to 0.4 seconds!
Incidentally, now that we are not trying to speed up the recursive
type hashing process, all the complicated business we had around
caching the result of the hashing is gone! I was thinking that hash
cashing was inherently a bad idea, especially for recursive types --
that refer to themselves directly or indirectly, because in those
case, depending on when you cached the hash value, the value of the
hashing can be different.
The abixml writer's code doesn't use the recursive type hash anymore
either; it uses the pointer value of the canonical type as hash.
Super fast too!
The patch had to fix pieces here and there to comply with the fact
that canonical types are now used across the board in a mandatory
fashion.
* include/abg-ir.h (canonical_types_map_type): Adjust this typedef
to make it point to an unordered_map which the key is now a string
and the value is a vector of types.
(type_or_decl_base::{get_cached_hash_value, set_cached_hash_value,
cached_hash}): Remove these member functions and type.
(struct type_base::cached_hash): Remove.
* src/abg-ir.cc (struct type_or_decl_base::priv::hash_): Remove.
(type_or_decl_base::priv::priv): Adjust.
(type_or_decl_base::{g,s}et_cached_hash_value): Remove.
(type_base::get_canonical_type_for): For declaration-only classes,
look at their definition for the canonical_type. Do not use
recursive type hashing anymore. Rather, use the pretty
representation string, and hash that.
(class_decl::base_spec::get_hash): Do away with hash value caching
here.
(class_decl::operator==): For decl-only classes, look at their
definitions for canonical types.
(hash_type_or_decl): Adjust comment. Use the canonical type
pointer value for type hash. That's the fast path. Otherwise, if
not available, fall back to a slow path which is the recursive
type hash we were using before.
* src/abg-dwarf-reader.cc (maybe_canonicalize_type): Schedule all
classes and typedef to classes for late canonicalization.
* src/abg-hash.cc (type_base::dynamic_hash::operator()): There is
no hash value cashing anymore.
(type_base::cached_hash::operator()): Remove.
* src/abg-reader.cc (read_context::get_type): Slight style
adjustment.
(read_translation_unit_from_file)
(read_translation_unit_from_buffer): Do not forget to canonicalize
types when reading just one translation unit.
(build_type_tparameter, build_template_tparameter): Canonicalize
the type.
* src/abg-writer.cc (struct type_hasher): New hasher type.
(type_ptr_map): Use a deep pointer comparison equal operator
functor, and canonical types as type hash values.
(write_class_decl): Do not write size and alignment on decl-only
classes. Do not record decl-only classes as being emitted. Their
definition must be emitted before.
* tests/test-read-write.cc (main): Do not do abi testing on
translation units (as opposed to doing it on abi corpora) as that
code is not wet yet. We need to know how to diff namespaces.
* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 21 Sep 2015 09:11:05 +0000 (11:11 +0200)]
Update qualified name of a decl when it's added to its context
The building of the qualified name of a declaration is showing up in
performance profile as a hot spot. This patch addresses that
performance issue by updating the qualified name of a declaration
whenever the declaration is added to its context and saving the
result. Getting the qualified name later is just a matter of a string
copy. I guess we can do something about those string copies later as
they don't show up high performance profiles at the moment.
* include/abg-ir.h (decl_base::priv_): Make this be public, so
that the qualified name updater function can access it.
(class class_decl): Make set_member_is_static() a friend function.
* src/abg-ir.cc (class ::qualified_name_setter): New tree walking
type.
(decl_base::get_qualified_parent_name): Do not do any computation
here. Just return the pre-computed qualified parent name string.
(decl_base::get_qualified_name): Likewise, for qualified name.
(scope_decl::{add,insert}_member_decl): Update the qualified name of the
newly added member. Set the scope of the member here. It's not
going to be set elsewhere, from now on.
(add_decl_to_scope): Do not set the scope here anymore. Just call
scope_decl::add_member_decl and let it do the work.
(insert_decl_into_scope): Likewise, just call
scope_decl::insert_member_decl and let it do the work.
(class_decl::{add_data_member, add_member_function}): Do not
handle details of context setting at this point. Let
scope_decl::add_member_decl do it. Adjust the properties of the
context relation afterwards. In add_data_member, when a data
member changes its static-ness, move the data member into the
class_decl::priv::non_static_data_members_ or out of it, as
necessary.
(class_decl::insert_member_decl): By default, a data member is
considered static.
(set_member_is_static): Move this definition after the definitions
of class_decl, so that this function can see those. Also, when a
data member changes its static-ness, move the data member into the
class_decl::priv::non_static_data_members_ or out of it, as
necessary.
(class_decl::add_member_function_template): As we the
underlying function template decl to the context, do not do any
scope adding for it here.
(::qualified_name_setter::{do_update, visit_begin}): Define new
member functions.
(update_qualified_name): Define new static function.
* src/abg-reader.cc (build_class_decl): Make build_function_decl,
build_var_decl, build_function_tdecl and build_class_tdecl
automatically add the created decl to their context, and then
update the properties of the resulting member decl later, just
like what we do in the DWARF reader.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 21 Sep 2015 08:53:33 +0000 (10:53 +0200)]
Add new test functions
This patch adds a new set of test functions that are going to be used
in subsequent patches to come.
* include/abg-fwd.h (is_function_decl, is_decl, is_namespace)
(is_scope_decl): Declare new function overloads.
* src/abg-ir.cc (is_function_decl, is_decl, is_namespace)
(is_scope_decl): Define them.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 21 Sep 2015 08:46:06 +0000 (10:46 +0200)]
Constify some diff-utils functor operators
* include/abg-diff-utils.h (deep_ptr_eq_functor::operator()): Make
the overloads be const.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 16 Sep 2015 09:37:22 +0000 (11:37 +0200)]
Support source_location_not_in and source_location_not_regexp suppressions
This patch adds support for properties source_location_not_in and
source_location_not_regexp in the [suppress_type] section of
suppression specifications. So the suppression specification:
[suppress_type]
source_location_not_in = foo1.h, foo2.h bar1.h bar2.h
suppresses ABI change reports about types that are *NOT* defined in
files foo{1,2}.h and bar{1,2}.h. The intended use of this construct is to
constrain abi change reports to types that are part of the API of a
given shared library. The API of the library is supposed to be
defined in foo.h and bar.h only.
Similarly, the suppression specification:
[suppress_type]
source_location_not_regexp = (foo|bar){1,2}\\.h
suppresses ABI change reports about types that are not defined in the
same set of files foo1.h, foo2.h, bar1.h and bar2.h.
* include/abg-ini.h (enum property_value::value_kind): Add a
LIST_PROPERTY_VALUE kind.
(class {list_property_value, list_property}): Declare new types.
(is_list_property, is_list_property_value): Declare new functions.
* src/abg-ini.cc (struct list_property_value::priv): Define new
type.
(list_property_value::{list_property_value, get_content,
set_content, as_string}): Define new member functions.
(is_list_property_value): Define new function.
(struct list_property::priv): Define new type.
(list_property::{list_property, get_value, set_value,
handle_escape}): Define new member functions.
(is_list_property): Define new function.
(read_context::buf_): New data member.
(read_context::{peek, get, put_back, good, eof, read_string,
read_list_property_value}): New member functions.
(read_context::read_next_char): Use the new read_context::{get,
good, eof} member function, rather than using the input stream
directly.
(read_context::{skip_white_spaces, skip_comments,
skip_white_spaces_or_comments, read_property_name,
read_function_name, read_function_argument,
read_function_call_expr, read_property_value,
read_tuple_property_value, read_section_name, read_section}):
Adjust to use the new member functions of read_context rather than
using the input stream directly.
(read_context::read_string_property_value): Likewise. Use the new
read_context::read_string() method.
(read_context::{read, write}_property): Support reading list_property.
* include/abg-comparison.h
(type_suppression::{get_source_locations_to_keep,
set_source_locations_to_keep,
set_source_location_to_keep_regex_str,
get_source_location_to_keep_regex_str}): Add new member functions.
* src/abg-comparison.cc
(type_suppression::priv::{source_location_to_keep_,
source_location_to_keep_regex_str_,
source_location_to_keep_regex_}): Add new data members.
(type_suppression::priv::{g,s}et_source_location_to_keep_regex):
Define new member functions.
(type_suppression::{g,s}et_source_locations_to_keep): Define new
member functions.
(type_suppression::{g,s}et_source_location_to_keep_regex_str):
Likewise.
(type_suppression::suppresses_type): Support
"source_location_not_regexp" and "source_location_not_in"
properties of suppression specifications.
(read_type_suppression): Likewise. Also adjust to the fact that
ta tuple property value that is a list of strings is not a list
property value.
* doc/manuals/libabigail-concepts.rst: Add documentation for
source_location_not_in and source_location_not_regexp.
* tests/data/test-diff-suppr/libtest26-loc-suppr-v{0,1}.so: New
binary test inputs.
* tests/data/test-diff-suppr/test26-loc-suppr-{0,1,2}.suppr: New
suppression specification test inputs.
* tests/data/test-diff-suppr/test26-loc-suppr-report-{0,1,2,3}.txt:
New test reference reports.
* tests/data/test-diff-suppr/test26-loc-suppr-v{0,1}.cc: Source
code of the test binary input above.
* tests/data/test-diff-suppr/test26-loc-suppr.h: Likewise.
* tests/data/Makefile.am: Add the new test material to source
distribution.
* tests/test-diff-suppr.cc (in_out_specs): Add the new test inputs above.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 16 Sep 2015 09:16:25 +0000 (11:16 +0200)]
Pass simple property data by reference
* include/abg-ini.h (simple_property::{simple_property,
set_value}): Pass the value shared pointer by reference.
* src/abg-ini.cc (simple_property::{simple_property, set_value):
Pass the value shared pointer by reference.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Tue, 15 Sep 2015 09:02:55 +0000 (11:02 +0200)]
Make string_ends_with() allow long suffixes
Make string_ends_with() allow suffixes that are as long as the string we are
looking at.
* src/abg-tools-utils.cc (string_ends_with): Allow suffixes of the
same size as the input string.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sun, 13 Sep 2015 13:47:10 +0000 (15:47 +0200)]
Add missing 'break' keyword in e_machine_to_string()
* src/abg-dwarf-reader.cc (e_machine_to_string): Add missing
'break' keywords in switch/case statement.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 9 Sep 2015 11:56:02 +0000 (13:56 +0200)]
Fix compilation warnings in abipkgdiff.cc
* tools/abipkgdiff.cc (package::erase_extraction_directory)
(extract_rpm, extract_deb, extract_tar)
(erase_created_temporary_directories_parent): Check the return
value of the system() function.
(extract_package): Add necessary white space.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 9 Sep 2015 07:19:10 +0000 (09:19 +0200)]
Fix spurious errors in the install-man-and-info-doc target
* doc/manuals/Makefile.am (install-man-and-info-doc): Don't check
for abidiff.info, that thing doesn't exist. Rather, check for
abigail.info. Use gzip -f in case the zipped file exists already.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 9 Sep 2015 06:17:27 +0000 (08:17 +0200)]
Compare qualified name in decl_base comparison operator
* src/abg-ir.cc (equals): In the overload for decl_base, compare
qualified names, not just names.
* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Tue, 8 Sep 2015 13:48:13 +0000 (15:48 +0200)]
Fix a stupid typo in function sorting code
* src/abg-comparison.cc (function_comp::operator()): Fix a typo
preventing the proper sorting of function name when their
declarator names are equal. Oops.
* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Tue, 8 Sep 2015 08:11:34 +0000 (10:11 +0200)]
Update manual for abipkgdiff
* doc/manuals/abipkgdiff.rst: Say we support tarballs and plain
directories.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 7 Sep 2015 21:42:17 +0000 (23:42 +0200)]
Adjust {s,g}et_show_stats() to use a reference
* include/abg-dwarf-reader.h ({s,g}et_show_stats): Use a reference
to the reader.
* tools/abidiff.cc (main): Adjust.
* tools/abidw.cc (main): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 7 Sep 2015 21:23:51 +0000 (23:23 +0200)]
Use cache type hash values only after type canonicalization is done
Look at this code:
struct list;
struct payload
{
int value;
list* parent_list; //<-- the hash value of struct list when looking
// through this pointer is the non-zero
// value as computed on the struct list
// type below.
};
struct list
{
payload* p; // <-- While walking the struct list type, the hash
// value of the 'struct list' sub-tree node when
// looking through this pointer is zero, because we
// are still computing the hash value of struct list.
// we do it this way to break the otherwise infinite
// recursion that might occur here.
list* next; // <-- likewise here.
list* prev; // <-- likewise here.
}; // <-- when we reach this point the hash value of struct list
// is computed and is different from zero.
Basically, when a type refers to itself in one of its sub-type (like
struct list here, where list::p refers to struct list, because its
type contains a pointer to struct list), then we need to devise a way
to break the infinite recursion we might fall into when computing its
hash value.
So, when computing the hash value of struct list, when we look at the
type of list::prev, which is "list*", we say that the hash value of the type
pointed to by the type of list::next (which is struct list itself) is
zero. This allows us to break the possibly infinite recursion here.
But then, this means that the hash value of "struct list" depends on
*when* we request that hash value. If we are computing the hash value
of struct list itself, then the temporary value of "struct list" is
zero. But then once we are done computing the hash value of "struct
list", that value becomes non-zero.
Hence, the hash value of a type depends on when that value is
computed.
But then if we want to cache that hash value and re-use it later,
which value should we cache? Definitely not the zero value!
So in other words, we can use (and thus cache) the hash value of a
given type T only after the hash values of all types which use T have
been computed.
To satisfy that condition, we decide to use the (cached) hash value of
each type only after we've computed all the hash values of all types
of the system.
So, during type canonicalization, when a type T is canonicalized, this
patch stores the hash value of T. But then it's only when all types
are canonicalized that the hashing code is allowed to re-use the
cached value of types.
This fixes the issues of spurious type differences introduced when the
same type was read either from DWARF or from abixml. Those
differences where introduced by differences in the order of hashing
types which sub-types refer to themselves. The patch also updates
regression tests accordingly.
* src/abg-dwarf-reader.cc (read_debug_info_into_corpus): Before we
read debug info and build the IR, set a flag in the environment
saying that type canonicalization isn't finished yet. But then,
after type canonicalization is done, flip that flag to say that
type canonicalization is done.
* src/abg-reader.cc (read_corpus_from_input): Likewise.
* src/abg-ir.cc (type_base::get_canonical_type_for): Once a type
has been canonicalized, cache its hash value.
* src/abg-hash.cc (type_base::dynamic_hash::operator()): If type
canonicalization has been done and if the type has a cached value,
use that one.
* tests/data/test-read-dwarf/test2.so.abi: Adjust.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 7 Sep 2015 20:27:50 +0000 (22:27 +0200)]
Introduce the concept of environment
There are resources needed by the type system and other artifacts of
libabigail. Today, when the life time of those resources need to be
greater than all of artifacts of Abigail, then said resources are made
global.
But then global resources are not great, if anything because they
complicate the future use of the library in concurrent computing
setups.
As I was in the need to add one resource to be used by the type
system, I decided to sit down and first overhaul how these long lived
resources needed to be handled.
And here comes the concept of "environment". An environment is a
place where one can put resources that need to live longer than all
the other artifacts of the Abigail system. And so, the code that
creates Abigail artifacts needs and environment of for said artifacts
to use. In other words, artifacts now use an environment.
This has interesting and strong implications. We can only compare two
artifacts if they use the same environment. This is quite a strong
requirement.
But then when this requirement is fulfilled, comparing two types
amounts to just comparing two pointer values; hash values for types
can also be cached. Now *that* is great for speed of comparison, is
it not?
This patch introduce the concept environment (which is basically a new
abigail::ir::environment type), removes the global variables and uses
the environment instead. Each ABI artifact (either type or decl) now
has a ::get_environment() member function to get its environment.
This patch also disables the caching of hash values because the
caching must happen only *after* all types have been canonicalized.
We were not respecting that requirement until now, and that introduces
wrong hash values. A subsequent patch is going to re-introduce hash
value caching again, once the infrastructure is in place to set a flag
in the environment (hah!) once type canonicalization is done, and then
later read that flag when some client code requests a hash value, to
know if we should look in the hash value cache or not.
The patch obviously changes the output of numerous regression tests
(if anything b/c it disables hash value caching) so 'make check'
yields regressions. But then, it's only the subsequent patch that
updates the tests.
* include/abg-ir.h: Adjust note about memory management.
(class environment): Declare new class.
(translation_unit::translation_unit): Take an environment in
parameter.
(translation_unit::{g,s}et_environment): Declare new member
functions.
(type_or_decl_base::{g,s}et_environment): Likewise.
(type_or_decl_base::{get_cached_hash_value,
set_cached_hash_value}): Change the name of
decl_base::peek_hash_value() and decl_base::set_hash() here into
these and move them here.
(type_or_decl_base::hashing_started): Move
decl_base::hashing_started() here.
({g,s}et_environment_for_artifact): Declare new functions.
(class decl_base): Move member functions hashing_started(),
peek_hash_value() and set_hash() on to the type_or_decl_base base
class.
(scope_decl::scope_decl): Initialize the virtual member
type_or_decl_base().
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove these static member
functions. They are now non-static member functions of the new
environment type.
* src/abg-ir.cc (class environment_setter): New internal class.
(get_canonical_types_map): Remove. This now becomes a member
function of the environment type.
(class usage_watchdog): Remove.
(usage_watchdog_{s,w}ptr): Remove these typedefs.
(get_usage_watchdog_wptr, ref_usage_watchdog)
(maybe_cleanup_type_system_data): Remove these functions.
(translation_unit::priv::usage_watchdog_): Remove data member.
(translation_unit::priv::env_): New data member.
(translation_unit::priv::priv): Take an environment and initialize
the new env_ data member. Do not initialize the removed
usage_watchdog_.
(translation_unit::translation_unit): Take an environment
parameter.
(translation_unit::get_global_scope): Set the environment of a new
global scope.
(translation_unit::{g,s}et_environment): New accessors.
(translation_unit::bind_function_type_life_time): Set the
environment of the function type.
(struct environment::priv): New class.
(environment::{environment, ~environment, get_canonical_types_map,
get_variadic_parameter_type_decl, canonicalization_is_done}): New
member functions.
(struct type_or_decl_base::priv): New class.
(type_or_decl_base::{type_or_decl_base, hashing_started,
get_cached_hash_value, set_cached_hash_value, set_environment,
get_environment, traverse}): New member functions.
({s,g}get_environment_for_artifact): New functions.
(decl_base::priv::{hash_, hashing_started}): Remove.
(decl_base::priv::priv): Adjust.
(decl_base::decl_base): In the copy constructor, initialize the
virtual base type_or_decl_base. Do not initialize hash_ and
hashing_started data member that got removed.
(decl_base::{hashing_started, peek_hash_value, set_hash}): Remove
member functions.
(strip_typedef): Set the environment of the new type which has its
typedefs stripped off. Adjust the call to type_or_void().
(scope_decl::{add, insert}_member_decl): Set the environment of
the new member decl to the environment of its scope.
(synthesize_type_from_translation_unit)
(synthesize_function_type_from_translation_unit): Set the
environment for the newly synthesized type. Adjust calls to
type_or_void().
(type_or_void): Take an environment in parameter. Get the void
type from the environment.
(get_canonical_types_map): Remove.
(type_base::get_canonical_type_for): Get the canonical types map
from the environment, not from a global variable.
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove.
(pointer_type_def::pointer_type_def): Adjust call to type_or_void.
(reference_type_def::reference_type_def): Likewise.
(function_decl::parameter::get_pretty_representation): Get the
variadic parameter type decl from the environment.
(class_decl::priv::classes_being_compared_): Remove static data
member.
(class_decl::priv::{mark_as_being_compared,
unmark_as_being_compared, comparison_started): Use the "classes
being compared" map from the environment.
(class_decl::base_spec::get_hash): Adjust.
(keep_type_alive): Get the alive types array from the environment)
not from a global variable anymore.
(get_next_string): Put the counter in thread-local storage.
* src/abg-hash.cc (scope_decl::hash::operator())
(function_decl::hash::operator()): Do not handle caching (here).
* include/abg-corpus.h (corpus::{g,s}et_environment): Declare new
accessors.
* src/abg-corpus.cc (corpus::priv::env): New data member.
(corpus::priv::priv): Initialize it.
(corpus::corpus): Take an environment in parameter.
(corpus::{g,s}et_environment): Define new member functions
(corpus::add): Set the environment of the newly added translation
unit, if it's not set already set. In any case, assert that the
translation unit must use the same environment as the corpus.
* include/abg-dwarf-reader.h (create_read_context)
(read_corpus_from_elf): Take an environment parameter.
({s,g}et_debug_info_root_path, {s,g}et_environment): Declare new
functions.
* src/abg-dwarf-reader.cc (read_context::{env_,
offline_callbacks_}): New data members.
(read_context::read_context): Initialize them.
(read_context::clear_per_translation_unit_data): Do not touch the
void type declaration, it doesn't belong to the translation unit.
(read_context::{env, offline_callbacks}): New accessors.
(read_context::{create_default_dwfl}): New member function.
(read_context::dwfl_handle): Add a setter overload.
({s,g}et_debug_info_root_path): Define new accessors.
(create_default_dwfl, create_dwfl_sptr, create_default_dwfl_sptr):
Remove these.
(build_translation_unit_and_add_to_ir): Adjust to pass the
environment to the newly created translation unit.
(build_function_decl): Adjust to pass the environment to the
created function and parameter types. Get variadic parameter type
node from the current environment, not from a global variable.
And do not try to canonicalize function types here.
(read_debug_info_into_corpus): Set the environment of the newly
created corpus.
(build_ir_node_for_void_type): Get the void type node from the
current environment, rather than from a global variable.
(create_read_context): Take the environment in parameter.
Create the default dwarf front end library handle using the new
member function of the read context. Set the current environment
used by the reader.
(read_corpus_from_elf): Take an environment in
parameter. Overhaul. This is now simpler.
(has_alt_debug_info): Adjust the call to create_read_context() to
make it pass an empty environment.
* include/abg-fwd.h (class environment): Forward declare.
* include/abg-reader.h (read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream)
(read_corpus_from_native_xml): Take an environment in parameter.
* src/abg-reader.cc (read_context::m_env): New data member.
(read_context::read_context): Initialize it.
(read_context::{get_environment, set_environment}): New data
member.
(read_translation_unit): Set environment of the new translation
unit.
(read_corpus_from_input): Set the environment of the new corpus.
(read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream, read_corpus_from_native_xml):
Take an environment in parameter.
(build_function_parameter): Get variadic parameter type from the environment.
* src/abg-comparison.cc (compute_diff): Add asserts in all the
overloads to ensure that the artifact being compared come from the
same environment.
* tests/print-diff-tree.cc (main): Create an env for the ABI
artifacts to use.
* tests/test-abidiff.cc (main): Likewise.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-ir-walker.cc (main): Likewise.
* tests/test-read-dwarf.cc (main): Likewise.
* tests/test-read-write.cc (main): Likewise.
* tools/abicompat.cc (main): Likewise.
* tools/abidiff.cc (main): Likewise.
* tools/abidw.cc (main): Likewise.
* tools/abilint.cc (main): Likewise.
* tools/abipkgdiff.cc (main): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Mon, 7 Sep 2015 20:37:53 +0000 (22:37 +0200)]
Fix redundant const qualifier stripping
In the DWARF reader, we strip the const qualifier when it applies to
reference types because a reference is always const. Those redundant
const qualifiers can later introduce spurious changes in type
comparison.
But then we were forgetting to add the stripped type to the IR, in
some cases. This patch fixes that.
* include/abg-ir.h (operator&, operator~): Add overloaded bitwise
operators for qualified_type_def::CV.
* src/abg-ir.cc (operator&, operator~): Define them.
* src/abg-dwarf-reader.cc (maybe_strip_qualification): Fix
comment. If there are multiple qualifiers, only strip the const
one.
(build_ir_node_from_die): Once we've built a qualified type, if
the 'const' qualifier is stripped, then add the new (stripped)
type to the set of new types.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 5 Sep 2015 08:29:00 +0000 (10:29 +0200)]
Fix wording in README
* README: Fix wording.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 2 Sep 2015 13:35:17 +0000 (15:35 +0200)]
Misc style fixes
* src/abg-hash.cc (class_decl::hash::operator()): Remove some dead
code.
* src/abg-ir.cc (equals): In the overload for class_decl,
re-indent.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 2 Sep 2015 13:33:27 +0000 (15:33 +0200)]
Re-arrange some regression tests order
runtestreaddwarf and runtestcanonicalizetypes.sh are now the tests
which takes the most time. Run them at the beginning.
* tests/Makefile.am: Run runtestreaddwarf and
runtestcanonicalizetypes at the beginning.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 2 Sep 2015 12:28:41 +0000 (14:28 +0200)]
Bug 18904 - Fix support for C++ rvalue references
* src/abg-comparison.cc (reference_diff::has_changes): Just
compare the references, rather than assuming that the change can
only be on underlying types.
(reference_diff::report): Describe lvalue/rvalue changes for
references.
* src/abg-ir.cc (reference_type_def::reference_type_def): Properly
set the name for an rvalue reference.
(equals): For references, compare lvalue-ness too.
(reference_type_def::get_qualified_name): Properly set rvalue
reference names.
* tests/data/test-diff-filter/test30-pr18904-rvalueref-liba.so:
New test input.
* tests/data/test-diff-filter/test30-pr18904-rvalueref-libb.so:
New test input.
* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt:
New test reference output.
* tests/data/Makefile.am: Add the new files to source
distribution.
* tests/test-diff-filter.cc (in_out_specs): Run the new tests.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 2 Sep 2015 11:41:34 +0000 (13:41 +0200)]
More type degradation fixes (from DWARF to abixml)
The series of fixes to make
"abidw foo > foo.abi && abidiff foo foo.abi"
work continues.
On a binary submitted as part of bug 18904, I am still seeing type
degradation. This patch addresses the different cases of degradation
that are happening.
* include/abg-fwd.h (get_type_scope): Declare new function.
* src/abg-hash.cc (var_decl::hash::operator()): Do not cache the
hash because that can alter the hash computing of a larger type
which embeds a var decl as a member declaration. This is
especially true if the var decl indirectly references the larger
type. The only way to cache the value of a var decl would be to
wait after all canonical types have been computed. We'd then seal
all types. After that sealing happens, we can cache var decls
starting from the top-level ones.
(function_decl::hash::operator()): Likewise.
* src/abg-ir.cc (get_type_scope): Define new functions.
* src/abg-reader.cc (read_is_declaration_only): Declare this
function earlier.
(typedef const_types_map_it): Adjust this to make it point to a
map of string and vector of types, as opposed to a map to string
and type as it was before.
(typedef types_map_it): New typedef.
(read_context::map_id_and_node): Map a type id to the last
xmlNodePtr that represent a *declaration*. That gives more leeway
to the declaration resolution code to choose the right definition
later. Otherwise, there are cases where the wrong definition. By
wrong definition, I mean a definition that is different from the
one chosen by the DWARF reading code, for a given declaration.
Basically for a given ABI corpus, a type declaration resolve to
the first definition seen in the corpus.
(read_context::get_all_type_decls): Define new member function.
(read_context::types_equal): Use qualified names only if both
types have a scope.
(read_context::key_type_decl): Now a given ID is associated to
*all* the declarations and definition that have that ID.
(read_translation_unit_from_input): Make sure the current corpus
node points to the right node.
(build_class_decl): Resolve class declarations to the first
definition seen in the corpus. Key a type decl before reading its
members as a reading a member can request the current decl. No
need to try and canonicalize a member type, as build_class_decl()
does that already.
* tests/data/test-read-dwarf/test16-pr18904.so: New test binary
input.
* tests/data/test-read-dwarf/test16-pr18904.so.abi: New test
output reference.
* tests/test-read-dwarf.cc: Run the test above.
* tests/data/Makefile.am: Add the new test input to source
distribution.
* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.
* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sun, 30 Aug 2015 15:56:19 +0000 (17:56 +0200)]
Bug 18892 - type degradation from DWARF to abixml on libtsan.so
abidiff-ing libtsan.so again the output of abidw libtsan.so does not
yield the empty set. This is because some types, especially an enum (in
certain cases) when read (de-serialized) from DWARF doesn't hash the
same as when de-serialized from abixml.
This is because an enum type can have a linkage name, referred to by
the DW_AT_linkage_name DWARF attribute. This linkage_name was being
read from DWARF but wasn't serialized to abixml. At de-serialization
time, well, the linkage_name information was lost. Oops.
Also, I have seen that in some case we can canonicalize enum types too
early, when we de-serialize them from abixml, before we are done
building them.
This patch addresses these issues.
* src/abg-reader.cc (read_context::maybe_canonicalize_type): Late
canonicalize enum types.
(build_enum_type_decl): Read the linkage name of the enum type.
* src/abg-writer.cc (write_enum_type_decl): Emit the linkage name
of the enum type.
* tests/data/test-read-dwarf/test15-pr18892.so: New binary test
input.
* tests/data/test-read-dwarf/test15-pr18892.so.abi: New test
output reference.
* tests/data/Makefile.am: Add the new test inputs above to source
distribution.
* tests/test-read-dwarf.cc (in_out_specs): Run the two tests above.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sun, 30 Aug 2015 14:19:50 +0000 (16:19 +0200)]
Bug 18893 - type degradation from dwarf to abixml on libGLU.so
abidiff-ing libGLU.so against the result of 'abidw libGLU.so' does not
yield the empty set. This is because hashing certain types when they
are read (de-serialized) from DWARF doesn't give the same result as
when they are de-serialized from abixml. I call this type
degradation. And it leads to spurious comparison differences.
This is due to several issues.
1/ The logical link between a class declaration and its definition
-- that is built when reading types from DWARF is not preserved in
abixml. So, for example, when a class S refers to itself via a
pointer to its declaration, that type might hash differently when
read from DWARF and when read from abixml. When read from abixml
it's a pointer to S itself. But then that 'self' can be a copy of S
that is defined in another file because abixml doesn't enforce the
One Definition Rule from C++ either.
2/ As the result of hashing is kept in a cache for var_decl and
function_decl, hashing those decl before their types are completely
built caches a value that becomes wrong when their type become
completely built.
3/ In DWARF, a class which has a virtual member function can still
be considered as being declaration-only. And its definition can
come later in the DWARF info. Our DWARF reader removes the
"declaration-only" flag from a class as soon as it sees virtual
member functions in that class; that makes us consider that class as
a definition. And then later when we read the real definition of
the class we have two classes of the same name, with different
layouts/size in the system. This leads to spurious comparison
differences too.
This patch addresses issues 1, 2 and 3.
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): Do not
consider that virtual member functions disqualify a class from
being declaration-only.
* src/abg-hash.cc (var_decl::hash::operator()): Do not cache the
result of hashing before we are done building the type of the
var_decl.
(function_decl::hash::operator()): Likewise, do not cache the
result of hashing before we are done building the type of the
function_decl.
* src/abg-reader.cc (build_class_decl): Build the link between a
class declaration and its definition. If there are several
definitions of a class in the corpus, keep just one.
* src/abg-writer.cc (write_class_is_declaration_only): Emit the
link between a class declaration and its definition.
(write_class_decl): Emit a class declaration even if it has a
definition. The definition is going to be emitted
separately.
* tests/data/test-read-dwarf/test14-pr18893.so: New binary test
input.
* tests/data/test-read-dwarf/test14-pr18893.so.abi: New test
reference output.
* tests/data/Makefile.am: Add the new test input files to source
distribution.
* tests/test-read-dwarf.cc (in_out_specs): Run the new tests.
* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sun, 30 Aug 2015 13:41:55 +0000 (15:41 +0200)]
Use common canonicalization oracle when reading class type from dwarf
When building a class type from DWARF, we were locally trying to
figure out if we should early canonicalize the resulting class type or
not. We should rather use the common code that knows how to decide
that. And this is what this patch does.
* src/abg-dwarf-reader.cc (build_ir_node_from_die):
(maybe_canonicalize_type): Move the specific logic that was in
build_ir_node_from_die (for class types) here.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sun, 30 Aug 2015 15:10:43 +0000 (17:10 +0200)]
Fix crash in file type guessing
* src/abg-tools-utils.cc (string_ends_with): Handle the case where
the string suffix is longer than the string itself.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 15:17:48 +0000 (17:17 +0200)]
Bug 18894 - Fix representation of enumerators in abixml format
It turns out that using a size_t to serialize an enumerator is not
enough to represent things like enum foo {value = -3}; We need to
represent it using ssize_t.
Also, the patch avoids early canonicalization (when reading DWARF) of
types that refer to themselves. This was leading to type degradation
(serializing the type from IR to abixml and de-serializing it back to
IR leads to a different type).
* include/abg-ir.h (enum_type_decl::enumerator::get_value()):
Change the type of this from size_t to ssize_t.
* src/abg-ir.cc (enum_type_decl::enumerator::get_value): Do the
same on the definition side.
(non_canonicalized_subtype_detector::visit_begin): If a type
refers to itself, late canonicalize it to have a similar hashing
result as what the abixml reader does.
* src/abg-reader.cc (build_enum_type_decl): Use ssize_t to read
the value of enumerators.
* tests/data/test-read-dwarf/test13-pr18894.so.abi: New test input.
* tests/data/Makefile.am: Add the new test inputs above to source
distribution.
* tests/test-read-dwarf.cc (in_out_specs): Add new test inputs.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 13:59:14 +0000 (15:59 +0200)]
Detect vtable changes from member function changes
This patch adds vtable changes detection based on the detection of
virtual member function changes. That is, when a member function
changes, if that member function is virtual, then infer if the change
implies changes to the vtable of the containing class.
Before that patch, we were doing the vtable change detection when we
were comparing two classes; we were then comparing their virtual
member functions. But as for a given class all its virtual member
functions are not necessarily emitted in the DWARF debug info (only
the virtual member functions that are used in a given translation unit
are emitted in that translation unit) it's not reliable to compare
virtual member functions as part of comparing a given class. We thus
decided some patches ago to stop comparing virtual member functions
when we compare two classes.
So with this patch now, we still detect changes to the vtable and emit
an appropriate message to the user.
* include/abg-ir.h (class_decl::{has_virtual_base, has_vtable}):
Declare new member functions.
* src/abg-comp-filter.cc (has_virtual_mem_fn_change): New overload
for function_decl_diff.
(has_virtual_mem_fn_change): In the overload for diff*, support
virtual member function changes detection for function_decl_diff*.
* src/abg-comparison.cc (function_decl_diff::report): Detect and
report changes to a vtable by looking a changes that can happen to
a given member function.
(corpus_diff::report): Detect and report changes to vtables by
looking at changes change to member functions.
* tests/data/test-diff-dwarf/test29-vtable-changes-report-0.txt:
New text input.
* tests/data/test-diff-dwarf/test29-vtable-changes-v{0,1}.cc: Source
code of new test input binaries.
* tests/data/test-diff-dwarf/test29-vtable-changes-v{0,1}.o: New
test input binaries.
* tests/data/test-diff-dwarf/test30-vtable-changes-report-0.txt:
New text input.
* tests/data/test-diff-dwarf/test30-vtable-changes-v{0,1}.cc: New
test input.
* tests/data/test-diff-dwarf/test30-vtable-changes-v{0,1}.o: New
test input binaries.
* tests/data/test-diff-dwarf/test31-vtable-changes-report-0.txt:
New test input.
* tests/data/test-diff-dwarf/test31-vtable-changes-v{0,1}.cc:
Source code of new test input binary.
* tests/data/test-diff-dwarf/test31-vtable-changes-v{0,1}.o: New
test input binary.
* tests/data/Makefile.am: Add the new test input files above to
source distribution.
* tests/test-diff-dwarf.cc (in_out_specs): Consume the new test
inputs above.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 11:38:06 +0000 (13:38 +0200)]
Do not hash or compare virtual member functions as par of classes
When comparing two classes, do not compare their virtual member
functions anymore, because DWARF might not represent all the virtual
member functions of a class, in a given translation unit.
We still detect changes to virtual member functions (adding or
removing) because the index of a given member function in a vtable is
a property of the member function itself. So if a vtable index
changes on a function, we detect it as part of comparing the exported
member functions themselves. Likewise, if a member function is added
or removed, we detect it; and so if it's a virtual member function
then we detect it too. In a subsequent patch, we'll add a dedicated
section to the report emitted by abidiff for changes to the vtable of
classes, I guess.
For now, this patch fixes some crashes we were having due to
discrepancies in hash values of classes, due to the fact that not all
of their virtual member functions were present in the debug info,
depending on the translation unit of the classes in question.
* src/abg-ir.cc (equals): When comparing two classes, do not
compare their virtual member functions.
* src/abg-hash.cc (class_decl::hash::operator()): Do not hash
virtual member functions when hashing a class.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 11:23:17 +0000 (13:23 +0200)]
Misc style fixes
* src/abg-ir.cc (qualified_type_def::get_qualified_name): Fix
typos in comments.
(class_decl::member_class_template::operator==): Add comments.
(operator==): Add comment for the overload of
class_decl::member_class_template_sptr.
(function_tdecl::operator==): Add comments.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 11:20:29 +0000 (13:20 +0200)]
Adjust many reference output for the non-regression test suite
So the last series of patches have changed the test output a lot.
This patch adjusts the reference output to have "make check" work
again. There is still one test that fails:
./build/tests/runtestreaddwarf. It'll be addressed in subsequent
patches from now.
* tests/data/test-abidiff/test-enum0-report.txt: Adjust.
* tests/data/test-abidiff/test-enum1-report.txt: Adjust.
* tests/data/test-abidiff/test-qual-type0-report.txt: Adjust.
* tests/data/test-abidiff/test-struct0-report.txt: Adjust.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Adjust.
* tests/data/test-read-dwarf/test11-pr18828.so.abi: Adjust.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Adjust.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
* tests/data/test-read-write/test17.xml: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 11:10:25 +0000 (13:10 +0200)]
Make test-read-dwarf.cc and test-read-write.cc abidiff the ABIs
use abidiff to compare the ABI of the input ABI against the result of
writing that input back into an XML format. It should yield the empty
set. I wonder why I haven't done this since the beginning. It turned
out we had to fix many things to make it work now. Just using "GNU
diff" to compare the output against a reference output is definitely
not enough.
* tests/test-read-dwarf.cc (main): Use abidiff to compare the
input elf file with the XML emitted. That should yield the empty
set.
* tests/test-read-write.cc (main): Likewise, use abidiff to
compare the input abixml file with the one that is emitted.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 11:07:47 +0000 (13:07 +0200)]
Add a new --noout option to abidw
* tools/abidw.cc (options::noout): New data member.
(options::options): Initialize it.
(display_usage): Add a usage string for the new option.
(parse_command_line): Parse the new option.
(main): If --noout is provided, do not emit the XML form.
* doc/manuals/abidw.rst: Document the new option.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 10:59:13 +0000 (12:59 +0200)]
Add a --no-architecture option to abidiff
This new option omits architectures when comparing ABIs.
* tools/abidiff.cc (options::no_arch): New data member.
(options::options): Initialize it.
(display_usage): Display a help string for the new options.
(parse_command_line): Parse the new options.
(main): If --no-architecture is provided, set the corpus
architecture to "".
* doc/manuals/abidiff.rst: Document the new options.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 09:36:15 +0000 (11:36 +0200)]
Read abixml as a whole file and fix lots discrepancies with dwarf
Forcing each TU to be read in a self contained way was a mistake
because it introduces differences with how DWARF is represented. In
DWARF, types need to be reconciled at the DSO level. I.e, some types
that are only declared in some TUs are to be defined later in other
TUs. So abixml needs to reflect that, otherwise, some types read from
abixml might wrongly appear to be different from the same type read
from DWARF.
But then we need to be able to use a type (refer to its type id)
before defining it later. That means, we need to read the abixml file
in, as a whole. Rather than walking it with a cursor like we used to
do.
This patch does that. That implies to be able to build (on-demand)
an entire translation unit, just because we refer to a type that is
inside that TU.
The patch also fixes some ancillary issues that are related or
uncovered by this "whole-corpus" way of seeing things; these issues were
causing type hashing differences with what the DWARF reader does.
* src/abg-reader.cc (class read_context): Move data member at
the top of the class like what is done elsewhere in the code
base.
(read_context::m_corp_node): New data member.
(read_context::read_context): Initialize it.
(read_context::{get,set}_corpus_node): New accessors.
(read_context::map_id_and_node): Accept that a node id previously
defined is defined again. In that case we just remember the first
mapping id -> xml-node. That seems to work for now.
(read_context::get_translation_unit): Fix the logic.
(read_context::m_wip_types_map): Rename
read_context::m_wip_classes_map into this.
(read_context::clear_wip_types_map): Rename
read_context::clear_wip_classes into this.
(read_context::mark_type_as_wip): Rename
read_context::mark_class_as_wip into this.
(read_context::unmark_type_as_wip): Rename
read_context::unmark_type_as_wip into this.
(read_context::is_wip_type): Rename read_context::is_wip_class
into this.
(read_context::types_equal): New member function.
(read_context::clear_per_translation_unit_data): Do not clear
anything anymore as the previous data that were per-tu are now
per-corpus.
(read_context::clear_per_corpus_data): Clear here the previous
data that were per-tu.
(read_context::maybe_canonicalize_type): Add a new force_delay
flag that forces the type to be late-canonicalized. Also force
late-canonicalize references, pointers, qualified-type and typedef
because they must be canonicalized once they've been added to
their context; but then this function might be called too early,
before they are added to their context.
(read_context::type_id_new_in_translation_unit): Remove this
member function.
(read_translation_unit_from_input): Be able to either use the
xmlTextReader interface, or get the current 'abi-instr' xml
element node. If using the xmlTextReader interface, use it to
move to the 'abi-instr' node, expand it and then use that. In
either case, call read_translation_unit() with the 'abi-instr' xml
element node.
(read_translation_unit): Take an 'abi-instr' XML element in
argument now, use that to read the translation unit, as opposed to
using the xmlTextReader interface we where using before to walk
the sub-tree of the abi-instr xml node.
(read_context::get_scope_for_node): If the scope is a new
translation unit, then build the new translation unit.
(read_symbol_db_from_input): Take the function and variable symbol
data bases, and read the current xml element node (do not use the
xmlTextReader interface anymore) to populate the function and
variable symbols.
(read_elf_needed_from_input): Do not use the xmlTextReader
interface anymore. Rather, use the current xml element node, look
for the 'elf-needed' xml element node and use it to populate the
set of elf dependencies.
(read_corpus_from_input): Rework to expand the contents of the
corpus node and use the result, rather than just exclusively
relying on the xmlTextReader interface.
(build_function_parameter): Build a proper IR node for variadic
parameters. Build function type node *after* having built all the
parameters IR, so that parameter indexing is the same as what is
done in the DWARF reader. Also, if the function is not being
added to its context yet, then delay the canonicalizing of its
type, just like what is done by the DWARF reader.
(build_qualified_type_decl, build_pointer_type_def)
(build_reference_type_def, build_enum_type_decl, build_type_decl):
Adjust. Do not enforce anymore that the ID of this type be new in
the current TU. Delay canonicalizing if the type is not being
added to its context. For typedefs, use an adapted way of
checking the consistency of the underlying type.
(build_array_type_def): Do not enforce anymore that the ID of this
type be new in the current TU. Support the fact that the array
might not have any DW_AT_byte_size attribute. Force late
canonicalizing if the array is not being added to its context.
(build_class_decl): Adjust. Reuse the
read_context::maybe_canonicalize_type() function rather than
trying to determine locally when to canonicalize.
(build_template_tparameter): Adjust
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 29 Aug 2015 08:26:33 +0000 (10:26 +0200)]
Fix handling of class declaration during DWARF reading
It appears now that forcing unresolved class declarations to be
declared is not a good idea. It's better to just leave them as is,
and they'll have a hash value of zero. We were forcing them to be
defined (with a size of 1) because they were used as base classes. It
appears that GCC and Clang (at least) allow base classes to be
non-complete, in case the base class has a vtable; in that case, the
full debug info of the base class would be emitted in another DSO,
where the vtable is emitted, making the base class be complete from a
debug info standpoint. So it's better for us to be in par with that
vision.
Furthermore, one of the reasons why they were not resolved, most of
the time, was that the resolution code was buggy; and that has been
fixed in a patch applied very recently.
So this patch removes the forcing code.
The patch also fixes the handling of class declaration during the
parsing. Basically, bugs in some versions of Clang are so that we
cannot completely trust the DW_AT_declaration property on a class.
What we do is that when we see that property, we flag the class as
being a declaration. But then if there is a DW_AT_byte_size property,
the class is considered as being defined. We were being over-zealous
in considering the class as being defined, because having a member
function was enough; this patch now only considers the presence of a
*virtual* member functions, data members, base classes or a
DW_AT_byte_size as being conditions for being defined.
* src/abg-dwarf-reader.cc (read_context::decl_only_classes_map_):
Remove this data member.
(read_context::{declaration_only_classes_to_force_defined,
schedule_declaration_only_class_for_forced_resolution}): Remove
these member functions.
(read_context::resolve_declaration_only_classes): Do not force
resolution of class declaration.
(build_class_type_and_add_to_ir): Do not schedule classes for
forced-resolution when they are used as base classes. The
presence of a member function is not enough to make the class be
defined. It needs to be a virtual member function.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 28 Aug 2015 17:34:51 +0000 (19:34 +0200)]
Fix important hashing issues
* src/abg-hash.cc (class_decl::hash::operator()): Do not force
base classes to have definitions anymore. GCC and Clang (at
least) some time emits debug info in which the definition of some
base classes are missing, especially when those base classes have
vtables. In that case, the definition of the class might it's in
the binary where the vtable is emitted, which might not be the
binary we are looking at. So let's relax the assertion we had
here for base classes. For hashing virtual member functions,
directly walk the virtual member functions by looking at
class_decl::get_virtual_mem_fns() rather than walking all
member functions and looking for the virtual ones. This is a
speed optimization but it also helps during debugging.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 28 Aug 2015 15:40:43 +0000 (17:40 +0200)]
Fix template comparison operators
There are two issues in comparing templates currently.
One is that comparing member class template recurses for ever (oops).
The other is that the logic of comparing function templates is wrong
and leads to false comparisons.
* include/abg-ir.h (function_tdecl::operator==): Introduce a new
virtual member operator that takes a function_tdecl&.
* src/abg-ir.cc
(class_decl::member_function_template::operator==): Avoid the
static cast in the overload for member_base. In the overload for
member_class_template, avoid infinite recursion.
(function_tdecl::operator==): In the overload for decl_base, do
not do the real work here in the overload for decl_base Rather,
the real work is done in the new overload for function_tdecl, and
all other overloads call that one.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 28 Aug 2015 15:11:15 +0000 (17:11 +0200)]
Use size/alignment of class definition when requested on declaration
Sometimes during hashing the "type sub-object" of a class can be
queried for its size or alignment. In those case, if the class is a
declaration that happens to be accompanied with a definition, its the
size/alignment of the definition that we want, not the one of the
declaration, that is zero. Otherwise, this can cause spurious hashing
changes between two class types that are otherwise equivalent modulo
the use of a class declaration.
This patch being part of a series that aims at fixing a number of type
hashing issues, the regression tests are adjusted at the end of the
series, not here.
* include/abg-ir.h (type_base::{set_size_in_bits,
set_alignment_in_bits}): Make these member functions virtual.
(class_decl::{set_size_in_bits, get_size_in_bits,
get_alignment_in_bits, set_alignment_in_bits}): Declare these
virtual member functions.
* src/abg-ir.cc (class_decl::{set_size_in_bits, get_size_in_bits,
get_alignment_in_bits, set_alignment_in_bits}): Define these
virtual functions.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 28 Aug 2015 14:45:18 +0000 (16:45 +0200)]
Fix type lookup algorithm
Until now, the type lookup algorithm was broken for c++. For two
reasons:
1/ The algorithm to break a fully qualified type name into name
components is buggy. When given the type name:
foo<ns1::t1, ns1::t2>::t3
the components making up the name are: "foo<ns1", "t1, ns1", "t2>"
and "t3. That is wrong. The components should be:
"foo<ns1::t1, ns2::t2>" and "t3".
2/ When a type is found, if it's a declaration, it's skipped. This
is wrong because if the declaration is accompanied with a
definition, it should be returned.
This patch addresses the two issues above. It allows more
declaration-only classes to be resolved and so reduces the number of
spurious hashing differences between two instances of the same type
which should otherwise have the same hash.
There is no regression test update with this patch because we really
need the full series this patch is part of, to fix the type hashing
correctness issues we have. So the regression test updates are coming
at the end of the series.
* src/abg-ir.cc (find_next_delim_in_cplus_type): Define new static
function.
(fqn_to_components): Use the new function above to break up a
fully qualified name into components, rather than the too simple
string::find_first_of() we were using previously.
(lookup_node_in_scope): If the found type (class) is a
declaration-only and if it has a definition, then return it.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 26 Aug 2015 10:49:40 +0000 (12:49 +0200)]
Make decl hashing always take qualified name into account
* src/abg-hash.cc (decl_base::hash::operator()(const decl_base&)):
Always hash the qualified name of the decl.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 26 Aug 2015 10:06:46 +0000 (12:06 +0200)]
Accept base classes which types are compatible with class type
Until now, a base class had to be a class itself. It couldn't be a
typedef to a class, for instance. Clang's debug info does allow base
classes which are compatible with classes (e.g, typedefs of classes),
which is correct. We ought to accept that. Hence this patch.
* include/abg-fwd.h (is_compatible_with_class_type): Declare a new
overload.
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): Rather
than requiring that base classes be of class type, just require
that they be compatible with class types.
* src/abg-ir.cc (is_compatible_with_class_type): Define a new
overload.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 26 Aug 2015 06:28:39 +0000 (08:28 +0200)]
Harden function_decl::get_pretty_representation()
This function can abort when called on a function_decl that is not a
member function. This patch addresses that issue.
* src/abg-ir.cc (function_decl::get_pretty_representation): Make
sure the function type is a member function before calling
get_member_function_is_{virtual,ctor,dtor,const}.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Tue, 25 Aug 2015 14:07:33 +0000 (16:07 +0200)]
Don't cache type qualified name before canonicalization
Caching the qualified name of a given type has always been subject to
subtle bugs. If the qualified name is queried (so it's computed)
before the type is added into its final content, then what is cached
is a non-qualified type name. Later when the type is finally added to
its context, querying its qualified name will just yield the cached
non-qualified name. And that has impact on hashing and comparison.
We needed a way to signal that the type is "fully built and added to
its final context". When the type is fully built then we can cache
its qualified name.
This patch uses the presence of the canonical type as the signal; if
the canonical type is present then the type is fully built and added
to its final context. And then at that point the cached qualified
name is used.
Note that this patch is the first of a series fixing several things
that influence hashing, comparison, the reading and writing of abixml.
It's only at the end of the series that an update to regression tests
is provided. In between, some patches of the series are going to
"break" the regression tests. That is fine.
* src/abg-ir.cc (decl_base::{get_qualified_parent_name,
get_qualified_name}): Use the qualified name cache only if the
type is fully built, i.e, when its canonical type is present.
(qualified_type_def::get_qualified_name): Likewise.
(pointer_type_def::get_qualified_name): Likewise.
(reference_type_def::get_qualified_name): Likewise.
(array_type_def::get_qualified_name): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 22 Aug 2015 12:27:37 +0000 (14:27 +0200)]
Misc style cleanups
* configure.ac: Fix some spelling typos.
* src/abg-tools-utils.cc (guess_file_type): Fix indentation.
* tests/test-diff-pkg.cc (int_out_specs): Add some vertical spaces
for better legibility.
* tools/abidiff.cc (main): Add a missing space.
* tools/abipkgdiff.cc (extract_deb): Fix a typo in the comment.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 22 Aug 2015 11:59:18 +0000 (13:59 +0200)]
Make abipkgdiff compare tar archives containing binaries
This patch adds support for comparing the ABI of binaries contained in
a tar archive.
If the archive is compressed with gzip, bzip2, lzip, lzma or xz, then
abipkgdiff recognizes the usual relevant file extensions and lets the
GNU tar program handle the decompression.
If the archive is not compressed, abipkgdiff recognizes the UStar
(Uniform Standard Tape ARchive) format, even if the archive file name
doesn't end with the .tar extension, and lets the GNU tar program
handle the extraction. If the file ends up with the .tar extension
anyway (even if it's not in the UStar format, abipkgdiff lets the GNU
tar program handle its extraction.
* config.h.in (WITH_TAR): New configuration preprocessor macro.
* configure.ac: Add a new --enable-tar option. It's turned on
automatically if the tar program is found in the PATH. Adjust the
build configuration report to add the tar archive support.
* include/abg-tools-utils.h (string_ends_with): Declare new
function.
(enum file_type): Add a new FILE_TYPE_TAR enumerator.
* src/abg-tools-utils.cc (string_ends_with): Define new function.
(operator<<(ostream&, file_type)): Serialize the new FILE_TYPE_TAR
enumerator.
(guess_file_type): Detect UStar format file by reading its magic
number. Detect compressed tar files based on the file path
extension.
* tools/abipkgdiff.cc (extract_tar): Define new function.
(extract_package): Handle tar packages.
(main): Handle tar archives.
* tools/abidiff.cc (main): Handle the new FILE_TYPE_TAR
enumerator.
* tools/abilint.cc (main): Likewise.
* tests/data/test-diff-pkg/tarpkg-0-dir{1,2}.ta{,r,.bz2, gz}: New
test input tarballs.
* tests/data/test-diff-pkg/tarpkg-0-report-0.txt: New test output
reference.
* tests/data/Makefile.am: Add the new test data file above to
source distribution.
* tests/test-diff-pkg.cc (in_out_specs): Add new tests cases.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 22 Aug 2015 10:15:16 +0000 (12:15 +0200)]
Misc style fixes in abipkgdiff
* include/abg-tools-utils.h (enum file_type): Fix the comment for
for the FILE_TYPE_DEB enumerator.
* tools/abipkgdiff.cc (main): Fix the style of the conditions.
Also, fix the text emitted.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 22 Aug 2015 09:44:08 +0000 (11:44 +0200)]
Make abipkgdiff compare directories containing binaries
abipkgdiff knows how to compare the ABI of binaries contained in .deb
and .rpm files. This patch adds support for comparing the ABI of
binaries contained in two directories.
* include/abg-tools-utils.h (enum file_type): Add a new
FILE_TYPE_DIR enumerator.
* src/abg-tools-utils.cc (operator<<(ostream&, file_type)):
Support serialization of the new FILE_TYPE_DIR enumerator.
(guess_file_type): Detect that the path given is a directory.
* tools/abipkgdiff.cc (package::package): If the package is a
directory, then set its extracted directory path to the path of
the directory.
(package::erase_extraction_directory): Do not erase the extraction
directory if the package is a directory provided by the user.
(extract_package): If the package is a directory provided by the
user, then there is nothing to extract.
(main): If the first package is a directory, then the second one
should be a directory as well.
* tools/abidiff.cc (main): Support directories as input.
* tools/abilint.cc (main): Likewise.
* tests/data/test-diff-pkg/dirpkg-0-dir{1,2}/libobj-v0.so: New
binary test inputs.
* test/data/test-diff-pkg/dirpkg-0-report-0.txt: New input test
file.
* tests/data/test-diff-pkg/dirpkg-1-dir{1,2}/obj-v0.cc: Source
code of the binary test inputs above.
* tests/data/Makefile.am: Add the new files above to the source
distribution.
* tests/test-diff-pkg.cc (in_out_specs): Add the new test input
files above to the set of tests this harness has to run over.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Sat, 22 Aug 2015 07:33:13 +0000 (09:33 +0200)]
[dwarf reader] Support reference types without explicit DW_AT_byte_size
On x86_64 at least, in the debug info emitted by Clang, reference
types don't necessarily have the DW_AT_byte_size property. In that
case, assume the size of the pointer type is the address size of the
current translation unit, rather than giving up and not building the
type.
* src/abg-dwarf-reader.cc (build_reference_type): If the type DIE
has no DW_AT_byte_size, assume the type size is the translation
unit's address size.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 21 Aug 2015 18:16:38 +0000 (20:16 +0200)]
[dwarf reader] Support pointer types without explicit DW_AT_byte_size
On x86_64 at least, in the debug info emitted by Clang, pointer types
don't necessarily have the DW_AT_byte_size property. In that case,
assume the size of the pointer type is the address size of the
current translation unit, rather than giving up and not building the
type.
* abg-dwarf-reader.cc (build_pointer_type_def): If the type DIE
has no DW_AT_byte_size, assume the type size is the translation
unit's address size.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 21 Aug 2015 11:08:38 +0000 (13:08 +0200)]
make abipkgdiff compile with GCC 4.4.7
GCC 4.4.7 won't let us declare an instance of string with __thread.
So for now, package::extracted_packages_parent_dir() juststores its string
globally. We are single-threaded for now anyway.
* tools/abipkgdiff.cc (package::extracted_packages_parent_dir):
The string holding the dir name is no more __thread, as this won't
compile with GCC 4.4.7
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 21 Aug 2015 10:15:21 +0000 (12:15 +0200)]
Misc style fixes
* src/abg-dwarf-reader.cc (read_context::die_type_map): Fix typo
in the comment.
* src/abg-ir.cc (peel_typedef_type): Fix typo in the comment.
* src/abg-reader.cc
(read_context::perform_late_type_canonicalizing): Fix a type in
the comment.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 21 Aug 2015 10:09:22 +0000 (12:09 +0200)]
Make get_pretty_representation work on method types
Until now, get_pretty_representation() considered method types just as
function types. This patch makes it know about them specifically. This
useful for debugging, at least.
* include/abg-fwd.h (is_method_type): Declare new overloads for
naked pointers.
(get_method_type_name): Declare new functions.
(get_pretty_representation): Declare new overloads for
method_type.
* src/abg-ir.cc (get_function_type_name): If the function type is
a method type, handle it as such.
(get_method_type_name): Define new functions.
(get_pretty_representation): If the function type is a method
type, handle it as such.
(get_pretty_representation): Define new overloads for method_type
and pointer/reference to method_type.
(is_method_type): Add overloads for naked pointers.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 21 Aug 2015 09:22:30 +0000 (11:22 +0200)]
Hash a class declaration the same as its definition
A class declaration hashes differently from its definition.
Since the abixml format can now use a class element id before defining
it, it's more consistent to stop representing class declarations in
the abixml format, when the class is actually defined in the corpus.
So this patch now hashes a class declaration the same as its
definition, when the definition is present. If the definition is not
present then the hash value of the declaration is just zero. This is
consistent with what is done elsewhere in the code as a hash value of
zero means the hash could not be computed, somehow, as the type
comparison code knows that a type with hash value zero can be equal to
a type with a hash value that is different from zero.
As a result, many tests which use the abixml format have been adjusted
to reflect the new form of abixml where class declarations are now
omitted when these declarations are accompanied with their definition.
I made sure that abidiff reports that former abixml output and the new
one are equivalent.
After this change abixml outputs should contain less redundant type
declarations. This is another step toward normalizing the abixml
output.
* src/abg-hash.cc (class_decl::hash::operator()(const class_decl&)):
If the class declaration has a definition, hash its definition
instead. Otherwise, if the class declaration has no definition,
just return a zero hash, like what we were doing before.
* src/abg-reader.cc (read_context::maybe_canonicalize_type): Do
not early canonicalize method types because most of the time, when
this function is called, the method hasn't been added to its
parent class yet. So wait until late before canonicalizing.
* src/abg-writer.cc (write_class_is_declaration_only): Do not emit
the "is-declaration-only" property if the declaration has a
definition.
(write_class_decl): If the class declaration has a definition,
emit the definition instead.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Adjust.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
* tests/data/test-read-write/test18.xml: Likewise.
* tests/data/test-read-write/test20.xml: Likewise.
* tests/data/test-read-write/test21.xml: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Thu, 20 Aug 2015 10:28:38 +0000 (12:28 +0200)]
Add a --stats to abidiff and abidw
For now, this new --stats emits diagnostics about the number of types
canonicalized at the very end of building the ABI corpus as well as
the number of types that were scheduled for late canonicalizing and
that couldn't be canonicalized.
* include/abg-dwarf-reader.h (get_show_stats)
(set_show_stats): New accessors for a new "show_stats" property of
the dwarf reader context.
* src/abg-dwarf-reader.cc: Include iostream to use std::cerr.
(dwarf_reader::show_stats_): New data member.
(dwarf_reader::dwarf_reader): Initialize it.
(dwarf_reader::show_stats)
(get_show_stats)
(set_show_stats): Define new accessors.
(dwarf_reader::die_type_map): Add const overload to this accessor.
(dwarf_reader::lookup_type_from_die_offset): Make this accessor
const.
(dwarf_reader::add_late_canonicalized_types_stats): New member
function.
(dwarf_reader::perform_late_type_canonicalizing): Emit the
statistics about late-canonicalized types if the user asked for
it.
* tools/abidiff.cc (options::show_stats): New data member.
(options::options): Initialize it.
(display_usage): Document it.
(parse_command_line): Parse the new --stats option.
(main): Create a dwarf reader context, set the show_stats to it
and then use that context to read the corpora before diffing them.
* tools/abidw.cc (options::show_stats): New data member.
(options::options): Initialize it.
(display_usage): Document it.
(parse_command_line): Parse the new --stats option.
(main): Set the show_stats to the dwarf reader context before
using it.
* doc/manuals/abidiff.rst: Update the manual.
* doc/manuals/abidw.rst: Update the manual.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 19 Aug 2015 16:59:53 +0000 (18:59 +0200)]
Canonicalize all types that got scheduled for late canonicalization
Until now, when late type canonicalization time come (after having
read all of the ABI corpus), the types scheduled for late
canonicalization were considered and only those that don't have
non-canonicalized sub-types were canonicalized.
This patch just canonicalizes all the scheduled type. As a result,
all types should now be canonicalized, so type comparison should be as
fast as a pointer comparison now. But then, loading DWARF is now even
longer, type canonicalization needs to happen.
* src/abg-dwarf-reader.cc
(read_context::canonicalize_types_scheduled): Canonicalize all
types scheduled for late canonicalization.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 19 Aug 2015 16:21:38 +0000 (18:21 +0200)]
Propagate canonical type of a class definition to its declaration
When a class type definition has its canonical type set, propagate it
to the class declaration.
* src/abg-ir.cc: (canonicalize): Propagate the canonical type of
the type definition to its declaration.
(class_decl::set_definition_of_declaration): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 19 Aug 2015 14:15:28 +0000 (16:15 +0200)]
Make type_has_non_canonicalized_subtype() tighter
type_has_non_canonicalized_subtype() gives up too quickly.
For instance, suppose it's looking a type 'foo'. If foo has no
canonicalized type yet and has a data member which type is foo* (for
instance), then type_has_non_canonicalized_subtype() just sees that
type 'foo*' has no canonicalized type, and so it returns, saying that
he found a non-canonicalized subtype for foo.
In that case though, what type_has_non_canonicalized_subtype() should
do is detect that foo* is a pointer to foo itself, so it shouldn't
count as a non-canonicalized sub-type. It should keep going and look
for other meaningful non-canonicalized sub-types.
And this what this patch does. It changes the sub-type walker that
type_has_non_canonicalized_subtype() uses, so that
- it doesn't flag sub-types that refer to the type we are looking
at as non-canonicalized sub-types. This is for sub-types that
are combinations of pointers, references and typedefs.
- it doesn't consider sub-types of member functions of the type we
are looking at, unless that member function is virtual.
The result is that more types are canonicalized early during DWARF
reading, and so there are less types to store on the side for late
canonicalization. This can have a big impact on, e.g, C++ libraries
with tens of thousands of types.
* include/abg-fwd.h (is_typedef, is_pointer_type)
(is_reference_type): Declare new overloads.
(peel_typedef_type): Renamed get_typedef_underlying_type into
this.
(peel_pointer_type, peel_reference_type)
(peel_typedef_pointer_or_reference_type): Declare new functions.
* src/abg-ir.cc (peel_typedef_type): Renamed
get_typedef_underlying_type into this.
(is_typedef, is_pointer_type, is_reference_type): Define new
overloads.
(peel_pointer_type, peel_reference_type)
(peel_typedef_pointer_or_reference_type): Define new functions.
(non_canonicalized_subtype_detector::has_non_canonical_type_):
Make the type of this data member be a type_base*, not a bool.
This is so that we can return the first non-canonicalized subtype
of the type we are looking at.
(non_canonicalized_subtype_detector::non_canonicalized_subtype_detector):
Adjust the data member initialization.
(non_canonicalized_subtype_detector::visit_begin): Add an overload
for function_decl*, to avoid looking into non-virtual member
functions.
In the overload for type_base*, peel typedefs, pointers and
reference of each sub-type that has no canonical type, to see if
refers to the type we are actually walking. If yes, then keep
going.
(type_has_non_canonicalized_subtype): Return the non-canonicalized
sub-type found.
* src/abg-comparison.cc (type_suppression::suppresses_diff):
Adjust for the get_typedef_underlying_type -> peel_typedef_type
renaming.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 19 Aug 2015 10:06:24 +0000 (12:06 +0200)]
Make decl_base::get_qualified_name() work when decl context changes
decl_base::get_qualified_name() caches its result. So when it's
first called on a decl that is not added to a scope, what is returned
is a non-qualified name. Which is all right. But then when the decl
is later added to a scope, the cached result of
decl_base::get_qualified_name() is not longer correct.
This patch resets the cache of decl_base::get_qualified_name() when
the decl gets added to a new scope.
* include/abg-ir.h (class decl_base): Make class scope_decl a
friend of decl_base.
(type_base::priv_): Make this protected, rather than private.
* src/abg-ir.cc (scope_decl::add_member_decl)
(scope_decl::insert_member_decl): Reset the cache of the result of
decl_base::get_qualified_name().
* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Tue, 18 Aug 2015 10:33:57 +0000 (12:33 +0200)]
Bug 18844 - assert failure in abidw at abg-dwarf-reader.cc:6537
The DWARF reader is not scheduling a declaration-only class for
resolution when the class has member types. When reading the code of
build_class_type_and_add_to_ir(), we see that the scheduling is done
before getting out of the function. But then, building members of the
class can trigger another invocation of
build_class_type_and_add_to_ir() before the current invocation
returns. In that case, the declaration-only class being built appears
as not being scheduled for resolution. And that is what violates the
assertion that declaration-only classes should be scheduled for
resolution whenever they are used.
This patch addresses the issue by scheduling the resolution earlier, when
we know we are dealing with a declaration-only class, and before
dealing with members of that classes.
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir):
Schedule declaration-only class resolution before the class
appears as usable as to other types being built.
* tests/data/test-read-dwarf/test12-pr18844.so: Add a new binary
test input.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: The reference
ABI XML output for the binary above.
* tests/data/Makefile.am: Add the new test inputs above to the
source distribution.
* tests/test-read-dwarf.cc (in_out_specs): Add the new test inputs
above to the set of input this test harness has to run over.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Tue, 18 Aug 2015 10:31:45 +0000 (12:31 +0200)]
Fix a little glitch in the test suite
* test-read-dwarf.cc (in_out_specs): Emit the output of the test11
to output/test-read-dwarf/test11-pr18828.so.abi, not
output/test-read-dwarf/test10-pr18828.so.abi.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Tue, 18 Aug 2015 10:07:18 +0000 (12:07 +0200)]
Escape XML property names that were not escaped before
Apparently we are not escaping XML property names for 'typedef-decl',
'namespace-decl' and 'var-decl' elements. I think it's not necessary
for namespace-decl, but well, you never know.
* src/abg-writer.cc (write_namespace_decl, write_typedef_decl)
(write_var_decl): Escape the XML characters that are forbidden in
XML properties, and that are emitted as value of the 'name'
property.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 22:10:26 +0000 (00:10 +0200)]
Bug 18828 - Handle force-resolving of multiple declarations-only of the same type
When a declaration-only type that is used in a context where it needs
to be complete (and no definition is present for that type in the ABI
corpus) handle cases where that type is was actually declared several
times.
* src/abg-dwarf-reader.cc
(read_context::resolve_declaration_only_classes): Accept that a
class that needs to be force-resolved might have been declared
several times. In that case, some instances of that
declaration-only class might have already been resolved (or
completed).
* tests/data/test-read-dwarf/test11-pr18828.so: New binary input.
It comes from bug https://sourceware.org/bugzilla/show_bug.cgi?id=18828.
* tests/data/test-read-dwarf/test11-pr18828.so.abi: The reference
output for the binary above.
* tests/data/Makefile.am: Add the test input files above to source
distribution.
* tests/test-read-dwarf.cc (in_out_specs): Add the test inputs
above to the set of input this test harness has to run over.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 22:03:07 +0000 (00:03 +0200)]
Avoid declaring a type several times in the same TU in the XML format
It appears a lot of duplicated type declarations can appear in a given
translation unit. This patch avoids that.
* src/abg-writer.cc (write_context::{record_type_id_as_emitted,
record_type_as_emitted, type_id_is_emitted, type_is_emitted,
clear_emitted_types_map}): New member functions.
(write_context::m_emitted_type_id_map): New data member.
(write_translation_unit): Clear the per-translation unit map of
emitted types. Do not emit a type that has already been emitted
in this translation unit.
(write_namespace_decl): Do not emit a type that has already been
emitted in this translation unit.
(write_type_decl, write_qualified_type_def)
(write_pointer_type_def, write_reference_type_def)
(write_array_type_def, write_typedef_decl, write_class_decl)
(write_type_tparameter, write_template_tparameter): Record the
type we've just written as having been written out.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust as
duplicated declarations got removed.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 21:45:14 +0000 (23:45 +0200)]
Misc style fixes in the XMLABI writer
This patch aligns some data members and function parameters. It also
makes use of the *_sptr typedef, rather than the longer
shared_ptr<something> types in function parameters.
* src/abg-writer.cc (write_context): Align data members.
(write_translation_unit): Remove useless horizontal white spaces.
(write_decl, write_qualified_type_def, write_pointer_type_def)
(write_reference_type_def, write_array_type_def)
(write_enum_type_decl, write_typedef_decl, write_class_decl)
(write_type_tparameter): Use the *_sptr typedefs rather than the
longer form of shared_ptr<sometype> in function signatures.
(write_enum_type_decl): In this function in particular, indent a
line properly.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 14:50:18 +0000 (16:50 +0200)]
Fix typos in abipkgdiff
* tools/abipkgdiff.cc (display_usage): s/pompare/compare. Give a
better help message for --help.
(extract_rpm): Insert a space after the path of the package being
extracted, when emitting a verbose message.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 14:48:35 +0000 (16:48 +0200)]
Install the manpage for abipkgdiff
* doc/manuals/Makefile.am (section1_manpages): Add abipkgdiff.1 to
the set of manpages to be install into section 1.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Wed, 12 Aug 2015 21:55:18 +0000 (23:55 +0200)]
Bug 18818 - abidw aborts on a class with a non-complete base class
On some binaries with debug info emitted by "Ubuntu clang version
3.6.0-2ubuntu1" and "GNU C++ 4.9.2" (as the value of the
DW_AT_producer property), it seems some classes can have a base class
that is not complete. E.g, the debug info (that I have extracted
using the command eu-readelf --debug-dump=info
<the-binary-attached-to-the-bug>) has these relevant pieces:
[...]
[ 5ff7] class_type
containing_type (ref4) [ 7485]
name (strp) "system_error"
byte_size (data1) 40
decl_file (data1) 46
decl_line (data1) 22
[ 6003] inheritance
type (ref4) [ 7480]
[...]
Here, we are looking at the type system_error (actually
boost::system::system_error) that inherits the type which DIE is
referred to as offset '7480'.
Then the definition of the DIE at offset 7480 is:
[...]
[ 7480] class_type
name (strp) "runtime_error"
declaration (flag_present)
[ 7485] class_type
name (strp) "exception"
declaration (flag_present)
[...]
You can see that the type "runtime_error" (actually
std::runtime_error) has the flag DW_AT_declaration set, marking it as
a declaration (with no definition yet). And no other DIE in the same
translation unit
(src/third_party/boost-1.56.0/libs/filesystem/src/codecvt_error_category.cpp)
or in the same DSO provides the definition for that declaration.
I believe this is ill-formed. A base class should be defined and have
a layout completed expressed and accessible from the translation unit
it's used in.
The patch I am proposing detects that the base class is still
incomplete when we finish loading the current binary. In that case,
the base class is made complete with a size of 1. Meaning it's an
empty class (with no data member and no base class). This works as a
viable work-around *if* the producer only omitted definitions for
empty classes. We'll need to fix the producers eventually.
* src/abg-dwarf-reader.cc
(read_context::decl_only_classes_to_force_defined_map_): New data
member.
(read_context::declaration_only_classes_to_force_defined): New
accessors.
(read_context::schedule_declaration_only_class_for_forced_resolution):
New member function.
(build_class_type_and_add_to_ir): If a base class is a
declaration-only class then mark it as needing to be force-defined
*if* it's still not defined at the end of the abi corpus loading.
(read_context::resolve_declaration_only_classes): If
declaration-only classes that need to force-defined are present
and not defined (when we reach the end of the ABI corpus) then
force-define them as empty classes.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so: New test
binary input file. This comes from a user binary submitted to bug
https://sourceware.org/bugzilla/show_bug.cgi?id=18818. The
original URL to the binary is
https://sourceware.org/bugzilla/attachment.cgi?id=8518.
* tests/data/test-read-dwarf/test9-pr18818-clang.so: New binary
input file. This comes from the same bug report as above. The
original URL to the binary is
https://sourceware.org/bugzilla/attachment.cgi?id=8511.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: New
reference output file.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
* tests/data/Makefile.am: Add the new files above to the source
distribution.
* tests/test-read-dwarf.cc (in_out_specs): Add the test inputs
above the set of tests input this harness has to run over.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 13:24:59 +0000 (15:24 +0200)]
Update the abipkgdiff manual to say that .deb files are now supported
* doc/manuals/abipkgdiff.rst: Say that .deb fiel are now supported
by abipkgdiff.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 13:24:12 +0000 (15:24 +0200)]
Update comment about the supported formats in abipkgdiff
* tools/abipkgdiff.cc: Now that .deb packages are supported, say
it.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 10:49:57 +0000 (12:49 +0200)]
Make the support of RPM and DEB package formats conditional
If at configure time the libabigail source tarball detects that
rpm2cpio and cpio are present then it enables the support for rpm
files. Users can explicitly enable or disable that support by passing
--enable-rpm or --disable-rpm to configure.
Similarly if it detects that dpkg is present at configure time then it
enables the support for deb files. Users can explicitly enable or
disable that support by passing --enable-deb or --disable-deb to
configure.
* config.h.in: Define WITH_DEB and WITH_RPM pre-processor macros.
* configure.ac: Add --enable-{rpm,deb} switches. Check for
rpm2cpio and cpio programs, unless --disable-rpm was provided. If
they are found and if --enable-rpm=auto was provided, then
consider that --enable-rpm=yes was provided. In that case, set
the WITH_RPM macro to 1. Otherwise, undefine that macro.
Similarly, check for dpkg unless --disable-deb was provided. If
it's found and if --enable-deb=auto was provided, consider that
--enable-deb=yes was provided. In that case, set the WITH_DEB
macro to 1. Otherwise, undefine that macro. Define the
ENABLE_RPM and ENABLE_DEB conditional automake variables, if the
rpm resp. deb support is enabled. Emit a notice about the rpm and
deb features being enabled or not, at the end of the configure
process.
* tests/test-diff-pkg.cc: Include the config.h header.
(in_out_spec): Guard rpm tests by the WITH_RPM macro. Similarly,
guard deb tests by the WITH_DEB macro.
* tools/abipkgdiff.cc: Include the config.h header.
(extract_rpm): Guard this function definition with the WITH_RPM
macro.
(extract_deb): Guard this function definition with the WITH_DEB
macro.
(extract_package): Guard the handling of rpm packages with the
WITH_RPM macro and the handling of deb package with the WITH_DEB
macro. If a package not-support package format is encountered,
emit an appropriate error message and error out.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Matthias Klose [Fri, 7 Aug 2015 08:48:17 +0000 (10:48 +0200)]
Add support for .deb files to abipkgdiff
This lets abipkgdiff compare debian binary packages.
The patch contains test cases for debian package with split debug info
that is referenced by the build-id scheme. These test cases come from
the bug report https://sourceware.org/bugzilla/show_bug.cgi?id=18792,
more particularly from the attachment
https://sourceware.org/bugzilla/attachment.cgi?id=8516.
* include/abg-tools-utils.h (file_type): Add FILE_TYPE_DEB.
* tools/abipkgdiff.cc (extract_deb): New.
(extract_package, main): Handle FILE_TYPE_DEB.
* src/abg-tools-utils.cc (operator<<): Handle FILE_TYPE_DEB.
(guess_file_type): Detect FILE_TYPE_DEB.
* tools/abidiff.cc (main): Handle FILE_TYPE_DEB.
* tools/abilint.cc (main): Handle FILE_TYPE_DEB.
* tests/data/test-diff-pkg/libsigc++-2.0-0c2a-dbgsym_2.4.0-1_amd64.ddeb:
Input debian debug info package; to be compared by the test
harness runtestdiffpkg.
* tests/data/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64.deb:
Input debian package; to be compared by the test harness
runtestdiffpkg.
* tests/data/test-diff-pkg/libsigc++-2.0-0v5-dbgsym_2.4.1-1ubuntu2_amd64.ddeb:
Input debug info package
* tests/data/test-diff-pkg/libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64.deb:
Input debian package; to be compared by the test harness
runtestdiffpkg.
* tests/data/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64--libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64-report-0.txt:
Reference output for the comparison of the packages above.
* tests/data/Makefile.am: Add the new files above to the source distribution.
* tests/test-diff-pkg.cc (in_out_specs): Add the input packages
above to the set of files to be compared by this test harness.
Signed-off-by: Matthias Klose <doko@debian.org>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 10:48:35 +0000 (12:48 +0200)]
Add configure check for rm and mkdir used by abipkgdiff
* configure.ac: Add configure checks for rm and mkdir used by
abipkgdiff.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 10:46:36 +0000 (12:46 +0200)]
Fix a comment in configure.ac
* configure.ac: Fix a comment.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Dodji Seketeli [Fri, 14 Aug 2015 11:21:33 +0000 (13:21 +0200)]
Do not remove api and website source files by accident
When the root source dir is used as root build dir, make clean can
remove the content of ${abs_builddir}/api which is then equal to
${abs_srcdir}/api. Oops. This patch fixes this.
* doc/Makefile.am: Do not remove the entirety of the build dir of
doxygen for the apidoc and the website as these can be also the
source dirs. Rather, remove that is under the html/ sub-directory
of the build dir, as this is always generated by doxygen.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>