library that the tool has to consider. The tool will thus filter
out ABI changes on types that are not defined in public headers.
+ * ``--dont-drop-private-types``
+
+ This option is to be used with the ``--headers-dir1`` and
+ ``--headers-dir2`` options. Without this option, types that are
+ *NOT* defined in the headers are entirely dropped from the
+ internal representation build by Libabigail to represent the ABI.
+ They thus don't have to be filtered out from the final ABI change
+ report because they are not even present in Libabigail's
+ representation.
+
+ With this option however, those private types are kept in the
+ internal representation and later filtered out from the report.
+
+ This options thus potentially makes Libabigail to potentially
+ consume more memory. It's meant to be mainly used for debugging
+ purposes.
+
* ``--stat``
Rather than displaying the detailed ABI differences between
/// @return true iff the current diff node should NOT be reported.
bool
diff::is_filtered_out() const
-{return priv_->is_filtered_out(get_category());}
+{
+ if (diff * canonical = get_canonical_diff())
+ if (canonical->get_category() & SUPPRESSED_CATEGORY)
+ // The canonical type was suppressed. This means all the class
+ // of equivalence of that canonical type was suppressed. So
+ // this node should be suppressed too.
+ return true;
+ return priv_->is_filtered_out(get_category());
+}
/// Test if this diff tree node is to be filtered out for reporting
/// purposes, but by considering only the categories that were *NOT*
visit_begin(diff* d)
{
if (d->is_suppressed())
- d->add_to_local_and_inherited_categories(SUPPRESSED_CATEGORY);
+ {
+ d->add_to_local_and_inherited_categories(SUPPRESSED_CATEGORY);
+
+ // If a node was suppressed, all the other nodes of its class
+ // of equivalence are suppressed too.
+ diff *canonical_diff = d->get_canonical_diff();
+ if (canonical_diff != d)
+ canonical_diff->add_to_category(SUPPRESSED_CATEGORY);
+ }
}
/// After visiting the children nodes of a given diff node,
if (has_non_empty_child
&& has_suppressed_child
&& !has_non_suppressed_child)
- d->add_to_category(SUPPRESSED_CATEGORY);
+ {
+ d->add_to_category(SUPPRESSED_CATEGORY);
+ // If a node was suppressed, all the other nodes of its class
+ // of equivalence are suppressed too.
+ diff *canonical_diff = d->get_canonical_diff();
+ if (canonical_diff != d)
+ canonical_diff->add_to_category(SUPPRESSED_CATEGORY);
+ }
}
}
}; //end struct suppression_categorization_visitor
test-diff-suppr/test33-v0.h \
test-diff-suppr/test33-v1.cc \
test-diff-suppr/test33-v1.h \
+test-diff-suppr/libtest34-v0.so \
+test-diff-suppr/libtest34-v1.so \
+test-diff-suppr/test34-priv-include-dir-v0/test34-priv-include-v0.h \
+test-diff-suppr/test34-priv-include-dir-v1/test34-priv-include-v1.h \
+test-diff-suppr/test34-pub-include-dir-v0/test34-pub-include-v0.h \
+test-diff-suppr/test34-pub-include-dir-v1/test34-pub-include-v1.h \
+test-diff-suppr/test34-report-0.txt \
+test-diff-suppr/test34-v0.c \
+test-diff-suppr/test34-v1.c \
\
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1 \
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1.abi \
================ changes of 'libtbb.so.2'===============
- Functions changes summary: 0 Removed, 7 Changed (17 filtered out), 17 Added functions
+ Functions changes summary: 0 Removed, 7 Changed (9 filtered out), 17 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Function symbols changes summary: 0 Removed, 0 Added function symbol not referenced by debug info
Variable symbols changes summary: 3 Removed, 0 Added variable symbols not referenced by debug info
in referenced type 'class tbb::task_group_context' at task.h:302:1:
1 data member insertion:
'tbb::internal::cpu_ctl_env_space tbb::task_group_context::my_cpu_ctl_env', at offset 896 (in bits) at task.h:380:1
- 1 data member changes (2 filtered):
+ 1 data member changes (1 filtered):
type of 'char tbb::task_group_context::_leading_padding[80]' changed:
type name changed from 'char[80]' to 'char[72]'
array type size changed from 640 to 576 bits:
--- /dev/null
+struct priv
+{
+ int m0;
+};
+
+void
+init1(struct priv* p)
+{
+ p->m0 = 0;
+}
+
+struct priv*
+init2(struct priv* p)
+{
+ p->m0 = 0xCAFEBABE;
+ return p;
+}
--- /dev/null
+struct priv
+{
+ unsigned m0;
+ char m1;
+};
+
+void
+init1 (struct priv* p)
+{
+ p->m0 = 0;
+ p->m1 = 0;
+}
+
+struct priv*
+init2(struct priv* p)
+{
+ p->m0 = 0xCAFEBABE;
+ p->m1 = 0xCA;
+ return p;
+}
--- /dev/null
+struct priv;
+typedef struct priv* priv_ptr;
+
+#define NULL (void*)0
+
+struct S
+{
+ priv_ptr p;
+};
+
+typedef struct S* s_ptr;
+
+void
+foo(s_ptr, int a);
+
+s_ptr
+bar(s_ptr, char a);
+
+void
+baz(s_ptr);
--- /dev/null
+struct priv;
+typedef struct priv* priv_ptr;
+
+#define NULL (void*)0
+
+struct S
+{
+ priv_ptr p;
+};
+
+typedef struct S* s_ptr;
+
+void
+foo(s_ptr, int a);
+
+s_ptr
+bar(s_ptr, char a);
+
+void
+baz(s_ptr);
--- /dev/null
+Functions changes summary: 0 Removed, 0 Changed (5 filtered out), 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
--- /dev/null
+/*
+ * Compile with:
+ * gcc -shared -g -Wall -o libtest33-v0.so test33-v0.c
+ */
+
+#include "test33-pub-include-dir-v0/test33-pub-include-v0.h"
+#include "test33-priv-include-dir-v0/test33-priv-include-v0.h"
+
+void
+foo(s_ptr ptr, int a)
+{
+ ptr->p = NULL;
+ ++a;
+}
+
+s_ptr
+bar(s_ptr ptr, char a)
+{
+ ptr->p = NULL;
+ ++a;
+ return ptr;
+}
+
+void
+baz(s_ptr ptr)
+{
+ ptr->p = NULL;
+}
--- /dev/null
+/*
+ * Compile with:
+ * gcc -shared -g -Wall -o libtest33-v1.so test33-v1.c
+ */
+
+#include "test33-pub-include-dir-v1/test33-pub-include-v1.h"
+#include "test33-priv-include-dir-v1/test33-priv-include-v1.h"
+
+void
+foo(s_ptr ptr, int a)
+{
+ ptr->p = NULL;
+ a++;
+}
+
+s_ptr
+bar(s_ptr ptr, char a)
+{
+ ptr->p = NULL;
+ a++;
+ return ptr;
+}
+
+void
+baz(s_ptr ptr)
+{
+ ptr->p = NULL;
+}
"",
"",
"",
- "--no-default-suppression",
+ "--no-default-suppression --dont-drop-private-types",
"data/test-diff-suppr/test30-report-0.txt",
"output/test-diff-suppr/test30-report-0.txt"
},
"data/test-diff-suppr/test30-include-dir-v0",
"data/test-diff-suppr/test30-include-dir-v1",
"",
- "--no-default-suppression",
+ "--no-default-suppression --dont-drop-private-types",
"data/test-diff-suppr/test30-report-1.txt",
"output/test-diff-suppr/test30-report-1.txt"
},
"data/test-diff-suppr/libtest33-v1.so",
"",
"",
- "data/test-diff-suppr/libtest33-1.suppr",
+ "data/test-diff-suppr/test33-suppr-1.txt",
"--no-default-suppression --no-show-locs --no-redundant",
"data/test-diff-suppr/test33-report-0.txt",
"output/test-diff-suppr/test33-report-0.txt"
},
+ {
+ "data/test-diff-suppr/libtest34-v0.so",
+ "data/test-diff-suppr/libtest34-v1.so",
+ "data/test-diff-suppr/test34-pub-include-dir-v0",
+ "data/test-diff-suppr/test34-pub-include-dir-v1",
+ "",
+ "--no-default-suppression --dont-drop-private-types",
+ "data/test-diff-suppr/test34-report-0.txt",
+ "output/test-diff-suppr/test34-report-0.txt"
+ },
// This should be the last entry
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};
vector<string> keep_var_regex_patterns;
string headers_dir1;
string headers_dir2;
+ bool drop_private_types;
bool no_default_supprs;
bool no_arch;
bool show_stats_only;
: display_usage(),
display_version(),
missing_operand(),
+ drop_private_types(true),
no_default_supprs(),
no_arch(),
show_stats_only(),
<< " --debug-info-dir2|--d2 <path> the root for the debug info of file2\n"
<< " --headers-dir1|--hd1 <path> the path to headers of file1\n"
<< " --headers-dir2|--hd2 <path> the path to headers of file2\n"
+ << " --dont-drop-private-types\n keep private types in "
+ "internal representation\n"
<< " --stat only display the diff stats\n"
<< " --symtabs only display the symbol tables of the corpora\n"
<< " --no-default-suppression don't load any "
opts.display_usage = true;
return true;
}
+ else if (!strcmp(argv[i], "--dont-drop-private-types"))
+ opts.drop_private_types = false;
else if (!strcmp(argv[i], "--no-default-suppression"))
opts.no_default_supprs = true;
else if (!strcmp(argv[i], "--no-architecture"))
i != opts.suppression_paths.end();
++i)
read_suppressions(*i, supprs);
- add_read_context_suppressions(read_ctxt, supprs);
+
+ if (opts.drop_private_types)
+ {
+ if (!opts.headers_dir1.empty())
+ {
+ // Generate suppression specification to avoid showing ABI
+ // changes on types that are not defined in public headers.
+ //
+ // As these suppression specifications are applied during the
+ // corpus loading, they are going to be dropped from the
+ // internal representation altogether.
+ suppression_sptr suppr =
+ gen_suppr_spec_from_headers(opts.headers_dir1);
+ if (suppr)
+ supprs.push_back(suppr);
+ }
+
+ if (!opts.headers_dir2.empty())
+ {
+ // Generate suppression specification to avoid showing ABI
+ // changes on types that are not defined in public headers.
+ //
+ // As these suppression specifications are applied during the
+ // corpus loading, they are going to be dropped from the
+ // internal representation altogether.
+ suppression_sptr suppr =
+ gen_suppr_spec_from_headers(opts.headers_dir2);
+ if (suppr)
+ supprs.push_back(suppr);
+ }
+ }
+
+ add_read_context_suppressions(read_ctxt, supprs);
}
/// Set the regex patterns describing the functions to drop from the
using abigail::suppr::suppression_sptr;
using abigail::suppr::suppressions_type;
using abigail::suppr::read_suppressions;
+using abigail::dwarf_reader::read_context_sptr;
+using abigail::dwarf_reader::create_read_context;
using abigail::dwarf_reader::get_soname_of_elf_file;
using abigail::dwarf_reader::get_type_of_elf_file;
using abigail::dwarf_reader::read_corpus_from_elf;
<< elf1.path
<< " ...\n";
- corpus_sptr corpus1 = read_corpus_from_elf(elf1.path, &di_dir1, env.get(),
- /*load_all_types=*/false,
- c1_status);
- if (!(c1_status & abigail::dwarf_reader::STATUS_OK))
- {
- if (verbose)
- emit_prefix("abipkgdiff", cerr)
- << "Could not read file '"
- << elf1.path
- << "' properly\n";
- return abigail::tools_utils::ABIDIFF_ERROR;
- }
+ corpus_sptr corpus1;
+ {
+ read_context_sptr c = create_read_context(elf1.path, &di_dir1, env.get(),
+ /*load_all_types=*/false);
+ add_read_context_suppressions(*c, priv_types_supprs1);
+ corpus1 = read_corpus_from_elf(*c, c1_status);
+
+ if (!(c1_status & abigail::dwarf_reader::STATUS_OK))
+ {
+ if (verbose)
+ emit_prefix("abipkgdiff", cerr)
+ << "Could not read file '"
+ << elf1.path
+ << "' properly\n";
+ return abigail::tools_utils::ABIDIFF_ERROR;
+ }
+ }
if (opts.fail_if_no_debug_info
&& (c1_status & abigail::dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND))
<< elf2.path
<< " ...\n";
- corpus_sptr corpus2 = read_corpus_from_elf(elf2.path, &di_dir2, env.get(),
- /*load_all_types=*/false,
- c2_status);
- if (!(c2_status & abigail::dwarf_reader::STATUS_OK))
- {
- if (verbose)
- emit_prefix("abipkgdiff", cerr)
- << "Could not find the read file '"
- << elf2.path
- << "' properly\n";
- return abigail::tools_utils::ABIDIFF_ERROR;
- }
+ corpus_sptr corpus2;
+ {
+ read_context_sptr c = create_read_context(elf2.path, &di_dir2, env.get(),
+ /*load_all_types=*/false);
+ add_read_context_suppressions(*c, priv_types_supprs2);
+ corpus2 = read_corpus_from_elf(*c, c2_status);
+
+ if (!(c2_status & abigail::dwarf_reader::STATUS_OK))
+ {
+ if (verbose)
+ emit_prefix("abipkgdiff", cerr)
+ << "Could not find the read file '"
+ << elf2.path
+ << "' properly\n";
+ return abigail::tools_utils::ABIDIFF_ERROR;
+ }
+ }
if (opts.fail_if_no_debug_info
&& (c2_status & abigail::dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND))