* include/abg-dwarf-reader.h (symbol_type, symbol_binding): New
enums.
(operator<<): Declare new overloads for the new enums above.
(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf):
Declare new entry points.
* src/abg-dwarf-reader.cc (lookup_symbol_from_elf)
(lookup_public_function_symbol_from_elf)
(lookup_public_variable_symbol_from_elf): Define new static
functions.
(read_context::elf_{module_, handle}_): New data members.
(read_context::{elf_module, elf_handle}): New accessors.
(read_context::load_debug_info): Store the elf module into
read_context::_elf_module_. Adjust.
(read_context::{lookup_symbol_from_elf,
lookup_public_function_symbol_from_elf,
lookup_public_variable_symbol_from_elf}): New member functions.
(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf)
(operator<<): Define public entry points.
* tools/bisym.cc: New tool to lookup a symbol in an elf file.
* tools/Makefile.am: Add the bisym.cc source file to the
distribution and arrange to compile it into a 'bisym' executable.
* tests/test-lookup-syms.cc: New test harness.
* tests/data/test-lookup-syms/test0-report.txt: New test input
for the harness above.
* tests/data/test-lookup-syms/test0.cc: Likewise.
* tests/data/test-lookup-syms/test0.o: Likewise
* tests/data/test-lookup-syms/test01-report.txt: Likewise.
* tests/data/test-lookup-syms/test02-report.txt: Likewise.
* tests/Makefile.am: Build the new runtestlookupsyms test and add
the new files to the distribution.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-corpus.h (enum corpus::origin): New enum.
(corpus::{g,s}et_origin): New accessors.
* src/abg-corpus.cc (corpus::priv::origin): New data member.
(corpus::priv::is_symbol_table_built): Move this up.
(corpus::priv::priv): Adjust.
(corpus::{g,s}et_origin): Define accessors.
* src/abg-dwarf-reader.cc (read_corpus_from_elf): Set the corpus
origin. Also set the path. Oops.
* src/abg-reader.cc (read_corpus_from_input)
(read_corpus_from_archive): Set the corpus origin.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (is_at_global_scope): Declare a new overload.
(get_linkage_name): Declare ...
* src/abg-ir.cc (get_linkage_name): ... these new entry points.
(is_at_global_scope): Define these new overloads useful for the
new get_linkage_name.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.h (class_diff::{deleted, inserted,
changed}_bases): Declare new member functions ...
* src/abg-comparison.cc ((class_diff::{deleted, inserted,
changed}_bases)): ... and define them.
* src/abg-comp-filter.cc (base_classes_added_or_removed): Define
new static functions.
(harmless_filter): Categorize base classes added or removed.
* tests/data/test-diff-dwarf/test8-report.txt: New test input.
* tests/data/test-diff-dwarf/test8-v0.cc: Likewise.
* tests/data/test-diff-dwarf/test8-v0.o: Likewise.
* tests/data/test-diff-dwarf/test8-v1.cc: Likewise.
* tests/data/test-diff-dwarf/test8-v1.o: Likewise.
* tests/data/test-diff-filter/test13-report.txt: New test input.
* tests/data/test-diff-filter/test13-v0.cc: Likewise.
* tests/data/test-diff-filter/test13-v0.o: Likewise.
* tests/data/test-diff-filter/test13-v1.cc: Likewise.
* tests/data/test-diff-filter/test13-v1.o: Likewise.
* tests/Makefile.am: Add the new files above to the source distribution.
* tests/test-diff-dwarf.cc: Use the new relevant input above to
run more tests.
* tests/test-diff-filter.cc: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.h
(diff_category::STATIC_DATA_MEMBER_CHANGE_CATEGORY): New category.
(diff_category::EVERYTHING_CATEGORY): Update
* src/abg-comp-filter.cc (static_data_member_type_size_changed)
(static_data_member_added_or_removed): Define new static
functions.
(harmless_filter::visit): Categorize changes to static data
members as STATIC_DATA_MEMBER_CHANGE_CATEGORY.
* tools/bidiff.cc (set_diff_context_from_opts):
STATIC_DATA_MEMBER_CHANGE_CATEGORY is falls into the harmless
group.
* tests/data/test-diff-filter/test12-report.txt: New test input.
* tests/data/test-diff-filter/test12-v0.cc: Likewise.
* tests/data/test-diff-filter/test12-v0.o: Likewise.
* tests/data/test-diff-filter/test12-v1.cc: Likewise.
* tests/data/test-diff-filter/test12-v1.o: Likewise.
* tools/bidiff.cc: Run this test with the additional input data
above.
* tests/Makefile.am: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (get_global_scope()): New overload for const
decl_base&. Move the other overloads up in the file.
(get_translation_unit): Add an overload for decl_base&. Constify
the others.
(dump_decl_location): Declare new functions.
* src/abg-ir.cc (get_global_scope): Define the overload for const
decl_base&. Write the other overloads in terms of this one.
(get_translation_unit): Likewise, define the overload for const
decl_base&. Write the other overloads in terms of this one.
(dump_decl_location): Define these new overloads.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (qualified_type_def::get_size_in_bits): Declare
new member function ...
* src/abg-ir.cc (qualified_type_def::get_size_in_bits): ... and
define it. Keep in mind that some times the size of the
underlying type can change between the moment the qualified type
is created and the end of its life time. That is because a
subsequent DIE (from DWARF) can alter the size of the underlying
type. This overload allows the user to always query the size of
the underlying type and keep the size of the qualified type in
sync with it.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (set_member_function_is_virtual): Declare new
function.
* include/abg-ir.h (class class_decl): Declare
set_member_function_is_virtual and member_function_is_virtual as
friends of class_decl.
(class_decl::add_member_function): Take an is_virtual flag.
(class_decl::get_num_virtual_functions): Remove.
(class_decl::get_virtual_mem_fns): New member function.
(mem_fn_context_rel::is_virtual_): New member.
(mem_fn_context_rel::mem_fn_context_rel): Adjust to initialize the
new is_virtual_ member.
(mem_fn_context_rel::is_virtual): New member functions.
* src/abg-comparison.cc (represent): Adjust.
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): Adjust.
* src/abg-ir.cc (member_function_is_virtual): Change this to use
mem_fn_context_rel::is_virtual.
(set_member_function_is_virtual): Define this new function.
(class_decl::priv::virtual_mem_fns_): New member to hold virtual
member functions.
(class_decl::get_virtual_mem_fns): Implement this member function.
(class_decl::get_num_virtual_functions): Remove.
(class_decl::add_member_function): Take a new is_virtual flag.
Add virtual member functions to
class_decl::priv::virtual_mem_fns_.
* src/abg-reader.cc (build_class_decl): Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (member_function_is_virtual): Declare new
function.
* include/abg-comparison.h
(diff_category::{NON_VIRT_MEM_FUN_CHANGE_CATEGORY,
VIRTUAL_MEMBER_CHANGE_CATEGORY}): New enumerators.
(diff_category::EVERYTHING_CATEGORY): Adjust.
(class_diff::{changed, deleted, inserted}_member_fns): Declare new
member functions.
* src/abg-comp-filter.cc (data_member_added_or_removed): Add
missing comments.
(has_non_virtual_mem_fn_change): New static predicate function.
(harmless_filter::visit): Categorize non-virtual member function
changes in a diff into NON_VIRT_MEM_FUN_CHANGE_CATEGORY.
* src/abg-comparison.cc
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY): New macro.
(report_mem_header): Count filtered functions for added/deleted
functions as well.
(class_diff::priv::count_filtered_changed_mem_fns): Renamed
priv::count_filtered_member_functions into this. Filter out
changes to non-virtual member functions here.
(class_diff::priv::count_filtered_{inserted, deleted}_mem_fns):
New member functions.
(class_diff::{deleted, inserted, changed}_member_fns): Define new
member functions.
(class_diff::report): Adjust count for filtered inserted/deleted
member functions. Do not report NON_VIRT_MEM_FUN_CHANGE_CATEGORY
if it's disallowed.
(class_diff::traverse): Propagate only
VIRTUAL_MEMBER_CHANGE_CATEGORY from member functions to their
enclosing class.
* src/abg-ir.cc (member_function_is_virtual): Define new
functions.
* tools/bidiff.cc (set_diff_context_from_opts): Adjust to add
NON_VIRT_MEM_FUN_CHANGE_CATEGORY into the harmless group and
VIRTUAL_MEMBER_CHANGE_CATEGORY into the harmful one.
* tests/data/test-diff-filter/test0-report.txt: New test input.
* tests/data/test-diff-filter/test10-report.txt: Likewise.
* tests/data/test-diff-filter/test10-v0.cc: Likewise.
* tests/data/test-diff-filter/test10-v0.o: Likewise.
* tests/data/test-diff-filter/test10-v1.cc: Likewise.
* tests/data/test-diff-filter/test10-v1.o: Likewise.
* tests/data/test-diff-filter/test11-report.txt: Likewise.
* tests/data/test-diff-filter/test11-v0.cc: Likewise.
* tests/data/test-diff-filter/test11-v0.o: Likewise.
* tests/data/test-diff-filter/test11-v1.cc: Likewise.
* tests/data/test-diff-filter/test11-v1.o: Likewise.
* tests/data/test-diff-filter/test2-report.txt: Likewise.
* tests/data/test-diff-filter/test9-report.txt: Likewise.
* tests/data/test-diff-filter/test9-v0.cc: Likewise.
* tests/data/test-diff-filter/test9-v0.o: Likewise.
* tests/data/test-diff-filter/test9-v1.cc: Likewise.
* tests/data/test-diff-filter/test9-v1.o: Likewise.
* tests/test-diff-filter.cc: Consume the test input above to run
more tests.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (class_decl::{priv}): New private data member.
(class_decl::{get_is_declaration_only, set_is_declaration_only,
is_struct, get_definition_of_declaration, get_earlier_declaration,
add_base_specifier, get_base_specifiers, get_member_types,
get_data_members, get_member_functions,
get_member_function_templates, get_member_class_templates}): Move
these methods out-of-line.
(class_decl::{comparison_started_,
declaration_,is_declaration_only_, definition_of_declaration,
is_struct_, bases_, member_types_, data_members_,
member_functions_, member_function_template,
member_class_templates_}): Move these data members into the pimpl
in ...
* src/abg-ir.cc
(class_decl::priv::{declaration_,is_declaration_only_,
definition_of_declaration, is_struct_, bases_, member_types_,
data_members_, member_functions_, member_function_template,
member_class_templates_}): ... here.
(class_decl::priv::classes_being_compared_): New data member.
(class_decl::priv::priv): Initialize the data members.
(class_decl::priv::{mark_as_being_compared,
unmark_as_being_compared, comparison_started): New methods.
(class_decl::{get_is_declaration_only, set_is_declaration_only,
is_struct, get_definition_of_declaration, add_base_specifier,
get_base_specifiers, get_member_types, get_data_members,
get_member_functions, get_member_function_templates,
get_member_class_templates}): Move these out-of-line in here.
(class_decl::{class_decl, set_definition_of_declaration,
set_earlier_declaration, insert_member_type, add_member_type,
add_data_member, add_member_function,
add_member_function_template, add_member_class_template,
has_no_base_nor_member}): Adjust.
(class_decl::operator==): Harden inf-loop prevention during class
comparison using the new priv::mark/unmark_as_being_compared()
functions. Now comparison of a class really compares member
functions again. And it is *slooow*. I should probably change
this to compare only virtual member functions. But at least this
should be correct and robust for now.
* tests/data/test-diff-filter/test0-report.txt: Adjust.
* test01-report.txt: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (get_data_member_offset): Declare new overload for
decl_base_sptr.
* include/abg-comparison.h (unsigned_decl_base_sptr_map)
(unsigned_changed_type_or_decl_map): New typedefs.
* src/abg-ir.cc (get_data_member_offset): Define new overload for decl_base_sptr.
* src/abg-comparison.cc (diff_kind::subtype_change_kind): New
enumerator for a change about a type or sub-type of a member of a
structure/enum.
(report_mem_header): Handle the new enumerator above.
(class_diff::priv::{deleted_dm_by_offset_, inserted_dm_by_offset_,
changed_dm_}): New data members.
(class_diff::priv::subtype_changed_dm_): Renamed
class_diff::priv::changed_data_members_ into this.
(class_diff::priv::subtype_changed_dm): Renamed
class_diff::priv::data_member_has_changed into this. Adjust.
(class_diff::count_filtered_subtype_changed_dm): Renamed
count_filtered_data_members into this. Adjust.
(class_diff::priv::count_filtered_changed_dm): New member
function.
(class_diff::lookup_tables_empty): Adjust.
(class_diff::ensure_lookup_tables_populated): Adjust. Detect when
a data member is deleted and added back to offset N, and be
prepared to present that as a change of data member at offset N.
(class_diff::report): Adjust. Report data members of a given
offset that have changed.
* tests/data/test-diff-dwarf/test6-report.txt: New reference
report for new test input.
* tests/data/test-diff-dwarf/test6-v0.cc: Source code for new test
input binary.
* tests/data/test-diff-dwarf/test6-v0.o: New test input binary.
* tests/data/test-diff-dwarf/test6-v1.cc: Source code for new test
input binary.
* tests/data/test-diff-dwarf/test6-v1.o: New test input binary.
* tests/test-diff-dwarf.cc: Adjust to include the new test inputs above.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.cc (pointer_map): New typedef.
(diff_context::{has_diff_for}): New overload for diff*.
(diff_context::{diff_has_been_traversed, mark_diff_as_traversed,
forget_traversed_diffs}): Declare new methods.
* src/abg-comparison.cc (ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Define new macros.
(diff_context::priv::traversed_diff_nodes_): New data member.
(diff_context::has_diff_for): New overload for diff*
(diff_context::{diff_has_been_traversed, mark_diff_as_traversed,
forget_traversed_diffs}): Define new member functions.
(diff_context::maybe_apply_filters): Forget the traversed diffs
before applying a filter.
({distinct_diff, var_diff, pointer_diff, reference_diff,
qualified_type_diff, enum_diff, class_diff, base_diff, scope_diff,
function_decl_diff, type_decl_diff, typedef_diff,
translation_unit_diff}::traverse): Ensure that the diff node is
traversed only once.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* src/abg-comp-filter.cc (data_member_added_or_removed): New
static function.
(harmless_filter::visit): Re-organize logic. Categorize data
member addition/removal into SIZE_OR_OFFSET_CHANGE_CATEGORY.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (struct {scope_decl, non_type_tparameter,
type_composition, class_decl}::hash): Declare hashers.
({scope_decl, var_decl, non_type_tparameter, type_composition,
class_decl}::get_hash): Provide new overloads of the get_hash.
* src/abg-hash.cc ({type_decl, scope_type_decl,
qualified_type_def, pointer_type_def, reference_type_def,
enum_type_decl, typedef_decl, var_decl,
function_decl}:#️⃣:operator()): If the hash is being
calculated, do not use the not-yet fully calculated hash value.
Rather, calculate the hash, cache it and return the value.
({class_decl, non_type_tparameter}:#️⃣:operator()): Moved the
{class_decl, non_type_tparameter}::hash declaration out of here
and stick it in include/abg-ir.h. Keep the definition of the
hashing operators here though.
(type_composition:#️⃣:operator()): New operator definition.
* src/abg-ir.cc ({scope_decl, var_decl, class_decl,
non_type_tparameter, type_composition}::get_hash): Define new
virtual overload.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (function_decl::get_hash): Declare new virtual
overload.
* src/abg-hash.cc (class_decl::base_spec:#️⃣:operator()):
Properly hash the base specifier so that it doesn't collide with
hashing a class.
* src/abg-ir.cc (decl_base::get_hash): Abort if we detect a
missing overload for this;
(function_decl::get_hash() const): Implement this missing
overload, allowing using the virtual decl_base::get_hash for
function_decl.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (type_base::get_{size,alignment}_in_bits): Make
this virtual.
(typedef_decl::get_{size,alignment}_in_bits): Add new member
functions. Get the size,alignment from the underlying type and
update the current size/alignment if they differ. Keep in mind
that the size of an underlying class_decl can change over its
lifetime, given how the dwarf reader reads the type information,
i.e, there can be a DIE for a class type with no size information
that will lead to the creation of a class_decl with size zero.
Later during the DWARF reading process, another DIE will
supplement the type information, adding size information to that
class_decl. In between, a typedef_decl might have been created
with the first version of the class_decl that has a zero size. I
guess this should be extended to the other type constructs that
have an underlying type (qualified types, references and pointers).
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (is_class_type): Declare new functions.
* src/abg-comp-filter.cc (harmful_filter::visit): Use the above to
convert a type into a class.
* src/abg-ir.cc (is_class_type): Define the new function.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.h (enum
diff_category::DECL_NAME_CHANGE_CATEGORY): New enumerator.
* src/abg-comparison.cc (report_name_size_and_alignment_changes)
({enum, typedef}_diff::report): Adjust to avoid emitting name
change report if the DECL_NAME_CHANGE_CATEGORY category of change
is currently disallowed.
* abg-comp-filter.cc (decl_name_changed): New static function.
(harmless_filter::visit): Detect that the decl name changed and
put the current diff node (and its parents) into the
DECL_NAME_CHANGE_CATEGORY category.
* tools/bidiff.cc (set_diff_context_from_opts): Set the new
DECL_NAME_CHANGE_CATEGORY category into the harmless_changes group
of categories.
* tests/data/test-diff-filter/test6-report.txt: New test input file.
* tests/data/test-diff-filter/test6-v0.cc: Likewise.
* tests/data/test-diff-filter/test6-v0.o: Likewise.
* tests/data/test-diff-filter/test6-v1.cc: Likewise.
* tests/data/test-diff-filter/test6-v1.o: Likewise.
* tests/data/test-diff-filter/test7-report.txt: Likewise.
* tests/data/test-diff-filter/test7-v0.cc: Likewise.
* tests/data/test-diff-filter/test7-v0.o: Likewise.
* tests/data/test-diff-filter/test7-v1.cc: Likewise.
* tests/data/test-diff-filter/test7-v1.o: Likewise.
* tests/test-diff-filter.cc: Take the new inputs above to run new tests.
* tests/Makefile.am: Add the new files above to the distribution.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.h
(diff_category::COMPATIBLE_TYPE_CHANGE_CATEGORY): New enumerator.
(operator|=(diff_category&, diff_category)): New declaration.
* include/abg-fwd.h (is_typedef, strip_typedef)
(types_are_compatible): New declarations.
* include/abg-ir.h (operator==(const decl_base_sptr, const
decl_base_sptr)): Added the consts here.
(operator==(const type_base_sptr, const type_base_sptr)): New
declaration.
* src/abg-comp-filter.cc (is_compatible_change): New static
function.
(harmless_filter::visit): Detect compatible changes and add the
sub-tree into the new COMPATIBLE_TYPE_CHANGE_CATEGORY if
applicable. Cleanup the logic.
* src/abg-comparison.cc (operator|=(diff_category&,
diff_category)): Define new function.
(operator==(const decl_base_sptr l, const decl_base_sptr r)): Add
consts.
(operator==(const type_base_sptr l, const type_base_sptr r)):
Define new operator.
(is_typedef, strip_typedef, types_are_compatible): New function
definitions.
* tests/data/test-diff-filter/test3-report.txt: New test report
reference.
* tests/data/test-diff-filter/test3-v0.cc: Source code for new
test input.
* tests/data/test-diff-filter/test3-v0.o: New test input.
* tests/data/test-diff-filter/test3-v1.cc: Source code for new
test input.
* tests/data/test-diff-filter/test3-v1.o: New test input.
* tests/test-diff-filter.cc: Adjust to consume the new tests
inputs above.
* tools/bidiff.cc: Add the new COMPATIBLE_TYPE_CHANGE_CATEGORY
into the --harmless group.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.h (unsigned_changed_parm_map)
(unsigned_parm_map): New typedefs.
* src/abg-comparison.cc
(function_decl_diff::subtype_changed_parms): Renamed this from
changed_parms.
(function_decl_diff::priv::subtype_changed_parms_}): Renamed this
from changed_parms_;
(function_decl_diff::priv::{deleted_parms_by_id_,
added_parms_by_id_, changed_parms_by_id_}): New members.
(function_decl_diff::ensure_lookup_tables_populated): Update the
new priv::changed_parms_by_id_ member to contain the parameters
that got changed, as opposed to the subtype_changed_parms_ member
that contain parameters that got a sub-type change. The other
priv::*_by_id_ members are helpers for this. Update them too.
(function_decl_diff::subtype_changed_parms): Renamed this from
::changed_parms.
(function_decl_diff::report): Report separately about parameters
having a sub-type change, and parameters that got changed. Note
that in both cases, the change is necessarily to a compatible
type.
* data/test-diff-dwarf/test2-v0.cc: New test file.
* data/test-diff-dwarf/test2-v0.o: Likewise.
* data/test-diff-dwarf/test2-v1.cc: Likewise.
* data/test-diff-dwarf/test2-v1.o: Likewise.
* data/test-diff-dwarf/test2-report.txt: Likewise.
* tests/Makefile.am: Add the new test files above to the
distribution.
* tests/test-diff-dwarf.cc: Consume the input files above to
actually perform a regression test.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.h
(diff_category::ACCESS_CHANGE_CATEGORY): Renamed
ACCESS_CHANGED_CATEGORY into this.
(diff_category::SIZE_OR_OFFSET_CHANGE_CATEGORY): Renamed
SIZE_CHANGED_CATEGORY into this. Changed its semantics to
incorporate offset changes as well.
* src/abg-comparison.cc (struct noop_deleter): Move this up.
(represent): Do not report filtered out data members.
(report_mem_header): Add a new num_filtered parameter to take
filtered-out members in account in members report headers.
Adjust.
(class_diff::priv::{count_filtered_bases,
count_filtered_data_members, count_filtered_member_functions}):
New member functions. When a member is filtered, do not report
it all.
({enum_diff, class_diff}::report): Adjust. Take filtered members
into account in headers.
(corpus_diff::priv::apply_filters_and_compute_diff_stats): New
member function.
(corpus_diff::priv::emit_diff_stats): Renamed
emit_corpus_diff_stats into this. Change it to take the stats in
parameter.
(corpus_diff::report): Adjust to re-use the above. Filter
varibles as well. Take the filtered functions & variables in
account in the stats. Do not report filtered-out functions &
variables at all.
* src/abg-comp-filter.cc (type_size_changed, access_changed)
(data_member_offset_changed): New predicates.
({harmless, harmful}_filter::visit): Adjust to use the new
predicates above. Update the harmful variant for the new
SIZE_OR_OFFSET_CHANGE_CATEGORY category.
* tools/bidiff.cc (set_diff_context_from_opts): Adjust for the
categories name changes.
* tests/data/test-diff-filter/test0-report.txt: New test input.
* tests/data/test-diff-filter/test0-v0.cc: Likewise.
* tests/data/test-diff-filter/test0-v0.o: Likewise.
* tests/data/test-diff-filter/test0-v1.cc: Likewise.
* tests/data/test-diff-filter/test0-v1.o: Likewise.
* tests/test-diff-filter.cc: New test harness.
* tests/Makefile.am: Add the new test files above to the
distribution.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comp-filter.h: New file.
* include/Makefile.am: Add the new include/abg-comp-filter.h to
the source distribution.
* include/abg-comparison.h (enum visiting_kind, diff_category): New enums.
(operator|): Declare new operator declaration for the new
visiting_kind enum.
(operator{|,^,&,~}): Declare new operator decl for the new
diff_category enum.
(diff_context::{get_allowed_category, set_allowed_category,
switch_categories_on, switch_categories_off, diff_filters,
add_diff_filter, maybe_apply_filters}): Declare new member functions.
(diff::{parent_, category_}): New members.
(diff::diff): Adjust.
(diff::{get_parent, set_parent, get_category, add_to_category,
is_filtered_out, to_be_reported}): New members.
(diff_node_visitor::{get_visiting_kind, set_visiting_kind}): New
members.
(diff_node_visitor::visit): Add a new flag to saying if the
visitor is being called in post or pre children traversing mode.
* src/abg-comparison.cc (operator|): Declare new operator
declaration for the new visiting_kind enum.
(operator{|,^,&,~}): Declare new operator decl for the new
diff_category enum.
(diff_context::priv::{allowed_category_, filters_}): New members.
(diff_context::diff_context): Add all known filters.
(diff_context::{get_allowed_category, set_allowed_category,
switch_categories_on, switch_categories_off, diff_filters,
add_diff_filter, maybe_apply_filters}): Define new member
functions.
(diff::{is_filtered_out, to_be_reported}): Define new members.
(*::report): Use the new diff::to_be_reported function.
(*::traverse): Adjust for pre/post visiting.
(var_diff::var_diff): Chain the type diff node to its parent.
({pointer_diff, reference_diff, qualified_type_diff,
typedef_diff}::underlying_type_diff): Chain the underlying type
diff node to its parent.
(enum_diff::enum_diff): Likewise.
(base_diff::underlying_class_diff): Likewise.
({class_diff, corpus_diff}::report): Do not report changed
(member) functions that have been filtered out. Rather report
that they have been filtered out.
({function_decl_diff, class_diff}::traverse): Chain underlying
type diff nodes to their parent.
(diff_node_visitor::visit): Add a new flag to saying if the
visitor is being called in post or pre children traversing mode.
Make sure to call the default diff::visit overload.
* src/abg-comp-filter.cc: New file.
* src/Makefile.am: Add the new abg-comp-filter.cc to the source
distribution.
* tools/bidiff.cc (options::show_harm{ful,less}_changes): New
members.
(display_usage): Add usage strings for --no-harmless and
--no-harmful options.
(parse_command_line): Parse --no-harmless and --no-harmful command
line options.
(set_diff_context_from_opts): Populate the diff context
accordingly.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-traverse.h (traversable_base::traversable): Change
the signature of this to return a boolean.
* include/abg-ir.h (ir_traversable_base::traverse): Change the
signature of this to return a boolean.
(*::traverse): Adjust.
(ir_node_visitor::visit): Change the signature of this to return a
boolean.
* src/abg-corpus.cc (symtab_build_visitor_type::visit): Adjust.
* src/abg-ir.cc (::traverse): Adjust.
* tests/test-walker.cc (name_printing_visitor::visit): Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (decl_base::get_hash): Make this virtual.
(class_decl::base_spec::get_hash): Declare a new virtual overload.
* src/abg-ir.cc (class_decl::base_spec::get_hash): Define.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (is_member_function)
(get_member_function_is_{ctor,dtor,const})
(get_member_function_vtable_offset): New function declarations.
* include/abg-ir.h (class_decl::member_function): Remove.
(class_decl::member_functions): Adjust. This is now just a vector
of method_decl_sptr.
(class_decl::add_member_function): Remove the overload taking
class_decl::member_function. Adjust the other overload to take a
method_decl_sptr.
(class mem_fn_context_rel): New class.
(class_decl::method_decl::set_scope): New virtual overload.
(class_decl::member_function): Remove.
(operator==): Remove the overload taking a
class_decl::member_function.
(class_decl::member_function::hash): Remove.
(ir_node_visitor::visit): Remove the overload taking a
class_decl::member_function.
* include/abg-comparison.h (changed_member_function_sptr)
(string_member_function_sptr_map): Adjust.
* src/abg-comparison.cc (represent): Adjust the overload taking a
class_decl::member_function to take a class_decl::method_decl.
(class_diff::{report, ensure_lookup_tables_populated}): Adjust.
* src/abg-corpus.cc (symtab_build_visitor_type::visit): Remove the
overload taking a class_decl::member_function.
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir):
Adjust.
* src/abg-hash.cc (decl_base:#️⃣:operator()): Use the fully
qualified name of the decl in the hash, to increase the likelihood
of avoiding hash collisions.
(method_type:#️⃣:operator()): Likewise.
(function_decl:#️⃣:operator()): Take member functions in
account.
(class_decl::member_function:#️⃣:operator()): Remove.
(class_decl:#️⃣:operator()): Adjust.
(type_base::dynamic_hash::operator()): Adjust.
* src/abg-ir.cc (is_member_function)
(get_member_function_is_{ctor,dtor,const})
(get_member_function_vtable_offset): New function definitions.
(function_decl::get_pretty_representation): Adjust.
(function_decl::operator): Take member functions in account here.
(class_decl::insert_member_decl): Adjust.
(mem_fn_context_rel::~mem_fn_context_rel): New definition.
(class_decl::member_function::*): Remove.
(class_decl::method_decl::set_scope): New definition.
(class_decl::get_num_virtual_functions): Adjust.
(class_decl::add_member_function): Remove overload taking a
class_decl::member_function. Define a new overload taking a
class_decl::method_decl.
(ir_node_visitor::visit): Remove the overload taking a
class_decl::member_function.
* src/abg-reader.cc (build_class_decl): Adjust.
* src/abg-writer.cc (write_voffset, write_class_decl): Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (has_scope): Delete the overloads for
type_base.
(get_member_is_static): Add an overload for decl_base*.
({is,get,set}_data_member,{get_,set}_data_member_is_laid_out)
({get,set}_data_member_offset): New access declarations.
* include/abg-ir.h (class context_rel): Move up.
(decl_base::set_context_rel): New definition.
(class dm_context_rel): New type.
(decl_base::hash_as_member): Remove.
(var_decl::set_scope): Declare new virtual member.
(class_decl::data_member): Remove.
(ir_node_visitor::visit): Remove the overload for
class_decl::data_member.
(represent_data_member): Remove the represent overload for
class_decl::data_member into this. Make it take a var_decl.
(represent): Change the overload that takes two
class_decl::data_member take two var_decl. And adjust it.
(class_diff::report): Adjust.
* src/abg-corpus.cc (symtab_build_visitor_type::visit): Remove the
overload that takes a class_decl::data_member*. Adjust the
overload that takes a var_decl to recognize (static) data members.
* src/abg-dwarf-reader.cc (build_translation_unit_and_add_to_ir)
(build_class_type_and_add_to_ir, build_ir_node_from_die):
Adjust.
* src/abg-hash.cc (var_decl:#️⃣:operator()): Adjust.
(class_decl::data_member:#️⃣:operator()): Remove.
(decl_base:#️⃣:operator()): Take the context relationship in
account here.
(decl_base::hash_as_member::operator()): Remove.
({enum_type_decl,typedef_decl}:#️⃣:operator()): Adjust.
(class_decl::member_function:#️⃣:operator()): Adjust.
(type_base::dynamic_hash::operator()): Adjust.
* src/abg-ir.cc (dm_context_rel::~dm_context_rel): New definition.
(has_scope): Remove overload for type_base.
(get_member_is_static): New overload for decl_base*.
(is_data_member): New function definition.
({get,set}_data_member_{offset,is_laid_out}): Define new
accessors.
(var_decl::set_scope): Define new member function. Make this set
a dm_context_rel as the context relationship.
(var_decl::operator==): Adjust to take in account the new data
member relationship.
(class_decl::class_decl): Adjust.
(class_decl::insert_member_decl): Adjust.
(class_decl::add_data_member): Remove the overload for
class_decl::data_member.
(class_decl::add_data_member): Adjust the overload for var_decl.
(operator==): Remove overload for class_decl::data_member*.
(class_decl::data_member::operator==): Likewise.
(ir_node_visitor::visit): Remove overload for
class_decl::data_member.
* src/abg-writer.cc (write_layout_offset, write_class_decl):
Adjust.
* tests/data/test-read-write/test20.xml: Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.h (class base_diff): New.
* include/abg-ir.h (function_decl::get_first_non_implicit_parm):
New member function.
(function_type::get_first_non_implicit_parm): Likewise.
* src/abg-comparison.cc (base_has_changed): Change parm to take
class_decl::base_spec_sptr.
(class_diff::ensure_lookup_tables_populated): Compare the base
specs not just the base classes.
(class_diff::report): Adjust. Report sub-type changes in the
member functions.
(base_diff::*): Define member functions.
(compute_diff): Define an overload for base_diff_sptr.
* src/abg-hash.cc ({function_type,
method_type}:#️⃣:operator()): Do not hash the implicit parm of
member functions.
(class_decl:#️⃣:operator()): Do not hash member types.
* src/abg-ir.cc (decl_base::decl_base): Initialize the
hashing_started_ member that got moved here from class_decl.
(decl_base::get_hash): Do not set the hash if it's being set b/c
we are in a class_decl.
(decl_base::operator==) Do not compare hashes for now. Two decls
can have different hashes and compare equal; think about an
incomplete type foo, that compares equal with a complete foo.
Their hashes will be different though. So for now, just avoid
comparing these.
(compare_function_types): Avoid comparing the implicit parameter
for member functions.
({function, method}_type::get_first_non_implicit_parm): New
definition.
* tests/data/test-read-write/test20.xml: Update.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (is_at_class_scope): Add new oveloads.
(as_non_member_type, as_non_member_class_decl): Remove.
(has_scope, is_member_decl, is_member_type): New function
declarations. (get_member_is_static, set_member_is_static):
Likewise. * include/abg-ir.h (enum access_specifier): Move to
the abigail:: namespace, from ...
(class_decl::access_specifier): ... here. (class
context_rel): New type. (decl_base::hash_as_member): New
hasher. (decl_base::context_): Change the type of this to
context_rel_sptr. (decl_base::get_context_rel): New protected
getter. (decl_base::get_scope): Move this out-of-line.
(class_decl::member_type): Remove.
(class_decl::member_types): Adjust this typedef.
(class_decl::{insert,add}_member_type): Make these take a
type_base_sptr now. (class_decl::add_member_type): Change the
overload that returned a member_type to return a
type_base_sptr. (get_member_access_specifier,
set_member_access_specifier): New function declarations. *
include/abg-comparison.h (class member_type_diff): Remove.
(compute_diff): Remove the overload for member_type_diff. *
src/abg-comparison.cc (compute_diff_for_types): Adjust for the
removal of class_decl::member_type.
(maybe_report_diff_for_class_members): New static function.
(report_name_size_and_alignment_changes): Do not report a name
change just because of a struct -> class change. ({var_diff,
enum_diff, function_decl_diff}::report): Use the new
maybe_report_diff_for_class_members. (class_diff::report):
Adjust for the removal of class_decl::member_type. Use the
new maybe_report_diff_for_class_members. (class member_diff):
Remove. * src/abg-dwarf-reader.cc (die_access_specifier)
(get_scope_for_die, build_translation_unit_and_add_to_ir)
(build_class_type_and_add_to_ir, build_function_decl)
(build_ir_node_from_die): Adjust. * abg-hash.cc (struct
decl_base::hash_as_member): Define. ({scope_type_decl,
enum_type_decl, typedef_decl}:#️⃣:operator()): Use the
decl_base::hash_as_member.
* src/abg-ir.cc (decl_base::decl_base): Adjust.
(decl_base::get_scope): New out-of-line getter.
(decl_base::{operator==, set_scope): Adjust.
(has_scope, is_member_decl, is_member_type)
(get_member_access_specifier, set_member_access_specifier)
(get_member_is_static, set_member_is_static, is_at_class_scope):
New function definitions.
(as_non_member_type, as_non_member_class_decl): Remove.
(get_node_name): Adjust.
(class_decl::{class_decl, set_earlier_declaration,
insert_member_decl, insert_member_type, add_member_type):
Likewise.
(class_decl::member_type::*) Remove.
* src/abg-reader.cc (read_access, build_qualified_type_decl)
(build_reference_type_def, build_typedef_decl)
(build_class_decl): Adjust.
* src/abg-writer.cc (write_access, write_member_type)
(write_class_decl): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (lookup_type_in_scope)
(lookup_var_decl_in_scope): New declarations.
* include/abg-ir.h (class_decl::get_is_declaration_only): Rename
is_declaration_only on this.
(class_decl::set_is_declaration_only):
* src/abg-comparison.cc (try_to_diff<class_decl>)
(class_diff::ensure_lookup_tables_populated)
(scope_diff::ensure_lookup_tables_populated): Update for the
get_is_declaration_only renaming.
* src/abg-dwarf-reader.cc (get_scope_for_die): Likewize.
(build_class_type_and_add_to_ir): Make sure that a member type or
data member is not already present in the class before adding it.
Also, if a decl-only class gets a data member, it's not a
decl-only class anymore.
* src/abg-hash.cc (class_decl:#️⃣:operator()): Update for the
get_is_declaration_only renaming.
* src/abg-ir.cc (scope_decl::find_iterator_for_member)
(look_through_decl_only_class): Likewise.
(lookup_type_in_scope, lookup_var_decl_in_scope, get_node_name)
(convert_node_to_decl, lookup_node_in_scope)
(lookup_type_in_scope): New definitions.
(class_decl::{set_definition_of_declaration,
set_earlier_declaration, operator==}): Update for the
get_is_declaration_only renaming.
* src/abg-reader.cc (build_class_decl): Likewise.
* src/abg-writer.cc (write_class_is_declaration_only): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (look_through_decl_only_class): New function
declaration.
* src/abg-comparison.cc (class_diff::length): Just compare the two
classes.
(compute_diff): Look through the two classes if they are
decl-only, and use their declaration for the diffing.
* src/abg-ir.cc (look_through_decl_only_class): Define this new
entry point.
(class_decl::set_definition_of_declaration): Allow setting a
definition that is itself a declaration-only.
* src/abg-writer.cc (write_class_decl): Declaration-only can now
have members, namely member types.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (class_decl::is_struct_): New member.
(class_decl::class_decl): Take an additional is_struct member.
(class_decl::is_struct): New getter.
* src/abg-ir.cc (class_decl::class_decl): Initialize the new
is_struct_ data member.
(class_decl::get_pretty_representation): Tell struct and class
apart.
* abg-reader.cc (read_is_struct): New static function.
(build_class_decl): Capture the struct-ness of the class.
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir):
Likewise.
* src/abg-writer.cc (write_is_struct): New static function.
(write_class_decl): Write the struct-ness of the class.
* tests/data/test-read-dwarf/test1.abi: Update test.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-sptr-utils.h: New file.
* include/Makefile.am: Add abg-sptr-utils. to the build system.
* include/abg-libxml-utils.h (reader_sptr, xml_char_sptr): Remove
these typedefs as there are now in abg-sptr-utils.
(build_sptr): Likewise for this template and its specializations
declarations.
* src/abg-libxml-utils.cc (sptr_utils::build_sptr): Mode the
definition of the specializations for xmlTextReader and xmlChar
into the sptr_utils namespace.
* include/abg-corpus.h
(corpus::{get_regex_patterns_of_fns_to_suppress,
get_regex_patterns_of_vars_to_suppress,
get_regex_patterns_of_fns_to_keep,
get_regex_patterns_of_vars_to_keep}): Declare new member
functions.
* src/abg-comparison.cc (sptr_utils::regex_t_deleter): Define new
functor.
(build_sptr) Define new specialization for regex_t.
(struct array_deleter): Remove unused functor.
(corpus::priv::regex_patterns_{fns,vars}_to_{suppress,keep}): New data
members.
(symtab_build_visitor_type::regex_patterns_{fns,vars}_to_{suppress,keep}):
Likewise.
(symtab_build_visitor_type::r_{fns,vars}_{suppress,keep})):
Likewise.
(symtab_build_visitor_type::symtab_build_visitor_type): Update the
signature of this constructor to take regex patterns for functions
and variables to suppress and to keep. Also, initialize the data
members from these new parameters.
(symtab_build_visitor_type::regex_{fns,vars}_{suppress,keep}): New
member functions.
(symtab_build_visitor_type::{add_fn_to_wip_fns,
add_var_to_wip_vars}): Likewise.
(symtab_build_visitor_type::visit) Use either add_fn_to_wip_fns or
add_var_to_wip_vars depending on the overload of the visit()
member.
(corpus::priv::build_symbol_table): Update for the change of the
symtab_build_visitor_type constructor signature.
(corpus::get_regex_patterns_of_{fns,vars}_to_{suppress,keep}):
Define new member functions.
* tools/bidiff.cc (options::{drop,keep}_{fn,var}_regex_patterns}):
New data member.
(display_usage): Add help strings for --drop, --drop-fn,
--drop-var, --keep, --keep-fn, --keep-var
(parse_command_line): Parse the command lines above.
(set_corpus_keep_drop_regex_patterns): Define new static function.
(main): Use the new set_corpus_keep_drop_regex_patterns.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (function_decl::parameter::get_name_id):
Declare new entry point.
* src/abg-comparison.cc
(function_decl_diff::ensure_lookup_tables_populated): Use the new
function_decl::parameter::get_name_id() for the unique name of the
parameter. Also, fix a little logic error: if a parm is deleted
and inserted, in all cases, consider it as not deleted.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.h (diff_context::show_stats_only):
Declare new accessors.
* src/abg-comparison.cc
(diff_context::priv::show_stats_only_): New member.
(diff_context::show_stats_only): Define new accessors.
(corpus_diff::report): If showing stats only, quit right after
showing the summary.
* tools/bidiff.cc (options::show_stats_only): New data member.
(options::options): Initialize the new data member.
(display_usage): Add help string for --stat.
(parse_command_line): Parse the --stat option.
(set_diff_context_from_opts): Update to set the show_stats_only
onto the context. Cleanup the logic to make it more compact.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-diff-utils.h (namespace diff_utils): Add comment.
(compute_diff): Update comments for some overloads where they were
missing.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-comparison.h (class member_type_diff): New class.
(member_type_diff_sptr): New convenience typedef.
(compute_diff): New overload for member_type_diff.
* src/abg-comparison.cc (struct member_type_diff::priv): New
definition.
(member_type_diff::{first_member_type, second_member_type,
underlying_type_diff, length}): New member function definitions.
(compute_diff): New definition for member type diffs.
(compute_diff_for_types): Support diffing
member types.
(class_diff::report): Do not use strip member types now that we
can properly diff them.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (decl_base::{location_, name_,
qualified_parent_name_, qualified_name_}): Make these data members
protected rather than private.
(decl_base::get_qualified_parent_name): Declare new member
functions.
(decl_base::get_qualified_name): Make the core overload virtual.
Simplify the other overload that calls the core one.
(qualified_type_def::build_name): Declare new protected helper
function.
(qualified_type_def::{get_cv_quals_string_prefix,
get_qualified_name}): Declare new functions.
(pointer_type_def::{get_qualified_name}}): Likewise.
(class_decl::member_type::get_qualified_name): Likewise.
* src/abg-ir.cc (decl_base::get_qualified_parent_name): New
definition.
(decl_base::get_name): Make this out-of-line.
(decl_base::get_qualified_name): The signature of this got
simplified. Make it use the new get_qualified_parent_name.
(qualified_type_def::{build_name, get_qualified_name,
get_cv_quals_string_prefix}): New definitions.
(qualified_type_def::qualified_type_def): Update the constructor
to use the new build_name function above.
(pointer_type_def::get_qualified_name): New definitions.
(reference_type_def::get_qualified_name): Likewise.
(class_decl::member_type::get_qualified_name): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h
(class_decl::member_base::set_access_specifier): Put the setter
for access specifier here, where it belongs ...
(class_decl::member_type::set_access_specifier): ... not here.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-ir.h (function_type::function_type): In the
constructor that takes a vector of parms, walk the vector and set
the indexes of the parms.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* include/abg-fwd.h (fqn_to_components)
(lookup_type_in_translation_unit, demangle_cplus_mangled_name):
Declare new public entry points
* src/abg-comparison.cc (corpus_diff::report): Report stuff about
global variables using their mangled name, and demangle them. If
there is no mangled name for the variable, then use its pretty
representation.
(compute_diff): For the corpus overload, compare global variables
using their mangled name, if its available; otherwise, fall back
to using their pretty representation.
* src/abg-corpus.cc (var_comp::operator()(const var_decl*,
const_var_decl*)): Compare variables using their mangled name in
priority. If it's not available then use their pretty
representation.
* src/abg-dwarf-reader.cc
(read_context::var_decls_to_re_add_to_tree): New accessor.
(build_translation_unit_and_add_to_ir): If there is what appears
to be a definition of a static member variable variable -- this is
in case this definition lacks the DW_AT_specification attribute
that links it to the DW_TAG_member or DW_TAG_variable DIE that is
a child of the right class/structure DIE -- that is not at the
right place in the DIE tree, remove it from the its current place
in the tree and try to hang it off of the right DIE. To do this,
de-mangle its mangled name, look at what is supposed to be the
parent class name, look it up in the translation unit IR, and if
found, stick the variable IR node in there, as a static member
variable. If not found, then bad luck.
(build_class_type_and_add_to_ir): Do not try to see if a member
variable is static here as the way I was doing it was unreliable.
Build the data member node directly w/o going through building a
variable node first. Register the data member in the die offset
-> IR node map.
(build_ir_node_from_die): When seeing DW_TAG_variable, look for a
DW_AT_specification attribute. If there is one, then it points to
a the DIE of a data member and means that data member is static.
Flag the IR node of that data member as static thus. Update the
die offset -> IR node map. If there is no DW_AT_specification
attribute or if it doesn't point to a data member DIE, schedule
this variable tag for a stage when after the whole IR is built for
the translation unit, the variable's mangled named is inspected,
its hypothetical parent struct/class is looked up and the variable
IR node is put into the node of the right struct/class IR node.
* src/abg-ir.cc (enum lookup_entity_kind): New.
(fqn_to_components, iterator, lookup_type_in_translation_unit)
(lookup_node_in_translation_unit, lookup_type_in_translation_unit)
(demangle_cplus_mangled_name): New function definitions.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>