mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-19 16:30:04 +00:00
640b3a2f59
379 Commits
Author | SHA1 | Message | Date | |
---|---|---|---|---|
Dodji Seketeli
|
640b3a2f59 |
Bug 19141 - Libabigail doesn't support common ELF symbols
Libabigail's internal representation of elf symbols fails to account for common symbols in relocatable files. There can be several common symbols of the same name (defined in a section of SHN_COMMON kind). In that case, Libabigail wrongly considers these multiple instances of the same common symbol as being alias, and that breaks some basic assumptions about aliases. Oops. This patch adds support for the common symbols (and the fact that relocatable files can have several instances of the same common symbol) and amends the ELF reader to make it properly represent those. * include/abg-ir.h (elf_symbol::elf_symbol): Take a new flag to say if the symbol is common. (elf_symbol::{is_common_symbol, has_other_common_instances, get_next_common_instance, add_common_instance}): New member functions. * src/abg-ir.cc (elf_symbol::priv::{is_common_, next_common_instance_): New data members. (elf_symbol::priv::priv): Adjust. (elf_symbol::{elf_symbol, create}): Take a new flag to say if the symbol is common. (textually_equals): Adjust to account for symbol common-ness. (elf_symbol::{is_common_symbol, has_other_common_instances, get_next_common_instance, add_common_instance}): Define new member functions. (elf_symbol::add_alias): Drive-by fix; compare symbols using pointer value. Value comparison is not necessary. * src/abg-dwarf-reader.cc (lookup_symbol_from_sysv_hash_tab) (lookup_symbol_from_gnu_hash_tab, lookup_symbol_from_symtab) (read_context::lookup_elf_symbol_from_index): Adjust the creation of the symbol to account for common-ness. (read_context::load_symbol_maps): Recognize instances of a given common symbol and represent them as such. Do not mistake this with symbol aliases. * src/abg-reader.cc (build_elf_symbol): Adjust the creation of the symbol to account for common-ness. * src/abg-writer.cc (write_elf_symbol): Adjust symbol serialization to account common-ness. * tests/data/test-types-stability/pr19141-get5d.o: Add new test binary input. * tests/data/test-types-stability/pr19142-topo.o: Likewise. * tests/data/Makefile.am: Add the new test inputs to source distribution. * tests/test-types-stability.cc (elf_paths): The the new test inputs into account. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
c3869ecc7b |
Bug 19434 - invalid character in attribute value
* include/abg-tools-utils.h (string_is_ascii_identifier): Declare new function. * src/abg-tools-utils.cc (string_is_ascii_identifier): Define new function. * src/abg-dwarf-reader.cc (build_function_type): Discard parameter name if it's made of non-identifier ascii characters. * tests/data/test-types-stability/pr19434-elf0: New test binary input file. * tests/data/Makefile.am: Add the new test input to source distribution. * tests/test-types-stability.cc: Test the new test input into account. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
f275939df2 |
Use worker threads pattern to speed up some tests
We are going to need to speed up more and more tests, and coding directly with libpthread for that can be tedious and bug-prone. So I devised an implementation for the worker threads design pattern instead, and used it to speed up some tests. * include/Makefile.am: Add the new abg-workers.h to source distribution. * include/abg-workers.h: New file. * src/Makefile.am: Add the new abg-worker.cc to source distribution. * src/abg-workers.cc: New file. * tests/test-utils.cc: Update copyright. Make get_src_dir() and get_build_dir() return a const char*, as opposed to returning a string. Make that const char reside in thread local storage, so that two concurrent threads can safely call these functions in parallel, without any race. * tests/test-utils.h: Make get_src_dir() and get_build_dir() return a const char*, as opposed to returning a string. * tests/test-abicompat.cc: Update copyright. Adjust for get_src_dir() and get_build_dir() change. * tests/test-abidiff.cc: Likewise. * tests/test-alt-dwarf-file.cc: Likewise. * tests/test-core-diff.cc: Likewise. * tests/test-diff-dwarf-abixml.cc: Likewise. * tests/test-diff-dwarf.cc: Likewise. * tests/test-diff-pkg.cc: Likewise. * tests/test-diff-suppr.cc: Likewise. * tests/test-lookup-syms.cc: Likewise. * tests/test-read-dwarf.cc: Likewise. * tests/test-read-write.cc: Likewise. * tests/test-types-stability.cc: Likewise. Use the new task queue type to run these tests in parallel. * tests/test-diff-filter.cc: Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
64375c64d3 |
Make enum values take 64 bits on all platforms
The is still some changes in the way values of enumerators are represented in 32 and 64 bits systems. This is because the type of enumerators is size_t which 32 bits on 32 bits systems and 64 bits on 64 bits systems. The problem is, the output of, abidw can thus be different on 32 and 64 bits, making some tests output be different on these platforms. This patch thus uses uint64_t to represent enumerator values on all platforms. * include/abg-ir.h: Include stdint.h for int64_t. (enumerator::enumerator): Take an int64_t value for the value of the enumerator. (enumerator::{s,g}et_value): Take/return an int64_t value. * src/abg-ir.cc (enum_type_decl::enumerator::priv): Store the value in an int64_t. (enumerator::priv::priv): Take a int64_t for the value. (enum_type_decl::enumerator::enumerator): Likewise. (enum_type_decl::enumerator::{s,g}et_value): Take/returnan int64_t value. * src/abg-dwarf-reader.cc (die_unsigned_constant_attribute): Take an uint64_t value. (die_signed_constant_attribute): Take an int64_t value. (die_location, die_size_in_bits, die_access_specifier) (die_virtuality, die_is_virtual, die_is_declared_inline) (build_translation_unit_and_add_to_ir, build_type_decl) (build_enum_type, build_pointer_type_def, build_array_type): Adjust. * src/abg-reader.cc (build_enum_type_decl): Adjust. * src/abg-writer.cc (write_enum_type_decl): Do not cast the result of enumerator::get_value() anymore, it's value is now a int64_t. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
5c8c049e70 |
Bug 19138 - Failure to relate variables address from DWARF and ELF
In this problem report libabigail's DWARF reader wrongly looks up the address of variables (that it got from DWARF) in the .bss section of the ELF file. But then, in these files (generated by the Intel C++ compiler) the variables we are looking at have their addresses in the .data1 section. This patch changes the DWARF/ELF reader to make it look for variable addresses in .data, .data1, .rodata and .bss sections, as it should be. * include/abg-dwarf-reader.h (elf_type::ELF_TYPE_RELOCATABLE): New enumerator. * src/abg-dwarf-reader.cc (find_section): Factorize this from ... (find_text_section, find_bss_section): ... these. (find_rodata_section, find_data_section, find_data1_section): Define new static functions. (elf_file_type): Move this static function definition up. (read_context::{get_elf_file_type, address_is_in_section, get_data_section_for_variable_address}): New member functions. (read_context::maybe_adjust_fn_sym_address): Adjust comment. Adjust to use the new read_context::get_data_section_for_variable_address(). * tests/data/test-types-stability/pr19138-elf0: New test input binary. * tests/data/Makefile.am: Add the new test input binary to the test suite. * tests/test-types-stability.cc (elf_paths): Take it into account. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
d50882bf4f |
Make class_decl::base_spec class follow the pimpl pattern
* include/abg-ir.h (class_decl::base_spec::priv): Declare new private data type. (class_decl::base_spec::priv_): Declare new pimpl data member. (class_decl::base_spec::{base_class_, offset_in_bits_, is_virtual_}): Remove. (class_decl::base_spec::{get_base_class, get_is_virtual, get_offset_in_bits}): Make these member functions out of line. * src/abg-ir.cc (struct class_decl::base_spec::priv): New type. (class_decl::base_spec::{get_base_class, get_is_virtual, get_offset_in_bits}): Define these functions here. (class_decl::base_spec::base_spec): Adjust because now there is only one pimpl data member to initialize. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Ondrej Oprala
|
6a7566d513 |
Add the option of printing the file, line and column information about a type being reported.
* bash-completion/abicompat: Complete the new "--no-show-locs" option. * bash-completion/abidiff: Likewise. * bash-completion/abidw: Likewise. * bash-completion/abipkgdiff: Likewise. * doc/manuals/abicompat.rst: Mention the new "--no-show-locs" option. * doc/manuals/abidiff.rst: Likewise. * doc/manuals/abidw.rst: Likewise. * doc/manuals/abipkgdiff.rst: Likewise. * include/abg-comparison.h (show_locs): Add declarations. * src/abg-comparison.cc: (diff_context::priv): Add a new switch called "show_locs_" and set its default value to false. (report_loc_info): New function. Outputting the extra information is conditionalized based on the associated diff contexts settings. (show_locs): define a getter/setter for diff_context::priv::show_locs_. ({distinct,pointer,reference,qualified_type,enum,class,scope,fn_parm, typedef,corpus}_diff::report): Call report_loc_info when appropriate. (maybe_report_diff_for_member): Likewise. (represent): Accept a const reference to a diff_context_sptr as a first argument and call report_loc_info on its second argument. * src/abg-dwarf-reader.cc: * tests/data/Makefile.am: Add the new test reference files. * tests/data/test-abicompat/test0-fn-changed-report-2.txt: New test reference output. * tests/data/test-abicompat/test5-fn-changed-report-1.txt: Likewise. * tests/data/test-abicompat/test6-var-changed-report-1.txt: Likewise. * tests/data/test-abicompat/test7-fn-changed-report-2.txt: Likewise. * tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt: Likewise. * tests/data/test-diff-filter/test31-pr18535-libstdc++-report-1.txt: Likewise. * tests/data/test-diff-pkg/dirpkg-3-report-2.txt: Likewise. * tests/data/test-diff-suppr/test6-fn-suppr-report-0-1.txt: Likewise. * tests/test-abidiff.cc: Explicitly create a diff context and turn off location emitting. * tests/test-diff-dwarf.cc: Likewise. * tests/test-abicompat.cc: Add --no-show-locs to all existing test arguments. Run a few of the existing tests again, but without this option. * tests/test-diff-filter.cc: Likewise. * tests/test-diff-pkg.cc: Likewise. * tests/test-diff-suppr.cc: Likewise. * tools/abicompat.cc: Handle the new "--no-show-locs" option. * tools/abidiff.cc: Likewise. * tools/abidw.cc: Likewise. * tools/abipkgdiff.cc: Likewise. Signed-off-by: Ondrej Oprala <ooprala@redhat.com> |
||
Dodji Seketeli
|
b017143876 |
[PERF] Access naked pointers for canonical types and function types
Performance profiling has shown that accessing shared_ptr to canonical types and function type during type comparison was noticeable slowing down the process. This patch thus access naked pointers for canonical types and function types at these performance hot spots. The profiling took place while running abidw --abidiff on the r300_dri.so binary. * include/abg-ir.h (type_base::get_naked_canonical_type): Declare new accessor. (function_decl::get_naked_canonical_type): Likewise. (function_decl::set_type): Pass a reference to the shared_ptr. * src/abg-ir.cc (type_base::priv::naked_canonical_type): New data member. (type_base::priv::priv): Initialize it. (canonicalize): Set the naked canonicalize type when we set its shared pointer. (type_base::get_naked_canonical_type): Define new accessor. ({pointer_type_def,reference_type_def,function_type,class_decl}::operator==): Use naked canonical pointers rather than the slower shared_ptr to canonical pointers. (function_decl::priv::naked_type_): New data member. (function_decl::priv::priv): Initialize it. (function_decl::get_naked_type): Define new accessor. (function_decl::set_type): Pass a reference to the shared_ptr . (equals): In the overload for function_decl, use the faster naked pointers to the type of the function. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
c0de97846c |
[PERF] Turn some pimpl pointers into naked pointers
The private data pointers of libabigail IR types are usually managed using shared_ptr. But performance profiling has shown that de-referencing some of these private data shared_ptr can have a noticeable performance impact. This is because de-referencing shared_ptr involves some locking that show up on some performance profile. So, for decl_base, type_base, and function_decl, this patch replaces the private data shared pointers by naked pointers. This speeds up the access to private data members, especially during comparison of class pointer, reference and function types. And that has a noticeable impact when libabigail handles huge binaries with lots of functions an type, like r300_dri.so. * include/abg-ir.h ({decl_base, type_base, function_decl}::priv_) Make this a naked pointer to priv, rather than a shared_ptr<priv>. * src/abg-ir.cc (decl_base::~decl_base): Destroy the private data pointer, aka pimpl pointer. (type_base::~type_base): Likewise. (function_decl::~function_decl): Likewise. (class_decl::~class_decl): Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
1466510881 |
[PERF] Pass a bunch of perf-sensitive smart pointers by reference
* include/abg-fwd.h (lookup_type_in_corpus, lookup_type_in_scope) (lookup_var_decl_in_scope): Pass the decls smart pointers by reference. * src/abg-ir.cc (lookup_type_in_corpus, lookup_type_in_scope) (lookup_var_decl_in_scope): Pass the decls smart pointers by reference, for performance reasons. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
0ec2416837 |
Bug 19126 - abidw segv on a dwz compressed version of r300_dri.so
Suppose a declaration D (which locus is in a file F) is imported at an offset offset of O1 into a compilation unit C1 and at an offset O2 (using DW_TAG_imported_unit) into a compilation unit C2. When the DWARF reader creates the ABI artifact for D in O1, its location is encoded by a location manager that is handled by C1. At O2 (in C2) the ABI artifact for D (created at O1, in C1) is re-used. But then, to decode the location of D, the DWARF reader wrongly uses the location manager that is handled by C2. It should use the location manager of C1, because that is the one used to encode the location of D. It picks the wrong location manager because it picks the wrong translation unit for D. Right now, the translation unit for a given declaration is the "current" translation unit at the moment the DIE was being inspected. And that is wrong when imported type units kick in. 1/ More generally, each ABI artifact should be associated with its translation unit, which is the current translation unit when the artifact was created. As there is just one copy of D, its translation unit should always be the same. 2/ Also, the location should ensure that about the location manager used to encode it is the same one used to decode it, so that this kind of bug cannot arise. This patch fixes the issue by doing 1/ and 2/. The r300_dri.so test case on which is was failing is not added to the test suite because it's too big. It was taking more than 55 minutes to have complete abidw --abidiff complete on that binary, on my machine. So I am going to work on the performance side of things, I think. * include/abg-ir.h (class location_manager): Forward declare it before class location. (location::loc_manager_): New data member. (location::location): Take the location manager in one overload and initialize the new loc_managers_ in all the overloads. (location::get_location_manager): New getter. (location::expand): New member function. (location::*): Add API doc to all entry points. (location_manager::expand_location): Take a const location. (type_or_decl_base::set_corpus): Remove. (type_or_decl_base::{get,set}_translation): New accessors. (decl_base::{decl_base,get_location}): Take or return a reference on location. (scope_decl::scope_decl): Likewise. (type_decl::type_decl): Likewise. (namespace_decl::namespace_decl): Likewise. (qualified_type_def::qualified_type_def): Likewise. (pointer_type_def::pointer_type_def): Likewise. (reference_type_def::reference_type_def): Likewise. (array_type_def::subrange_type::{subrange_type, get_location}): Likewise. (enum_type_decl::enum_type_decl): Likewise. (typedef_decl::typedef_decl): Likewise. (var_decl::var_decl): Likewise. (function_decl::function_decl): Likewise. (function_decl::parameter::parameter): Likewise. (template_decl::template_decl): Likewise. (type_tparameter::type_tparameter): Likewise. (non_type_tparameter::non_type_tparameter): Likewise. (function_tdecl::function_tdecl): Likewise. (class_tdecl::class_tdecl): Likewise. (class_decl::class_decl): Likewise. (class_decl::method_decl::method_decl): Likewise. * src/abg-ir.cc (location::expand_location): Define new member function. (type_or_decl_base::priv::corpus_): Remove. (type_or_decl_base::priv::translation_unit_): New data member. (type_or_decl_base::priv::priv): Adjust. (type_or_decl_base::set_corpus): Remove. (type_or_decl_base::get_corpus): Adjust. (type_or_decl_base::{get,set}_translation_unit): New member functions. (decl_base::priv::priv): Take a reference to location. (decl_base::decl_base): Likewise. (decl_base::get_location): Return a reference to location. (location_manager::create_new_location): Adjust. (location_manager::expand_location): Take a reference to location. (translation_unit::get_global_scope()): Adjust. (translation_unit::bind_function_type_life_time): Likewise. (scope_decl::{add,insert}_member_decl): Adjust. (get_translation_unit): Likewise. (type_decl::type_decl): Take a reference to location. (namespace_decl::namespace_decl): Likewise. (qualified_type_def::qualified_type_def): Likewise. (pointer_type_def::pointer_type_def): Likewise. (reference_type_def::reference_type_def): Likewise. (array_type_def::subrange_type::priv::priv): Likewise. (array_type_def::subrange_type::{subrange_type, get_location}): Likewise. (enum_type_decl::enum_type_decl): Likewise. (typedef_decl::typedef_decl): Likewise. (var_decl::var_decl): Likewise. (function_decl::function_decl): Likewise. (function_decl::parameter::parameter): Likewise. (template_decl::template_decl): Likewise. (type_tparameter::type_tparameter): Likewise. (non_type_tparameter::non_type_tparameter): Likewise. (function_tdecl::function_tdecl): Likewise. (class_tdecl::class_tdecl): Likewise. (class_decl::class_decl): Likewise. (class_decl::method_decl::method_decl): Likewise. * src/abg-writer.cc (write_location): Take a reference to location and adjust. (write_array_type_def, write_function_decl, dump_decl_location): Adjust. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
2eda63d0f2 |
Fix internal name for pointers, typedefs and arrays
Internal names (and pretty representation) of types are used for type canonicalization. These were not being correctly computed for pointers typedefs and arrays because we were forgetting sometimes to use internal names of the underlying types, especially because of caching issues. This patch addresses that. Note that I noticed this while comparing the two versions of libgromacs_d.so.0.0.0 involved in the comparison referenced by bug https://bugzilla.redhat.com/show_bug.cgi?id=1283906. But then that library is too big (and takes too much time) to be included as a non regression test :( * include/abg-ir.h (pointer_type_def::priv_): New data structure. The type is now pimpled. (typedef_decl::priv_): Likewise. * src/abg-ir.cc (struct pointer_type_def::priv): New struct. (pointer_type_def::pointer_type_def): Adjust. (pointer_type_def::get_pointed_to_type): Likewise. (pointer_type_def::get_qualified_name): Store temporary/internal names into different caches. (array_type_def::priv::{temp_internal_qualified_name_, internal_qualified_name_}): New data members. (get_type_representation): In the overload for array_type_def, take requests for internal names into account. (array_type_def::get_qualified_name): Take requests for internal names into account. Store temporary/internal names into different caches. (typedef_decl::priv): New struct. (typedef_decl::typedef_decl): Adjust. (typedef_decl::get_underlying_type): Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
fa4b7c8069 |
Fix comparison in qualified_type_diff::has_changes
* src/abg-comparison.cc (qualified_type_diff::has_changes): Make this stupid and simple, now that we have (fast) canonical type based comparison. * include/abg-ir.h (qualified_type_diff::operator==): Add an overload for qualified_type_diff here. (operator==): Likewise. * src/abg-ir.cc (qualified_type_diff::operator==): Define it. (operator==): Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
43c908ed15 |
Bug 19336 - Better handle redundantly qualified reference types
Sometimes we can see const references in DWARF. But then, a reference is always const, so that qualified reference is redundant. Furthermore, having that construct make its way into the internal representation can cause awkward diagnostics. The DWARF reader was thus eliding such redundant qualifiers in the function "maybe_strip_qualification". It was doing so by stripping the qualifier from the qualified type. So const reference, for instance, becomes a (non-qualified) reference. In that case, we are turning a qualified type into a non-qualified one. But as the accompanying problem report suggests, this can cause issues during the DWARF parsing. This is because a given Debug Information Entry (DIE) of qualified type kind can be referenced elsewhere, by another type. That other type expects that DIE to be a qualified type. And libabigail's DWARF reader code enforces that. So the internal representation of a type resulting from a qualified type DIE must be a qualified type itself. So the way the function "maybe_strip_qualification" was doing the redundancy elision was wrong. This patch fixes that by keeping the type qualified, but introducing a "no-op" qualifier. Actually, the IR already has that "no-op" qualifier: abigail::ir::qualified_type_def::CV_NONE. So now "maybe_strip_qualification" just turns the CV_CONST qualifier into a CV_NONE one when the former is redundant. Now that the libabigail type system actually *has* types qualified with this no-op qualifier, we need to handle things like printing the name of such qualified types. When we are printing the name of the type for internal reasons (i.e, for type canonicalization purposes) we need to make a difference between the name of a no-op qualified type and the name of the underlying type of the qualified type, otherwise, the canonicalizer wrongly considers the two types as being equal. But then when we are printing the name of the no-op qualified type for diagnostics reasons, then the name is the same as the name of its underlying unqualified type. * src/abg-dwarf-reader.cc (maybe_strip_qualification): Do not nuke the qualified type. Rather, just turn the redundant const qualifier into a no-op one. * src/abg-comparison.cc (compute_diff_for_types): Look through no-op qualified types. * include/abg-ir.h (decl_base::{peek,set}_temporary_qualified_name): Declare new accessors. * src/abg-ir.cc (decl_base::priv::temporary_qualified_name_): New data member. (decl_base::{peek,set}_temporary_qualified_name): Define new accessors. (qualified_type_def::priv::{temporary_internal_name_, internal_name}): New data members. (qualified_type_def::build_name): For a no-op qualified type, the internal name (which contains the 'none' qualifier) is different from the non-internal name. (qualified_type_def::get_qualified_name): Handle temporary names and non-temporary names in two different caches. Also handle internal and non-internal names in two different caches. This makes four different caches. (qualified_name_setter::do_update): Do not touch the non-internal, non-temporary qualified name cache if the qualified parent name is empty. * tools/abidw.cc (main): change --check-alternate-debug-info to make it *not* display the name/path to the alternate debug info, when it's found. Rather, only --check-alternate-debug-info-base-name keeps displaying the base name of the alternate debug info. * tests/data/test-alt-dwarf-file/test1-libgromacs-debug-dir/*: New test material. * tests/data/Makefile.am: Add the new test material to the build system. * tests/test-alt-dwarf-file.cc (in_out_specs): Take the new test input into account. * tests/data/test-read-dwarf/test1.abi: Adjust. * tests/data/test-read-dwarf/test7.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/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. * tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi: Likewise. * tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi: Likewise. * tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi: Likewise. * tests/data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi: Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
1bee40c075 |
Do not forget to peel qualified type off when peeling types
When peeling off typedefs, references and pointers to see if a type is made of a class type, we forget to peel qualified types off. This is in the context of parsing type info from DWARF and to determine if we should delay type canonicalization (because a given type is made of a class) or not. Fixed thus. * include/abg-fwd.h (peel_qualified_type): Declare new function ... * src/abg-ir.cc (peel_qualified_type): ... and define it. (peel_typedef_pointer_or_reference_type): Peel qualified types here too. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
35dd76bc69 |
Constify is_qualified_type()
* include/abg-fwd.h (is_qualified_type): Make this take a const parameter. * src/abg-ir.cc (is_qualified_type): Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
86ec69a86d |
Read enum values in the size_t and write them in ssize_t
Make sure to read enum values in the widest possible integer (size_t) but write them (in abixml writer) using a signed type to ease comparison. This makes the runtestreaddwarf pass on 32 bit x86, because we were losing some precision reading enum values using a signed integer. * include/abg-ir.h (enum_type_def::enumerator::get_value): Return a size_t. * src/abg-ir.cc (enum_type_decl::enumerator::get_value): Likewise. * src/abg-dwarf-reader.cc (die_signed_constant_attribute): #if-out this static function that is not used anymore. (build_enum_type): Read the value of the enumerator using a size_t value. * src/abg-reader.cc (build_enum_type_decl): Read the enum value using a long long int. * src/abg-writer.cc (write_enum_type_decl): Write using a ssize_t. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
266fa9288e |
Add --version option to several libabigail tools
This patch changed the revision number of the libabigail library to make it reflect the fact that we are not in "release candidate" mode, before the first 1.0 release. So the revision number is now "rc0". The configuration manager has been updated to support version numbers that are strings, so that it can supports things like "rc0". Then, several libabigail tools have been modified to support the --version option to display their version number. * configure.ac: Set the version revision to "rc0". * doc/manuals/abicompat.rst: Adjust manual for new --version option. * doc/manuals/abidiff.rst: Likewise. * doc/manuals/abidw.rst: Likewise. * doc/manuals/abilint.rst: Likewise. * doc/manuals/abipkgdiff.rst: Likewise. * include/abg-config.h (config::{m_format_minor, m_format_major}): Make these be strings. (config::{get,set}_format_minor_version_number): Make these return strings. (config::{get,set}_format_major_version_number): Make these return or take strings. (abigail_get_library_version): Make this take strings. * src/abg-config.cc (config::config): Adjust. (config::{get,set}_format_major_version_number): Make these return or take strings. (config::{get,set}_format_minor_version_number): Make these return strings. (abigail_get_library_version): Make this take strings. * include/abg-version.h.in: Make the version variables be strings. * src/abg-writer.cc (write_translation_unit): The version numbers are now strings so adjust. * tools/{abicompat,abidiff,abidw,abilint,abipkgdiff,abisym}.cc (options::display_version): New data member. (options::options): Initialize it. (display_usage): Add documentation for new --version option. (parse_command_line): Parse new --version option. (main): Support --version. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
ba980025fb |
Bug 19173 - Abidiff doesn't detect symbol size change in library
It appears that libabigail does not represent the size of ELF symbols, so it doesn't detect when a symbol size changes without impacting the size of the type of said symbol, as described by debug info. It appears that Address Sanitizer as implemented by Clang does change the size of variable symbols when it instruments those variables. And of course, the size of type of said symbols (as described by debug information) remains unchanged. This patch makes Libabigail become aware of symbol sizes, especially for variables. Symbol sizes for functions are ignored for now, because a change in a function symbol size is not an ABI change. The patch makes libabigail detect and report symbol size changes for variables, but looking at the ELF information, independently from the debug information. The patch adjusts the existing tests and adds a new test using the binaries that were filed in the bug report. * include/abg-ir.h (elf_symbol::{elf_symbol, create}): Take a size parameter. (elf_symbol::{get,set}_size): New accessors. * src/abg-ir.cc (elf_symbol::priv::size_): New data member. (elf_symbol::priv::priv): Initialize it. (elf_symbol::{elf_symbol, create}) Take a size parameter. (textually_equals): Compare the size of variable symbols. (elf_symbol::{get, set}_size): New accessors. * src/abg-comparison.cc (maybe_report_diff_for_symbol): New static function. ({function_decl_diff,var_diff}::report): Use it. * src/abg-dwarf-reader.cc (lookup_symbol_from_sysv_hash_tab) (lookup_symbol_from_gnu_hash_tab, lookup_symbol_from_symtab) (read_context::lookup_elf_symbol_from_index): Set the size of the elf symbols' internal representation. * src/abg-reader.cc (build_elf_symbol): Read the size attribute if present. * src/abg-writer.cc (write_elf_symbol): Write the size attribute for variable symbols, if it's not zero. * tests/data/test-diff-dwarf/test34-pr19173-libfoo.so: New test input binary. * tests/data/test-diff-dwarf/test34-pr19173-libfoo2.so: Likewise. * tests/data/test-diff-dwarf/test34-pr19173-libfoo-report-0.txt: New reference test output. * tests/data/Makefile.am: Add the new test input binaries to the build system. * tests/test-diff-dwarf.cc (in_out_specs): Add the new test input above to the test harness. * tests/data/test-diff-dwarf/test9-report.txt: Adjust. * tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt: Likewise. * tests/data/test-read-dwarf/test0.abi: Likewise. * tests/data/test-read-dwarf/test1.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/test15-pr18892.so.abi: Likewise. * tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise. * tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi: Likewise. * tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi: Likewise. * tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi: Likewise. * tests/data/test-read-dwarf/test21-pr19092.so.abi: Likewise. * tests/data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi: Likewise. * tests/data/test-read-dwarf/test6.so.abi: Likewise. * tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
4adbafaa43 |
Pass a bunch of parameters by reference as they ought to be
* include/abg-ir.h (operator==): In the overload for elf_symbol_sptr, pass the parameters by reference. * src/abg-ir.cc (operator==): Do the same at definition site. * src/abg-comparison.cc (maybe_report_diff_for_member): Pass parameters by reference. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
7b35e89315 |
Bug 19139 - DWARF reader doesn't handle garbage in function names
In this bug, the DWARF debug info of the binary (generated by Intel's ICC compiler) has interesting constructs like: [ 6b5a0] subprogram decl_line (data2) 787 decl_column (data1) 15 decl_file (data1) 46 declaration (flag) accessibility (data1) public (1) type (ref4) [ 6b56a] prototyped (flag) name (string) "ldiv" MIPS_linkage_name (string) "ldiv" [ 6b5b6] formal_parameter type (ref4) [ 5f2aa] name (string) "$Ë2" [ 6b5bf] formal_parameter type (ref4) [ 5f2aa] name (string) "$Ë3" Note the strings that make up the name of the formal parameters of the function, near the end: [ 6b5b6] formal_parameter type (ref4) [ 5f2aa] name (string) "$Ë2" [ 6b5bf] formal_parameter type (ref4) [ 5f2aa] name (string) "$Ë3" The strings "$Ë2" and $Ë3" (which are the names of the parameters of the function) are garbage. Libabigail's DWARF reader naively uses those strings as names for the function parameters, in the type of the function. Then, the abixml writer emits an XML document, with these strings as property values, representing the name of the type of the function. And of course, the XML later chokes when it tries to read that XML document, saying that the property is not valid UTF-8. This patch addresses the issue by dropping those garbage names on the floor, for function type names. In that context, any string that is not made of ASCII characters is considered as being garbage, for now. The patch, in the abixml writer, also escapes function parameters names so that they don't contain characters that are not allowed in XML. The abixml reader already handles the un-escaping of the names it reads, so I think there is nothing to do there. Ultimately, I guess I should get the unicode value of the characters of that string, encode the string into UTF-8 and use the result as the name for the parameter. That would mean using UTF-8 strings for function parameter names, and, for all declarations names. But that is too much for worfk too little gain for now. The great majority of the binaries we are dealing with are still using ASCII for declaration names. The patch also introduces a new test harness that runs "abidw --abidiff" on a bunch of input binaries. This harness runs over the binaries that were submitted in this bug report. * include/abg-tools-utils.h (string_is_ascii): Declare new function ... * src/abg-tools-utils.cc (string_is_ascii): ... and define it. * src/abg-writer.cc (write_function_type): Escape forbidden XML characters in function type names. * src/abg-dwarf-reader.cc (build_function_type): If a parameter name is not ascii, drop it on the floor. * tests/data/test-types-stability/pr19139-DomainNeighborMapInst.o: New test input binary. * tests/data/test-types-stability/pr19202-libmpi_gpfs.so.5.0: Likewise. * tests/data/Makefile.am: Add the new binaries above to the build system. * tests/test-types-stability.cc: New test harness. * tests/Makefile.am: Add the new test harness to the build system. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
089b3fc762 |
Support updating a class in the abixml reader
In DWARF, the same class declaration can be present several times but with different "views", that is, it can be present in a first translation unit, but without any member type; then in a subsequent translation unit, its member types are defined. In another, it'll be completely defined, with all its data members and base classes. The DWARF reader knows how to amend the class to add new members to it, as they show up in the debug information. This patch adds the same functionality to the abixml reader. The writer has already started to write class declarations with different "views" too, since it's started to avoid duplicating full class definitions in every translation unit that uses them. Without this patch, abixml misses some class members, and that is a bug. * include/abg-ir.h (class_decl::{find_base_class, find_member_type, find_data_member}): Declare new member functions .. * src/abg-ir.cc (class_decl::{find_base_class, find_member_type, find_data_member}): ... and define them. * src/abg-reader.cc (build_class_decl): Add the ability to update a class to add new data members, member types and base classes to it, if necessary. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
caaeaea10b |
Misc style cleanup
* include/abg-fwd.h: Remove unnecessary declaration of class parameter. * src/abg-ir.cc: Remove trailing space in a comment. * src/abg-reader.cc: Fix a comment. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
093bc5da06 |
Pass some more parameters in reference
Profiling as shown that we might gain some precious cycles by passing some well chosen parameters by reference. * include/abg-ir.h (operator==): For the type_base_sptr and decl_base_sptr overloads, pass the parameters by reference. ({var,function}_decl::{set,get}_symbol): Pass the elf_symbol_ptr by reference. * src/abg-ir.cc (operator==): For the type_base_sptr and decl_base_sptr overloads, pass the parameters by reference, now in the definition. ({var,function}_decl::{set,get}_symbol): Pass the elf_symbol_ptr by reference, now in the definition. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
7bb65377a5 |
Accelerate a slow path in hash_type_or_decl()
Profiling shows that hash_type_or_decl() is very slow when hashing function parameters and base class specifications. This is because in those two cases we use the slow recursive hashing algorithm to hash types, rather than using the faster one based on using the pointer values of canonical types when possible. This was making corpora comparison very slow, as it uses hash_type_or_decl() to hash diffs of ABI artifacts. This patch fixes that. * include/abg-ir.h (is_function_parameter, is_class_base_spec): Declare new functions. * src/abg-ir.cc (is_function_parameter, is_class_base_spec): Define them. (hash_type_or_decl): Handle hashing of function parameters are class base specifications with the fast path of type hashing. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
60425d2996 |
Implement fast type lookup in a corpus
Profiling has shown that on libraries with a lot of class types declarations (more than 10K types), the phase of resolving those declarations to their definition was a hot spot. The lookup of the type definition inside the entire corpus was the bottleneck. This patch removes (or loosen) that bottleneck by doing away with the graph-walking-based type lookup algorithm that was used. Rather, maps of name -> types are maintained by each scope, in each translation unit. Those maps are updated each time a type is added to a scope. And looking up a type amounts to a lookup in a map. Way faster. * include/abg-fwd.h (components_to_type_name): Declare new function. * include/abg-ir.h (string_type_base_wptr_map_type): New typedef. (translation_unit::{get,set}_types): Declare new member functions. * src/abg-ir.cc (translation_unit::priv::types_): New data member. (translation_unit::{get,set}_types): Define these member functions. (maybe_update_types_lookup_map): Define new static function. (components_to_type_name): Define new function. (scope_decl::{add_member_decl, insert_member_decl}): Call the new maybe_update_types_lookup_map. (scope_decl::find_iterator_for_member): Fix logic. (class_decl::set_is_declaration_only): When a class declaration becomes a definition, update the name -> type map maintained in the scope of the class. (lookup_type_in_translation_unit): Use the hash map of qualified name -> types that is now maintained in the translation unit. This is way faster than the previous walking algorithm. * src/abg-dwarf-reader.cc (build_translation_unit_and_add_to_ir): When fixing up global variable declarations that need to be re-added to the translation unit, use the new fast type lookup function. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
4b754229d1 |
Make canonicalization non sensitive to struct-ness of subtypes
In a previous patch, we made canonicalization independant from
struct-ness of class types. This was in this commit:
|
||
Dodji Seketeli
|
f1c48fe80f |
Handle aliased function decls when comparing decls in general
When comparing two declarations, we look at their linkage name. When the linkage names are different, then we infer that the two decls are different. But then, for *function* decls, it can happen that two different linkage names are actually for different symbols that do alias; the (ELF) symbols are different but they have the same address; so they point to the same "thing". The two functions are not different, then. And we were not supporting this last case of diffent linkage names that are aliases of each other. This patch adds support for that. * include/abg-ir.h (is_function_decl): Add a const to the reference parameter, making it comply with the definition. * src/abg-ir.cc (equals): In the overload for decl_base, when the two linkage names are different, consider the case of the decls being aliased functions. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
1a6b957401 |
Fix const-ness of a function parameter
* include/abg-fwd.h (is_function_decl): Add a const to the parameter to make it comply with the definition in abg-ir.cc. Woops. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
f95af3a89a |
Do not compare access specs for member types & functions
It turns that in some DWARF (e.g, from the r300_dri.so binary in bug libabigail/19024) the same class Foo can be declared as a struct, and later defined as a class. Or the other way around. In some cases, Foo can be declared as a struct, have a member type Foo::Type with no access specifier, and later that member type is still present with no access specifier when Foo is defined as a class. So when comparing Foo::Type (from struct Foo) against Foo::Type (from class Foo) we must not consider the access specification of Type, otherwise, as in the first case it's 'public' and in the second case it's 'private', the two member types would be considered different. And something similar happens for member function declarations too. This patch thus avoids comparing access specifiers for member types and functions. Though it can be considered as a regression compared to what was being done before, access specifiers don't have an impact on ABI per se. And they can cause noise in the result, as we are seeing here. * include/abg-fwd.h (is_function_decl): Declare a new overload. * src/abg-ir.cc (is_function_decl): Define a new overload. (equals): In the overload for decl_base, do not compare access specifiers when comparing member functions and types. * tests/data/test-diff-dwarf/test0-report.txt: Adjust. * tests/data/test-diff-filter/test0-report.txt: Likewise. * tests/data/test-diff-filter/test01-report.txt: Likewise. * tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt: Likewise. * tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt: Likewise. * tests/data/test-diff-filter/test4-report.txt: Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
e9bdb488b3 |
Bug 19025 - abixml writer forgets to emit some member types
When a member type (a type that is a member of a class) M is referenced by some types emitted by abixml, but the context of M (the class type which M is a member of) is not itself referenced by any ABI artifact, then abixml forgets to emit the context of M and thus M itself. With this patch, when the abixml writer has emitted almost all ABI artifacts for the current translation unit, it looks for types that have been referenced by the emitted ABI artifacts, but that haven't been emitted themselves. It then emits those referenced-but-not-emitted types, and makes sure their contexts are emitted as well. * include/abg-fwd.h (is_namespace): Fix prototype. * src/abg-writer.cc (struct type_ptr_comp_functor): New internal type. (sort_type_ptr_map): New static function. (write_context::m_referenced_types_map): Renamed m_referenced_fntypes_map data member into this. (write_context::get_referenced_types): New member function. (write_context::record_type_as_referenced): Renamed record_fntype_as_referenced member function into this. Adjust. (write_context::type_is_referenced): Renamed fntype_is_referenced into this. (write_context::clear_referenced_types_map): Renamed clear_referenced_fntypes_map member function into this. Adjust. (write_decl_in_scope): New static function. (write_translation_unit): Use it here to emit types that are referenced by other types in the TU, but that are not emitted. Adjust. (write_pointer_type_def, write_reference_type_def) (write_typedef_decl): Record the underlying types referenced by the emitted types as being, well, referenced. * tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so: New test binary input. * tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi: New reference output of the binary input above. * tests/data/Makefile.am: Add the new test material above to the source distribution. * tests/test-read-dwarf.cc (in_out_spec): Add the 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/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. * tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi: Likewise. * tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi: Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
0e3416e7e2 |
Bug 19023 - Type canonicalization is sensitive to struct-ness
In some debug info of some shared library, the same type can be present as a struct in some translation units, and as a class in others. As we are using the "pretty representation" of types to hash types during type canonicalization, a "class foo" and "struct foo" are (wrongly) considered different, because those pretty representations are different. This patch changes the canonicalization code to make it independent from the struct-ness of the class being canonicalized. * include/abg-ir.h (class_decl::is_struct): Declare a setter for the "is-struct" property. * src/abg-ir.cc (class_decl::is_struct): And define that setter here. (type_base::get_canonical_type_for): Temporarily set the 'is-struct' flag of the class type to 'false' before building its pretty representation. * tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so: New test input binary. * tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi: New test reference output. * tests/data/Makefile.am: Add the new test material above to the source distribution. * tests/test-read-dwarf.cc (in_out_specs): Add the two new test inputs to the list of test inputs to consider. * tests/data/test-read-dwarf/test14-pr18893.so.abi: Adjust. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
48801d23e4 |
Bug 19037 - Make ABI corpus support several functions with same symbol
It turns out that, in DWARF, there can be function template instantiations foo<int>(int) and foo<TypedefOfInt>(TypedefOfInt) which have the same symbol name, if TypedefOfInt is a typedef of int. An ABI corpus retains only one function declaration per symbol name. So in the example of the bug the input DWARF has the two instantiations, but libabigail is just keeping one of the two; so the abixml only has one of the two template instantiations. This patch changes the ABI corpus model so that it represents the fact that there can be several function declarations for a given symbol. The patch then adjust the comparison engine to make it know about this new model. * include/abg-corpus.h (corpus::exported_decls_builder::str_{fn,var}_ptr_map_type): Remove these typedefs from here as they only used internally in abg-corpus.cc. So we move them there instead. * src/abg-corpus.cc (str_fn_ptrs_map_type): New typedef. (str_var_ptr_map_type): Moved the typedef that was in corpus::exported_decls_builder here. (corpus::exported_decls_builder::id_fns_map_): Rename the fns_ data member into this. Make it have a str_fn_ptrs_map_type as a type. (corpus::exported_decls_builder::id_fns_map): Renamed the fns_map() accessor into this one. (corpus::exported_decls_builder::{fn_id_is_in_id_fns_map, fn_is_in_fns}): New member functions. (corpus::exported_decls_builder::fn_is_in_id_fns_map): Rename fn_is_in_map into this. (corpus::exported_decls_builder::add_fn_to_id_fns_map): Rename add_fn_to_map into this. (corpus::exported_decls_builder::add_fn_to_exported): Adjust. (corpus::exported_decls_builder::maybe_add_fn_to_exported_fns): Adjust. * src/abg-comparison.cc (function_decl_diff::report): Emit reports about function name changes (for a given function ID) only if there are sub-type changes to be reported for the function. In that case, do not forget to emit the sub-type changes after the name changes have been reported. (corpus_diff::priv::ensure_lookup_tables_populated): Several functions of the same ID can be removed or added from/to the corpus. * tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so: New test input binary. * tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi: New test output reference. * tests/data/Makefile.am: Add the new test materials to the source distribution. * tests/test-read-dwarf.cc (in_out_specs): Adjust to add the new test inputs above. Signed-off-by: Dodji Seketeli <dodji@redhat.com> |
||
Dodji Seketeli
|
9a0abd846b |
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
|
6e36a4381d |
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
|
38e17e0e07 |
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
|
da4aaf467a |
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
|
db02f0bdb4 |
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
|
9cb146a013 |
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
|
4ec793b9d0 |
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
|
4173b2a421 |
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
|
912eb7e36b |
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
|
3e146f14ba |
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
|
0cc38b2327 |
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
|
46c263fbae |
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
|
16299395d7 |
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
|
110494af94 |
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
|
a717ca6faf |
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
|
b2e5366d3f |
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:#️⃣:operator()) (function_decl:#️⃣: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
|
bb5085741b |
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> |