libabigail
Loading...
Searching...
No Matches
abg-corpus.cc
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2// -*- mode: C++ -*-
3//
4// Copyright (C) 2013-2026 Red Hat, Inc.
5
6/// @file
7
8#include "config.h"
9
10#include <algorithm>
11#include <cassert>
12#include <cstdio>
13#include <cstring>
14#include <stdexcept>
15#include <unordered_map>
16#include <set>
17#include <memory>
18#include <fstream>
19#include <sstream>
20#include "abg-internal.h"
21
22// <headers defining libabigail's API go under here>
23ABG_BEGIN_EXPORT_DECLARATIONS
24
25#include "abg-corpus.h"
26#include "abg-ir.h"
27#include "abg-reader.h"
28#include "abg-sptr-utils.h"
29#include "abg-symtab-reader.h"
30#include "abg-tools-utils.h"
31#include "abg-writer.h"
32
33ABG_END_EXPORT_DECLARATIONS
34// </headers defining libabigail's API>
35
36#include "abg-corpus-priv.h"
37#include "abg-ir-priv.h"
38
39namespace abigail
40{
41
42namespace ir
43{
44
45using std::ostringstream;
46using std::unordered_map;
47using std::list;
48using std::vector;
49
51
52/// Constructor of @ref corpus::exported_decls_builder.
53///
54/// @param fns a reference to the vector of exported functions.
55///
56/// @param vars a reference to the vector of exported variables.
57///
58/// @param fns_suppress_regexps the regular expressions that designate
59/// the functions to suppress from the exported functions set.
60///
61/// @param vars_suppress_regexps the regular expressions that designate
62/// the variables to suppress from the exported variables set.
63///
64/// @param fns_keep_regexps the regular expressions that designate the
65/// functions to keep in the exported functions set.
66///
67/// @param fns_keep_regexps the regular expressions that designate the
68/// functions to keep in the exported functions set.
69///
70/// @param vars_keep_regexps the regular expressions that designate
71/// the variables to keep in the exported variables set.
72///
73/// @param sym_id_of_fns_to_keep the IDs of the functions to keep in
74/// the exported functions set.
75///
76/// @param sym_id_of_vars_to_keep the IDs of the variables to keep in
77/// the exported variables set.
78corpus::exported_decls_builder
79::exported_decls_builder(functions& fns,
80 variables& vars,
81 strings_type& fns_suppress_regexps,
82 strings_type& vars_suppress_regexps,
83 strings_type& fns_keep_regexps,
84 strings_type& vars_keep_regexps,
85 strings_type& sym_id_of_fns_to_keep,
86 strings_type& sym_id_of_vars_to_keep)
87 : priv_(new priv(fns, vars,
88 fns_suppress_regexps,
89 vars_suppress_regexps,
90 fns_keep_regexps,
91 vars_keep_regexps,
92 sym_id_of_fns_to_keep,
93 sym_id_of_vars_to_keep))
94{
95}
96
97/// Getter for the reference to the vector of exported functions.
98/// This vector is shared with with the @ref corpus. It's where the
99/// set of exported function is ultimately stored.
100///
101/// @return a reference to the vector of exported functions.
105
106/// Test if a given function ID maps to several functions in the same corpus.
107///
108/// The magic of ELF symbol aliases makes it possible for an ELF
109/// symbol alias to designate several different functions. This
110/// function tests if the ELF symbol of a given function has a aliases
111/// that designates another function or not.
112///
113/// @param fn the function to consider.
114///
115/// @return the set of functions designated by the ELF symbol of @p
116/// fn, or nullptr if the function ID maps to just @p fn.
117std::unordered_set<const function_decl*>*
119{
120 std::unordered_set<const function_decl*> *fns_for_id =
121 priv_->fn_id_is_in_id_fns_map(fn);
122 if (fns_for_id && fns_for_id->size() > 1)
123 return fns_for_id;
124
125 return nullptr;
126}
127
128/// Getter for the reference to the vector of exported variables.
129/// This vector is shared with with the @ref corpus. It's where the
130/// set of exported variable is ultimately stored.
131///
132/// @return a reference to the vector of exported variables.
136
137/// Consider at all the tunables that control wether a function should
138/// be added to the set of exported function and if it fits in, add
139/// the function to that set.
140///
141/// @param fn the function to add the set of exported functions.
142///
143/// @param do_update if true, add the function to the set of exported
144/// functions even if one already exists there. Otherwise, if a
145/// function's ID is already recorded as being exported, do not add @p
146/// fn.
147///
148/// @return true iff the function was added to the set of exported
149/// functions.
150bool
152 bool do_update)
153{
155 return false;
156
157 const string& fn_id = priv_->get_id(*fn);
158 ABG_ASSERT(!fn_id.empty());
159
160 if (!do_update && priv_->fn_id_is_in_id_fns_map(fn))
161 return false;
162
163 {
164 if (priv_->keep_wrt_id_of_fns_to_keep(fn)
165 && priv_->keep_wrt_regex_of_fns_to_suppress(fn)
166 && priv_->keep_wrt_regex_of_fns_to_keep(fn))
167 {
168 priv_->add_fn_to_exported(fn, do_update);
169 return true;
170 }
171 }
172 return false;
173}
174
175/// Consider at all the tunables that control wether a variable should
176/// be added to the set of exported variable and if it fits in, add
177/// the variable to that set.
178///
179/// @param fn the variable to add the set of exported variables.
180///
181/// @return true iff the variable was added to the set of exported
182/// variables.
183bool
185{
186 if (!var->get_is_in_public_symbol_table())
187 return false;
188
189 const interned_string& var_id = priv_->get_id(*var);
190 ABG_ASSERT(!var_id.empty());
191
192 if (priv_->var_is_in_id_vars_map(var))
193 return false;
194
195 {
196 if (priv_->keep_wrt_id_of_vars_to_keep(var)
197 && priv_->keep_wrt_regex_of_vars_to_suppress(var)
198 && priv_->keep_wrt_regex_of_vars_to_keep(var))
199 {
200 priv_->add_var_to_exported(var);
201 return true;
202 }
203 }
204 return false;
205}
206
207// </corpus::exported_decls_builder>
208
209/// Convenience typedef for a hash map of pointer to function_decl and
210/// boolean.
211typedef unordered_map<const function_decl*,
212 bool,
215
216/// Convenience typedef for a hash map of string and pointer to
217/// function_decl.
218typedef unordered_map<string, const function_decl*> str_fn_ptr_map_type;
219
220/// Convenience typedef for a hash map of pointer to var_decl and boolean.
221typedef unordered_map<const var_decl*,
222 bool,
225
226/// This is a comparison functor for comparing pointers to @ref
227/// function_decl.
228struct func_comp
229{
230 /// The comparisong operator for pointers to @ref function_decl. It
231 /// performs a string comparison of the mangled names of the
232 /// functions. If the functions don't have mangled names, it
233 /// compares their names instead.
234 ///
235 /// @param first the first function to consider in the comparison.
236 ///
237 /// @param second the second function to consider in the comparison.
238 ///
239 /// @return true if the (mangled) name of the first function is less
240 /// than the (mangled)name of the second one, false otherwise.
241 bool
242 operator()(const function_decl* first,
243 const function_decl* second) const
244 {
245 ABG_ASSERT(first != 0 && second != 0);
246
247 string first_name, second_name;
248 first_name = first->get_linkage_name();
249 if (first_name.empty())
250 first_name = first->get_name();
251 ABG_ASSERT(!first_name.empty());
252
253 second_name = second->get_linkage_name();
254 if (second_name.empty())
255 second_name = second->get_name();
256 ABG_ASSERT(!second_name.empty());
257
258 if (first_name != second_name)
259 return first_name < second_name;
260
261 // If the functions are member functions, sort them using the hash
262 // value and canonical index of their class.
263 if (is_member_function(first) && is_member_function(second))
264 {
265 class_or_union_sptr first_scope =
267 class_or_union_sptr second_scope =
269 type_base* fc = first_scope
270 ? first_scope->get_naked_canonical_type()
271 : nullptr;
272 type_base* sc = second_scope
273 ? second_scope->get_naked_canonical_type()
274 : nullptr;
275 if (fc && sc)
276 {
277 hash_t fh = peek_hash_value(*fc);
278 hash_t sh = peek_hash_value(*sc);
279 if (fh && sh && *fh != *sh)
280 return *fh < *sh;
281
282 size_t f_cti = get_canonical_type_index(fc);
283 size_t s_cti = get_canonical_type_index(sc);
284 if (f_cti != s_cti)
285 return f_cti < s_cti;
286 }
287 }
288
289 return first_name < second_name;
290 }
291};
292
293/// This is a comparison functor for comparing pointers to @ref
294/// var_decl.
295struct var_comp
296{
297 /// The comparison operator for pointers to @ref var_decl.
298 ///
299 /// It perform a string comparison on the names of the variables.
300 ///
301 /// @param first the first variable to consider for the comparison.
302 ///
303 /// @param second the second variable to consider for the comparison.
304 ///
305 /// @return true if first is less than second, false otherwise.
306 bool
307 operator()(const var_decl* first,
308 const var_decl* second) const
309 {
310 ABG_ASSERT(first != 0 && second != 0);
311
312 string first_name, second_name;
313 first_name = first->get_linkage_name();
314 if (first_name.empty())
315 {
316 first_name = first->get_pretty_representation();
317 second_name = second->get_pretty_representation();
318 ABG_ASSERT(!second_name.empty());
319 }
320 ABG_ASSERT(!first_name.empty());
321
322 if (second_name.empty())
323 second_name = second->get_linkage_name();
324
325 if (second_name.empty())
326 {
327 second_name = second->get_pretty_representation();
328 first_name = first->get_pretty_representation();
329 ABG_ASSERT(!first_name.empty());
330 }
331 ABG_ASSERT(!second_name.empty());
332
333 return first_name < second_name;
334 }
335
336 bool
337 operator()(const var_decl_sptr& first,
338 const var_decl_sptr& second) const
339 {return operator()(first.get(), second.get());}
340};
341
342/// A comparison functor to compare elf_symbols for the purpose of
343/// sorting.
344struct comp_elf_symbols_functor
345{
346 bool
347 operator()(const elf_symbol& l,
348 const elf_symbol& r) const
349 {return l.get_id_string() < r.get_id_string();}
350
351 bool
352 operator()(const elf_symbol_sptr l,
353 const elf_symbol_sptr r) const
354 {return operator()(*l, *r);}
355}; // end struct comp_elf_symbols_functor
356
357
358// <corpus stuff>
359
360/// Get the maps that associate a name to a certain kind of type.
361type_maps&
363{return types_;}
364
365/// Get the maps that associate a name to a certain kind of type.
366const type_maps&
368{return types_;}
369
370/// Return a sorted vector of function symbols for this corpus.
371///
372/// Note that the first time this function is called, the symbols are
373/// sorted and cached. Subsequent invocations of this function return
374/// the cached vector that was built previously.
375///
376/// @return the sorted list of function symbols.
377const elf_symbols&
379{
380 if (!sorted_fun_symbols)
381 {
382 if (symtab_)
383 {
384 auto filter = symtab_->make_filter();
385 filter.set_functions();
386 sorted_fun_symbols = elf_symbols(symtab_->begin(filter),
387 symtab_->end());
388 }
389 else
390 sorted_fun_symbols = elf_symbols();
391 }
392 return *sorted_fun_symbols;
393}
394
395/// Return a map from name to function symbol for this corpus.
396///
397/// Note that the first time this function is called, the map is built.
398/// Subsequent invocations of this function return the cached map that was
399/// built previously.
400///
401/// @return the name function symbol map
404{
405 if (!fun_symbol_map)
406 {
407 fun_symbol_map = string_elf_symbols_map_type();
408 for (const auto& symbol : get_sorted_fun_symbols())
409 {
410 (*fun_symbol_map)[symbol->get_name()].push_back(symbol);
411 (*fun_symbol_map)[symbol->get_id_string()].push_back(symbol);
412 }
413 }
414 return *fun_symbol_map;
415}
416
417/// Getter for a sorted vector of the function symbols undefined in
418/// this corpus.
419///
420/// @return a vector of the function symbols undefined in this corpus,
421/// sorted by name and then version.
422const elf_symbols&
424{
425 if (!sorted_undefined_fun_symbols)
426 {
427 if (symtab_)
428 {
429 auto filter = symtab_->make_filter();
430 filter.set_functions();
431 filter.set_undefined_symbols();
432 filter.set_public_symbols(false);
433
434 sorted_undefined_fun_symbols =
435 elf_symbols(symtab_->begin(filter), symtab_->end());
436 }
437 else
438 sorted_undefined_fun_symbols = elf_symbols();
439 }
440 return *sorted_undefined_fun_symbols;
441}
442
443/// Return a map from name to undefined function symbol for this corpus.
444///
445/// Note that the first time this function is called, the map is built.
446/// Subsequent invocations of this function return the cached map that was
447/// built previously.
448///
449/// @return the name function symbol map for undefined symbols
452{
453 if (!undefined_fun_symbol_map)
454 {
455 undefined_fun_symbol_map = string_elf_symbols_map_type();
456 for (const auto& symbol : get_sorted_undefined_fun_symbols())
457 {
458 (*undefined_fun_symbol_map)[symbol->get_name()].push_back(symbol);
459 (*undefined_fun_symbol_map)[symbol->get_id_string()].push_back(symbol);
460 }
461 }
462 return *undefined_fun_symbol_map;
463}
464
465/// Return a list of symbols that are not referenced by any function of
466/// corpus::get_functions().
467///
468/// Note that this function considers the list of function symbols to keep,
469/// that is provided by corpus::get_sym_ids_of_fns_to_keep(). If a given
470/// unreferenced function symbol is not in the list of functions to keep, then
471/// that symbol is dropped and will not be part of the resulting table of
472/// unreferenced symbol that is built.
473///
474/// @return list of symbols that are not referenced by any function
475const elf_symbols&
477{
478 if (!unrefed_fun_symbols)
479 {
480 unrefed_fun_symbols = elf_symbols();
481 if (symtab_)
482 {
483 unordered_map<string, bool> refed_funs;
484
485 for (const auto& function : fns)
486 if (elf_symbol_sptr sym = function->get_symbol())
487 {
488 refed_funs[sym->get_id_string()] = true;
489 for (elf_symbol_sptr a = sym->get_next_alias();
490 a && !a->is_main_symbol(); a = a->get_next_alias())
491 refed_funs[a->get_id_string()] = true;
492 }
493
494 auto filter = symtab_->make_filter();
495 filter.set_functions();
496 for (const auto& symbol :
497 symtab_reader::filtered_symtab(*symtab_, filter))
498 {
499 const std::string sym_id = symbol->get_id_string();
500 if (refed_funs.find(sym_id) == refed_funs.end())
501 {
502 bool keep = sym_id_fns_to_keep.empty();
503 for (const auto& id : sym_id_fns_to_keep)
504 {
505 if (id == sym_id)
506 {
507 keep = true;
508 break;
509 }
510 }
511 if (keep)
512 unrefed_fun_symbols->push_back(symbol);
513 }
514 }
515 }
516 }
517 return *unrefed_fun_symbols;
518}
519
520/// Getter for the sorted vector of variable symbols for this corpus.
521///
522/// Note that the first time this function is called, it computes the
523/// sorted vector, caches the result and returns it. Subsequent
524/// invocations of this function just return the cached vector.
525///
526/// @return the sorted vector of variable symbols for this corpus.
527const elf_symbols&
529{
530 if (!sorted_var_symbols)
531 {
532 if (symtab_)
533 {
534 auto filter = symtab_->make_filter();
535 filter.set_variables();
536
537 sorted_var_symbols = elf_symbols(symtab_->begin(filter),
538 symtab_->end());
539 }
540 else
541 sorted_var_symbols = elf_symbols();
542 }
543 return *sorted_var_symbols;
544}
545
546/// Return a map from name to variable symbol for this corpus.
547///
548/// Note that the first time this function is called, the map is built.
549/// Subsequent invocations of this function return the cached map that was
550/// built previously.
551///
552/// @return the name variable symbol map
555{
556 if (!var_symbol_map)
557 {
558 var_symbol_map = string_elf_symbols_map_type();
559 for (const auto& symbol : get_sorted_var_symbols())
560 (*var_symbol_map)[symbol->get_name()].push_back(symbol);
561 }
562 return *var_symbol_map;
563}
564
565/// Getter for a sorted vector of the variable symbols undefined in
566/// this corpus.
567///
568/// @return a vector of the variable symbols undefined in this corpus,
569/// sorted by name and then version.
570const elf_symbols&
572{
573 if (!sorted_undefined_var_symbols)
574 {
575 if (symtab_)
576 {
577 auto filter = symtab_->make_filter();
578 filter.set_variables();
579 filter.set_undefined_symbols();
580 filter.set_public_symbols(false);
581
582 sorted_undefined_var_symbols =
583 elf_symbols(symtab_->begin(filter), symtab_->end());
584 }
585 else
586 sorted_undefined_var_symbols = elf_symbols();
587 }
588 return *sorted_undefined_var_symbols;
589}
590
591/// Return a map from name to undefined variable symbol for this corpus.
592///
593/// Note that the first time this function is called, the map is built.
594/// Subsequent invocations of this function return the cached map that was
595/// built previously.
596///
597/// @return the name undefined variable symbol map
600{
601 if (!undefined_var_symbol_map)
602 {
603 undefined_var_symbol_map = string_elf_symbols_map_type();
604 for (const auto& symbol : get_sorted_undefined_var_symbols())
605 (*undefined_var_symbol_map)[symbol->get_name()].push_back(symbol);
606 }
607 return *undefined_var_symbol_map;
608}
609
610/// Return a list of symbols that are not referenced by any variable of
611/// corpus::get_variables().
612///
613/// Note that this function considers the list of variable symbols to keep,
614/// that is provided by corpus::get_sym_ids_of_vars_to_keep(). If a given
615/// unreferenced variable symbol is not in the list of variable to keep, then
616/// that symbol is dropped and will not be part of the resulting table of
617/// unreferenced symbol that is built.
618///
619/// @return list of symbols that are not referenced by any variable
620const elf_symbols&
622{
623 if (!unrefed_var_symbols)
624 {
625 unrefed_var_symbols = elf_symbols();
626 if (symtab_)
627 {
628 unordered_map<string, bool> refed_vars;
629 for (const auto& variable : vars)
630 if (elf_symbol_sptr sym = variable->get_symbol())
631 {
632 refed_vars[sym->get_id_string()] = true;
633 for (elf_symbol_sptr a = sym->get_next_alias();
634 a && !a->is_main_symbol(); a = a->get_next_alias())
635 refed_vars[a->get_id_string()] = true;
636 }
637
638 auto filter = symtab_->make_filter();
639 filter.set_variables();
640 for (const auto& symbol :
641 symtab_reader::filtered_symtab(*symtab_, filter))
642 {
643 const std::string sym_id = symbol->get_id_string();
644 if (refed_vars.find(sym_id) == refed_vars.end())
645 {
646 bool keep = sym_id_vars_to_keep.empty();
647 for (const auto& id : sym_id_vars_to_keep)
648 {
649 if (id == sym_id)
650 {
651 keep = true;
652 break;
653 }
654 }
655 if (keep)
656 unrefed_var_symbols->push_back(symbol);
657 }
658 }
659 }
660 }
661 return *unrefed_var_symbols;
662}
663
664
665/// Lookup the function which has a given function ID.
666///
667/// Note that there can have been several functions with the same ID.
668/// This is because debug info can declare the same function in
669/// several different translation units. Normally, all these function
670/// should be equal. But still, this function returns all these
671/// functions.
672///
673/// @param id the ID of the function to lookup. This ID must be
674/// either the result of invoking function::get_id() of
675/// elf_symbol::get_id_string().
676///
677/// @return the set of functions which ID is @p id, or nil if no
678/// function with that ID was found.
679const std::unordered_set<const function_decl*>*
681{
683 if (b)
684 {
685 auto i = b->priv_->id_fns_map_.find(id);
686 if (i == b->priv_->id_fns_map_.end())
687 return 0;
688 return &i->second;
689 }
690 return nullptr;
691}
692
693/// Get the member function variant that belongs to the canonical type
694/// of the containing type.
695///
696/// If the function we are looking at has no containing type, then
697/// return the same function.
698///
699/// @param fn the function to consider.
700///
701/// @return the canonical function for @p fn.
702static const function_decl*
703get_canonical_function(const function_decl *fn)
704{
705 if (!fn)
706 return nullptr;
707
708 const function_decl* canonical_function = fn;
709 class_or_union_sptr scope = nullptr, canonical_scope = nullptr;
710 scope = is_class_or_union_type(fn->get_scope());
711
712 if (scope)
713 {
714 scope = look_through_decl_only_class(scope);
715 canonical_scope = is_class_or_union_type(scope->get_canonical_type());
716
717 if (// When the canonicalized type and the canonical type are
718 // from the same ABI corpus, no problem, do the thing for
719 // all functions. The set of member functions of the
720 // canonical type represents the union of the member
721 // functions of all it canonicalized peer types. So the
722 // member function that is on the canonical type is the
723 // "right one" that is going to be serialized into ABIXML in
724 // the end.
725 (canonical_scope && canonical_scope->get_corpus() == scope->get_corpus())
726 // But when the two types come from different ABI corpora,
727 // then, only consider virtual member functions because
728 // these are the only one that we know are equivalent
729 // because they are taken into account during the c14n
730 // process. Non-virtual members are not taken into account
731 // by the c14n so they might be different.
733 {
735 ABG_ASSERT(!ln.empty());
736 canonical_function =
737 canonical_scope->find_member_function(ln);
738 if (!canonical_function)
739 canonical_function = fn;
740 }
741 }
742
743 return canonical_function;
744}
745
746/// Remove redundant functions from the "fns" vector.
747void
749{
750 // This set cannot contain two identical function, by construction.
751 functions_set_type fns_set;
752
753 lock_guard<recursive_mutex> lock(get_mutex());
754 // Perform the de-duplication by filing fns_set with the content of
755 // fns.
756 for (auto& f : fns)
757 fns_set.insert(get_canonical_function(f));
758
759 // Clear the original non-deduplicated functions vector.
760 fns.clear();
761
762 // Fill fns back with the de-duplicated set of functions.
763 for (auto& f : fns_set)
764 fns.push_back(f);
765
766 // Do something similar for the set of functions associated to each
767 // function ID.
769 if (b)
770 for (auto& entry : b->priv_->id_fns_map_)
771 {
772 functions_set_type f_set;
773 if (entry.second.size() > 1)
774 {
775 for (auto& fn : entry.second)
776 {
777 // Replace each one of the member functions associated
778 // with the linkage_name entry.first with the matching
779 // member function of the canonical class of its
780 // containing class. That should reduce the number of
781 // functions in entry.second to just one, if there is
782 // no ODR violation.
783 auto canonical_function = get_canonical_function(fn);
784 f_set.insert(canonical_function);
785 }
786
787 entry.second.clear();
788 for (auto& fn : f_set)
789 {
790 auto it = fns_set.find(fn);
791 if (it != fns_set.end())
792 entry.second.insert(*it);
793 }
794 }
795 }
796}
797
798/// Set the "compute-non-reachable-types' property of the corpus.
799/// When it's set to true, then the debug info reader loads all
800/// non-reachable types from the binary.
801///
802/// @param f the new value of the property.
803void
805{do_compute_non_reachable_types_ = f;}
806
807/// Get the "compute-non-reachable-types' property of the corpus.
808/// When it's set to true, then the debug info reader loads all
809/// non-reachable types from the binary.
810///
811/// @return f the new value of the property.
812bool
814{return do_compute_non_reachable_types_.load();}
815
816/// Getter of the recursive mutex of this corpus.
817///
818/// @return the recursive mutex associated to this corpus.
819recursive_mutex&
821{return mutex_;}
822
823/// Getter of whether the types reachable from this ABI are
824/// canonicalized or not.
825///
826/// @return true iff the types reachable from this ABI are
827/// canonicalized.
828bool
830{return types_are_canonicalized_.load();}
831
832/// Setter of whether the types reachable from this ABI are
833/// canonicalized or not.
834///
835/// @param f set to true iff the types reachable from this ABI are
836/// canonicalized.
837void
839{types_are_canonicalized_ = f;}
840
841/// Destructor of the @ref corpus::priv type.
845
846/// Constructor of the @ref corpus type.
847///
848/// @param env the environment of the corpus.
849///
850/// @param path the path to the file containing the ABI corpus.
851corpus::corpus(const ir::environment& env, const string& path)
852{
853 priv_.reset(new priv(path, env));
854 init_format_version();
855}
856
857corpus::~corpus() = default;
858
859/// Getter of the enviroment of the corpus.
860///
861/// @return the environment of this corpus.
862const environment&
864{return priv_->env;}
865
866/// Test if logging was requested.
867///
868/// @return true iff logging was requested.
869bool
871{return priv_->do_log;}
872
873/// Request logging, or not.
874///
875/// @param f true iff logging is requested.
876void
878{priv_->do_log = f;}
879
880/// Add a translation unit to the current ABI Corpus.
881///
882/// Note that two translation units with the same path (as returned by
883/// translation_unit::get_path) cannot be added to the same @ref
884/// corpus. If that happens, the library aborts.
885///
886/// @param tu the new translation unit to add.
887void
889{
890 lock_guard<recursive_mutex> lock(priv_->get_mutex());
891
892 ABG_ASSERT(priv_->members.insert(tu).second);
893
894 // Update the path -> translation_unit map.
895 string_tu_map_type::const_iterator i =
896 priv_->path_tu_map.find(tu->get_absolute_path());
897 ABG_ASSERT(i == priv_->path_tu_map.end());
898 priv_->path_tu_map[tu->get_absolute_path()] = tu;
899 i = priv_->path_tu_map.find(tu->get_path());
900 if (i == priv_->path_tu_map.end())
901 priv_->path_tu_map[tu->get_path()] = tu;
902
903 tu->set_corpus(this);
904}
905
906/// Return the list of translation units of the current corpus.
907///
908/// @return the list of translation units of the current corpus.
911{return priv_->members;}
912
913/// Find the translation unit that has a given path.
914///
915/// @param path the path of the translation unit to look for.
916///
917/// @return the translation unit found, if any. Otherwise, return
918/// nil.
920corpus::find_translation_unit(const string &path) const
921{
922 lock_guard<recursive_mutex> lock(priv_->get_mutex());
923 string_tu_map_type::const_iterator i =
924 priv_->path_tu_map.find(path);
925
926 if (i == priv_->path_tu_map.end())
927 return translation_unit_sptr();
928 return i->second;
929}
930
931/// Erase the translation units contained in this in-memory object.
932///
933/// Note that the on-disk archive file that contains the serialized
934/// representation of this object is not modified.
935void
937{
938 lock_guard<recursive_mutex> lock(priv_->get_mutex());
939 priv_->members.clear();
940}
941
942/// Get the maps that associate a name to a certain kind of type.
943///
944/// @return the maps that associate a name to a certain kind of type.
947{return priv_->types_;}
948
949/// Get the maps that associate a name to a certain kind of type.
950///
951/// @return the maps that associate a name to a certain kind of
952/// type.
953const type_maps&
955{return priv_->types_;}
956
957/// Get the maps that associate a location string to a certain kind of
958/// type.
959///
960/// The location string is the result of the invocation to the
961/// function abigail::ir::location::expand(). It has the form
962/// "file.c:4:1", with 'file.c' being the file name, '4' being the
963/// line number and '1' being the column number.
964///
965/// @return the maps.
966const type_maps&
968{return priv_->type_per_loc_map_;}
969
970/// Test if the recording of reachable types (and thus, indirectly,
971/// the recording of non-reachable types) is activated for the
972/// current @ref corpus.
973///
974/// @return true iff the recording of reachable types is activated for
975/// the current @ref corpus.
976bool
978{
979 lock_guard<recursive_mutex> lock(priv_->get_mutex());
980 return !priv_->reachable_types_from_pub_ifaces_.empty();
981}
982
983/// Record a type as being reachable from public interfaces (global
984/// functions and variables).
985///
986/// @param t the type to record as reachable.
987bool
989{
992 return false;
993 {
994 lock_guard<recursive_mutex> lock(priv_->get_mutex());
995 priv_->reachable_types_from_pub_ifaces_.insert(e);
996 }
997 return true;
998}
999
1000void
1001corpus::remove_type_from_reachable_types(const type_base& t)
1002{
1003 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1004 type_base* examplar = get_exemplar_type(&t);
1005 priv_->reachable_types_from_pub_ifaces_.erase(examplar);
1006}
1007
1008/// Test if a type is reachable from public interfaces (global
1009/// functions and variables).
1010///
1011/// For a type to be considered reachable from public interfaces, it
1012/// must have been previously marked as such by calling
1013/// corpus::record_type_as_reachable_from_public_interfaces.
1014///
1015/// @param t the type to test for.
1016///
1017/// @return true iff @p t is reachable from public interfaces.
1018bool
1020{
1021 if (!priv_->get_compute_non_reachable_types())
1022 return true;
1023
1024 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1025 type_base* examplar = get_exemplar_type(&t);
1026 auto it = priv_->reachable_types_from_pub_ifaces_.find(examplar);
1027 if (it == priv_->reachable_types_from_pub_ifaces_.end())
1028 return false;
1029 return true;
1030}
1031
1032/// Test if a given type is reachable from public interfaces of either
1033/// the ABI corpus it belongs to, or if necessary,from the public
1034/// interfaces of the main corpus of the corpus_group the type belongs
1035/// to.
1036///
1037/// @param t the type to consider.
1038///
1039/// @return true iff @p t is reachable from public interface of
1040bool
1042{
1043 const corpus* abi = t.get_corpus();
1044 if (!abi)
1045 // If there is no ABI corpus associated, then all types are deemed
1046 // reachable.
1047 return true;
1048
1049 if (!abi->priv_->get_compute_non_reachable_types())
1050 return true;
1051
1052 bool result = abi->type_is_reachable_from_public_interfaces(t);
1053
1054 // If we couldn't determine reachability from the ABI of the type,
1055 // then, if the type belongs to an ABI corpus that is part of a
1056 // corpus_group, check reachability from the group.
1057 if (!result)
1058 if (const corpus_group* group = abi->get_group())
1059 if (group->type_is_reachable_from_public_interfaces(t))
1060 result = true;
1061
1062 return result;
1063}
1064
1065/// Getter of a sorted vector of the types that are *NOT* reachable
1066/// from public interfaces.
1067///
1068/// Note that for this to be non-empty, the libabigail reader that
1069/// analyzed the input (be it a binary or an abixml file) must have be
1070/// configured to load types that are not reachable from public
1071/// interfaces.
1072///
1073/// @return a reference to a vector of sorted types NON reachable from
1074/// public interfaces.
1077{
1078 if (!priv_->get_compute_non_reachable_types())
1079 return priv_->non_reachable_types_from_pub_ifaces_;
1080
1081 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1082 if (priv_->non_reachable_types_from_pub_ifaces_.empty())
1083 {
1084 const type_maps& types = get_types();
1085 for (auto& type_wptr : types.get_types_sorted())
1086 {
1087 type_base_sptr t(type_wptr);
1088 if (auto clazz = is_class_or_union_type(t))
1090 type_base_sptr examplar_type = get_exemplar_type(t);
1091 if (!type_is_reachable_from_public_interfaces(*examplar_type))
1092 priv_->non_reachable_types_from_pub_ifaces_.insert(examplar_type.get());
1093 }
1094 }
1095
1096 return priv_->non_reachable_types_from_pub_ifaces_;
1097}
1098
1100corpus::get_sorted_types_not_reachable_from_public_interfaces() const
1101{
1102 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1103 if (priv_->sorted_non_reachable_types_from_pub_ifaces_.empty())
1104 {
1106 priv_->sorted_non_reachable_types_from_pub_ifaces_.push_back(type);
1107
1108 type_topo_comp comp;
1109 sort(priv_->sorted_non_reachable_types_from_pub_ifaces_.begin(),
1110 priv_->sorted_non_reachable_types_from_pub_ifaces_.end(),
1111 comp);
1112 }
1113 return priv_->sorted_non_reachable_types_from_pub_ifaces_;
1114}
1115
1116/// A pass that markes the types that are reachable from the ABI
1117/// interfaces.
1118class reachable_types_marker : public abigail::ir::ir_node_visitor
1119{
1120 corpus& corpus_;
1121
1122public:
1123
1124 reachable_types_marker() = delete;
1125
1126 reachable_types_marker(corpus& abi)
1127 : corpus_(abi)
1128 {
1129 allow_visiting_already_visited_type_node(false);
1130 // Member type nodes are not marked reachable by default.
1131 allow_visiting_member_type_nodes(false);
1132 }
1133
1134 /// This is a sub-routine of
1135 /// corpus::record_type_as_reachable_from_public_interfaces.
1136 ///
1137 /// This function walks the sub-types of a given type which has been
1138 /// marked as being reachable from a public interface and marks the
1139 /// sub-types as reachable as well.
1140 ///
1141 /// @param type the which to consider sub-types for.
1142 ///
1143 /// @param rec_types the types that have been explored so far. This
1144 /// is to detect cycles and avoid endless loops.
1145 void
1146 maybe_record_subtypes_as_reachable(type_base* type,
1147 std::unordered_set<type_base*>& rec_types)
1148 {
1149 if (!type)
1150 return;
1151
1152 auto examplar_type = get_exemplar_type(type);
1153 ABG_ASSERT(examplar_type);
1154
1155 if (rec_types.find(examplar_type) != rec_types.end())
1156 return;
1157
1158 rec_types.insert(examplar_type);
1159
1160 auto abi = examplar_type->get_corpus();
1161 ABG_ASSERT(abi);
1162
1163 if (auto d = is_decl(examplar_type))
1164 {
1165 for (auto n : d->get_naming_typedefs())
1166 abi->record_type_as_reachable_from_public_interfaces(*n);
1167 }
1168
1169 if (auto d = is_enum_type(examplar_type))
1170 {
1171 if (auto u = d->get_underlying_type())
1172 abi->record_type_as_reachable_from_public_interfaces(*u);
1173 }
1174 else if (auto typdef = is_typedef(examplar_type))
1175 {
1176 if (auto u = typdef->get_underlying_type())
1177 if (abi->record_type_as_reachable_from_public_interfaces(*u))
1178 maybe_record_subtypes_as_reachable(u.get(), rec_types);
1179 }
1180 else if (auto ptr = is_pointer_type(examplar_type))
1181 {
1182 if (auto p = ptr->get_pointed_to_type())
1183 if (abi->record_type_as_reachable_from_public_interfaces(*p))
1184 maybe_record_subtypes_as_reachable(p.get(), rec_types);
1185 }
1186 else if (auto ref = is_reference_type(examplar_type))
1187 {
1188 if (auto p = ref->get_pointed_to_type())
1189 if (abi->record_type_as_reachable_from_public_interfaces(*p))
1190 maybe_record_subtypes_as_reachable(p.get(), rec_types);
1191 }
1192 else if (auto q = is_qualified_type(examplar_type))
1193 {
1194 if (auto u = q->get_underlying_type())
1195 if (abi->record_type_as_reachable_from_public_interfaces(*u))
1196 maybe_record_subtypes_as_reachable(u.get(), rec_types);
1197 }
1198 else if (auto a = is_array_type(examplar_type))
1199 {
1200 if (auto e = a->get_element_type())
1201 if (abi->record_type_as_reachable_from_public_interfaces(*e))
1202 maybe_record_subtypes_as_reachable(e.get(), rec_types);
1203
1204 for (auto s : a->get_subranges())
1205 if (abi->record_type_as_reachable_from_public_interfaces(*s))
1206 maybe_record_subtypes_as_reachable(s.get(), rec_types);
1207 }
1208 else if (auto fn_type = is_function_type(examplar_type))
1209 {
1210 if (auto t = fn_type->get_return_type())
1211 if (abi->record_type_as_reachable_from_public_interfaces(*t))
1212 maybe_record_subtypes_as_reachable(t.get(), rec_types);
1213
1214 for (auto parm : fn_type->get_parameters())
1215 if (auto t = parm->get_type())
1216 if (abi->record_type_as_reachable_from_public_interfaces(*t))
1217 maybe_record_subtypes_as_reachable(t.get(), rec_types);
1218 }
1219 else if (auto cou = is_class_or_union_type(examplar_type))
1220 {
1221 for (auto dm : cou->get_data_members())
1222 if (auto t = dm->get_type())
1223 if (abi->record_type_as_reachable_from_public_interfaces(*t))
1224 maybe_record_subtypes_as_reachable(t.get(), rec_types);
1225
1226 for (auto mf : cou->get_member_functions())
1227 if (auto t = mf->get_type())
1228 if (abi->record_type_as_reachable_from_public_interfaces(*t))
1229 maybe_record_subtypes_as_reachable(t.get(), rec_types);
1230
1231 // NOTE: do *NOT* mark member types as being systematically
1232 // reachable. A given member type will be marked as reachable
1233 // if it's (in)directly used as a type by a decl. I am thus
1234 // commenting below what should NOT be done.
1235 //
1236 // So the code below shall NOT be un-commented.
1237 //
1238 // for (auto t : cou->get_sorted_member_types())
1239 // if (abi->record_type_as_reachable_from_public_interfaces(*t))
1240 // maybe_record_subtypes_as_reachable(t.get(), rec_types);
1241
1242 if (auto klass = is_class_type(cou))
1243 {
1244 for (auto b : klass->get_base_specifiers())
1245 if (auto bc = b->get_base_class())
1246 if (abi->record_type_as_reachable_from_public_interfaces(*bc))
1247 maybe_record_subtypes_as_reachable(bc.get(), rec_types);
1248
1249 for (auto f : klass->get_virtual_mem_fns())
1250 if (auto t = f->get_type())
1251 if (abi->record_type_as_reachable_from_public_interfaces(*t))
1252 maybe_record_subtypes_as_reachable(t.get(), rec_types);
1253 }
1254 }
1255
1256 rec_types.erase(examplar_type);
1257 }
1258
1259 /// The visitor code of the pass.
1260 ///
1261 /// @param type the type to mark as reachable.
1262 ///
1263 /// @return true, always.
1264 virtual bool
1265 visit_begin(type_base* type)
1266 {
1267 if (corpus_.record_type_as_reachable_from_public_interfaces(*type))
1268 {
1269 std::unordered_set<type_base*> rec_types;
1270 maybe_record_subtypes_as_reachable(type, rec_types);
1271 }
1272 return true;
1273 }
1274};// end class non_reachable_type_is_marker
1275
1276void
1277corpus::mark_non_reachable_types()
1278{
1279 priv_->set_compute_non_reachable_types(true);
1280
1281 reachable_types_marker walker(*this);
1282
1283 for (auto function : get_functions())
1284 if (function)
1285 {
1286 const_cast<function_decl*>(function)->traverse(walker);
1287 if (auto type = is_type(function->get_scope()))
1288 {
1289 type = type->get_canonical_type();
1290 type->traverse(walker);
1291 }
1292 }
1293
1294 for (auto variable : get_variables())
1295 if (variable)
1296 {
1297 variable->traverse(walker);
1298 if (auto type = is_type(variable->get_scope()))
1299 {
1300 type = type->get_canonical_type();
1301 type->traverse(walker);
1302 }
1303 }
1304
1305 if (!get_environment().analyze_exported_interfaces_only())
1306 {
1307 for (auto function : get_undefined_functions())
1308 if (function)
1309 {
1310 const_cast<function_decl*>(function)->traverse(walker);
1311 if (auto type = is_type(function->get_scope()))
1312 {
1313 type = type->get_canonical_type();
1314 type->traverse(walker);
1315 }
1316 }
1317
1318 for (auto variable : get_undefined_variables())
1319 if (variable)
1320 {
1321 variable->traverse(walker);
1322 if (auto type = is_type(variable->get_scope()))
1323 {
1324 type = type->get_canonical_type();
1325 type->traverse(walker);
1326 }
1327 }
1328 }
1329}
1330
1331/// Get the maps that associate a location string to a certain kind of
1332/// type.
1333///
1334/// The location string is the result of the invocation to the
1335/// function abigail::ir::location::expand(). It has the form
1336/// "file.c:4:1", with 'file.c' being the file name, '4' being the
1337/// line number and '1' being the column number.
1338///
1339/// @return the maps.
1340type_maps&
1342{return priv_->type_per_loc_map_;}
1343
1344/// Getter of the group this corpus is a member of.
1345///
1346/// @return the group this corpus is a member of, or nil if it's not
1347/// part of any @ref corpus_group.
1348const corpus_group*
1350{return priv_->group;}
1351
1352/// Getter of the group this corpus belongs to.
1353///
1354/// @return the group this corpus belong to, or nil if it's not part
1355/// of any @ref corpus_group.
1358{return priv_->group;}
1359
1360/// Setter of the group this corpus belongs to.
1361///
1362/// @param g the new group.
1363void
1364corpus::set_group(corpus_group* g)
1365{
1366 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1367 priv_->group = g;
1368}
1369
1370/// Initialize the abixml serialization format version number of the
1371/// corpus.
1372///
1373/// This function sets the format version number ot the default one
1374/// supported by the current version of Libabigail.
1375void
1376corpus::init_format_version()
1377{
1379 (priv_->env.get_config().get_format_major_version_number());
1381 (priv_->env.get_config().get_format_minor_version_number());
1382}
1383
1384/// Getter for the origin of the corpus.
1385///
1386/// @return the origin of the corpus.
1389{return priv_->origin_;}
1390
1391/// Setter for the origin of the corpus.
1392///
1393/// @param o the new origin for the corpus.
1394void
1396{
1397 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1398 priv_->origin_ = o;
1399}
1400
1401/// Getter of the major version number of the abixml serialization
1402/// format.
1403///
1404/// @return the major version number of the abixml format.
1405string&
1407{return priv_->format_major_version_number_;}
1408
1409/// Setter of the major version number of the abixml serialization
1410/// format.
1411///
1412/// @param maj the new major version numberof the abixml format.
1413void
1415{
1416 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1417 priv_->format_major_version_number_ = maj;
1418}
1419
1420/// Getter of the minor version number of the abixml serialization
1421/// format.
1422///
1423/// @return the minor version number of the abixml serialization
1424/// format.
1425string&
1427{return priv_->format_minor_version_number_;}
1428
1429/// Setter of the minor version number of the abixml serialization
1430/// format.
1431///
1432/// @param min the new minor version number of the abixml
1433/// serialization format.
1434void
1436{
1437 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1438 priv_->format_minor_version_number_ = min;
1439}
1440
1441/// Get the file path associated to the corpus file.
1442///
1443/// A subsequent call to corpus::read will deserialize the content of
1444/// the abi file expected at this path; likewise, a call to
1445/// corpus::write will serialize the translation units contained in
1446/// the corpus object into the on-disk file at this path.
1447///
1448/// @return the file path associated to the current corpus.
1449string&
1451{return priv_->path;}
1452
1453/// Set the file path associated to the corpus file.
1454///
1455/// A subsequent call to corpus::read will deserialize the content of
1456/// the abi file expected at this path; likewise, a call to
1457/// corpus::write will serialize the translation units contained in
1458/// the corpus object into the on-disk file at this path.
1459///
1460/// @param path the new file path to assciate to the current corpus.
1461void
1462corpus::set_path(const string& path)
1463{
1464 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1465 priv_->path = path;
1466}
1467
1468/// Getter of the needed property of the corpus.
1469///
1470/// This property is meaningful for, e.g, corpora built from ELF
1471/// shared library files. In that case, this is a vector of names of
1472/// dependencies of the ELF shared library file.
1473///
1474/// @return the vector of dependencies needed by this corpus.
1475const vector<string>&
1477{return priv_->needed;}
1478
1479/// Setter of the needed property of the corpus.
1480///
1481/// This property is meaningful for, e.g, corpora built from ELF
1482/// shared library files. In that case, this is a vector of names of
1483/// dependencies of the ELF shared library file.
1484///
1485/// @param needed the new vector of dependencies needed by this
1486/// corpus.
1487void
1488corpus::set_needed(const vector<string>& needed)
1489{
1490 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1491 priv_->needed = needed;
1492}
1493
1494/// Getter for the soname property of the corpus.
1495///
1496/// This property is meaningful for, e.g, corpora built from ELF
1497/// shared library files. In that case, this is the shared object
1498/// name exported by the shared library.
1499///
1500/// @return the soname property of the corpus.
1501const string&
1503{return priv_->soname;}
1504
1505/// Setter for the soname property of the corpus.
1506///
1507/// This property is meaningful for, e.g, corpora built from ELF
1508/// shared library files. In that case, this is the shared object
1509/// name exported by the shared library.
1510///
1511/// @param soname the new soname property of the corpus.
1512void
1513corpus::set_soname(const string& soname)
1514{
1515 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1516 priv_->soname = soname;
1517}
1518
1519/// Getter for the architecture name of the corpus.
1520///
1521/// This property is meaningful for e.g, corpora built from ELF shared
1522/// library files. In that case, this is a string representation of
1523/// the Elf{32,64}_Ehdr::e_machine field.
1524///
1525/// @return the architecture name string.
1526const string&
1528{return priv_->architecture_name;}
1529
1530/// Setter for the architecture name of the corpus.
1531///
1532/// This property is meaningful for e.g, corpora built from ELF shared
1533/// library files. In that case, this is a string representation of
1534/// the Elf{32,64}_Ehdr::e_machine field.
1535///
1536/// @param arch the architecture name string.
1537void
1539{
1540 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1541 priv_->architecture_name = arch;
1542}
1543
1544/// Tests if the corpus is empty from an ABI surface perspective. I.e. if all
1545/// of these criteria are true:
1546/// - all translation units (members) are empty
1547/// - the maps function and variable symbols are not having entries
1548/// - for shared libraries:
1549/// - the soname is empty
1550/// - there are no DT_NEEDED entries
1551///
1552/// @return true if the corpus contains no translation unit.
1553bool
1555{
1556 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1557 bool members_empty = true;
1558 for (translation_units::const_iterator i = priv_->members.begin(),
1559 e = priv_->members.end();
1560 i != e; ++i)
1561 {
1562 if (!(*i)->is_empty())
1563 {
1564 members_empty = false;
1565 break;
1566 }
1567 }
1568 return (members_empty
1569 && (!get_symtab() || !get_symtab()->has_symbols())
1570 && priv_->soname.empty()
1571 && priv_->needed.empty()
1572 && priv_->architecture_name.empty()
1573 && !priv_->group);
1574}
1575
1576/// Compare the current @ref corpus against another one.
1577///
1578/// @param other the other corpus to compare against.
1579///
1580/// @return true if the two corpus are equal, false otherwise.
1581bool
1582corpus::operator==(const corpus& other) const
1583{
1584 translation_units::const_iterator i, j;
1585 for (i = get_translation_units().begin(),
1586 j = other.get_translation_units().begin();
1587 (i != get_translation_units().end()
1588 && j != other.get_translation_units().end());
1589 ++i, ++j)
1590 if ((**i) != (**j))
1591 return false;
1592
1593 return (i == get_translation_units().end()
1594 && j == other.get_translation_units().end());
1595}
1596
1597/// Setter for the symtab object.
1598///
1599/// @param symtab a shared pointer to the new symtab object
1600void
1602{
1603 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1604 priv_->symtab_ = symtab;
1605}
1606
1607/// Getter for the symtab object.
1608///
1609/// @return a shared pointer to the symtab object
1612{return priv_->symtab_;}
1613
1614/// Getter for the function symbols map.
1615///
1616/// @return a reference to the function symbols map.
1619{return priv_->get_fun_symbol_map();}
1620
1621/// Getter for the map of function symbols that are undefined in this
1622/// corpus.
1623///
1624/// @return the map of function symbols not defined in this corpus.
1625/// The key of the map is the name of the function symbol. The value
1626/// is a vector of all the function symbols that have the same name.
1629{return priv_->get_undefined_fun_symbol_map();}
1630
1631/// Return a sorted vector of function symbols for this corpus.
1632///
1633/// Note that the first time this function is called, the symbols are
1634/// sorted and cached. Subsequent invocations of this function return
1635/// the cached vector that was built previously.
1636///
1637/// @return the sorted list of function symbols.
1638const elf_symbols&
1640{return priv_->get_sorted_fun_symbols();}
1641
1642/// Getter for a sorted vector of the function symbols undefined in
1643/// this corpus.
1644///
1645/// @return a vector of the function symbols undefined in this corpus,
1646/// sorted by name and then version.
1647const elf_symbols&
1649{return priv_->get_sorted_undefined_fun_symbols();}
1650
1651/// Getter for the sorted vector of variable symbols for this corpus.
1652///
1653/// Note that the first time this function is called, it computes the
1654/// sorted vector, caches the result and returns it. Subsequent
1655/// invocations of this function just return the cached vector.
1656///
1657/// @return the sorted vector of variable symbols for this corpus.
1658const elf_symbols&
1660{return priv_->get_sorted_var_symbols();}
1661
1662/// Getter for a sorted vector of the variable symbols undefined in
1663/// this corpus.
1664///
1665/// @return a vector of the variable symbols undefined in this corpus,
1666/// sorted by name and then version.
1667const elf_symbols&
1669{return priv_->get_sorted_undefined_var_symbols();}
1670
1671/// Getter for the variable symbols map.
1672///
1673/// @return a reference to the variabl symbols map.
1676{return priv_->get_var_symbol_map();}
1677
1678/// Getter for the map of variable symbols that are undefined in this
1679/// corpus.
1680///
1681/// @return the map of variable symbols not defined in this corpus.
1682/// The key of the map is the name of the variable symbol. The value
1683/// is a vector of all the variable symbols that have the same name.
1686{return priv_->get_undefined_var_symbol_map();}
1687
1688/// Look in the function symbols map for a symbol with a given name.
1689///
1690/// @param n the name of the symbol to look for.
1691///
1692/// return the first symbol with the name @p n.
1693const elf_symbol_sptr
1695{
1696 if (get_fun_symbol_map().empty() && get_undefined_fun_symbol_map().empty())
1697 return elf_symbol_sptr();
1698
1699 string_elf_symbols_map_type::const_iterator it = get_fun_symbol_map().find(n);
1700 if ( it == get_fun_symbol_map().end())
1701 {
1702 it = get_undefined_fun_symbol_map().find(n);
1703 if (it == get_undefined_fun_symbol_map().end())
1704 return elf_symbol_sptr();
1705 }
1706 return it->second[0];
1707}
1708
1709/// Look into a set of symbols and look for a symbol that has a given
1710/// version.
1711///
1712/// This is a sub-routine for corpus::lookup_function_symbol() and
1713/// corpus::lookup_variable_symbol().
1714///
1715/// @param version the version of the symbol to look for.
1716///
1717/// @param symbols the set of symbols to consider.
1718///
1719/// @return the symbol found, or nil if none was found.
1720static const elf_symbol_sptr
1721find_symbol_by_version(const elf_symbol::version& version,
1722 const vector<elf_symbol_sptr>& symbols)
1723{
1724 if (version.is_empty())
1725 {
1726 // We are looing for a symbol with no version.
1727
1728 // So first look for possible aliases with no version
1729 for (elf_symbols::const_iterator s = symbols.begin();
1730 s != symbols.end();
1731 ++s)
1732 if ((*s)->get_version().is_empty())
1733 return *s;
1734
1735 // Or, look for a version that is a default one!
1736 for (elf_symbols::const_iterator s = symbols.begin();
1737 s != symbols.end();
1738 ++s)
1739 if ((*s)->get_version().is_default())
1740 return *s;
1741 }
1742 else
1743 // We are looking for a symbol with a particular defined version.
1744 for (elf_symbols::const_iterator s = symbols.begin();
1745 s != symbols.end();
1746 ++s)
1747 if ((*s)->get_version().str() == version.str())
1748 return *s;
1749
1750 return elf_symbol_sptr();
1751}
1752
1753/// Look in the function symbols map for a symbol with a given name.
1754///
1755/// @param symbol_name the name of the symbol to look for.
1756///
1757/// @param version the version of the symbol to look for.
1758///
1759/// return the symbol with name @p symbol_name and with version @p
1760/// version, or nil if no symbol has been found with that name and
1761/// version.
1762const elf_symbol_sptr
1763corpus::lookup_function_symbol(const string& symbol_name,
1764 const elf_symbol::version& version) const
1765{
1766 if (get_fun_symbol_map().empty() && get_undefined_fun_symbol_map().empty())
1767 return elf_symbol_sptr();
1768
1769 string_elf_symbols_map_type::const_iterator it =
1770 get_fun_symbol_map().find(symbol_name);
1771 if ( it == get_fun_symbol_map().end())
1772 {
1773 it = get_undefined_fun_symbol_map().find(symbol_name);
1774 if (it == get_undefined_fun_symbol_map().end())
1775 return elf_symbol_sptr();
1776 }
1777
1778 return find_symbol_by_version(version, it->second);
1779}
1780
1781/// Look in the function symbols map for a symbol with the same name
1782/// and version as a given symbol.
1783///
1784/// @param symbol the symbol to look for.
1785///
1786/// return the symbol with the same name and version as @p symbol.
1787const elf_symbol_sptr
1789{return lookup_function_symbol(symbol.get_name(), symbol.get_version());}
1790
1791/// Look in the function symbols map for a symbol with the same name
1792/// and version as a given symbol.
1793///
1794/// @param symbol the symbol to look for.
1795///
1796/// return the symbol with the same name and version as @p symbol.
1797const elf_symbol_sptr
1799{
1800 if (!symbol)
1801 return nullptr;
1802 return lookup_function_symbol(*symbol);
1803}
1804
1805
1806/// Look in the variable symbols map for a symbol with a given name.
1807///
1808/// @param n the name of the symbol to look for.
1809///
1810/// return the first symbol with the name @p n.
1811const elf_symbol_sptr
1813{
1814 if (get_var_symbol_map().empty() && get_undefined_var_symbol_map().empty())
1815 return elf_symbol_sptr();
1816
1817 string_elf_symbols_map_type::const_iterator it = get_var_symbol_map().find(n);
1818 if ( it == get_var_symbol_map().end())
1819 {
1820 it = get_undefined_var_symbol_map().find(n);
1821 if (it == get_undefined_var_symbol_map().end())
1822 return elf_symbol_sptr();
1823 }
1824 return it->second[0];
1825}
1826
1827/// Look in the variable symbols map for a symbol with a given name.
1828///
1829/// @param symbol_name the name of the symbol to look for.
1830///
1831/// @param symbol_version the version of the symbol to look for.
1832///
1833/// return the first symbol with the name @p symbol_name and with
1834/// version @p version.
1835const elf_symbol_sptr
1836corpus::lookup_variable_symbol(const string& symbol_name,
1837 const elf_symbol::version& version) const
1838{
1839 if (get_var_symbol_map().empty() && get_undefined_var_symbol_map().empty())
1840 return elf_symbol_sptr();
1841
1842 string_elf_symbols_map_type::const_iterator it =
1843 get_var_symbol_map().find(symbol_name);
1844 if ( it == get_var_symbol_map().end())
1845 {
1846 it = get_undefined_var_symbol_map().find(symbol_name);
1847 if (it == get_undefined_var_symbol_map().end())
1848 return elf_symbol_sptr();
1849 }
1850
1851 return find_symbol_by_version(version, it->second);
1852}
1853
1854/// Look in the variable symbols map for a symbol with the same name
1855/// and version as a given symbol.
1856///
1857/// @param symbol the symbol to look for.
1858///
1859/// return the symbol with the same name and version as @p symbol.
1860const elf_symbol_sptr
1862{return lookup_variable_symbol(symbol.get_name(), symbol.get_version());}
1863
1864/// Return the functions public decl table of the current corpus.
1865///
1866/// The function public decl tables is a vector of all the functions
1867/// and member functions found in the current corpus.
1868///
1869/// Note that the caller can suppress some functions from the vector
1870/// supplying regular expressions describing the set of functions she
1871/// want to see removed from the public decl table by populating the
1872/// vector of regular expressions returned by
1873/// corpus::get_regex_patterns_of_fns_to_suppress().
1874///
1875/// @return the vector of functions of the public decl table. The
1876/// functions are sorted using their mangled name or name if they
1877/// don't have mangle names.
1878const corpus::functions&
1880{return priv_->fns;}
1881
1882/// Lookup the function which has a given function ID.
1883///
1884/// Note that there can have been several functions with the same ID.
1885/// This is because debug info can declare the same function in
1886/// several different translation units. Normally, all these function
1887/// should be equal. But still, this function returns all these
1888/// functions.
1889///
1890/// @param id the ID of the function to lookup. This ID must be
1891/// either the result of invoking function::get_id() of
1892/// elf_symbol::get_id_string().
1893///
1894/// @return the set of functions which ID is @p id, or nil if no
1895/// function with that ID was found.
1896const std::unordered_set<const function_decl*>*
1898{return priv_->lookup_functions(id);}
1899
1900/// Lookup the function which has a given function ID.
1901///
1902/// Note that there can have been several functions with the same ID.
1903/// This is because debug info can declare the same function in
1904/// several different translation units. Normally, all these function
1905/// should be equal. But still, this function returns all these
1906/// functions.
1907///
1908/// @param id the ID of the function to lookup. This ID must be
1909/// either the result of invoking function::get_id() of
1910/// elf_symbol::get_id_string().
1911///
1912/// @return the set of functions which ID is @p id, or nil if no
1913/// function with that ID was found.
1914const std::unordered_set<const function_decl*>*
1915corpus::lookup_functions(const char* id) const
1916{
1917 if (!id)
1918 return nullptr;
1919
1920 interned_string string_id = priv_->env.intern(id);
1921 return lookup_functions(string_id);
1922}
1923
1924/// Lookup the function which has a given function ID.
1925///
1926/// Note that there can have been several functions with the same ID.
1927/// This is because debug info can declare the same function in
1928/// several different translation units. Normally, all these function
1929/// should be equal. But still, this function returns all these
1930/// functions.
1931///
1932/// @param id the ID of the function to lookup. This ID must be
1933/// either the result of invoking function::get_id() of
1934/// elf_symbol::get_id_string().
1935///
1936/// @return the set of functions which ID is @p id, or nil if no
1937/// function with that ID was found.
1938const std::unordered_set<const function_decl*>*
1939corpus::lookup_functions(const string& id) const
1940{
1941 interned_string string_id = priv_->env.intern(id);
1942 return lookup_functions(string_id);
1943}
1944
1945/// Lookup the exported variables which all have a given variable ID.
1946///
1947/// @param id the ID of the variable to look up.
1948///
1949/// @return a pointer to the set of variables with ID @p id, or
1950/// nullptr if no variable was found with that ID.
1951const std::unordered_set<var_decl_sptr>*
1953{
1955 auto i = b->priv_->id_vars_map_.find(id);
1956 if (i == b->priv_->id_vars_map_.end())
1957 return nullptr;
1958 return &i->second;
1959}
1960
1961/// Lookup the exported variables which all have a given variable ID.
1962///
1963/// @param id the ID of the variable to look up.
1964///
1965/// @return a pointer to the set of variables with ID @p id, or
1966/// nullptr if no variable was found with that ID.
1967const std::unordered_set<var_decl_sptr>*
1968corpus::lookup_variables(const char* id) const
1969{
1970 if (!id)
1971 return nullptr;
1972
1973 interned_string string_id = priv_->env.intern(id);
1974 return lookup_variables(string_id);
1975}
1976
1977/// Sort the set of functions exported by this corpus.
1978///
1979/// This function removes redundant functions from the vector of
1980/// functions that make up the ABI entry points and then sort the
1981/// resulting de-duplicated vector of functions.
1982///
1983/// Normally, unless you are writting a front-end that creates an ABI
1984/// @ref corpus, you shouldn't be calling this because the code that
1985/// creates the corpus for should do it for you. In any case, this
1986/// function should be called after the types carried by the
1987/// environment of the corpus are canonicalized.
1988void
1990{
1991 priv_->remove_redundant_functions();
1992
1993 func_comp fc;
1994
1995 lock_guard<recursive_mutex> lock(priv_->get_mutex());
1996 {
1997 std::sort(priv_->fns.begin(), priv_->fns.end(), fc);
1998
1999 priv_->sorted_undefined_fns.clear();
2000
2001 for (auto& f : priv_->undefined_fns)
2002 priv_->sorted_undefined_fns.push_back(f);
2003
2004 std::sort(priv_->sorted_undefined_fns.begin(),
2005 priv_->sorted_undefined_fns.end(), fc);
2006 }
2007}
2008
2009/// Return the public decl table of the global variables of the
2010/// current corpus.
2011///
2012/// The variable public decls table is a vector of all the public
2013/// global variables and static member variables found in the current
2014/// corpus.
2015///
2016/// Note that the caller can suppress some variables from the vector
2017/// supplying regular expressions describing the set of variables she
2018/// wants to see removed from the public decl table by populating the
2019/// vector of regular expressions returned by
2020/// corpus::get_regex_patterns_of_fns_to_suppress().
2021///
2022/// @return the vector of variables of the public decl table. The
2023/// variables are sorted using their name.
2024const corpus::variables&
2026{return priv_->vars;}
2027
2028/// Sort the set of variables exported by this corpus.
2029///
2030/// Normally, you shouldn't be calling this as the code that creates
2031/// the corpus for you should do it for you too.
2032void
2034{
2035 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2036
2037 var_comp vc;
2038 std::sort(priv_->vars.begin(), priv_->vars.end(), vc);
2039
2040 priv_->sorted_undefined_vars.clear();
2041 for (auto& f : priv_->undefined_vars)
2042 priv_->sorted_undefined_vars.push_back(f);
2043
2044 std::sort(priv_->sorted_undefined_vars.begin(),
2045 priv_->sorted_undefined_vars.end(), vc);
2046}
2047
2048/// Getter of the undefined functions of the corpus.
2049///
2050/// Undefined functions are functions which symbols are not defined.
2051///
2052/// @return a set of @ref function_decl* representing the functions
2053/// that are undefined in the corpus.
2056{return priv_->undefined_fns;}
2057
2058/// Getter of the undefined functions of the corpus.
2059///
2060/// @return a set of @ref function_decl* representing the functions
2061/// that are undefined in the corpus.
2064{return priv_->undefined_fns;}
2065
2066/// Getter of the sorted vector of undefined functions of the corpus.
2067///
2068/// @return a vector of @ref function_decl* representing the functions
2069/// that are undefined in the corpus.
2070const corpus::functions&
2072{
2073 if (priv_->sorted_undefined_fns.empty()
2074 && !priv_->undefined_fns.empty())
2075 // We have undefined functions but we haven't sorted them yet.
2076 // Let's do the sorting now then.
2077 const_cast<corpus*>(this)->sort_functions();
2078
2079 return priv_->sorted_undefined_fns;
2080}
2081
2082void
2083corpus::add_undefined_function(const function_decl* fn)
2084{
2085 if (fn)
2086 {
2087 lock_guard<mutex> lock(priv_->undefined_fns_mutex_);
2088 get_undefined_functions().insert(fn);
2089 }
2090}
2091
2092/// Getter of the undefined variables of the corpus.
2093///
2094/// @return a set of @ref var_decl* representing the variables that
2095/// are undefined in the corpus.
2098{return priv_->undefined_vars;}
2099
2100/// Getter of the undefined variables of the corpus.
2101///
2102/// @return a set of @ref var_decl* representing the variables that
2103/// are undefined in the corpus.
2106{return priv_->undefined_vars;}
2107
2108/// Getter of the sorted vector of undefined variables of the corpus.
2109///
2110/// @return a sorted vector of @ref var_decl* representing the
2111/// variables that are undefined in the corpus.
2112const corpus::variables&
2114{
2115 if (priv_->sorted_undefined_vars.empty()
2116 && !priv_->undefined_vars.empty())
2117 // We have undefined variables but we haven't sorted them yet.
2118 // Let's do the sorting now then.
2119 const_cast<corpus*>(this)->sort_variables();
2120
2121 return priv_->sorted_undefined_vars;
2122}
2123
2124void
2125corpus::add_undefined_variable(const var_decl_sptr& var)
2126{
2127 if (var)
2128 {
2129 lock_guard<mutex> lock(priv_->undefined_vars_mutex_);
2130 get_undefined_variables().insert(var);
2131 }
2132}
2133/// Getter of the set of function symbols that are not referenced by
2134/// any function exported by the current corpus.
2135///
2136/// When the corpus has been created from an ELF library or program,
2137/// this function returns the set of function symbols not referenced
2138/// by any debug information.
2139///
2140/// @return the vector of function symbols not referenced by any
2141/// function exported by the current corpus.
2142const elf_symbols&
2144{return priv_->get_unreferenced_function_symbols();}
2145
2146/// Getter of the set of variable symbols that are not referenced by
2147/// any variable exported by the current corpus.
2148///
2149/// When the corpus has been created from an ELF library or program,
2150/// this function returns the set of variable symbols not referenced
2151/// by any debug information.
2152///
2153/// @return the vector of variable symbols not referenced by any
2154/// variable exported by the current corpus.
2155const elf_symbols&
2157{return priv_->get_unreferenced_variable_symbols();}
2158
2159/// Accessor for the regex patterns describing the functions to drop
2160/// from the public decl table.
2161///
2162/// @return the regex patterns describing the functions to drop from
2163/// the public decl table.
2164vector<string>&
2166{return priv_->regex_patterns_fns_to_suppress;}
2167
2168/// Accessor for the regex patterns describing the functions to drop
2169/// from the public decl table.
2170///
2171/// @return the regex patterns describing the functions to drop from
2172/// the public decl table.
2173const vector<string>&
2175{return priv_->regex_patterns_fns_to_suppress;}
2176
2177/// Accessor for the regex patterns describing the variables to drop
2178/// from the public decl table.
2179///
2180/// @return the regex patterns describing the variables to drop from
2181/// the public decl table.
2182vector<string>&
2184{return priv_->regex_patterns_vars_to_suppress;}
2185
2186/// Accessor for the regex patterns describing the variables to drop
2187/// from the public decl table.
2188///
2189/// @return the regex patterns describing the variables to drop from
2190/// the public decl table.
2191const vector<string>&
2193{return priv_->regex_patterns_vars_to_suppress;}
2194
2195/// Accessor for the regex patterns describing the functions to keep
2196/// into the public decl table. The other functions not matches by these
2197/// regexes are dropped from the public decl table.
2198///
2199/// @return the regex patterns describing the functions to keep into
2200/// the public decl table.
2201vector<string>&
2203{return priv_->regex_patterns_fns_to_keep;}
2204
2205/// Accessor for the regex patterns describing the functions to keep
2206/// into the public decl table. The other functions not matches by these
2207/// regexes are dropped from the public decl table.
2208///
2209/// @return the regex patterns describing the functions to keep into
2210/// the public decl table.
2211const vector<string>&
2213{return priv_->regex_patterns_fns_to_keep;}
2214
2215/// Getter for the vector of function symbol IDs to keep.
2216///
2217/// A symbol ID is a string made of the name of the symbol and its
2218/// version, separated by one or two '@'.
2219///
2220/// @return a vector of IDs of function symbols to keep.
2221vector<string>&
2223{return priv_->sym_id_fns_to_keep;}
2224
2225/// Getter for the vector of function symbol IDs to keep.
2226///
2227/// A symbol ID is a string made of the name of the symbol and its
2228/// version, separated by one or two '@'.
2229///
2230/// @return a vector of IDs of function symbols to keep.
2231const vector<string>&
2233{return priv_->sym_id_fns_to_keep;}
2234
2235/// Accessor for the regex patterns describing the variables to keep
2236/// into the public decl table. The other variables not matches by these
2237/// regexes are dropped from the public decl table.
2238///
2239/// @return the regex patterns describing the variables to keep into
2240/// the public decl table.
2241vector<string>&
2243{return priv_->regex_patterns_vars_to_keep;}
2244
2245/// Accessor for the regex patterns describing the variables to keep
2246/// into the public decl table. The other variables not matches by these
2247/// regexes are dropped from the public decl table.
2248///
2249/// @return the regex patterns describing the variables to keep into
2250/// the public decl table.
2251const vector<string>&
2253{return priv_->regex_patterns_vars_to_keep;}
2254
2255/// Getter for the vector of variable symbol IDs to keep.
2256///
2257/// A symbol ID is a string made of the name of the symbol and its
2258/// version, separated by one or two '@'.
2259///
2260/// @return a vector of IDs of variable symbols to keep.
2261vector<string>&
2263{return priv_->sym_id_vars_to_keep;}
2264
2265/// Getter for the vector of variable symbol IDs to keep.
2266///
2267/// A symbol ID is a string made of the name of the symbol and its
2268/// version, separated by one or two '@'.
2269///
2270/// @return a vector of IDs of variable symbols to keep.
2271const vector<string>&
2273{return priv_->sym_id_vars_to_keep;}
2274
2275/// After the set of exported functions and variables have been built,
2276/// consider all the tunables that control that set and see if some
2277/// functions need to be removed from that set; if so, remove them.
2278void
2280{
2281 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2282 string sym_name, sym_version;
2283
2284 functions fns_to_keep;
2286 for (auto f = priv_->fns.begin(); f != priv_->fns.end(); ++f)
2287 {
2288 if (b->priv_->keep_wrt_id_of_fns_to_keep(*f)
2289 && b->priv_->keep_wrt_regex_of_fns_to_suppress(*f)
2290 && b->priv_->keep_wrt_regex_of_fns_to_keep(*f))
2291 fns_to_keep.push_back(*f);
2292 }
2293 priv_->fns = fns_to_keep;
2294
2295 variables vars_to_keep;
2296 for (auto v = priv_->vars.begin(); v != priv_->vars.end(); ++v)
2297 {
2298 if (b->priv_->keep_wrt_id_of_vars_to_keep(*v)
2299 && b->priv_->keep_wrt_regex_of_vars_to_suppress(*v)
2300 && b->priv_->keep_wrt_regex_of_vars_to_keep(*v))
2301 vars_to_keep.push_back(*v);
2302 }
2303 priv_->vars = vars_to_keep;
2304}
2305
2306/// Getter for the object that is responsible for determining what
2307/// decls ought to be in the set of exported decls.
2308///
2309/// The object does have methods to add the decls to the set of
2310/// exported decls, right at the place where the corpus expects it,
2311/// so that there is no unnecessary copying involved.
2312///
2313/// @return a (smart) pointer to the instance of @ref
2314/// corpus::exported_decls_builder that is responsible for determine
2315/// what decls ought to be in the set of exported decls.
2318{
2319 {
2320 lock_guard<mutex> lock(priv_->exported_decls_builder_mutex);
2321 if (!priv_->exported_decls_builder)
2322 {
2323 priv_->exported_decls_builder.reset
2324 (new exported_decls_builder(priv_->fns,
2325 priv_->vars,
2326 priv_->regex_patterns_fns_to_suppress,
2327 priv_->regex_patterns_vars_to_suppress,
2328 priv_->regex_patterns_fns_to_keep,
2329 priv_->regex_patterns_vars_to_keep,
2330 priv_->sym_id_fns_to_keep,
2331 priv_->sym_id_vars_to_keep));
2332 }
2333 }
2334 return priv_->exported_decls_builder;
2335}
2336
2337/// Bitwise | operator for the corpus::origin type.
2338///
2339/// @param l the left-hand side operand of the | operation.
2340///
2341/// @param r the right-hand side operand of the | operation.
2342///
2343/// @return the result of the operation.
2346{
2347 return static_cast<corpus::origin>
2348 (static_cast<uint32_t>(l) | static_cast<uint32_t>(r));
2349}
2350
2351/// Bitwise |= operator for the corpus::origin type.
2352///
2353/// @param l the left-hand side operand for the |= operation.
2354///
2355/// @param r the right-hand side operand for the |= operation.
2356///
2357/// @return the result of the operation.
2360{
2361 l = l | r;
2362 return l;
2363}
2364
2365/// Bitwise & operator for the corpus::origin type.
2366///
2367/// @param l the left-hand side operand of the & operation.
2368///
2369/// @param r the right-hand side operand of the & operation.
2370///
2371/// @return the result of the operation.
2374{
2375 return static_cast<corpus::origin>
2376 (static_cast<uint32_t>(l) & static_cast<uint32_t>(r));
2377}
2378
2379/// Bitwise &= operator for the corpus::origin type.
2380///
2381/// @param l the left-hand side operand of the &= operation.
2382///
2383/// @param r the right-hand side operand of the &= operation.
2384///
2385/// @return the result of the operation.
2388{
2389 l = l & r;
2390 return l;
2391}
2392
2393// </corpus stuff>
2394
2395// <corpus_group stuff>
2396
2397/// Type of the private data of @ref corpus_group
2398struct corpus_group::priv
2399{
2400 recursive_mutex mutex;
2401 std::set<string> corpora_paths;
2402 corpora_type corpora;
2403 istring_function_decl_ptr_map_type fns_map;
2405 istring_var_decl_ptr_map_type vars_map;
2406 corpus::variables vars;
2407 string_elf_symbols_map_type var_symbol_map;
2408 string_elf_symbols_map_type fun_symbol_map;
2409 elf_symbols sorted_var_symbols;
2410 elf_symbols sorted_fun_symbols;
2411 unordered_map<string, elf_symbol_sptr> unrefed_fun_symbol_map;
2412 elf_symbols unrefed_fun_symbols;
2413 bool unrefed_fun_symbols_built;
2414 unordered_map<string, elf_symbol_sptr> unrefed_var_symbol_map;
2415 elf_symbols unrefed_var_symbols;
2416 bool unrefed_var_symbols_built;
2417 unordered_set<interned_string, hash_interned_string> pub_type_pretty_reprs_;
2418
2419 priv()
2420 : unrefed_fun_symbols_built(),
2421 unrefed_var_symbols_built()
2422 {}
2423
2424 /// Add symbols to the set of corpus group function symbols that are
2425 /// *NOT* referenced by debug info.
2426 ///
2427 /// @param syms the set the symbols to add.
2428 void
2429 add_unref_fun_symbols(const elf_symbols& syms)
2430 {
2431 lock_guard<recursive_mutex> lock(get_mutex());
2432 for (elf_symbols::const_iterator e = syms.begin();
2433 e != syms.end();
2434 ++e)
2435 {
2436 string sym_id = (*e)->get_id_string();
2437 unordered_map<string, elf_symbol_sptr>::const_iterator j =
2438 unrefed_fun_symbol_map.find(sym_id);
2439 if (j != unrefed_fun_symbol_map.end())
2440 continue;
2441
2442 unrefed_fun_symbol_map[sym_id] = *e;
2443 unrefed_fun_symbols.push_back(*e);
2444 }
2445 unrefed_fun_symbols_built = true;
2446 }
2447
2448 /// Add symbols to the set of corpus group variable symbols that are
2449 /// *NOT* referenced by debug info.
2450 ///
2451 /// @param syms the set the symbols to add.
2452 void
2453 add_unref_var_symbols(const elf_symbols& syms)
2454 {
2455 lock_guard<recursive_mutex> lock(get_mutex());
2456 for (elf_symbols::const_iterator e = syms.begin();
2457 e != syms.end();
2458 ++e)
2459 {
2460 string sym_id = (*e)->get_id_string();
2461 unordered_map<string, elf_symbol_sptr>::const_iterator j =
2462 unrefed_var_symbol_map.find(sym_id);
2463 if (j != unrefed_var_symbol_map.end())
2464 continue;
2465
2466 unrefed_var_symbol_map[sym_id] = *e;
2467 unrefed_var_symbols.push_back(*e);
2468 }
2469 unrefed_var_symbols_built = true;
2470 }
2471
2472 recursive_mutex&
2473 get_mutex()
2474 {return mutex;}
2475}; // end corpus_group::priv
2476
2477/// Constructor of the @ref corpus_group type.
2478///
2479/// @param env the environment of the @ref corpus_group.
2480///
2481/// @param path the path to the file represented by the corpus group.
2482corpus_group::corpus_group(const environment& env, const string& path = "")
2483 : corpus(env, path), priv_(new priv)
2484{}
2485
2486/// Desctructor of the @ref corpus_group type.
2489
2490/// Add a new corpus to the current instance of @ref corpus_group.
2491///
2492/// @param corp the new corpus to add.
2493void
2494corpus_group::add_corpus(const corpus_sptr& corp)
2495{
2496 if (!corp)
2497 return;
2498
2499 if (!corp->get_path().empty()
2500 && has_corpus(corp->get_path()))
2501 return;
2502
2503 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2504 {
2505 // Ensure the new architecture name matches the current one.
2506 string cur_arch = get_architecture_name(),
2507 corp_arch = corp->get_architecture_name();
2508 if (cur_arch.empty())
2509 set_architecture_name(corp_arch);
2510 else if (cur_arch != corp_arch)
2511 {
2512 std::cerr << "corpus '" << corp->get_path() << "'"
2513 << " has architecture '" << corp_arch << "'"
2514 << " but expected '" << cur_arch << "'\n";
2516 }
2517
2518 priv_->corpora.push_back(corp);
2519 corp->set_group(this);
2520 priv_->corpora_paths.insert(corp->get_path());
2521 }
2522
2523 /// Add the unreferenced function and variable symbols of this
2524 /// corpus to the unreferenced symbols of the current corpus group.
2525 priv_->add_unref_fun_symbols(get_unreferenced_function_symbols());
2526 priv_->add_unref_var_symbols(get_unreferenced_variable_symbols());
2527
2528 // Copy the reachable types from the added corpus to the group.
2529 for (auto& t : corp->priv_->reachable_types_from_pub_ifaces_)
2531}
2532
2533/// Test if a corpus of a given path has been added to the group.
2534///
2535/// @param path the path to the corpus to consider.
2536///
2537/// @return true iff a corpus with path @p path is already present in
2538/// the groupâ‹…
2539bool
2540corpus_group::has_corpus(const string& path)
2541{
2542 if (priv_->corpora_paths.find(path) != priv_->corpora_paths.end())
2543 return true;
2544 return false;
2545}
2546
2547/// Getter of the vector of corpora held by the current @ref
2548/// corpus_group.
2549///
2550/// @return the vector corpora.
2551const corpus_group::corpora_type&
2553{return priv_->corpora;}
2554
2555/// Getter of the first corpus added to this Group.
2556///
2557/// @return the first corpus added to this Group.
2558const corpus_sptr
2560{return const_cast<corpus_group*>(this)->get_main_corpus();}
2561
2562/// Getter of the first corpus added to this Group.
2563///
2564/// @return the first corpus added to this Group.
2565corpus_sptr
2567{
2568 if (!get_corpora().empty())
2569 return get_corpora().front();
2570 return corpus_sptr();
2571}
2572
2573/// Test if the current corpus group is empty.
2574///
2575/// @return true iff the current corpus group is empty.
2576bool
2578{return get_corpora().empty();}
2579
2580/// Get the functions exported by the corpora of the current corpus
2581/// group.
2582///
2583/// Upon its first invocation, this function walks the corpora
2584/// contained in the corpus group and caches the functions they exported.
2585///
2586/// Subsequent invocations just return the cached functions.
2587///
2588/// @return the exported functions.
2589const corpus::functions&
2591{
2592 if (priv_->fns.empty())
2593 {
2594 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2595 for (corpora_type::const_iterator i = get_corpora().begin();
2596 i != get_corpora().end();
2597 ++i)
2598 {
2599 corpus_sptr c = *i;
2600 for (corpus::functions::const_iterator f = c->get_functions().begin();
2601 f != c->get_functions().end();
2602 ++f)
2603 {
2604 interned_string fid = (*f)->get_id();
2605 istring_function_decl_ptr_map_type::const_iterator j =
2606 priv_->fns_map.find(fid);
2607
2608 if (j != priv_->fns_map.end())
2609 // Don't cache the same function twice ...
2610 continue;
2611
2612 priv_->fns_map[fid] = *f;
2613 // really cache the function now.
2614 priv_->fns.push_back(*f);
2615 }
2616 }
2617 }
2618
2619 return priv_->fns;
2620}
2621
2622/// Get the global variables exported by the corpora of the current
2623/// corpus group.
2624///
2625/// Upon its first invocation, this function walks the corpora
2626/// contained in the corpus group and caches the variables they
2627/// export.
2628///
2629/// @return the exported variables.
2630const corpus::variables&
2632{
2633 if (priv_->vars.empty())
2634 {
2635 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2636 for (corpora_type::const_iterator i = get_corpora().begin();
2637 i != get_corpora().end();
2638 ++i)
2639 {
2640 corpus_sptr c = *i;
2641 for (corpus::variables::const_iterator v = c->get_variables().begin();
2642 v != c->get_variables().end();
2643 ++v)
2644 {
2645 interned_string vid = (*v)->get_id();
2646 istring_var_decl_ptr_map_type::const_iterator j =
2647 priv_->vars_map.find(vid);
2648
2649 if (j != priv_->vars_map.end())
2650 // Don't cache the same variable twice ...
2651 continue;
2652
2653 priv_->vars_map[vid] = *v;
2654 // Really cache the variable now.
2655 priv_->vars.push_back(*v);
2656 }
2657 }
2658 }
2659
2660 return priv_->vars;
2661}
2662
2663/// Get the symbols of the global variables exported by the corpora of
2664/// the current @ref corpus_group.
2665///
2666/// @return the symbols of the global variables exported by the corpora
2669{
2670 if (priv_->var_symbol_map.empty())
2671 {
2672 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2673 for (corpora_type::const_iterator i = get_corpora().begin();
2674 i != get_corpora().end();
2675 ++i)
2676 priv_->var_symbol_map.insert((*i)->get_var_symbol_map().begin(),
2677 (*i)->get_var_symbol_map().end());
2678 }
2679 return priv_->var_symbol_map;
2680}
2681
2682/// Get the symbols of the global functions exported by the corpora of
2683/// the current @ref corpus_group.
2684///
2685/// @return the symbols of the global functions exported by the corpora
2688{
2689 if (priv_->fun_symbol_map.empty())
2690 {
2691 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2692 for (corpora_type::const_iterator i = get_corpora().begin();
2693 i != get_corpora().end();
2694 ++i)
2695 priv_->fun_symbol_map.insert((*i)->get_fun_symbol_map().begin(),
2696 (*i)->get_fun_symbol_map().end());
2697 }
2698
2699 return priv_->fun_symbol_map;
2700}
2701
2702/// Get a sorted vector of the symbols of the functions exported by
2703/// the corpora of the current group.
2704///
2705/// @return the sorted vectors of the exported function symbols.
2706const elf_symbols&
2708{
2709 if (priv_->sorted_fun_symbols.empty()
2710 && !get_fun_symbol_map().empty())
2711 {
2712 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2713 for (corpora_type::const_iterator i = get_corpora().begin();
2714 i != get_corpora().end();
2715 ++i)
2716 {
2717 corpus_sptr c = *i;
2718 for (string_elf_symbols_map_type::const_iterator j =
2719 c->get_fun_symbol_map().begin();
2720 j != c->get_fun_symbol_map().begin();
2721 ++j)
2722 priv_->sorted_fun_symbols.insert(priv_->sorted_fun_symbols.end(),
2723 j->second.begin(),
2724 j->second.end());
2725 }
2726 comp_elf_symbols_functor comp;
2727 std::sort(priv_->sorted_fun_symbols.begin(),
2728 priv_->sorted_fun_symbols.end(),
2729 comp);
2730 }
2731
2732 return priv_->sorted_fun_symbols;
2733}
2734
2735/// Get a sorted vector of the symbols of the variables exported by
2736/// the corpora of the current group.
2737///
2738/// @return the sorted vectors of the exported variable symbols.
2739const elf_symbols&
2741{
2742 if (priv_->sorted_var_symbols.empty()
2743 && !get_var_symbol_map().empty())
2744 {
2745 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2746 for (corpora_type::const_iterator i = get_corpora().begin();
2747 i != get_corpora().end();
2748 ++i)
2749 {
2750 corpus_sptr c = *i;
2751 for (string_elf_symbols_map_type::const_iterator j =
2752 c->get_var_symbol_map().begin();
2753 j != c->get_var_symbol_map().begin();
2754 ++j)
2755 priv_->sorted_var_symbols.insert(priv_->sorted_var_symbols.end(),
2756 j->second.begin(),
2757 j->second.end());
2758 }
2759 comp_elf_symbols_functor comp;
2760 std::sort(priv_->sorted_var_symbols.begin(),
2761 priv_->sorted_var_symbols.end(),
2762 comp);
2763 }
2764
2765 return priv_->sorted_var_symbols;
2766}
2767
2768/// Get the set of function symbols not referenced by any debug info,
2769/// from all the corpora of the current corpus group.
2770///
2771/// Upon its first invocation, this function possibly walks all the
2772/// copora of this corpus group and caches the unreferenced symbols
2773/// they export. The function then returns the cache.
2774///
2775/// Upon subsequent invocations, this functions just returns the
2776/// cached symbols.
2777///
2778/// @return the unreferenced symbols.
2779const elf_symbols&
2781{
2782 if (!priv_->unrefed_fun_symbols_built)
2783 if (priv_->unrefed_fun_symbols.empty())
2784 {
2785 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2786 for (corpora_type::const_iterator i = get_corpora().begin();
2787 i != get_corpora().end();
2788 ++i)
2789 {
2790 corpus_sptr c = *i;
2791 for (elf_symbols::const_iterator e =
2792 c->get_unreferenced_function_symbols().begin();
2793 e != c->get_unreferenced_function_symbols().end();
2794 ++e)
2795 {
2796 string sym_id = (*e)->get_id_string();
2797 unordered_map<string, elf_symbol_sptr>::const_iterator j =
2798 priv_->unrefed_fun_symbol_map.find(sym_id);
2799 if (j != priv_->unrefed_fun_symbol_map.end())
2800 continue;
2801
2802 priv_->unrefed_fun_symbol_map[sym_id] = *e;
2803 priv_->unrefed_fun_symbols.push_back(*e);
2804 }
2805 }
2806 priv_->unrefed_fun_symbols_built = true;
2807 }
2808
2809 return priv_->unrefed_fun_symbols;
2810}
2811
2812/// Get the set of variable symbols not referenced by any debug info,
2813/// from all the corpora of the current corpus group.
2814///
2815/// Upon its first invocation, this function possibly walks all the
2816/// copora of this corpus group and caches the unreferenced symbols
2817/// they export. The function then returns the cache.
2818///
2819/// Upon subsequent invocations, this functions just returns the
2820/// cached symbols.
2821///
2822/// @return the unreferenced symbols.
2823const elf_symbols&
2825{
2826 if (!priv_->unrefed_var_symbols_built)
2827 if (priv_->unrefed_var_symbols.empty())
2828 {
2829 lock_guard<recursive_mutex> lock(priv_->get_mutex());
2830 for (corpora_type::const_iterator i = get_corpora().begin();
2831 i != get_corpora().end();
2832 ++i)
2833 {
2834 corpus_sptr c = *i;
2835 for (elf_symbols::const_iterator e =
2836 c->get_unreferenced_variable_symbols().begin();
2837 e != c->get_unreferenced_variable_symbols().end();
2838 ++e)
2839 {
2840 string sym_id = (*e)->get_id_string();
2841 unordered_map<string, elf_symbol_sptr>::const_iterator j =
2842 priv_->unrefed_var_symbol_map.find(sym_id);
2843 if (j != priv_->unrefed_var_symbol_map.end())
2844 continue;
2845
2846 priv_->unrefed_var_symbol_map[sym_id] = *e;
2847 priv_->unrefed_var_symbols.push_back(*e);
2848 }
2849 }
2850 priv_->unrefed_var_symbols_built = true;
2851 }
2852
2853 return priv_->unrefed_var_symbols;
2854}
2855
2856/// Lookup the function which has a given function ID.
2857///
2858/// Note that there can have been several functions with the same ID.
2859/// This is because debug info can declare the same function in
2860/// several different translation units. Normally, all these
2861/// functions should be equal. But still, this function returns all
2862/// these functions.
2863///
2864/// Also, note that this function cycles over each corpora of the
2865/// corpus group, invokes corpus::lookup_functions on them and returns
2866/// the result of the first one that succeeds.
2867///
2868/// @param id the ID of the function to lookup. This ID must be
2869/// either the result of invoking function::get_id() of
2870/// elf_symbol::get_id_string().
2871///
2872/// @return the set of functions which ID is @p id, or nil if no
2873/// function with that ID was found.
2874const std::unordered_set<const function_decl*>*
2876{
2877 for (auto& corp :get_corpora())
2878 if (auto fns = corp->lookup_functions(id))
2879 return fns;
2880
2881 return nullptr;
2882}
2883
2884/// Lookup the function which has a given function ID.
2885///
2886/// Note that there can have been several functions with the same ID.
2887/// This is because debug info can declare the same function in
2888/// several different translation units. Normally, all these
2889/// functions should be equal. But still, this function returns all
2890/// these functions.
2891///
2892/// Also, note that this function cycles over each corpora of the
2893/// corpus group, invokes corpus::lookup_functions on them and returns
2894/// the result of the first one that succeeds.
2895///
2896/// @param id the ID of the function to lookup. This ID must be
2897/// either the result of invoking function::get_id() of
2898/// elf_symbol::get_id_string().
2899///
2900/// @return the set of functions which ID is @p id, or nil if no
2901/// function with that ID was found.
2902const std::unordered_set<const function_decl*>*
2904{
2905 for (auto& corp :get_corpora())
2906 if (const auto& fns = corp->lookup_functions(id))
2907 return fns;
2908
2909 return nullptr;
2910}
2911
2912/// Lookup the exported variables which all have a given variable ID.
2913///
2914/// Note that this function cycles over each corpora of the corpus
2915/// group, invokes corpus::lookup_variabless on them and returns the
2916/// result of the first one that succeeds.
2917///
2918/// @param id the ID of the variable to look up.
2919///
2920/// @return a pointer to the set of variables with ID @p id, or
2921/// nullptr if no variable was found with that ID.
2922const std::unordered_set<var_decl_sptr>*
2924{
2925 for (auto& corp :get_corpora())
2926 if (const auto& vars = corp->lookup_variables(id))
2927 return vars;
2928
2929 return nullptr;
2930}
2931
2932/// Lookup the exported variables which all have a given variable ID.
2933///
2934/// Note that this function cycles over each corpora of the corpus
2935/// group, invokes corpus::lookup_variabless on them and returns the
2936/// result of the first one that succeeds.
2937///
2938/// @param id the ID of the variable to look up.
2939///
2940/// @return a pointer to the set of variables with ID @p id, or
2941/// nullptr if no variable was found with that ID.
2942const std::unordered_set<var_decl_sptr>*
2944{
2945 for (auto& corp :get_corpora())
2946 if (const auto& vars = corp->lookup_variables(id))
2947 return vars;
2948
2949 return nullptr;
2950}
2951
2952/// Test if a @ref corpus is a @ref corpus_group.
2953///
2954/// @param corpus the corpus to consider.
2955///
2956/// @return the @ref corpus_group is @p corpus is a corpus group, or
2957/// nil.
2958corpus_group_sptr
2959is_corpus_group(const corpus_sptr& corpus)
2960{return std::dynamic_pointer_cast<corpus_group>(corpus);}
2961
2962// </corpus_group stuff>
2963
2964void
2965dumptypes(const vector<type_base_wptr>& types,
2966 const char* output_file,
2967 const corpus& abi,
2968 bool emit_location)
2969{
2970 if (!output_file)
2971 return;
2972
2973 std::ofstream of(output_file);
2974 if (of.fail() ||!of.is_open())
2975 return;
2976
2977 string repr;
2978 for (auto& t : types)
2979 {
2980 type_base_sptr type(t.lock().get(), sptr_utils::noop_deleter());
2981 repr = type->get_pretty_representation();
2982 std::ostringstream os;
2983 os << "'" << repr << "'";
2984 if (emit_location)
2985 if (decl_base_sptr decl = get_type_declaration(type))
2986 os << ":" << decl->get_location().expand();
2987 os << " // ";
2989 os << " r";
2990 else
2991 os << " nr";
2992 of << os.str() << "\n";
2993 }
2994 of.close();
2995}
2996
2997}// end namespace ir
2998}// end namespace abigail
The private data and functions of the abigail::ir::corpus type.
std::shared_ptr< symtab > symtab_sptr
Convenience typedef for a shared pointer to a symtab.
Definition abg-fwd.h:1743
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects,...
Definition abg-fwd.h:1790
This contains the private implementation of the suppression engine of libabigail.
Types of the main internal representation of libabigail.
This file contains the declarations of the entry points to de-serialize an instance of abigail::trans...
Utilities to ease the wrapping of C types into std::shared_ptr.
This contains the declarations for the symtab reader.
#define ABG_ASSERT_NOT_REACHED
A macro that expands to aborting the program when executed.
This file contains the declarations of the entry points to de-serialize an instance of abigail::trans...
The abstraction of an interned string.
bool empty() const
Test if the current instance of interned_string is empty.
Definition abg-ir.cc:232
The type of the private data of corpus::exported_decls_builder type.
Abstracts the building of the set of exported variables and functions.
Definition abg-corpus.h:427
const functions & exported_functions() const
Getter for the reference to the vector of exported functions. This vector is shared with with the cor...
std::unordered_set< const function_decl * > * fn_id_maps_to_several_fns(const function_decl *)
Test if a given function ID maps to several functions in the same corpus.
bool maybe_add_fn_to_exported_fns(function_decl *, bool do_update=false)
Consider at all the tunables that control wether a function should be added to the set of exported fu...
bool maybe_add_var_to_exported_vars(const var_decl_sptr &)
Consider at all the tunables that control wether a variable should be added to the set of exported va...
const variables & exported_variables() const
Getter for the reference to the vector of exported variables. This vector is shared with with the cor...
Abstraction of a group of corpora.
Definition abg-corpus.h:470
virtual const elf_symbols & get_sorted_var_symbols() const
Get a sorted vector of the symbols of the variables exported by the corpora of the current group.
bool has_corpus(const string &)
Test if a corpus of a given path has been added to the group.
const corpora_type & get_corpora() const
Getter of the vector of corpora held by the current corpus_group.
virtual const string_elf_symbols_map_type & get_var_symbol_map() const
Get the symbols of the global variables exported by the corpora of the current corpus_group.
virtual const elf_symbols & get_sorted_fun_symbols() const
Get a sorted vector of the symbols of the functions exported by the corpora of the current group.
virtual const std::unordered_set< const function_decl * > * lookup_functions(const interned_string &id) const
Lookup the function which has a given function ID.
virtual bool is_empty() const
Test if the current corpus group is empty.
virtual const string_elf_symbols_map_type & get_fun_symbol_map() const
Get the symbols of the global functions exported by the corpora of the current corpus_group.
const corpus_sptr get_main_corpus() const
Getter of the first corpus added to this Group.
virtual const elf_symbols & get_unreferenced_function_symbols() const
Get the set of function symbols not referenced by any debug info, from all the corpora of the current...
virtual const elf_symbols & get_unreferenced_variable_symbols() const
Get the set of variable symbols not referenced by any debug info, from all the corpora of the current...
virtual const std::unordered_set< var_decl_sptr > * lookup_variables(const interned_string &id) const
Lookup the exported variables which all have a given variable ID.
virtual const corpus::variables & get_variables() const
Get the global variables exported by the corpora of the current corpus group.
virtual ~corpus_group()
Desctructor of the corpus_group type.
void add_corpus(const corpus_sptr &)
Add a new corpus to the current instance of corpus_group.
virtual const corpus::functions & get_functions() const
Get the functions exported by the corpora of the current corpus group.
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
Definition abg-corpus.h:95
virtual const elf_symbols & get_sorted_var_symbols() const
Getter for the sorted vector of variable symbols for this corpus.
const elf_symbol_sptr lookup_function_symbol(const string &n) const
Look in the function symbols map for a symbol with a given name.
origin
This abstracts where the corpus comes from. That is, either it has been read from the native xml form...
Definition abg-corpus.h:121
void sort_functions()
Sort the set of functions exported by this corpus.
void set_soname(const string &)
Setter for the soname property of the corpus.
const functions_set & get_undefined_functions() const
Getter of the undefined functions of the corpus.
const vector< string > & get_needed() const
Getter of the needed property of the corpus.
exported_decls_builder_sptr get_exported_decls_builder() const
Getter for the object that is responsible for determining what decls ought to be in the set of export...
void maybe_drop_some_exported_decls()
After the set of exported functions and variables have been built, consider all the tunables that con...
const string_elf_symbols_map_type & get_undefined_var_symbol_map() const
Getter for the map of variable symbols that are undefined in this corpus.
void add(const translation_unit_sptr &)
Add a translation unit to the current ABI Corpus.
std::unordered_set< const function_decl * > functions_set
Convenience typedef for std::unordered_set<const function_decl*>
Definition abg-corpus.h:104
virtual const string_elf_symbols_map_type & get_var_symbol_map() const
Getter for the variable symbols map.
shared_ptr< exported_decls_builder > exported_decls_builder_sptr
Convenience typedef for shared_ptr<exported_decls_builder>.
Definition abg-corpus.h:115
const variables & get_sorted_undefined_variables() const
Getter of the sorted vector of undefined variables of the corpus.
const elf_symbol_sptr lookup_variable_symbol(const string &n) const
Look in the variable symbols map for a symbol with a given name.
vector< var_decl_sptr > variables
Convenience typedef for std::vector<abigail::ir::var_decl*>
Definition abg-corpus.h:107
virtual const elf_symbols & get_sorted_fun_symbols() const
Return a sorted vector of function symbols for this corpus.
const string & get_soname()
Getter for the soname property of the corpus.
const translation_units & get_translation_units() const
Return the list of translation units of the current corpus.
const symtab_reader::symtab_sptr & get_symtab() const
Getter for the symtab object.
virtual const std::unordered_set< const function_decl * > * lookup_functions(const interned_string &id) const
Lookup the function which has a given function ID.
const variables_set & get_undefined_variables() const
Getter of the undefined variables of the corpus.
origin get_origin() const
Getter for the origin of the corpus.
virtual bool is_empty() const
Tests if the corpus is empty from an ABI surface perspective. I.e. if all of these criteria are true:
type_maps & get_types()
Get the maps that associate a name to a certain kind of type.
vector< string > & get_sym_ids_of_vars_to_keep()
Getter for the vector of variable symbol IDs to keep.
bool do_log() const
Test if logging was requested.
const translation_unit_sptr find_translation_unit(const string &path) const
Find the translation unit that has a given path.
const elf_symbols & get_sorted_undefined_fun_symbols() const
Getter for a sorted vector of the function symbols undefined in this corpus.
string & get_path() const
Get the file path associated to the corpus file.
const string_elf_symbols_map_type & get_undefined_fun_symbol_map() const
Getter for the map of function symbols that are undefined in this corpus.
void set_origin(origin)
Setter for the origin of the corpus.
virtual const string_elf_symbols_map_type & get_fun_symbol_map() const
Getter for the function symbols map.
bool operator==(const corpus &) const
Compare the current corpus against another one.
type_maps & get_type_per_loc_map()
Get the maps that associate a location string to a certain kind of type.
void drop_translation_units()
Erase the translation units contained in this in-memory object.
void sort_variables()
Sort the set of variables exported by this corpus.
vector< string > & get_regex_patterns_of_vars_to_keep()
Accessor for the regex patterns describing the variables to keep into the public decl table....
vector< string > & get_regex_patterns_of_vars_to_suppress()
Accessor for the regex patterns describing the variables to drop from the public decl table.
const corpus_group * get_group() const
Getter of the group this corpus is a member of.
vector< string > & get_regex_patterns_of_fns_to_suppress()
Accessor for the regex patterns describing the functions to drop from the public decl table.
const functions & get_sorted_undefined_functions() const
Getter of the sorted vector of undefined functions of the corpus.
const canonical_type_ptr_set_type & get_types_not_reachable_from_public_interfaces() const
Getter of a sorted vector of the types that are *NOT* reachable from public interfaces.
virtual const elf_symbols & get_unreferenced_function_symbols() const
Getter of the set of function symbols that are not referenced by any function exported by the current...
void set_path(const string &)
Set the file path associated to the corpus file.
virtual const elf_symbols & get_unreferenced_variable_symbols() const
Getter of the set of variable symbols that are not referenced by any variable exported by the current...
bool type_is_reachable_from_public_interfaces(const type_base &) const
Test if a type is reachable from public interfaces (global functions and variables).
virtual bool recording_types_reachable_from_public_interface_supported()
Test if the recording of reachable types (and thus, indirectly, the recording of non-reachable types)...
virtual const std::unordered_set< var_decl_sptr > * lookup_variables(const interned_string &id) const
Lookup the exported variables which all have a given variable ID.
virtual const variables & get_variables() const
Return the public decl table of the global variables of the current corpus.
const elf_symbols & get_sorted_undefined_var_symbols() const
Getter for a sorted vector of the variable symbols undefined in this corpus.
void set_needed(const vector< string > &)
Setter of the needed property of the corpus.
vector< string > & get_sym_ids_of_fns_to_keep()
Getter for the vector of function symbol IDs to keep.
vector< const function_decl * > functions
Convenience typedef for std::vector<abigail::ir::function_decl*>
Definition abg-corpus.h:101
void set_architecture_name(const string &)
Setter for the architecture name of the corpus.
bool record_type_as_reachable_from_public_interfaces(const type_base &)
Record a type as being reachable from public interfaces (global functions and variables).
void set_symtab(symtab_reader::symtab_sptr)
Setter for the symtab object.
void set_format_major_version_number(const string &)
Setter of the major version number of the abixml serialization format.
const string & get_architecture_name() const
Getter for the architecture name of the corpus.
vector< string > strings_type
A convenience typedef for std::vector<string>.
Definition abg-corpus.h:98
std::unordered_set< var_decl_sptr > variables_set
Convenience typedef for std::unordered_set<const var_decl*>.
Definition abg-corpus.h:110
const environment & get_environment() const
Getter of the enviroment of the corpus.
vector< string > & get_regex_patterns_of_fns_to_keep()
Accessor for the regex patterns describing the functions to keep into the public decl table....
void set_format_minor_version_number(const string &)
Setter of the minor version number of the abixml serialization format.
string & get_format_minor_version_number() const
Getter of the minor version number of the abixml serialization format.
virtual const functions & get_functions() const
Return the functions public decl table of the current corpus.
string & get_format_major_version_number() const
Getter of the major version number of the abixml serialization format.
virtual const interned_string & get_name() const
Getter for the name of the current decl.
Definition abg-ir.cc:5946
scope_decl_sptr get_scope() const
Return the type containing the current decl, if any.
Definition abg-ir.cc:5923
const interned_string & get_linkage_name() const
Getter for the mangled name.
Definition abg-ir.cc:5881
bool get_is_in_public_symbol_table() const
Test if the decl is defined in a ELF symbol table as a public symbol.
Definition abg-ir.cc:5670
The abstraction of the version of an ELF symbol.
Definition abg-ir.h:1230
const string & str() const
Getter for the version name.
Definition abg-ir.cc:3834
Abstraction of an elf symbol.
Definition abg-ir.h:959
const string & get_name() const
Getter for the name of the elf_symbol.
Definition abg-ir.cc:2687
version & get_version() const
Getter for the version of the current instanc of elf_symbol.
Definition abg-ir.cc:2768
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition abg-ir.h:216
Abstraction for a function declaration.
Definition abg-ir.h:3167
The base class for the visitor type hierarchy used for traversing a translation unit.
Definition abg-ir.h:4756
An abstraction helper for type declarations.
Definition abg-ir.h:2014
type_base * get_naked_canonical_type() const
Getter of the canonical type pointer.
Definition abg-ir.cc:17165
This is a type that aggregates maps of all the kinds of types that are supported by libabigail.
Definition abg-ir.h:593
const vector< type_base_wptr > & get_types_sorted() const
Getter of all types types sorted by their pretty representation.
Definition abg-ir.cc:1583
const corpus * get_corpus() const
Get the corpus this ABI artifact belongs to.
Definition abg-ir.cc:5243
Abstracts a variable declaration.
Definition abg-ir.h:3069
virtual string get_pretty_representation(bool internal=false, bool qualified_name=true) const
Build and return the pretty representation of this variable.
Definition abg-ir.cc:22525
Helper class to allow range-for loops on symtabs for C++11 and later code. It serves as a proxy for t...
hash_t peek_hash_value(const type_or_decl_base &artefact)
Get the hash value associated to an IR node.
Definition abg-ir.cc:30142
size_t get_canonical_type_index(const type_base &t)
Getter of the canonical type index of a given type.
Definition abg-ir.cc:492
corpus::origin operator|=(corpus::origin &l, corpus::origin r)
Bitwise |= operator for the corpus::origin type.
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition abg-ir.cc:12031
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition abg-ir.h:924
type_base_sptr get_exemplar_type(type_base_sptr type)
For a given type, return its exemplar type.
Definition abg-ir.cc:30277
bool is_class_type(const type_or_decl_base &t)
Test whether a type is a class.
Definition abg-ir.cc:12395
std::vector< elf_symbol_sptr > elf_symbols
Convenience typedef for a vector of elf_symbol.
Definition abg-ir.h:940
corpus_group_sptr is_corpus_group(const corpus_sptr &corpus)
Test if a corpus is a corpus_group.
class_or_union * is_class_or_union_type(const type_or_decl_base *t)
Test if a type is a class_or_union.
Definition abg-ir.cc:12626
unordered_map< string, const function_decl * > str_fn_ptr_map_type
Convenience typedef for a hash map of string and pointer to function_decl.
function_type_sptr is_function_type(const type_or_decl_base_sptr &t)
Test whether a type is a function_type.
Definition abg-ir.cc:13088
typedef_decl_sptr is_typedef(const type_or_decl_base_sptr t)
Test whether a type is a typedef.
Definition abg-ir.cc:12241
reference_type_def * is_reference_type(type_or_decl_base *t, bool look_through_qualifiers)
Test whether a type is a reference_type_def.
Definition abg-ir.cc:12881
corpus::origin operator|(corpus::origin l, corpus::origin r)
Bitwise | operator for the corpus::origin type.
unordered_map< const function_decl *, bool, function_decl::hash, function_decl::ptr_equal > fn_ptr_map_type
Convenience typedef for a hash map of pointer to function_decl and boolean.
const enum_type_decl * is_enum_type(const type_or_decl_base *d)
Test if a decl is an enum_type_decl.
Definition abg-ir.cc:12330
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition abg-fwd.h:257
corpus::origin operator&(corpus::origin l, corpus::origin r)
Bitwise & operator for the corpus::origin type.
shared_ptr< translation_unit > translation_unit_sptr
Convenience typedef for a shared pointer on a translation_unit type.
Definition abg-fwd.h:137
unordered_map< const var_decl *, bool, var_decl::hash, var_decl::ptr_equal > var_ptr_map_type
Convenience typedef for a hash map of pointer to var_decl and boolean.
bool is_member_function(const function_decl &f)
Test whether a function_decl is a member function.
Definition abg-ir.cc:7454
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition abg-ir.cc:11971
method_decl * is_method_decl(const type_or_decl_base *d)
Test if a function_decl is actually a method_decl.
Definition abg-ir.cc:26879
vector< type_base * > type_base_ptrs_type
Helper typedef for a vector of pointer to type_base.
Definition abg-ir.h:143
bool get_member_function_is_virtual(const function_decl &f)
Test if a given member function is virtual.
Definition abg-ir.cc:7742
const pointer_type_def * is_pointer_type(const type_or_decl_base *t, bool look_through_qualifiers)
Test whether a type is a pointer_type_def.
Definition abg-ir.cc:12709
class_or_union * look_through_decl_only_class(class_or_union *the_class)
If a class (or union) is a decl-only class, get its definition. Otherwise, just return the initial cl...
Definition abg-ir.cc:13148
const decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition abg-ir.cc:11414
array_type_def * is_array_type(const type_or_decl_base *type, bool look_through_qualifiers)
Test if a type is an array_type_def.
Definition abg-ir.cc:13353
std::set< translation_unit_sptr, shared_translation_unit_comp > translation_units
Convenience typedef for an ordered set of translation_unit_sptr.
Definition abg-ir.h:887
corpus::origin operator&=(corpus::origin &l, corpus::origin r)
Bitwise &= operator for the corpus::origin type.
qualified_type_def * is_qualified_type(const type_or_decl_base *t)
Test whether a type is a reference_type_def.
Definition abg-ir.cc:13068
std::unordered_map< string, elf_symbols > string_elf_symbols_map_type
Convenience typedef for a map which key is a string and which value is a vector of elf_symbol.
Definition abg-ir.h:945
unordered_set< const function_decl *, c11d_decl_hasher< function_decl >, c11d_decl_eq< function_decl > > functions_set_type
A set of hashed function decls. The hash value is the canonical type of the function....
Definition abg-corpus.h:69
unordered_set< type_base *, canonical_type_hash > canonical_type_ptr_set_type
Helper typedef for an unordered set of type_base* which uses pointer value to tell its members appart...
Definition abg-ir.h:140
std::shared_ptr< regex_t > regex_t_sptr
A convenience typedef for a shared pointer of regex_t.
Definition abg-fwd.h:84
Toplevel namespace for libabigail.
A functor to compare instances of var_decl base on their qualified names.
The private data of the corpus type.
const elf_symbols & get_sorted_var_symbols() const
Getter for the sorted vector of variable symbols for this corpus.
bool types_are_canonicalized() const
Getter of whether the types reachable from this ABI are canonicalized or not.
const string_elf_symbols_map_type & get_undefined_var_symbol_map() const
Return a map from name to undefined variable symbol for this corpus.
const string_elf_symbols_map_type & get_var_symbol_map() const
Return a map from name to variable symbol for this corpus.
const elf_symbols & get_sorted_fun_symbols() const
Return a sorted vector of function symbols for this corpus.
bool get_compute_non_reachable_types() const
Get the "compute-non-reachable-types' property of the corpus. When it's set to true,...
const std::unordered_set< const function_decl * > * lookup_functions(const interned_string &id)
Lookup the function which has a given function ID.
type_maps & get_types()
Get the maps that associate a name to a certain kind of type.
const elf_symbols & get_sorted_undefined_fun_symbols() const
Getter for a sorted vector of the function symbols undefined in this corpus.
const string_elf_symbols_map_type & get_undefined_fun_symbol_map() const
Return a map from name to undefined function symbol for this corpus.
const string_elf_symbols_map_type & get_fun_symbol_map() const
Return a map from name to function symbol for this corpus.
void remove_redundant_functions()
Remove redundant functions from the "fns" vector.
const elf_symbols & get_unreferenced_function_symbols() const
Return a list of symbols that are not referenced by any function of corpus::get_functions().
const elf_symbols & get_unreferenced_variable_symbols() const
Return a list of symbols that are not referenced by any variable of corpus::get_variables().
const elf_symbols & get_sorted_undefined_var_symbols() const
Getter for a sorted vector of the variable symbols undefined in this corpus.
~priv()
Destructor of the corpus::priv type.
void set_compute_non_reachable_types(bool f)
Set the "compute-non-reachable-types' property of the corpus. When it's set to true,...
recursive_mutex & get_mutex()
Getter of the recursive mutex of this corpus.
Equality functor for instances of function_decl.
Definition abg-ir.h:4713
A functor to sort types somewhat topologically. That is, types are sorted in a way that makes the one...
A comparison functor for pointers to var_decl.
Definition abg-ir.h:4692
A deleter for shared pointers that ... doesn't delete the object managed by the shared pointer.