libabigail
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-2025 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 
19 #include "abg-internal.h"
20 
21 // <headers defining libabigail's API go under here>
22 ABG_BEGIN_EXPORT_DECLARATIONS
23 
24 #include "abg-corpus.h"
25 #include "abg-ir.h"
26 #include "abg-reader.h"
27 #include "abg-sptr-utils.h"
28 #include "abg-symtab-reader.h"
29 #include "abg-tools-utils.h"
30 #include "abg-writer.h"
31 
33 // </headers defining libabigail's API>
34 
35 #include "abg-corpus-priv.h"
36 #include "abg-ir-priv.h"
37 
38 namespace abigail
39 {
40 
41 namespace ir
42 {
43 
44 using std::ostringstream;
45 using std::unordered_map;
46 using std::list;
47 using std::vector;
48 
50 
51 /// Constructor of @ref corpus::exported_decls_builder.
52 ///
53 /// @param fns a reference to the vector of exported functions.
54 ///
55 /// @param vars a reference to the vector of exported variables.
56 ///
57 /// @param fns_suppress_regexps the regular expressions that designate
58 /// the functions to suppress from the exported functions set.
59 ///
60 /// @param vars_suppress_regexps the regular expressions that designate
61 /// the variables to suppress from the exported variables set.
62 ///
63 /// @param fns_keep_regexps the regular expressions that designate the
64 /// functions to keep in the exported functions set.
65 ///
66 /// @param fns_keep_regexps the regular expressions that designate the
67 /// functions to keep in the exported functions set.
68 ///
69 /// @param vars_keep_regexps the regular expressions that designate
70 /// the variables to keep in the exported variables set.
71 ///
72 /// @param sym_id_of_fns_to_keep the IDs of the functions to keep in
73 /// the exported functions set.
74 ///
75 /// @param sym_id_of_vars_to_keep the IDs of the variables to keep in
76 /// the exported variables set.
77 corpus::exported_decls_builder
78 ::exported_decls_builder(functions& fns,
79  variables& vars,
80  strings_type& fns_suppress_regexps,
81  strings_type& vars_suppress_regexps,
82  strings_type& fns_keep_regexps,
83  strings_type& vars_keep_regexps,
84  strings_type& sym_id_of_fns_to_keep,
85  strings_type& sym_id_of_vars_to_keep)
86  : priv_(new priv(fns, vars,
87  fns_suppress_regexps,
88  vars_suppress_regexps,
89  fns_keep_regexps,
90  vars_keep_regexps,
91  sym_id_of_fns_to_keep,
92  sym_id_of_vars_to_keep))
93 {
94 }
95 
96 /// Getter for the reference to the vector of exported functions.
97 /// This vector is shared with with the @ref corpus. It's where the
98 /// set of exported function is ultimately stored.
99 ///
100 /// @return a reference to the vector of exported functions.
101 const corpus::functions&
103 {return priv_->fns_;}
104 
105 /// Getter for the reference to the vector of exported functions.
106 /// This vector is shared with with the @ref corpus. It's where the
107 /// set of exported function is ultimately stored.
108 ///
109 /// @return a reference to the vector of exported functions.
112 {return priv_->fns_;}
113 
114 /// Test if a given function ID maps to several functions in the same corpus.
115 ///
116 /// The magic of ELF symbol aliases makes it possible for an ELF
117 /// symbol alias to designate several different functions. This
118 /// function tests if the ELF symbol of a given function has a aliases
119 /// that designates another function or not.
120 ///
121 /// @param fn the function to consider.
122 ///
123 /// @return the set of functions designated by the ELF symbol of @p
124 /// fn, or nullptr if the function ID maps to just @p fn.
125 std::unordered_set<function_decl*>*
127 {
128  std::unordered_set<function_decl*> *fns_for_id =
129  priv_->fn_id_is_in_id_fns_map(fn);
130  if (fns_for_id && fns_for_id->size() > 1)
131  return fns_for_id;
132 
133  return nullptr;
134 }
135 
136 /// Getter for the reference to the vector of exported variables.
137 /// This vector is shared with with the @ref corpus. It's where the
138 /// set of exported variable is ultimately stored.
139 ///
140 /// @return a reference to the vector of exported variables.
141 const corpus::variables&
143 {return priv_->vars_;}
144 
145 /// Getter for the reference to the vector of exported variables.
146 /// This vector is shared with with the @ref corpus. It's where the
147 /// set of exported variable is ultimately stored.
148 ///
149 /// @return a reference to the vector of exported variables.
152 {return priv_->vars_;}
153 
154 /// Consider at all the tunables that control wether a function should
155 /// be added to the set of exported function and if it fits in, add
156 /// the function to that set.
157 ///
158 /// @param fn the function to add the set of exported functions.
159 ///
160 /// @return true iff the function was added to the set of exported
161 /// functions.
162 bool
164 {
166  return false;
167 
168  const string& fn_id = priv_->get_id(*fn);
169  ABG_ASSERT(!fn_id.empty());
170 
171  if (priv_->fn_is_in_id_fns_map(fn))
172  return false;
173 
174  if (priv_->keep_wrt_id_of_fns_to_keep(fn)
175  && priv_->keep_wrt_regex_of_fns_to_suppress(fn)
176  && priv_->keep_wrt_regex_of_fns_to_keep(fn))
177  {
178  priv_->add_fn_to_exported(fn);
179  return true;
180  }
181  return false;
182 }
183 
184 /// Consider at all the tunables that control wether a variable should
185 /// be added to the set of exported variable and if it fits in, add
186 /// the variable to that set.
187 ///
188 /// @param fn the variable to add the set of exported variables.
189 ///
190 /// @return true iff the variable was added to the set of exported
191 /// variables.
192 bool
194 {
195  if (!var->get_is_in_public_symbol_table())
196  return false;
197 
198  const interned_string& var_id = priv_->get_id(*var);
199  ABG_ASSERT(!var_id.empty());
200 
201  if (priv_->var_is_in_id_vars_map(var))
202  return false;
203 
204  if (priv_->keep_wrt_id_of_vars_to_keep(var)
205  && priv_->keep_wrt_regex_of_vars_to_suppress(var)
206  && priv_->keep_wrt_regex_of_vars_to_keep(var))
207  {
208  priv_->add_var_to_exported(var);
209  return true;
210  }
211  return false;
212 }
213 
214 // </corpus::exported_decls_builder>
215 
216 /// Convenience typedef for a hash map of pointer to function_decl and
217 /// boolean.
218 typedef unordered_map<const function_decl*,
219  bool,
222 
223 /// Convenience typedef for a hash map of string and pointer to
224 /// function_decl.
225 typedef unordered_map<string, const function_decl*> str_fn_ptr_map_type;
226 
227 /// Convenience typedef for a hash map of pointer to var_decl and boolean.
228 typedef unordered_map<const var_decl*,
229  bool,
232 
233 /// This is a comparison functor for comparing pointers to @ref
234 /// function_decl.
235 struct func_comp
236 {
237  /// The comparisong operator for pointers to @ref function_decl. It
238  /// performs a string comparison of the mangled names of the
239  /// functions. If the functions don't have mangled names, it
240  /// compares their names instead.
241  ///
242  /// @param first the first function to consider in the comparison.
243  ///
244  /// @param second the second function to consider in the comparison.
245  ///
246  /// @return true if the (mangled) name of the first function is less
247  /// than the (mangled)name of the second one, false otherwise.
248  bool
249  operator()(const function_decl* first,
250  const function_decl* second) const
251  {
252  ABG_ASSERT(first != 0 && second != 0);
253 
254  string first_name, second_name;
255  first_name = first->get_linkage_name();
256  if (first_name.empty())
257  first_name = first->get_name();
258  ABG_ASSERT(!first_name.empty());
259 
260  second_name = second->get_linkage_name();
261  if (second_name.empty())
262  second_name = second->get_name();
263  ABG_ASSERT(!second_name.empty());
264 
265  return first_name < second_name;
266  }
267 };
268 
269 /// This is a comparison functor for comparing pointers to @ref
270 /// var_decl.
271 struct var_comp
272 {
273  /// The comparison operator for pointers to @ref var_decl.
274  ///
275  /// It perform a string comparison on the names of the variables.
276  ///
277  /// @param first the first variable to consider for the comparison.
278  ///
279  /// @param second the second variable to consider for the comparison.
280  ///
281  /// @return true if first is less than second, false otherwise.
282  bool
283  operator()(const var_decl* first,
284  const var_decl* second) const
285  {
286  ABG_ASSERT(first != 0 && second != 0);
287 
288  string first_name, second_name;
289  first_name = first->get_linkage_name();
290  if (first_name.empty())
291  {
292  first_name = first->get_pretty_representation();
293  second_name = second->get_pretty_representation();
294  ABG_ASSERT(!second_name.empty());
295  }
296  ABG_ASSERT(!first_name.empty());
297 
298  if (second_name.empty())
299  second_name = second->get_linkage_name();
300 
301  if (second_name.empty())
302  {
303  second_name = second->get_pretty_representation();
304  first_name = first->get_pretty_representation();
305  ABG_ASSERT(!first_name.empty());
306  }
307  ABG_ASSERT(!second_name.empty());
308 
309  return first_name < second_name;
310  }
311 
312  bool
313  operator()(const var_decl_sptr& first,
314  const var_decl_sptr& second) const
315  {return operator()(first.get(), second.get());}
316 };
317 
318 /// A comparison functor to compare elf_symbols for the purpose of
319 /// sorting.
320 struct comp_elf_symbols_functor
321 {
322  bool
323  operator()(const elf_symbol& l,
324  const elf_symbol& r) const
325  {return l.get_id_string() < r.get_id_string();}
326 
327  bool
328  operator()(const elf_symbol_sptr l,
329  const elf_symbol_sptr r) const
330  {return operator()(*l, *r);}
331 }; // end struct comp_elf_symbols_functor
332 
333 
334 // <corpus stuff>
335 
336 /// Get the maps that associate a name to a certain kind of type.
337 type_maps&
339 {return types_;}
340 
341 /// Get the maps that associate a name to a certain kind of type.
342 const type_maps&
344 {return types_;}
345 
346 /// Return a sorted vector of function symbols for this corpus.
347 ///
348 /// Note that the first time this function is called, the symbols are
349 /// sorted and cached. Subsequent invocations of this function return
350 /// the cached vector that was built previously.
351 ///
352 /// @return the sorted list of function symbols.
353 const elf_symbols&
355 {
356  if (!sorted_fun_symbols)
357  {
358  if (symtab_)
359  {
360  auto filter = symtab_->make_filter();
361  filter.set_functions();
362  sorted_fun_symbols = elf_symbols(symtab_->begin(filter),
363  symtab_->end());
364  }
365  else
366  sorted_fun_symbols = elf_symbols();
367  }
368  return *sorted_fun_symbols;
369 }
370 
371 /// Return a map from name to function symbol for this corpus.
372 ///
373 /// Note that the first time this function is called, the map is built.
374 /// Subsequent invocations of this function return the cached map that was
375 /// built previously.
376 ///
377 /// @return the name function symbol map
380 {
381  if (!fun_symbol_map)
382  {
383  fun_symbol_map = string_elf_symbols_map_type();
384  for (const auto& symbol : get_sorted_fun_symbols())
385  (*fun_symbol_map)[symbol->get_name()].push_back(symbol);
386  }
387  return *fun_symbol_map;
388 }
389 
390 /// Getter for a sorted vector of the function symbols undefined in
391 /// this corpus.
392 ///
393 /// @return a vector of the function symbols undefined in this corpus,
394 /// sorted by name and then version.
395 const elf_symbols&
397 {
398  if (!sorted_undefined_fun_symbols)
399  {
400  if (symtab_)
401  {
402  auto filter = symtab_->make_filter();
403  filter.set_functions();
404  filter.set_undefined_symbols();
405  filter.set_public_symbols(false);
406 
407  sorted_undefined_fun_symbols =
408  elf_symbols(symtab_->begin(filter), symtab_->end());
409  }
410  else
411  sorted_undefined_fun_symbols = elf_symbols();
412  }
413  return *sorted_undefined_fun_symbols;
414 }
415 
416 /// Return a map from name to undefined function symbol for this corpus.
417 ///
418 /// Note that the first time this function is called, the map is built.
419 /// Subsequent invocations of this function return the cached map that was
420 /// built previously.
421 ///
422 /// @return the name function symbol map for undefined symbols
425 {
426  if (!undefined_fun_symbol_map)
427  {
428  undefined_fun_symbol_map = string_elf_symbols_map_type();
429  for (const auto& symbol : get_sorted_undefined_fun_symbols())
430  (*undefined_fun_symbol_map)[symbol->get_name()].push_back(symbol);
431  }
432  return *undefined_fun_symbol_map;
433 }
434 
435 /// Return a list of symbols that are not referenced by any function of
436 /// corpus::get_functions().
437 ///
438 /// Note that this function considers the list of function symbols to keep,
439 /// that is provided by corpus::get_sym_ids_of_fns_to_keep(). If a given
440 /// unreferenced function symbol is not in the list of functions to keep, then
441 /// that symbol is dropped and will not be part of the resulting table of
442 /// unreferenced symbol that is built.
443 ///
444 /// @return list of symbols that are not referenced by any function
445 const elf_symbols&
447 {
448  if (!unrefed_fun_symbols)
449  {
450  unrefed_fun_symbols = elf_symbols();
451  if (symtab_)
452  {
453  unordered_map<string, bool> refed_funs;
454 
455  for (const auto& function : fns)
456  if (elf_symbol_sptr sym = function->get_symbol())
457  {
458  refed_funs[sym->get_id_string()] = true;
459  for (elf_symbol_sptr a = sym->get_next_alias();
460  a && !a->is_main_symbol(); a = a->get_next_alias())
461  refed_funs[a->get_id_string()] = true;
462  }
463 
464  auto filter = symtab_->make_filter();
465  filter.set_functions();
466  for (const auto& symbol :
467  symtab_reader::filtered_symtab(*symtab_, filter))
468  {
469  const std::string sym_id = symbol->get_id_string();
470  if (refed_funs.find(sym_id) == refed_funs.end())
471  {
472  bool keep = sym_id_fns_to_keep.empty();
473  for (const auto& id : sym_id_fns_to_keep)
474  {
475  if (id == sym_id)
476  {
477  keep = true;
478  break;
479  }
480  }
481  if (keep)
482  unrefed_fun_symbols->push_back(symbol);
483  }
484  }
485  }
486  }
487  return *unrefed_fun_symbols;
488 }
489 
490 /// Getter for the sorted vector of variable symbols for this corpus.
491 ///
492 /// Note that the first time this function is called, it computes the
493 /// sorted vector, caches the result and returns it. Subsequent
494 /// invocations of this function just return the cached vector.
495 ///
496 /// @return the sorted vector of variable symbols for this corpus.
497 const elf_symbols&
499 {
500  if (!sorted_var_symbols)
501  {
502  if (symtab_)
503  {
504  auto filter = symtab_->make_filter();
505  filter.set_variables();
506 
507  sorted_var_symbols = elf_symbols(symtab_->begin(filter),
508  symtab_->end());
509  }
510  else
511  sorted_var_symbols = elf_symbols();
512  }
513  return *sorted_var_symbols;
514 }
515 
516 /// Return a map from name to variable symbol for this corpus.
517 ///
518 /// Note that the first time this function is called, the map is built.
519 /// Subsequent invocations of this function return the cached map that was
520 /// built previously.
521 ///
522 /// @return the name variable symbol map
525 {
526  if (!var_symbol_map)
527  {
528  var_symbol_map = string_elf_symbols_map_type();
529  for (const auto& symbol : get_sorted_var_symbols())
530  (*var_symbol_map)[symbol->get_name()].push_back(symbol);
531  }
532  return *var_symbol_map;
533 }
534 
535 /// Getter for a sorted vector of the variable symbols undefined in
536 /// this corpus.
537 ///
538 /// @return a vector of the variable symbols undefined in this corpus,
539 /// sorted by name and then version.
540 const elf_symbols&
542 {
543  if (!sorted_undefined_var_symbols)
544  {
545  if (symtab_)
546  {
547  auto filter = symtab_->make_filter();
548  filter.set_variables();
549  filter.set_undefined_symbols();
550  filter.set_public_symbols(false);
551 
552  sorted_undefined_var_symbols =
553  elf_symbols(symtab_->begin(filter), symtab_->end());
554  }
555  else
556  sorted_undefined_var_symbols = elf_symbols();
557  }
558  return *sorted_undefined_var_symbols;
559 }
560 
561 /// Return a map from name to undefined variable symbol for this corpus.
562 ///
563 /// Note that the first time this function is called, the map is built.
564 /// Subsequent invocations of this function return the cached map that was
565 /// built previously.
566 ///
567 /// @return the name undefined variable symbol map
570 {
571  if (!undefined_var_symbol_map)
572  {
573  undefined_var_symbol_map = string_elf_symbols_map_type();
574  for (const auto& symbol : get_sorted_undefined_var_symbols())
575  (*undefined_var_symbol_map)[symbol->get_name()].push_back(symbol);
576  }
577  return *undefined_var_symbol_map;
578 }
579 
580 /// Return a list of symbols that are not referenced by any variable of
581 /// corpus::get_variables().
582 ///
583 /// Note that this function considers the list of variable symbols to keep,
584 /// that is provided by corpus::get_sym_ids_of_vars_to_keep(). If a given
585 /// unreferenced variable symbol is not in the list of variable to keep, then
586 /// that symbol is dropped and will not be part of the resulting table of
587 /// unreferenced symbol that is built.
588 ///
589 /// @return list of symbols that are not referenced by any variable
590 const elf_symbols&
592 {
593  if (!unrefed_var_symbols)
594  {
595  unrefed_var_symbols = elf_symbols();
596  if (symtab_)
597  {
598  unordered_map<string, bool> refed_vars;
599  for (const auto& variable : vars)
600  if (elf_symbol_sptr sym = variable->get_symbol())
601  {
602  refed_vars[sym->get_id_string()] = true;
603  for (elf_symbol_sptr a = sym->get_next_alias();
604  a && !a->is_main_symbol(); a = a->get_next_alias())
605  refed_vars[a->get_id_string()] = true;
606  }
607 
608  auto filter = symtab_->make_filter();
609  filter.set_variables();
610  for (const auto& symbol :
611  symtab_reader::filtered_symtab(*symtab_, filter))
612  {
613  const std::string sym_id = symbol->get_id_string();
614  if (refed_vars.find(sym_id) == refed_vars.end())
615  {
616  bool keep = sym_id_vars_to_keep.empty();
617  for (const auto& id : sym_id_vars_to_keep)
618  {
619  if (id == sym_id)
620  {
621  keep = true;
622  break;
623  }
624  }
625  if (keep)
626  unrefed_var_symbols->push_back(symbol);
627  }
628  }
629  }
630  }
631  return *unrefed_var_symbols;
632 }
633 
634 
635 /// Getter of the set of pretty representation of types that are
636 /// reachable from public interfaces (global functions and variables).
637 ///
638 /// @return the set of pretty representation of types that are
639 /// reachable from public interfaces (global functions and variables).
640 unordered_set<interned_string, hash_interned_string>*
642 {
643  if (group)
644  return group->get_public_types_pretty_representations();
645 
646  if (pub_type_pretty_reprs_ == 0)
647  pub_type_pretty_reprs_ =
648  new unordered_set<interned_string, hash_interned_string>;
649  return pub_type_pretty_reprs_;
650 }
651 
652 /// Lookup the function which has a given function ID.
653 ///
654 /// Note that there can have been several functions with the same ID.
655 /// This is because debug info can declare the same function in
656 /// several different translation units. Normally, all these function
657 /// should be equal. But still, this function returns all these
658 /// functions.
659 ///
660 /// @param id the ID of the function to lookup. This ID must be
661 /// either the result of invoking function::get_id() of
662 /// elf_symbol::get_id_string().
663 ///
664 /// @return the set of functions which ID is @p id, or nil if no
665 /// function with that ID was found.
666 std::unordered_set<function_decl*>*
668 {
670  if (b)
671  {
672  auto i = b->priv_->id_fns_map_.find(id);
673  if (i == b->priv_->id_fns_map_.end())
674  return 0;
675  return &i->second;
676  }
677  return nullptr;
678 }
679 
680 /// Destructor of the @ref corpus::priv type.
682 {
683  delete pub_type_pretty_reprs_;
684 }
685 
686 /// Constructor of the @ref corpus type.
687 ///
688 /// @param env the environment of the corpus.
689 ///
690 /// @param path the path to the file containing the ABI corpus.
691 corpus::corpus(const ir::environment& env, const string& path)
692 {
693  priv_.reset(new priv(path, env));
694  init_format_version();
695 }
696 
697 corpus::~corpus() = default;
698 
699 /// Getter of the enviroment of the corpus.
700 ///
701 /// @return the environment of this corpus.
702 const environment&
704 {return priv_->env;}
705 
706 /// Test if logging was requested.
707 ///
708 /// @return true iff logging was requested.
709 bool
711 {return priv_->do_log;}
712 
713 /// Request logging, or not.
714 ///
715 /// @param f true iff logging is requested.
716 void
718 {priv_->do_log = f;}
719 
720 /// Add a translation unit to the current ABI Corpus.
721 ///
722 /// Note that two translation units with the same path (as returned by
723 /// translation_unit::get_path) cannot be added to the same @ref
724 /// corpus. If that happens, the library aborts.
725 ///
726 /// @param tu the new translation unit to add.
727 void
729 {
730  ABG_ASSERT(priv_->members.insert(tu).second);
731 
732  // Update the path -> translation_unit map.
733  string_tu_map_type::const_iterator i =
734  priv_->path_tu_map.find(tu->get_absolute_path());
735  ABG_ASSERT(i == priv_->path_tu_map.end());
736  priv_->path_tu_map[tu->get_absolute_path()] = tu;
737 
738  tu->set_corpus(this);
739 }
740 
741 /// Return the list of translation units of the current corpus.
742 ///
743 /// @return the list of translation units of the current corpus.
744 const translation_units&
746 {return priv_->members;}
747 
748 /// Find the translation unit that has a given path.
749 ///
750 /// @param path the path of the translation unit to look for.
751 ///
752 /// @return the translation unit found, if any. Otherwise, return
753 /// nil.
755 corpus::find_translation_unit(const string &path) const
756 {
757  string_tu_map_type::const_iterator i =
758  priv_->path_tu_map.find(path);
759 
760  if (i == priv_->path_tu_map.end())
761  return translation_unit_sptr();
762  return i->second;
763 }
764 
765 /// Erase the translation units contained in this in-memory object.
766 ///
767 /// Note that the on-disk archive file that contains the serialized
768 /// representation of this object is not modified.
769 void
771 {priv_->members.clear();}
772 
773 /// Get the maps that associate a name to a certain kind of type.
774 ///
775 /// @return the maps that associate a name to a certain kind of type.
776 type_maps&
778 {return priv_->types_;}
779 
780 /// Get the maps that associate a name to a certain kind of type.
781 ///
782 /// @return the maps that associate a name to a certain kind of
783 /// type.
784 const type_maps&
786 {return priv_->types_;}
787 
788 /// Get the maps that associate a location string to a certain kind of
789 /// type.
790 ///
791 /// The location string is the result of the invocation to the
792 /// function abigail::ir::location::expand(). It has the form
793 /// "file.c:4:1", with 'file.c' being the file name, '4' being the
794 /// line number and '1' being the column number.
795 ///
796 /// @return the maps.
797 const type_maps&
799 {return priv_->type_per_loc_map_;}
800 
801 /// Test if the recording of reachable types (and thus, indirectly,
802 /// the recording of non-reachable types) is activated for the
803 /// current @ref corpus.
804 ///
805 /// @return true iff the recording of reachable types is activated for
806 /// the current @ref corpus.
807 bool
809 {
810  return (priv_->get_public_types_pretty_representations()
811  && !priv_->get_public_types_pretty_representations()->empty());
812 }
813 
814 /// Record a type as being reachable from public interfaces (global
815 /// functions and variables).
816 ///
817 /// @param t the type to record as reachable.
818 void
820 {
821  string repr = get_pretty_representation(&t, /*internal=*/false);
822  interned_string s = t.get_environment().intern(repr);
823  priv_->get_public_types_pretty_representations()->insert(s);
824 }
825 
826 /// Test if a type is reachable from public interfaces (global
827 /// functions and variables).
828 ///
829 /// For a type to be considered reachable from public interfaces, it
830 /// must have been previously marked as such by calling
831 /// corpus::record_type_as_reachable_from_public_interfaces.
832 ///
833 /// @param t the type to test for.
834 ///
835 /// @return true iff @p t is reachable from public interfaces.
836 bool
838 {
839  string repr = get_pretty_representation(&t, /*internal=*/false);
840  interned_string s = t.get_environment().intern(repr);
841 
842  return (priv_->get_public_types_pretty_representations()->find(s)
843  != priv_->get_public_types_pretty_representations()->end());
844 }
845 
846 /// Getter of a sorted vector of the types that are *NOT* reachable
847 /// from public interfaces.
848 ///
849 /// Note that for this to be non-empty, the libabigail reader that
850 /// analyzed the input (be it a binary or an abixml file) must have be
851 /// configured to load types that are not reachable from public
852 /// interfaces.
853 ///
854 /// @return a reference to a vector of sorted types NON reachable from
855 /// public interfaces.
856 const vector<type_base_wptr>&
858 {
859  if (priv_->types_not_reachable_from_pub_ifaces_.empty())
860  {
861  const type_maps& types = get_types();
862  for (vector<type_base_wptr>::const_iterator it =
863  types.get_types_sorted_by_name().begin();
864  it != types.get_types_sorted_by_name().end();
865  ++it)
866  {
867  type_base_sptr t(*it);
869  priv_->types_not_reachable_from_pub_ifaces_.push_back(t);
870  }
871  }
872 
873  return priv_->types_not_reachable_from_pub_ifaces_;
874 }
875 
876 /// Get the maps that associate a location string to a certain kind of
877 /// type.
878 ///
879 /// The location string is the result of the invocation to the
880 /// function abigail::ir::location::expand(). It has the form
881 /// "file.c:4:1", with 'file.c' being the file name, '4' being the
882 /// line number and '1' being the column number.
883 ///
884 /// @return the maps.
885 type_maps&
887 {return priv_->type_per_loc_map_;}
888 
889 /// Getter of the group this corpus is a member of.
890 ///
891 /// @return the group this corpus is a member of, or nil if it's not
892 /// part of any @ref corpus_group.
893 const corpus_group*
895 {return priv_->group;}
896 
897 /// Getter of the group this corpus belongs to.
898 ///
899 /// @return the group this corpus belong to, or nil if it's not part
900 /// of any @ref corpus_group.
903 {return priv_->group;}
904 
905 /// Setter of the group this corpus belongs to.
906 ///
907 /// @param g the new group.
908 void
909 corpus::set_group(corpus_group* g)
910 {priv_->group = g;}
911 
912 /// Initialize the abixml serialization format version number of the
913 /// corpus.
914 ///
915 /// This function sets the format version number ot the default one
916 /// supported by the current version of Libabigail.
917 void
918 corpus::init_format_version()
919 {
921  (priv_->env.get_config().get_format_major_version_number());
923  (priv_->env.get_config().get_format_minor_version_number());
924 }
925 
926 /// Getter for the origin of the corpus.
927 ///
928 /// @return the origin of the corpus.
931 {return priv_->origin_;}
932 
933 /// Setter for the origin of the corpus.
934 ///
935 /// @param o the new origin for the corpus.
936 void
938 {priv_->origin_ = o;}
939 
940 /// Getter of the major version number of the abixml serialization
941 /// format.
942 ///
943 /// @return the major version number of the abixml format.
944 string&
946 {return priv_->format_major_version_number_;}
947 
948 /// Setter of the major version number of the abixml serialization
949 /// format.
950 ///
951 /// @param maj the new major version numberof the abixml format.
952 void
954 {priv_->format_major_version_number_ = maj;}
955 
956 /// Getter of the minor version number of the abixml serialization
957 /// format.
958 ///
959 /// @return the minor version number of the abixml serialization
960 /// format.
961 string&
963 {return priv_->format_minor_version_number_;}
964 
965 /// Setter of the minor version number of the abixml serialization
966 /// format.
967 ///
968 /// @param min the new minor version number of the abixml
969 /// serialization format.
970 void
972 {priv_->format_minor_version_number_ = min;}
973 
974 /// Get the file path associated to the corpus file.
975 ///
976 /// A subsequent call to corpus::read will deserialize the content of
977 /// the abi file expected at this path; likewise, a call to
978 /// corpus::write will serialize the translation units contained in
979 /// the corpus object into the on-disk file at this path.
980 ///
981 /// @return the file path associated to the current corpus.
982 string&
984 {return priv_->path;}
985 
986 /// Set the file path associated to the corpus file.
987 ///
988 /// A subsequent call to corpus::read will deserialize the content of
989 /// the abi file expected at this path; likewise, a call to
990 /// corpus::write will serialize the translation units contained in
991 /// the corpus object into the on-disk file at this path.
992 ///
993 /// @param path the new file path to assciate to the current corpus.
994 void
995 corpus::set_path(const string& path)
996 {priv_->path = path;}
997 
998 /// Getter of the needed property of the corpus.
999 ///
1000 /// This property is meaningful for, e.g, corpora built from ELF
1001 /// shared library files. In that case, this is a vector of names of
1002 /// dependencies of the ELF shared library file.
1003 ///
1004 /// @return the vector of dependencies needed by this corpus.
1005 const vector<string>&
1007 {return priv_->needed;}
1008 
1009 /// Setter of the needed property of the corpus.
1010 ///
1011 /// This property is meaningful for, e.g, corpora built from ELF
1012 /// shared library files. In that case, this is a vector of names of
1013 /// dependencies of the ELF shared library file.
1014 ///
1015 /// @param needed the new vector of dependencies needed by this
1016 /// corpus.
1017 void
1018 corpus::set_needed(const vector<string>& needed)
1019 {priv_->needed = needed;}
1020 
1021 /// Getter for the soname property of the corpus.
1022 ///
1023 /// This property is meaningful for, e.g, corpora built from ELF
1024 /// shared library files. In that case, this is the shared object
1025 /// name exported by the shared library.
1026 ///
1027 /// @return the soname property of the corpus.
1028 const string&
1030 {return priv_->soname;}
1031 
1032 /// Setter for the soname property of the corpus.
1033 ///
1034 /// This property is meaningful for, e.g, corpora built from ELF
1035 /// shared library files. In that case, this is the shared object
1036 /// name exported by the shared library.
1037 ///
1038 /// @param soname the new soname property of the corpus.
1039 void
1040 corpus::set_soname(const string& soname)
1041 {priv_->soname = soname;}
1042 
1043 /// Getter for the architecture name of the corpus.
1044 ///
1045 /// This property is meaningful for e.g, corpora built from ELF shared
1046 /// library files. In that case, this is a string representation of
1047 /// the Elf{32,64}_Ehdr::e_machine field.
1048 ///
1049 /// @return the architecture name string.
1050 const string&
1052 {return priv_->architecture_name;}
1053 
1054 /// Setter for the architecture name of the corpus.
1055 ///
1056 /// This property is meaningful for e.g, corpora built from ELF shared
1057 /// library files. In that case, this is a string representation of
1058 /// the Elf{32,64}_Ehdr::e_machine field.
1059 ///
1060 /// @param arch the architecture name string.
1061 void
1063 {priv_->architecture_name = arch;}
1064 
1065 /// Tests if the corpus is empty from an ABI surface perspective. I.e. if all
1066 /// of these criteria are true:
1067 /// - all translation units (members) are empty
1068 /// - the maps function and variable symbols are not having entries
1069 /// - for shared libraries:
1070 /// - the soname is empty
1071 /// - there are no DT_NEEDED entries
1072 ///
1073 /// @return true if the corpus contains no translation unit.
1074 bool
1076 {
1077  bool members_empty = true;
1078  for (translation_units::const_iterator i = priv_->members.begin(),
1079  e = priv_->members.end();
1080  i != e; ++i)
1081  {
1082  if (!(*i)->is_empty())
1083  {
1084  members_empty = false;
1085  break;
1086  }
1087  }
1088  return (members_empty
1089  && (!get_symtab() || !get_symtab()->has_symbols())
1090  && priv_->soname.empty()
1091  && priv_->needed.empty()
1092  && priv_->architecture_name.empty()
1093  && !priv_->group);
1094 }
1095 
1096 /// Compare the current @ref corpus against another one.
1097 ///
1098 /// @param other the other corpus to compare against.
1099 ///
1100 /// @return true if the two corpus are equal, false otherwise.
1101 bool
1102 corpus::operator==(const corpus& other) const
1103 {
1104  translation_units::const_iterator i, j;
1105  for (i = get_translation_units().begin(),
1106  j = other.get_translation_units().begin();
1107  (i != get_translation_units().end()
1108  && j != other.get_translation_units().end());
1109  ++i, ++j)
1110  if ((**i) != (**j))
1111  return false;
1112 
1113  return (i == get_translation_units().end()
1114  && j == other.get_translation_units().end());
1115 }
1116 
1117 /// Setter for the symtab object.
1118 ///
1119 /// @param symtab a shared pointer to the new symtab object
1120 void
1121 corpus::set_symtab(symtab_reader::symtab_sptr symtab)
1122 {priv_->symtab_ = symtab;}
1123 
1124 /// Getter for the symtab object.
1125 ///
1126 /// @return a shared pointer to the symtab object
1127 const symtab_reader::symtab_sptr&
1129 {return priv_->symtab_;}
1130 
1131 /// Getter for the function symbols map.
1132 ///
1133 /// @return a reference to the function symbols map.
1136 {return priv_->get_fun_symbol_map();}
1137 
1138 /// Getter for the map of function symbols that are undefined in this
1139 /// corpus.
1140 ///
1141 /// @return the map of function symbols not defined in this corpus.
1142 /// The key of the map is the name of the function symbol. The value
1143 /// is a vector of all the function symbols that have the same name.
1146 {return priv_->get_undefined_fun_symbol_map();}
1147 
1148 /// Return a sorted vector of function symbols for this corpus.
1149 ///
1150 /// Note that the first time this function is called, the symbols are
1151 /// sorted and cached. Subsequent invocations of this function return
1152 /// the cached vector that was built previously.
1153 ///
1154 /// @return the sorted list of function symbols.
1155 const elf_symbols&
1157 {return priv_->get_sorted_fun_symbols();}
1158 
1159 /// Getter for a sorted vector of the function symbols undefined in
1160 /// this corpus.
1161 ///
1162 /// @return a vector of the function symbols undefined in this corpus,
1163 /// sorted by name and then version.
1164 const elf_symbols&
1166 {return priv_->get_sorted_undefined_fun_symbols();}
1167 
1168 /// Getter for the sorted vector of variable symbols for this corpus.
1169 ///
1170 /// Note that the first time this function is called, it computes the
1171 /// sorted vector, caches the result and returns it. Subsequent
1172 /// invocations of this function just return the cached vector.
1173 ///
1174 /// @return the sorted vector of variable symbols for this corpus.
1175 const elf_symbols&
1177 {return priv_->get_sorted_var_symbols();}
1178 
1179 /// Getter for a sorted vector of the variable symbols undefined in
1180 /// this corpus.
1181 ///
1182 /// @return a vector of the variable symbols undefined in this corpus,
1183 /// sorted by name and then version.
1184 const elf_symbols&
1186 {return priv_->get_sorted_undefined_var_symbols();}
1187 
1188 /// Getter for the variable symbols map.
1189 ///
1190 /// @return a reference to the variabl symbols map.
1193 {return priv_->get_var_symbol_map();}
1194 
1195 /// Getter for the map of variable symbols that are undefined in this
1196 /// corpus.
1197 ///
1198 /// @return the map of variable symbols not defined in this corpus.
1199 /// The key of the map is the name of the variable symbol. The value
1200 /// is a vector of all the variable symbols that have the same name.
1203 {return priv_->get_undefined_var_symbol_map();}
1204 
1205 /// Look in the function symbols map for a symbol with a given name.
1206 ///
1207 /// @param n the name of the symbol to look for.
1208 ///
1209 /// return the first symbol with the name @p n.
1210 const elf_symbol_sptr
1211 corpus::lookup_function_symbol(const string& n) const
1212 {
1213  if (get_fun_symbol_map().empty() && get_undefined_fun_symbol_map().empty())
1214  return elf_symbol_sptr();
1215 
1216  string_elf_symbols_map_type::const_iterator it = get_fun_symbol_map().find(n);
1217  if ( it == get_fun_symbol_map().end())
1218  {
1219  it = get_undefined_fun_symbol_map().find(n);
1220  if (it == get_undefined_fun_symbol_map().end())
1221  return elf_symbol_sptr();
1222  }
1223  return it->second[0];
1224 }
1225 
1226 /// Look into a set of symbols and look for a symbol that has a given
1227 /// version.
1228 ///
1229 /// This is a sub-routine for corpus::lookup_function_symbol() and
1230 /// corpus::lookup_variable_symbol().
1231 ///
1232 /// @param version the version of the symbol to look for.
1233 ///
1234 /// @param symbols the set of symbols to consider.
1235 ///
1236 /// @return the symbol found, or nil if none was found.
1237 static const elf_symbol_sptr
1238 find_symbol_by_version(const elf_symbol::version& version,
1239  const vector<elf_symbol_sptr>& symbols)
1240 {
1241  if (version.is_empty())
1242  {
1243  // We are looing for a symbol with no version.
1244 
1245  // So first look for possible aliases with no version
1246  for (elf_symbols::const_iterator s = symbols.begin();
1247  s != symbols.end();
1248  ++s)
1249  if ((*s)->get_version().is_empty())
1250  return *s;
1251 
1252  // Or, look for a version that is a default one!
1253  for (elf_symbols::const_iterator s = symbols.begin();
1254  s != symbols.end();
1255  ++s)
1256  if ((*s)->get_version().is_default())
1257  return *s;
1258  }
1259  else
1260  // We are looking for a symbol with a particular defined version.
1261  for (elf_symbols::const_iterator s = symbols.begin();
1262  s != symbols.end();
1263  ++s)
1264  if ((*s)->get_version().str() == version.str())
1265  return *s;
1266 
1267  return elf_symbol_sptr();
1268 }
1269 
1270 /// Look in the function symbols map for a symbol with a given name.
1271 ///
1272 /// @param symbol_name the name of the symbol to look for.
1273 ///
1274 /// @param version the version of the symbol to look for.
1275 ///
1276 /// return the symbol with name @p symbol_name and with version @p
1277 /// version, or nil if no symbol has been found with that name and
1278 /// version.
1279 const elf_symbol_sptr
1280 corpus::lookup_function_symbol(const string& symbol_name,
1281  const elf_symbol::version& version) const
1282 {
1283  if (get_fun_symbol_map().empty() && get_undefined_fun_symbol_map().empty())
1284  return elf_symbol_sptr();
1285 
1286  string_elf_symbols_map_type::const_iterator it =
1287  get_fun_symbol_map().find(symbol_name);
1288  if ( it == get_fun_symbol_map().end())
1289  {
1290  it = get_undefined_fun_symbol_map().find(symbol_name);
1291  if (it == get_undefined_fun_symbol_map().end())
1292  return elf_symbol_sptr();
1293  }
1294 
1295  return find_symbol_by_version(version, it->second);
1296 }
1297 
1298 /// Look in the function symbols map for a symbol with the same name
1299 /// and version as a given symbol.
1300 ///
1301 /// @param symbol the symbol to look for.
1302 ///
1303 /// return the symbol with the same name and version as @p symbol.
1304 const elf_symbol_sptr
1306 {return lookup_function_symbol(symbol.get_name(), symbol.get_version());}
1307 
1308 /// Look in the variable symbols map for a symbol with a given name.
1309 ///
1310 /// @param n the name of the symbol to look for.
1311 ///
1312 /// return the first symbol with the name @p n.
1313 const elf_symbol_sptr
1314 corpus::lookup_variable_symbol(const string& n) const
1315 {
1316  if (get_var_symbol_map().empty() && get_undefined_var_symbol_map().empty())
1317  return elf_symbol_sptr();
1318 
1319  string_elf_symbols_map_type::const_iterator it = get_var_symbol_map().find(n);
1320  if ( it == get_var_symbol_map().end())
1321  {
1322  it = get_undefined_var_symbol_map().find(n);
1323  if (it == get_undefined_var_symbol_map().end())
1324  return elf_symbol_sptr();
1325  }
1326  return it->second[0];
1327 }
1328 
1329 /// Look in the variable symbols map for a symbol with a given name.
1330 ///
1331 /// @param symbol_name the name of the symbol to look for.
1332 ///
1333 /// @param symbol_version the version of the symbol to look for.
1334 ///
1335 /// return the first symbol with the name @p symbol_name and with
1336 /// version @p version.
1337 const elf_symbol_sptr
1338 corpus::lookup_variable_symbol(const string& symbol_name,
1339  const elf_symbol::version& version) const
1340 {
1341  if (get_var_symbol_map().empty() && get_undefined_var_symbol_map().empty())
1342  return elf_symbol_sptr();
1343 
1344  string_elf_symbols_map_type::const_iterator it =
1345  get_var_symbol_map().find(symbol_name);
1346  if ( it == get_var_symbol_map().end())
1347  {
1348  it = get_undefined_var_symbol_map().find(symbol_name);
1349  if (it == get_undefined_var_symbol_map().end())
1350  return elf_symbol_sptr();
1351  }
1352 
1353  return find_symbol_by_version(version, it->second);
1354 }
1355 
1356 /// Look in the variable symbols map for a symbol with the same name
1357 /// and version as a given symbol.
1358 ///
1359 /// @param symbol the symbol to look for.
1360 ///
1361 /// return the symbol with the same name and version as @p symbol.
1362 const elf_symbol_sptr
1364 {return lookup_variable_symbol(symbol.get_name(), symbol.get_version());}
1365 
1366 /// Return the functions public decl table of the current corpus.
1367 ///
1368 /// The function public decl tables is a vector of all the functions
1369 /// and member functions found in the current corpus.
1370 ///
1371 /// Note that the caller can suppress some functions from the vector
1372 /// supplying regular expressions describing the set of functions she
1373 /// want to see removed from the public decl table by populating the
1374 /// vector of regular expressions returned by
1375 /// corpus::get_regex_patterns_of_fns_to_suppress().
1376 ///
1377 /// @return the vector of functions of the public decl table. The
1378 /// functions are sorted using their mangled name or name if they
1379 /// don't have mangle names.
1380 const corpus::functions&
1382 {return priv_->fns;}
1383 
1384 /// Lookup the function which has a given function ID.
1385 ///
1386 /// Note that there can have been several functions with the same ID.
1387 /// This is because debug info can declare the same function in
1388 /// several different translation units. Normally, all these function
1389 /// should be equal. But still, this function returns all these
1390 /// functions.
1391 ///
1392 /// @param id the ID of the function to lookup. This ID must be
1393 /// either the result of invoking function::get_id() of
1394 /// elf_symbol::get_id_string().
1395 ///
1396 /// @return the set of functions which ID is @p id, or nil if no
1397 /// function with that ID was found.
1398 const std::unordered_set<function_decl*>*
1400 {return priv_->lookup_functions(id);}
1401 
1402 const std::unordered_set<function_decl*>*
1403 corpus::lookup_functions(const char* id) const
1404 {
1405  if (!id)
1406  return nullptr;
1407 
1408  interned_string string_id = priv_->env.intern(id);
1409  return lookup_functions(string_id);
1410 }
1411 
1412 /// Lookup the exported variables which all have a given variable ID.
1413 ///
1414 /// @param id the ID of the variable to look up.
1415 ///
1416 /// @return a pointer to the set of variables with ID @p id, or
1417 /// nullptr if no variable was found with that ID.
1418 const std::unordered_set<var_decl_sptr>*
1420 {
1422  auto i = b->priv_->id_vars_map_.find(id);
1423  if (i == b->priv_->id_vars_map_.end())
1424  return nullptr;
1425  return &i->second;
1426 }
1427 
1428 /// Lookup the exported variables which all have a given variable ID.
1429 ///
1430 /// @param id the ID of the variable to look up.
1431 ///
1432 /// @return a pointer to the set of variables with ID @p id, or
1433 /// nullptr if no variable was found with that ID.
1434 const std::unordered_set<var_decl_sptr>*
1435 corpus::lookup_variables(const char* id) const
1436 {
1437  if (!id)
1438  return nullptr;
1439 
1440  interned_string string_id = priv_->env.intern(id);
1441  return lookup_variables(string_id);
1442 }
1443 
1444 /// Sort the set of functions exported by this corpus.
1445 ///
1446 /// Normally, you shouldn't be calling this as the code that creates
1447 /// the corpus for you should do it for you too.
1448 void
1450 {
1451  func_comp fc;
1452  std::sort(priv_->fns.begin(), priv_->fns.end(), fc);
1453 
1454  priv_->sorted_undefined_fns.clear();
1455 
1456  for (auto& f : priv_->undefined_fns)
1457  priv_->sorted_undefined_fns.push_back(f);
1458 
1459  std::sort(priv_->sorted_undefined_fns.begin(),
1460  priv_->sorted_undefined_fns.end(), fc);
1461 }
1462 
1463 /// Return the public decl table of the global variables of the
1464 /// current corpus.
1465 ///
1466 /// The variable public decls table is a vector of all the public
1467 /// global variables and static member variables found in the current
1468 /// corpus.
1469 ///
1470 /// Note that the caller can suppress some variables from the vector
1471 /// supplying regular expressions describing the set of variables she
1472 /// wants to see removed from the public decl table by populating the
1473 /// vector of regular expressions returned by
1474 /// corpus::get_regex_patterns_of_fns_to_suppress().
1475 ///
1476 /// @return the vector of variables of the public decl table. The
1477 /// variables are sorted using their name.
1478 const corpus::variables&
1480 {return priv_->vars;}
1481 
1482 /// Sort the set of variables exported by this corpus.
1483 ///
1484 /// Normally, you shouldn't be calling this as the code that creates
1485 /// the corpus for you should do it for you too.
1486 void
1488 {
1489  var_comp vc;
1490  std::sort(priv_->vars.begin(), priv_->vars.end(), vc);
1491 
1492  priv_->sorted_undefined_vars.clear();
1493  for (auto& f : priv_->undefined_vars)
1494  priv_->sorted_undefined_vars.push_back(f);
1495 
1496  std::sort(priv_->sorted_undefined_vars.begin(),
1497  priv_->sorted_undefined_vars.end(), vc);
1498 }
1499 
1500 /// Getter of the undefined functions of the corpus.
1501 ///
1502 /// Undefined functions are functions which symbols are not defined.
1503 ///
1504 /// @return a set of @ref function_decl* representing the functions
1505 /// that are undefined in the corpus.
1506 const corpus::functions_set&
1508 {return priv_->undefined_fns;}
1509 
1510 /// Getter of the undefined functions of the corpus.
1511 ///
1512 /// @return a set of @ref function_decl* representing the functions
1513 /// that are undefined in the corpus.
1516 {return priv_->undefined_fns;}
1517 
1518 /// Getter of the sorted vector of undefined functions of the corpus.
1519 ///
1520 /// @return a vector of @ref function_decl* representing the functions
1521 /// that are undefined in the corpus.
1522 const corpus::functions&
1524 {
1525  if (priv_->sorted_undefined_fns.empty()
1526  && !priv_->undefined_fns.empty())
1527  // We have undefined functions but we haven't sorted them yet.
1528  // Let's do the sorting now then.
1529  const_cast<corpus*>(this)->sort_functions();
1530 
1531  return priv_->sorted_undefined_fns;
1532 }
1533 
1534 /// Getter of the undefined variables of the corpus.
1535 ///
1536 /// @return a set of @ref var_decl* representing the variables that
1537 /// are undefined in the corpus.
1538 const corpus::variables_set&
1540 {return priv_->undefined_vars;}
1541 
1542 /// Getter of the undefined variables of the corpus.
1543 ///
1544 /// @return a set of @ref var_decl* representing the variables that
1545 /// are undefined in the corpus.
1548 {return priv_->undefined_vars;}
1549 
1550 /// Getter of the sorted vector of undefined variables of the corpus.
1551 ///
1552 /// @return a sorted vector of @ref var_decl* representing the
1553 /// variables that are undefined in the corpus.
1554 const corpus::variables&
1556 {
1557  if (priv_->sorted_undefined_vars.empty()
1558  && !priv_->undefined_vars.empty())
1559  // We have undefined variables but we haven't sorted them yet.
1560  // Let's do the sorting now then.
1561  const_cast<corpus*>(this)->sort_variables();
1562 
1563  return priv_->sorted_undefined_vars;
1564 }
1565 
1566 /// Getter of the set of function symbols that are not referenced by
1567 /// any function exported by the current corpus.
1568 ///
1569 /// When the corpus has been created from an ELF library or program,
1570 /// this function returns the set of function symbols not referenced
1571 /// by any debug information.
1572 ///
1573 /// @return the vector of function symbols not referenced by any
1574 /// function exported by the current corpus.
1575 const elf_symbols&
1577 {return priv_->get_unreferenced_function_symbols();}
1578 
1579 /// Getter of the set of variable symbols that are not referenced by
1580 /// any variable exported by the current corpus.
1581 ///
1582 /// When the corpus has been created from an ELF library or program,
1583 /// this function returns the set of variable symbols not referenced
1584 /// by any debug information.
1585 ///
1586 /// @return the vector of variable symbols not referenced by any
1587 /// variable exported by the current corpus.
1588 const elf_symbols&
1590 {return priv_->get_unreferenced_variable_symbols();}
1591 
1592 /// Accessor for the regex patterns describing the functions to drop
1593 /// from the public decl table.
1594 ///
1595 /// @return the regex patterns describing the functions to drop from
1596 /// the public decl table.
1597 vector<string>&
1599 {return priv_->regex_patterns_fns_to_suppress;}
1600 
1601 /// Accessor for the regex patterns describing the functions to drop
1602 /// from the public decl table.
1603 ///
1604 /// @return the regex patterns describing the functions to drop from
1605 /// the public decl table.
1606 const vector<string>&
1608 {return priv_->regex_patterns_fns_to_suppress;}
1609 
1610 /// Accessor for the regex patterns describing the variables to drop
1611 /// from the public decl table.
1612 ///
1613 /// @return the regex patterns describing the variables to drop from
1614 /// the public decl table.
1615 vector<string>&
1617 {return priv_->regex_patterns_vars_to_suppress;}
1618 
1619 /// Accessor for the regex patterns describing the variables to drop
1620 /// from the public decl table.
1621 ///
1622 /// @return the regex patterns describing the variables to drop from
1623 /// the public decl table.
1624 const vector<string>&
1626 {return priv_->regex_patterns_vars_to_suppress;}
1627 
1628 /// Accessor for the regex patterns describing the functions to keep
1629 /// into the public decl table. The other functions not matches by these
1630 /// regexes are dropped from the public decl table.
1631 ///
1632 /// @return the regex patterns describing the functions to keep into
1633 /// the public decl table.
1634 vector<string>&
1636 {return priv_->regex_patterns_fns_to_keep;}
1637 
1638 /// Accessor for the regex patterns describing the functions to keep
1639 /// into the public decl table. The other functions not matches by these
1640 /// regexes are dropped from the public decl table.
1641 ///
1642 /// @return the regex patterns describing the functions to keep into
1643 /// the public decl table.
1644 const vector<string>&
1646 {return priv_->regex_patterns_fns_to_keep;}
1647 
1648 /// Getter for the vector of function symbol IDs to keep.
1649 ///
1650 /// A symbol ID is a string made of the name of the symbol and its
1651 /// version, separated by one or two '@'.
1652 ///
1653 /// @return a vector of IDs of function symbols to keep.
1654 vector<string>&
1656 {return priv_->sym_id_fns_to_keep;}
1657 
1658 /// Getter for the vector of function symbol IDs to keep.
1659 ///
1660 /// A symbol ID is a string made of the name of the symbol and its
1661 /// version, separated by one or two '@'.
1662 ///
1663 /// @return a vector of IDs of function symbols to keep.
1664 const vector<string>&
1666 {return priv_->sym_id_fns_to_keep;}
1667 
1668 /// Accessor for the regex patterns describing the variables to keep
1669 /// into the public decl table. The other variables not matches by these
1670 /// regexes are dropped from the public decl table.
1671 ///
1672 /// @return the regex patterns describing the variables to keep into
1673 /// the public decl table.
1674 vector<string>&
1676 {return priv_->regex_patterns_vars_to_keep;}
1677 
1678 /// Accessor for the regex patterns describing the variables to keep
1679 /// into the public decl table. The other variables not matches by these
1680 /// regexes are dropped from the public decl table.
1681 ///
1682 /// @return the regex patterns describing the variables to keep into
1683 /// the public decl table.
1684 const vector<string>&
1686 {return priv_->regex_patterns_vars_to_keep;}
1687 
1688 /// Getter for the vector of variable symbol IDs to keep.
1689 ///
1690 /// A symbol ID is a string made of the name of the symbol and its
1691 /// version, separated by one or two '@'.
1692 ///
1693 /// @return a vector of IDs of variable symbols to keep.
1694 vector<string>&
1696 {return priv_->sym_id_vars_to_keep;}
1697 
1698 /// Getter for the vector of variable symbol IDs to keep.
1699 ///
1700 /// A symbol ID is a string made of the name of the symbol and its
1701 /// version, separated by one or two '@'.
1702 ///
1703 /// @return a vector of IDs of variable symbols to keep.
1704 const vector<string>&
1706 {return priv_->sym_id_vars_to_keep;}
1707 
1708 /// After the set of exported functions and variables have been built,
1709 /// consider all the tunables that control that set and see if some
1710 /// functions need to be removed from that set; if so, remove them.
1711 void
1713 {
1714  string sym_name, sym_version;
1715 
1716  functions fns_to_keep;
1718  for (auto f = priv_->fns.begin(); f != priv_->fns.end(); ++f)
1719  {
1720  if (b->priv_->keep_wrt_id_of_fns_to_keep(*f)
1721  && b->priv_->keep_wrt_regex_of_fns_to_suppress(*f)
1722  && b->priv_->keep_wrt_regex_of_fns_to_keep(*f))
1723  fns_to_keep.push_back(*f);
1724  }
1725  priv_->fns = fns_to_keep;
1726 
1727  variables vars_to_keep;
1728  for (auto v = priv_->vars.begin(); v != priv_->vars.end(); ++v)
1729  {
1730  if (b->priv_->keep_wrt_id_of_vars_to_keep(*v)
1731  && b->priv_->keep_wrt_regex_of_vars_to_suppress(*v)
1732  && b->priv_->keep_wrt_regex_of_vars_to_keep(*v))
1733  vars_to_keep.push_back(*v);
1734  }
1735  priv_->vars = vars_to_keep;
1736 }
1737 
1738 /// Getter for the object that is responsible for determining what
1739 /// decls ought to be in the set of exported decls.
1740 ///
1741 /// The object does have methods to add the decls to the set of
1742 /// exported decls, right at the place where the corpus expects it,
1743 /// so that there is no unnecessary copying involved.
1744 ///
1745 /// @return a (smart) pointer to the instance of @ref
1746 /// corpus::exported_decls_builder that is responsible for determine
1747 /// what decls ought to be in the set of exported decls.
1750 {
1751  if (!priv_->exported_decls_builder)
1752  {
1753  priv_->exported_decls_builder.reset
1754  (new exported_decls_builder(priv_->fns,
1755  priv_->vars,
1756  priv_->regex_patterns_fns_to_suppress,
1757  priv_->regex_patterns_vars_to_suppress,
1758  priv_->regex_patterns_fns_to_keep,
1759  priv_->regex_patterns_vars_to_keep,
1760  priv_->sym_id_fns_to_keep,
1761  priv_->sym_id_vars_to_keep));
1762  }
1763  return priv_->exported_decls_builder;
1764 }
1765 
1766 /// Bitwise | operator for the corpus::origin type.
1767 ///
1768 /// @param l the left-hand side operand of the | operation.
1769 ///
1770 /// @param r the right-hand side operand of the | operation.
1771 ///
1772 /// @return the result of the operation.
1775 {
1776  return static_cast<corpus::origin>
1777  (static_cast<uint32_t>(l) | static_cast<uint32_t>(r));
1778 }
1779 
1780 /// Bitwise |= operator for the corpus::origin type.
1781 ///
1782 /// @param l the left-hand side operand for the |= operation.
1783 ///
1784 /// @param r the right-hand side operand for the |= operation.
1785 ///
1786 /// @return the result of the operation.
1789 {
1790  l = l | r;
1791  return l;
1792 }
1793 
1794 /// Bitwise & operator for the corpus::origin type.
1795 ///
1796 /// @param l the left-hand side operand of the & operation.
1797 ///
1798 /// @param r the right-hand side operand of the & operation.
1799 ///
1800 /// @return the result of the operation.
1803 {
1804  return static_cast<corpus::origin>
1805  (static_cast<uint32_t>(l) & static_cast<uint32_t>(r));
1806 }
1807 
1808 /// Bitwise &= operator for the corpus::origin type.
1809 ///
1810 /// @param l the left-hand side operand of the &= operation.
1811 ///
1812 /// @param r the right-hand side operand of the &= operation.
1813 ///
1814 /// @return the result of the operation.
1817 {
1818  l = l & r;
1819  return l;
1820 }
1821 
1822 // </corpus stuff>
1823 
1824 // <corpus_group stuff>
1825 
1826 /// Type of the private data of @ref corpus_group
1827 struct corpus_group::priv
1828 {
1829  std::set<string> corpora_paths;
1830  corpora_type corpora;
1831  istring_function_decl_ptr_map_type fns_map;
1832  corpus::functions fns;
1833  istring_var_decl_ptr_map_type vars_map;
1834  corpus::variables vars;
1835  string_elf_symbols_map_type var_symbol_map;
1836  string_elf_symbols_map_type fun_symbol_map;
1837  elf_symbols sorted_var_symbols;
1838  elf_symbols sorted_fun_symbols;
1839  unordered_map<string, elf_symbol_sptr> unrefed_fun_symbol_map;
1840  elf_symbols unrefed_fun_symbols;
1841  bool unrefed_fun_symbols_built;
1842  unordered_map<string, elf_symbol_sptr> unrefed_var_symbol_map;
1843  elf_symbols unrefed_var_symbols;
1844  bool unrefed_var_symbols_built;
1845  unordered_set<interned_string, hash_interned_string> pub_type_pretty_reprs_;
1846 
1847  priv()
1848  : unrefed_fun_symbols_built(),
1849  unrefed_var_symbols_built()
1850  {}
1851 
1852  /// Add symbols to the set of corpus group function symbols that are
1853  /// *NOT* referenced by debug info.
1854  ///
1855  /// @param syms the set the symbols to add.
1856  void
1857  add_unref_fun_symbols(const elf_symbols& syms)
1858  {
1859  for (elf_symbols::const_iterator e =
1860  syms.begin(); e != syms.end(); ++e)
1861  {
1862  string sym_id = (*e)->get_id_string();
1863  unordered_map<string, elf_symbol_sptr>::const_iterator j =
1864  unrefed_fun_symbol_map.find(sym_id);
1865  if (j != unrefed_fun_symbol_map.end())
1866  continue;
1867 
1868  unrefed_fun_symbol_map[sym_id] = *e;
1869  unrefed_fun_symbols.push_back(*e);
1870  }
1871  unrefed_fun_symbols_built = true;
1872  }
1873 
1874  /// Add symbols to the set of corpus group variable symbols that are
1875  /// *NOT* referenced by debug info.
1876  ///
1877  /// @param syms the set the symbols to add.
1878  void
1879  add_unref_var_symbols(const elf_symbols& syms)
1880  {
1881  for (elf_symbols::const_iterator e =
1882  syms.begin(); e != syms.end(); ++e)
1883  {
1884  string sym_id = (*e)->get_id_string();
1885  unordered_map<string, elf_symbol_sptr>::const_iterator j =
1886  unrefed_var_symbol_map.find(sym_id);
1887  if (j != unrefed_var_symbol_map.end())
1888  continue;
1889 
1890  unrefed_var_symbol_map[sym_id] = *e;
1891  unrefed_var_symbols.push_back(*e);
1892  }
1893  unrefed_var_symbols_built = true;
1894  }
1895 }; // end corpus_group::priv
1896 
1897 /// Constructor of the @ref corpus_group type.
1898 ///
1899 /// @param env the environment of the @ref corpus_group.
1900 ///
1901 /// @param path the path to the file represented by the corpus group.
1902 corpus_group::corpus_group(const environment& env, const string& path = "")
1903  : corpus(env, path), priv_(new priv)
1904 {}
1905 
1906 /// Desctructor of the @ref corpus_group type.
1908 {}
1909 
1910 /// Add a new corpus to the current instance of @ref corpus_group.
1911 ///
1912 /// @param corp the new corpus to add.
1913 void
1914 corpus_group::add_corpus(const corpus_sptr& corp)
1915 {
1916  if (!corp)
1917  return;
1918 
1919  if (!corp->get_path().empty()
1920  && has_corpus(corp->get_path()))
1921  return;
1922 
1923  // Ensure the new architecture name matches the current one.
1924  string cur_arch = get_architecture_name(),
1925  corp_arch = corp->get_architecture_name();
1926  if (cur_arch.empty())
1927  set_architecture_name(corp_arch);
1928  else if (cur_arch != corp_arch)
1929  {
1930  std::cerr << "corpus '" << corp->get_path() << "'"
1931  << " has architecture '" << corp_arch << "'"
1932  << " but expected '" << cur_arch << "'\n";
1934  }
1935 
1936  priv_->corpora.push_back(corp);
1937  corp->set_group(this);
1938  priv_->corpora_paths.insert(corp->get_path());
1939 
1940  /// Add the unreferenced function and variable symbols of this
1941  /// corpus to the unreferenced symbols of the current corpus group.
1942  priv_->add_unref_fun_symbols(get_unreferenced_function_symbols());
1943  priv_->add_unref_var_symbols(get_unreferenced_variable_symbols());
1944 }
1945 
1946 /// Test if a corpus of a given path has been added to the group.
1947 ///
1948 /// @param path the path to the corpus to consider.
1949 ///
1950 /// @return true iff a corpus with path @p path is already present in
1951 /// the groupâ‹…
1952 bool
1953 corpus_group::has_corpus(const string& path)
1954 {
1955  if (priv_->corpora_paths.find(path) != priv_->corpora_paths.end())
1956  return true;
1957  return false;
1958 }
1959 
1960 /// Getter of the vector of corpora held by the current @ref
1961 /// corpus_group.
1962 ///
1963 /// @return the vector corpora.
1964 const corpus_group::corpora_type&
1966 {return priv_->corpora;}
1967 
1968 /// Getter of the first corpus added to this Group.
1969 ///
1970 /// @return the first corpus added to this Group.
1971 const corpus_sptr
1973 {return const_cast<corpus_group*>(this)->get_main_corpus();}
1974 
1975 /// Getter of the first corpus added to this Group.
1976 ///
1977 /// @return the first corpus added to this Group.
1978 corpus_sptr
1980 {
1981  if (!get_corpora().empty())
1982  return get_corpora().front();
1983  return corpus_sptr();
1984 }
1985 
1986 /// Test if the current corpus group is empty.
1987 ///
1988 /// @return true iff the current corpus group is empty.
1989 bool
1991 {return get_corpora().empty();}
1992 
1993 /// Get the functions exported by the corpora of the current corpus
1994 /// group.
1995 ///
1996 /// Upon its first invocation, this function walks the corpora
1997 /// contained in the corpus group and caches the functions they exported.
1998 ///
1999 /// Subsequent invocations just return the cached functions.
2000 ///
2001 /// @return the exported functions.
2002 const corpus::functions&
2004 {
2005  if (priv_->fns.empty())
2006  for (corpora_type::const_iterator i = get_corpora().begin();
2007  i != get_corpora().end();
2008  ++i)
2009  {
2010  corpus_sptr c = *i;
2011  for (corpus::functions::const_iterator f = c->get_functions().begin();
2012  f != c->get_functions().end();
2013  ++f)
2014  {
2015  interned_string fid = (*f)->get_id();
2016  istring_function_decl_ptr_map_type::const_iterator j =
2017  priv_->fns_map.find(fid);
2018 
2019  if (j != priv_->fns_map.end())
2020  // Don't cache the same function twice ...
2021  continue;
2022 
2023  priv_->fns_map[fid] = *f;
2024  // really cache the function now.
2025  priv_->fns.push_back(*f);
2026  }
2027  }
2028 
2029  return priv_->fns;
2030 }
2031 
2032 /// Get the global variables exported by the corpora of the current
2033 /// corpus group.
2034 ///
2035 /// Upon its first invocation, this function walks the corpora
2036 /// contained in the corpus group and caches the variables they
2037 /// export.
2038 ///
2039 /// @return the exported variables.
2040 const corpus::variables&
2042 {
2043  if (priv_->vars.empty())
2044  for (corpora_type::const_iterator i = get_corpora().begin();
2045  i != get_corpora().end();
2046  ++i)
2047  {
2048  corpus_sptr c = *i;
2049  for (corpus::variables::const_iterator v = c->get_variables().begin();
2050  v != c->get_variables().end();
2051  ++v)
2052  {
2053  interned_string vid = (*v)->get_id();
2054  istring_var_decl_ptr_map_type::const_iterator j =
2055  priv_->vars_map.find(vid);
2056 
2057  if (j != priv_->vars_map.end())
2058  // Don't cache the same variable twice ...
2059  continue;
2060 
2061  priv_->vars_map[vid] = *v;
2062  // Really cache the variable now.
2063  priv_->vars.push_back(*v);
2064  }
2065  }
2066 
2067  return priv_->vars;
2068 }
2069 
2070 /// Get the symbols of the global variables exported by the corpora of
2071 /// the current @ref corpus_group.
2072 ///
2073 /// @return the symbols of the global variables exported by the corpora
2076 {
2077  if (priv_->var_symbol_map.empty())
2078  for (corpora_type::const_iterator i = get_corpora().begin();
2079  i != get_corpora().end();
2080  ++i)
2081  priv_->var_symbol_map.insert((*i)->get_var_symbol_map().begin(),
2082  (*i)->get_var_symbol_map().end());
2083 
2084  return priv_->var_symbol_map;
2085 }
2086 
2087 /// Get the symbols of the global functions exported by the corpora of
2088 /// the current @ref corpus_group.
2089 ///
2090 /// @return the symbols of the global functions exported by the corpora
2093 {
2094  if (priv_->fun_symbol_map.empty())
2095  for (corpora_type::const_iterator i = get_corpora().begin();
2096  i != get_corpora().end();
2097  ++i)
2098  priv_->fun_symbol_map.insert((*i)->get_fun_symbol_map().begin(),
2099  (*i)->get_fun_symbol_map().end());
2100 
2101  return priv_->fun_symbol_map;
2102 }
2103 
2104 /// Get a sorted vector of the symbols of the functions exported by
2105 /// the corpora of the current group.
2106 ///
2107 /// @return the sorted vectors of the exported function symbols.
2108 const elf_symbols&
2110 {
2111  if (priv_->sorted_fun_symbols.empty()
2112  && !get_fun_symbol_map().empty())
2113  {
2114  for (corpora_type::const_iterator i = get_corpora().begin();
2115  i != get_corpora().end();
2116  ++i)
2117  {
2118  corpus_sptr c = *i;
2119  for (string_elf_symbols_map_type::const_iterator j =
2120  c->get_fun_symbol_map().begin();
2121  j != c->get_fun_symbol_map().begin();
2122  ++j)
2123  priv_->sorted_fun_symbols.insert(priv_->sorted_fun_symbols.end(),
2124  j->second.begin(),
2125  j->second.end());
2126  }
2127  comp_elf_symbols_functor comp;
2128  std::sort(priv_->sorted_fun_symbols.begin(),
2129  priv_->sorted_fun_symbols.end(),
2130  comp);
2131  }
2132 
2133  return priv_->sorted_fun_symbols;
2134 }
2135 
2136 /// Get a sorted vector of the symbols of the variables exported by
2137 /// the corpora of the current group.
2138 ///
2139 /// @return the sorted vectors of the exported variable symbols.
2140 const elf_symbols&
2142 {
2143  if (priv_->sorted_var_symbols.empty()
2144  && !get_var_symbol_map().empty())
2145  {
2146  for (corpora_type::const_iterator i = get_corpora().begin();
2147  i != get_corpora().end();
2148  ++i)
2149  {
2150  corpus_sptr c = *i;
2151  for (string_elf_symbols_map_type::const_iterator j =
2152  c->get_var_symbol_map().begin();
2153  j != c->get_var_symbol_map().begin();
2154  ++j)
2155  priv_->sorted_var_symbols.insert(priv_->sorted_var_symbols.end(),
2156  j->second.begin(),
2157  j->second.end());
2158  }
2159  comp_elf_symbols_functor comp;
2160  std::sort(priv_->sorted_var_symbols.begin(),
2161  priv_->sorted_var_symbols.end(),
2162  comp);
2163  }
2164 
2165  return priv_->sorted_var_symbols;
2166 }
2167 
2168 /// Get the set of function symbols not referenced by any debug info,
2169 /// from all the corpora of the current corpus group.
2170 ///
2171 /// Upon its first invocation, this function possibly walks all the
2172 /// copora of this corpus group and caches the unreferenced symbols
2173 /// they export. The function then returns the cache.
2174 ///
2175 /// Upon subsequent invocations, this functions just returns the
2176 /// cached symbols.
2177 ///
2178 /// @return the unreferenced symbols.
2179 const elf_symbols&
2181 {
2182  if (!priv_->unrefed_fun_symbols_built)
2183  if (priv_->unrefed_fun_symbols.empty())
2184  {
2185  for (corpora_type::const_iterator i = get_corpora().begin();
2186  i != get_corpora().end();
2187  ++i)
2188  {
2189  corpus_sptr c = *i;
2190  for (elf_symbols::const_iterator e =
2191  c->get_unreferenced_function_symbols().begin();
2192  e != c->get_unreferenced_function_symbols().end();
2193  ++e)
2194  {
2195  string sym_id = (*e)->get_id_string();
2196  unordered_map<string, elf_symbol_sptr>::const_iterator j =
2197  priv_->unrefed_fun_symbol_map.find(sym_id);
2198  if (j != priv_->unrefed_fun_symbol_map.end())
2199  continue;
2200 
2201  priv_->unrefed_fun_symbol_map[sym_id] = *e;
2202  priv_->unrefed_fun_symbols.push_back(*e);
2203  }
2204  }
2205  priv_->unrefed_fun_symbols_built = true;
2206  }
2207 
2208  return priv_->unrefed_fun_symbols;
2209 }
2210 
2211 /// Get the set of variable symbols not referenced by any debug info,
2212 /// from all the corpora of the current corpus group.
2213 ///
2214 /// Upon its first invocation, this function possibly walks all the
2215 /// copora of this corpus group and caches the unreferenced symbols
2216 /// they export. The function then returns the cache.
2217 ///
2218 /// Upon subsequent invocations, this functions just returns the
2219 /// cached symbols.
2220 ///
2221 /// @return the unreferenced symbols.
2222 const elf_symbols&
2224 {
2225  if (!priv_->unrefed_var_symbols_built)
2226  if (priv_->unrefed_var_symbols.empty())
2227  {
2228  for (corpora_type::const_iterator i = get_corpora().begin();
2229  i != get_corpora().end();
2230  ++i)
2231  {
2232  corpus_sptr c = *i;
2233  for (elf_symbols::const_iterator e =
2234  c->get_unreferenced_variable_symbols().begin();
2235  e != c->get_unreferenced_variable_symbols().end();
2236  ++e)
2237  {
2238  string sym_id = (*e)->get_id_string();
2239  unordered_map<string, elf_symbol_sptr>::const_iterator j =
2240  priv_->unrefed_var_symbol_map.find(sym_id);
2241  if (j != priv_->unrefed_var_symbol_map.end())
2242  continue;
2243 
2244  priv_->unrefed_var_symbol_map[sym_id] = *e;
2245  priv_->unrefed_var_symbols.push_back(*e);
2246  }
2247  }
2248  priv_->unrefed_var_symbols_built = true;
2249  }
2250 
2251  return priv_->unrefed_var_symbols;
2252 }
2253 
2254 /// Getter of a pointer to the set of types reachable from public
2255 /// interfaces of a given corpus group.
2256 unordered_set<interned_string, hash_interned_string>*
2258 {return &priv_->pub_type_pretty_reprs_;}
2259 
2260 /// Test if the recording of reachable types (and thus, indirectly,
2261 /// the recording of non-reachable types) is activated for the
2262 /// current @ref corpus_group.
2263 ///
2264 /// @return true iff the recording of reachable types is activated for
2265 /// the current @ref corpus_group.
2266 bool
2268 {return !get_public_types_pretty_representations()->empty();}
2269 
2270 /// Lookup the function which has a given function ID.
2271 ///
2272 /// Note that there can have been several functions with the same ID.
2273 /// This is because debug info can declare the same function in
2274 /// several different translation units. Normally, all these
2275 /// functions should be equal. But still, this function returns all
2276 /// these functions.
2277 ///
2278 /// Also, note that this function cycles over each corpora of the
2279 /// corpus group, invokes corpus::lookup_functions on them and returns
2280 /// the result of the first one that succeeds.
2281 ///
2282 /// @param id the ID of the function to lookup. This ID must be
2283 /// either the result of invoking function::get_id() of
2284 /// elf_symbol::get_id_string().
2285 ///
2286 /// @return the set of functions which ID is @p id, or nil if no
2287 /// function with that ID was found.
2288 const std::unordered_set<function_decl*>*
2290 {
2291  for (auto& corp :get_corpora())
2292  if (auto fns = corp->lookup_functions(id))
2293  return fns;
2294 
2295  return nullptr;
2296 }
2297 
2298 /// Lookup the function which has a given function ID.
2299 ///
2300 /// Note that there can have been several functions with the same ID.
2301 /// This is because debug info can declare the same function in
2302 /// several different translation units. Normally, all these
2303 /// functions should be equal. But still, this function returns all
2304 /// these functions.
2305 ///
2306 /// Also, note that this function cycles over each corpora of the
2307 /// corpus group, invokes corpus::lookup_functions on them and returns
2308 /// the result of the first one that succeeds.
2309 ///
2310 /// @param id the ID of the function to lookup. This ID must be
2311 /// either the result of invoking function::get_id() of
2312 /// elf_symbol::get_id_string().
2313 ///
2314 /// @return the set of functions which ID is @p id, or nil if no
2315 /// function with that ID was found.
2316 const std::unordered_set<function_decl*>*
2317 corpus_group::lookup_functions(const char* id) const
2318 {
2319  for (auto& corp :get_corpora())
2320  if (const auto& fns = corp->lookup_functions(id))
2321  return fns;
2322 
2323  return nullptr;
2324 }
2325 
2326 /// Lookup the exported variables which all have a given variable ID.
2327 ///
2328 /// Note that this function cycles over each corpora of the corpus
2329 /// group, invokes corpus::lookup_variabless on them and returns the
2330 /// result of the first one that succeeds.
2331 ///
2332 /// @param id the ID of the variable to look up.
2333 ///
2334 /// @return a pointer to the set of variables with ID @p id, or
2335 /// nullptr if no variable was found with that ID.
2336 const std::unordered_set<var_decl_sptr>*
2338 {
2339  for (auto& corp :get_corpora())
2340  if (const auto& vars = corp->lookup_variables(id))
2341  return vars;
2342 
2343  return nullptr;
2344 }
2345 
2346 /// Lookup the exported variables which all have a given variable ID.
2347 ///
2348 /// Note that this function cycles over each corpora of the corpus
2349 /// group, invokes corpus::lookup_variabless on them and returns the
2350 /// result of the first one that succeeds.
2351 ///
2352 /// @param id the ID of the variable to look up.
2353 ///
2354 /// @return a pointer to the set of variables with ID @p id, or
2355 /// nullptr if no variable was found with that ID.
2356 const std::unordered_set<var_decl_sptr>*
2357 corpus_group::lookup_variables(const char* id) const
2358 {
2359  for (auto& corp :get_corpora())
2360  if (const auto& vars = corp->lookup_variables(id))
2361  return vars;
2362 
2363  return nullptr;
2364 }
2365 
2366 /// Test if a @ref corpus is a @ref corpus_group.
2367 ///
2368 /// @param corpus the corpus to consider.
2369 ///
2370 /// @return the @ref corpus_group is @p corpus is a corpus group, or
2371 /// nil.
2372 corpus_group_sptr
2373 is_corpus_group(const corpus_sptr& corpus)
2374 {return std::dynamic_pointer_cast<corpus_group>(corpus);}
2375 
2376 // </corpus_group stuff>
2377 
2378 }// end namespace ir
2379 }// end namespace abigail
const variables & get_sorted_undefined_variables() const
Getter of the sorted vector of undefined variables of the corpus.
Definition: abg-corpus.cc:1555
const vector< type_base_wptr > & get_types_not_reachable_from_public_interfaces() const
Getter of a sorted vector of the types that are *NOT* reachable from public interfaces.
Definition: abg-corpus.cc:857
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)...
Definition: abg-corpus.cc:808
virtual const string_elf_symbols_map_type & get_var_symbol_map() const
Getter for the variable symbols map.
Definition: abg-corpus.cc:1192
void sort_functions()
Sort the set of functions exported by this corpus.
Definition: abg-corpus.cc:1449
vector< string > & get_regex_patterns_of_fns_to_keep()
Accessor for the regex patterns describing the functions to keep into the public decl table...
Definition: abg-corpus.cc:1635
const variables_set & get_undefined_variables() const
Getter of the undefined variables of the corpus.
Definition: abg-corpus.cc:1539
virtual const elf_symbols & get_sorted_var_symbols() const
Getter for the sorted vector of variable symbols for this corpus.
Definition: abg-corpus.cc:1176
type_maps & get_types()
Get the maps that associate a name to a certain kind of type.
Definition: abg-corpus.cc:338
unordered_set< interned_string, hash_interned_string > * get_public_types_pretty_representations()
Getter of the set of pretty representation of types that are reachable from public interfaces (global...
Definition: abg-corpus.cc:641
const string & str() const
Getter for the version name.
Definition: abg-ir.cc:3205
void set_path(const string &)
Set the file path associated to the corpus file.
Definition: abg-corpus.cc:995
corpus_group_sptr is_corpus_group(const corpus_sptr &corpus)
Test if a corpus is a corpus_group.
Definition: abg-corpus.cc:2373
const elf_symbols & get_sorted_undefined_fun_symbols() const
Getter for a sorted vector of the function symbols undefined in this corpus.
Definition: abg-corpus.cc:1165
string & get_format_minor_version_number() const
Getter of the minor version number of the abixml serialization format.
Definition: abg-corpus.cc:962
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.
void set_needed(const vector< string > &)
Setter of the needed property of the corpus.
Definition: abg-corpus.cc:1018
bool operator==(const corpus &) const
Compare the current corpus against another one.
Definition: abg-corpus.cc:1102
const vector< type_base_wptr > & get_types_sorted_by_name() const
Getter of all types types sorted by their pretty representation.
Definition: abg-ir.cc:1157
const elf_symbols & get_unreferenced_function_symbols() const
Return a list of symbols that are not referenced by any function of corpus::get_functions().
Definition: abg-corpus.cc:446
An abstraction helper for type declarations.
Definition: abg-ir.h:2002
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...
Definition: abg-corpus.cc:2223
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...
Definition: abg-corpus.cc:2109
void set_architecture_name(const string &)
Setter for the architecture name of the corpus.
Definition: abg-corpus.cc:1062
A comparison functor for pointers to var_decl.
Definition: abg-ir.h:4750
type_maps & get_types()
Get the maps that associate a name to a certain kind of type.
Definition: abg-corpus.cc:777
#define ABG_ASSERT_NOT_REACHED
A macro that expands to aborting the program when executed.
Helper class to allow range-for loops on symtabs for C++11 and later code. It serves as a proxy for t...
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
Definition: abg-corpus.h:24
virtual const std::unordered_set< function_decl * > * lookup_functions(const interned_string &id) const
Lookup the function which has a given function ID.
Definition: abg-corpus.cc:2289
const translation_units & get_translation_units() const
Return the list of translation units of the current corpus.
Definition: abg-corpus.cc:745
virtual const variables & get_variables() const
Return the public decl table of the global variables of the current corpus.
Definition: abg-corpus.cc:1479
void set_format_minor_version_number(const string &)
Setter of the minor version number of the abixml serialization format.
Definition: abg-corpus.cc:971
bool maybe_add_fn_to_exported_fns(function_decl *)
Consider at all the tunables that control wether a function should be added to the set of exported fu...
Definition: abg-corpus.cc:163
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.
Definition: abg-corpus.cc:231
virtual const functions & get_functions() const
Return the functions public decl table of the current corpus.
Definition: abg-corpus.cc:1381
const functions & exported_functions() const
Getter for the reference to the vector of exported functions. This vector is shared with with the cor...
Definition: abg-corpus.cc:102
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:889
vector< string > & get_regex_patterns_of_vars_to_keep()
Accessor for the regex patterns describing the variables to keep into the public decl table...
Definition: abg-corpus.cc:1675
virtual const corpus::functions & get_functions() const
Get the functions exported by the corpora of the current corpus group.
Definition: abg-corpus.cc:2003
bool empty() const
Test if the current instance of interned_string is empty.
const elf_symbols & get_sorted_var_symbols() const
Getter for the sorted vector of variable symbols for this corpus.
Definition: abg-corpus.cc:498
void sort_variables()
Sort the set of variables exported by this corpus.
Definition: abg-corpus.cc:1487
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:253
virtual const corpus::variables & get_variables() const
Get the global variables exported by the corpora of the current corpus group.
Definition: abg-corpus.cc:2041
const translation_unit_sptr find_translation_unit(const string &path) const
Find the translation unit that has a given path.
Definition: abg-corpus.cc:755
const string_elf_symbols_map_type & get_undefined_var_symbol_map() const
Return a map from name to undefined variable symbol for this corpus.
Definition: abg-corpus.cc:569
shared_ptr< translation_unit > translation_unit_sptr
Convenience typedef for a shared pointer on a translation_unit type.
Definition: abg-fwd.h:133
virtual const interned_string & get_name() const
Getter for the name of the current decl.
Definition: abg-ir.cc:4811
const string & get_name() const
Getter for the name of the elf_symbol.
Definition: abg-ir.cc:2159
vector< string > & get_sym_ids_of_vars_to_keep()
Getter for the vector of variable symbol IDs to keep.
Definition: abg-corpus.cc:1695
void set_soname(const string &)
Setter for the soname property of the corpus.
Definition: abg-corpus.cc:1040
string & get_format_major_version_number() const
Getter of the major version number of the abixml serialization format.
Definition: abg-corpus.cc:945
This contains the declarations for the symtab reader.
const corpora_type & get_corpora() const
Getter of the vector of corpora held by the current corpus_group.
Definition: abg-corpus.cc:1965
Abstracts a variable declaration.
Definition: abg-ir.h:3067
A functor to compare instances of var_decl base on their qualified names.
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.
Definition: abg-corpus.cc:221
std::vector< elf_symbol_sptr > elf_symbols
Convenience typedef for a vector of elf_symbol.
Definition: abg-ir.h:942
const vector< string > & get_needed() const
Getter of the needed property of the corpus.
Definition: abg-corpus.cc:1006
virtual const elf_symbols & get_sorted_fun_symbols() const
Return a sorted vector of function symbols for this corpus.
Definition: abg-corpus.cc:1156
const elf_symbol_sptr lookup_variable_symbol(const string &n) const
Look in the variable symbols map for a symbol with a given name.
Definition: abg-corpus.cc:1314
corpus::origin operator&=(corpus::origin &l, corpus::origin r)
Bitwise &= operator for the corpus::origin type.
Definition: abg-corpus.cc:1816
type_maps & get_type_per_loc_map()
Get the maps that associate a location string to a certain kind of type.
Definition: abg-corpus.cc:886
vector< var_decl_sptr > variables
Convenience typedef for std::vector
Definition: abg-corpus.h:37
const environment & get_environment() const
Getter of the environment of the current ABI artifact.
Definition: abg-ir.cc:4202
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...
Definition: abg-corpus.cc:1589
void maybe_drop_some_exported_decls()
After the set of exported functions and variables have been built, consider all the tunables that con...
Definition: abg-corpus.cc:1712
Toplevel namespace for libabigail.
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.
Definition: abg-corpus.cc:2075
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:947
origin
This abstracts where the corpus comes from. That is, either it has been read from the native xml form...
Definition: abg-corpus.h:50
This contains the private implementation of the suppression engine of libabigail. ...
~priv()
Destructor of the corpus::priv type.
Definition: abg-corpus.cc:681
unordered_set< interned_string, hash_interned_string > * get_public_types_pretty_representations()
Getter of a pointer to the set of types reachable from public interfaces of a given corpus group...
Definition: abg-corpus.cc:2257
Abstraction for a function declaration.
Definition: abg-ir.h:3164
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:...
Definition: abg-corpus.cc:1075
void add_corpus(const corpus_sptr &)
Add a new corpus to the current instance of corpus_group.
Definition: abg-corpus.cc:1914
Types of the main internal representation of libabigail.
const interned_string & get_linkage_name() const
Getter for the mangled name.
Definition: abg-ir.cc:4760
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:4577
vector< string > strings_type
A convenience typedef for std::vector.
Definition: abg-corpus.h:28
const elf_symbols & get_sorted_undefined_fun_symbols() const
Getter for a sorted vector of the function symbols undefined in this corpus.
Definition: abg-corpus.cc:396
void add(const translation_unit_sptr &)
Add a translation unit to the current ABI Corpus.
Definition: abg-corpus.cc:728
unordered_map< string, const function_decl * > str_fn_ptr_map_type
Convenience typedef for a hash map of string and pointer to function_decl.
Definition: abg-corpus.cc:225
The type of the private data of corpus::exported_decls_builder type.
const functions_set & get_undefined_functions() const
Getter of the undefined functions of the corpus.
Definition: abg-corpus.cc:1507
This is a type that aggregates maps of all the kinds of types that are supported by libabigail...
Definition: abg-ir.h:601
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.
Definition: abg-corpus.cc:1202
Abstraction of an elf symbol.
Definition: abg-ir.h:960
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition: abg-ir.h:147
This file contains the declarations of the entry points to de-serialize an instance of abigail::trans...
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.
Definition: abg-corpus.cc:2092
const elf_symbol_sptr lookup_function_symbol(const string &n) const
Look in the function symbols map for a symbol with a given name.
Definition: abg-corpus.cc:1211
virtual bool is_empty() const
Test if the current corpus group is empty.
Definition: abg-corpus.cc:1990
void drop_translation_units()
Erase the translation units contained in this in-memory object.
Definition: abg-corpus.cc:770
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition: abg-ir.h:924
const elf_symbols & get_sorted_fun_symbols() const
Return a sorted vector of function symbols for this corpus.
Definition: abg-corpus.cc:354
std::shared_ptr< regex_t > regex_t_sptr
A convenience typedef for a shared pointer of regex_t.
Definition: abg-fwd.h:87
#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:1743
interned_string intern(const string &) const
Do intern a string.
Definition: abg-ir.cc:3721
const string_elf_symbols_map_type & get_fun_symbol_map() const
Return a map from name to function symbol for this corpus.
Definition: abg-corpus.cc:379
const string_elf_symbols_map_type & get_undefined_fun_symbol_map() const
Return a map from name to undefined function symbol for this corpus.
Definition: abg-corpus.cc:424
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...
Definition: abg-corpus.cc:1749
void record_type_as_reachable_from_public_interfaces(const type_base &)
Record a type as being reachable from public interfaces (global functions and variables).
Definition: abg-corpus.cc:819
Abstracts the building of the set of exported variables and functions.
Definition: abg-corpus.h:336
const symtab_reader::symtab_sptr & get_symtab() const
Getter for the symtab object.
Definition: abg-corpus.cc:1128
std::unordered_set< 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.
Definition: abg-corpus.cc:126
string & get_path() const
Get the file path associated to the corpus file.
Definition: abg-corpus.cc:983
const corpus_sptr get_main_corpus() const
Getter of the first corpus added to this Group.
Definition: abg-corpus.cc:1972
const elf_symbols & get_unreferenced_variable_symbols() const
Return a list of symbols that are not referenced by any variable of corpus::get_variables().
Definition: abg-corpus.cc:591
const string_elf_symbols_map_type & get_var_symbol_map() const
Return a map from name to variable symbol for this corpus.
Definition: abg-corpus.cc:524
corpus::origin operator|(corpus::origin l, corpus::origin r)
Bitwise | operator for the corpus::origin type.
Definition: abg-corpus.cc:1774
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:21770
Equality functor for instances of function_decl.
Definition: abg-ir.h:4771
vector< string > & get_sym_ids_of_fns_to_keep()
Getter for the vector of function symbol IDs to keep.
Definition: abg-corpus.cc:1655
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...
Definition: abg-corpus.cc:193
version & get_version() const
Getter for the version of the current instanc of elf_symbol.
Definition: abg-ir.cc:2218
const environment & get_environment() const
Getter of the enviroment of the corpus.
Definition: abg-corpus.cc:703
corpus::origin operator|=(corpus::origin &l, corpus::origin r)
Bitwise |= operator for the corpus::origin type.
Definition: abg-corpus.cc:1788
vector< string > & get_regex_patterns_of_fns_to_suppress()
Accessor for the regex patterns describing the functions to drop from the public decl table...
Definition: abg-corpus.cc:1598
void set_origin(origin)
Setter for the origin of the corpus.
Definition: abg-corpus.cc:937
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...
Definition: abg-corpus.cc:2141
The abstraction of an interned string.
vector< string > & get_regex_patterns_of_vars_to_suppress()
Accessor for the regex patterns describing the variables to drop from the public decl table...
Definition: abg-corpus.cc:1616
std::unordered_set< function_decl * > * lookup_functions(const interned_string &id)
Lookup the function which has a given function ID.
Definition: abg-corpus.cc:667
const functions & get_sorted_undefined_functions() const
Getter of the sorted vector of undefined functions of the corpus.
Definition: abg-corpus.cc:1523
void set_format_major_version_number(const string &)
Setter of the major version number of the abixml serialization format.
Definition: abg-corpus.cc:953
bool type_is_reachable_from_public_interfaces(const type_base &) const
Test if a type is reachable from public interfaces (global functions and variables).
Definition: abg-corpus.cc:837
The abstraction of the version of an ELF symbol.
Definition: abg-ir.h:1231
std::unordered_set< var_decl_sptr > variables_set
Convenience typedef for std::unordered_set.
Definition: abg-corpus.h:40
const corpus_group * get_group() const
Getter of the group this corpus is a member of.
Definition: abg-corpus.cc:894
The private data of the corpus type.
Abstraction of a group of corpora.
Definition: abg-corpus.h:385
const elf_symbols & get_sorted_undefined_var_symbols() const
Getter for a sorted vector of the variable symbols undefined in this corpus.
Definition: abg-corpus.cc:1185
origin get_origin() const
Getter for the origin of the corpus.
Definition: abg-corpus.cc:930
The private data and functions of the abigail::ir::corpus type.
string get_pretty_representation(const type_or_decl_base *tod, bool internal)
Build and return a copy of the pretty representation of an ABI artifact that could be either a type o...
Definition: abg-ir.cc:9286
const variables & exported_variables() const
Getter for the reference to the vector of exported variables. This vector is shared with with the cor...
Definition: abg-corpus.cc:142
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...
Definition: abg-corpus.cc:1576
const string & get_soname()
Getter for the soname property of the corpus.
Definition: abg-corpus.cc:1029
corpus::origin operator&(corpus::origin l, corpus::origin r)
Bitwise & operator for the corpus::origin type.
Definition: abg-corpus.cc:1802
const elf_symbols & get_sorted_undefined_var_symbols() const
Getter for a sorted vector of the variable symbols undefined in this corpus.
Definition: abg-corpus.cc:541
void set_symtab(symtab_reader::symtab_sptr)
Setter for the symtab object.
Definition: abg-corpus.cc:1121
virtual ~corpus_group()
Desctructor of the corpus_group type.
Definition: abg-corpus.cc:1907
const string & get_architecture_name() const
Getter for the architecture name of the corpus.
Definition: abg-corpus.cc:1051
virtual const std::unordered_set< function_decl * > * lookup_functions(const interned_string &id) const
Lookup the function which has a given function ID.
Definition: abg-corpus.cc:1399
virtual const string_elf_symbols_map_type & get_fun_symbol_map() const
Getter for the function symbols map.
Definition: abg-corpus.cc:1135
bool has_corpus(const string &)
Test if a corpus of a given path has been added to the group.
Definition: abg-corpus.cc:1953
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...
Definition: abg-corpus.cc:2180
bool do_log() const
Test if logging was requested.
Definition: abg-corpus.cc:710
std::unordered_set< const function_decl * > functions_set
Convenience typedef for std::unordered_set
Definition: abg-corpus.h:34
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.
Definition: abg-corpus.cc:2337
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.
Definition: abg-corpus.cc:1419
hash_t hash(uint64_t v, uint64_t seed)
Hash an integer value and combine it with a hash previously computed.
Definition: abg-hash.cc:196
vector< const function_decl * > functions
Convenience typedef for std::vector
Definition: abg-corpus.h:31
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.
Definition: abg-corpus.cc:1145
shared_ptr< exported_decls_builder > exported_decls_builder_sptr
Convenience typedef for shared_ptr.
Definition: abg-corpus.h:42
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)...
Definition: abg-corpus.cc:2267