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