From b2e5366d3f0819507006b4369f1fcc0aa93ca283 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Mon, 7 Sep 2015 22:27:50 +0200 Subject: [PATCH] Introduce the concept of environment There are resources needed by the type system and other artifacts of libabigail. Today, when the life time of those resources need to be greater than all of artifacts of Abigail, then said resources are made global. But then global resources are not great, if anything because they complicate the future use of the library in concurrent computing setups. As I was in the need to add one resource to be used by the type system, I decided to sit down and first overhaul how these long lived resources needed to be handled. And here comes the concept of "environment". An environment is a place where one can put resources that need to live longer than all the other artifacts of the Abigail system. And so, the code that creates Abigail artifacts needs and environment of for said artifacts to use. In other words, artifacts now use an environment. This has interesting and strong implications. We can only compare two artifacts if they use the same environment. This is quite a strong requirement. But then when this requirement is fulfilled, comparing two types amounts to just comparing two pointer values; hash values for types can also be cached. Now *that* is great for speed of comparison, is it not? This patch introduce the concept environment (which is basically a new abigail::ir::environment type), removes the global variables and uses the environment instead. Each ABI artifact (either type or decl) now has a ::get_environment() member function to get its environment. This patch also disables the caching of hash values because the caching must happen only *after* all types have been canonicalized. We were not respecting that requirement until now, and that introduces wrong hash values. A subsequent patch is going to re-introduce hash value caching again, once the infrastructure is in place to set a flag in the environment (hah!) once type canonicalization is done, and then later read that flag when some client code requests a hash value, to know if we should look in the hash value cache or not. The patch obviously changes the output of numerous regression tests (if anything b/c it disables hash value caching) so 'make check' yields regressions. But then, it's only the subsequent patch that updates the tests. * include/abg-ir.h: Adjust note about memory management. (class environment): Declare new class. (translation_unit::translation_unit): Take an environment in parameter. (translation_unit::{g,s}et_environment): Declare new member functions. (type_or_decl_base::{g,s}et_environment): Likewise. (type_or_decl_base::{get_cached_hash_value, set_cached_hash_value}): Change the name of decl_base::peek_hash_value() and decl_base::set_hash() here into these and move them here. (type_or_decl_base::hashing_started): Move decl_base::hashing_started() here. ({g,s}et_environment_for_artifact): Declare new functions. (class decl_base): Move member functions hashing_started(), peek_hash_value() and set_hash() on to the type_or_decl_base base class. (scope_decl::scope_decl): Initialize the virtual member type_or_decl_base(). (type_decl::{get_void_type_decl, get_variadic_parameter_type_decl}): Remove these static member functions. They are now non-static member functions of the new environment type. * src/abg-ir.cc (class environment_setter): New internal class. (get_canonical_types_map): Remove. This now becomes a member function of the environment type. (class usage_watchdog): Remove. (usage_watchdog_{s,w}ptr): Remove these typedefs. (get_usage_watchdog_wptr, ref_usage_watchdog) (maybe_cleanup_type_system_data): Remove these functions. (translation_unit::priv::usage_watchdog_): Remove data member. (translation_unit::priv::env_): New data member. (translation_unit::priv::priv): Take an environment and initialize the new env_ data member. Do not initialize the removed usage_watchdog_. (translation_unit::translation_unit): Take an environment parameter. (translation_unit::get_global_scope): Set the environment of a new global scope. (translation_unit::{g,s}et_environment): New accessors. (translation_unit::bind_function_type_life_time): Set the environment of the function type. (struct environment::priv): New class. (environment::{environment, ~environment, get_canonical_types_map, get_variadic_parameter_type_decl, canonicalization_is_done}): New member functions. (struct type_or_decl_base::priv): New class. (type_or_decl_base::{type_or_decl_base, hashing_started, get_cached_hash_value, set_cached_hash_value, set_environment, get_environment, traverse}): New member functions. ({s,g}get_environment_for_artifact): New functions. (decl_base::priv::{hash_, hashing_started}): Remove. (decl_base::priv::priv): Adjust. (decl_base::decl_base): In the copy constructor, initialize the virtual base type_or_decl_base. Do not initialize hash_ and hashing_started data member that got removed. (decl_base::{hashing_started, peek_hash_value, set_hash}): Remove member functions. (strip_typedef): Set the environment of the new type which has its typedefs stripped off. Adjust the call to type_or_void(). (scope_decl::{add, insert}_member_decl): Set the environment of the new member decl to the environment of its scope. (synthesize_type_from_translation_unit) (synthesize_function_type_from_translation_unit): Set the environment for the newly synthesized type. Adjust calls to type_or_void(). (type_or_void): Take an environment in parameter. Get the void type from the environment. (get_canonical_types_map): Remove. (type_base::get_canonical_type_for): Get the canonical types map from the environment, not from a global variable. (type_decl::{get_void_type_decl, get_variadic_parameter_type_decl}): Remove. (pointer_type_def::pointer_type_def): Adjust call to type_or_void. (reference_type_def::reference_type_def): Likewise. (function_decl::parameter::get_pretty_representation): Get the variadic parameter type decl from the environment. (class_decl::priv::classes_being_compared_): Remove static data member. (class_decl::priv::{mark_as_being_compared, unmark_as_being_compared, comparison_started): Use the "classes being compared" map from the environment. (class_decl::base_spec::get_hash): Adjust. (keep_type_alive): Get the alive types array from the environment) not from a global variable anymore. (get_next_string): Put the counter in thread-local storage. * src/abg-hash.cc (scope_decl::hash::operator()) (function_decl::hash::operator()): Do not handle caching (here). * include/abg-corpus.h (corpus::{g,s}et_environment): Declare new accessors. * src/abg-corpus.cc (corpus::priv::env): New data member. (corpus::priv::priv): Initialize it. (corpus::corpus): Take an environment in parameter. (corpus::{g,s}et_environment): Define new member functions (corpus::add): Set the environment of the newly added translation unit, if it's not set already set. In any case, assert that the translation unit must use the same environment as the corpus. * include/abg-dwarf-reader.h (create_read_context) (read_corpus_from_elf): Take an environment parameter. ({s,g}et_debug_info_root_path, {s,g}et_environment): Declare new functions. * src/abg-dwarf-reader.cc (read_context::{env_, offline_callbacks_}): New data members. (read_context::read_context): Initialize them. (read_context::clear_per_translation_unit_data): Do not touch the void type declaration, it doesn't belong to the translation unit. (read_context::{env, offline_callbacks}): New accessors. (read_context::{create_default_dwfl}): New member function. (read_context::dwfl_handle): Add a setter overload. ({s,g}et_debug_info_root_path): Define new accessors. (create_default_dwfl, create_dwfl_sptr, create_default_dwfl_sptr): Remove these. (build_translation_unit_and_add_to_ir): Adjust to pass the environment to the newly created translation unit. (build_function_decl): Adjust to pass the environment to the created function and parameter types. Get variadic parameter type node from the current environment, not from a global variable. And do not try to canonicalize function types here. (read_debug_info_into_corpus): Set the environment of the newly created corpus. (build_ir_node_for_void_type): Get the void type node from the current environment, rather than from a global variable. (create_read_context): Take the environment in parameter. Create the default dwarf front end library handle using the new member function of the read context. Set the current environment used by the reader. (read_corpus_from_elf): Take an environment in parameter. Overhaul. This is now simpler. (has_alt_debug_info): Adjust the call to create_read_context() to make it pass an empty environment. * include/abg-fwd.h (class environment): Forward declare. * include/abg-reader.h (read_translation_unit_from_file) (read_translation_unit_from_buffer) (read_translation_unit_from_istream) (read_corpus_from_native_xml): Take an environment in parameter. * src/abg-reader.cc (read_context::m_env): New data member. (read_context::read_context): Initialize it. (read_context::{get_environment, set_environment}): New data member. (read_translation_unit): Set environment of the new translation unit. (read_corpus_from_input): Set the environment of the new corpus. (read_translation_unit_from_file) (read_translation_unit_from_buffer) (read_translation_unit_from_istream, read_corpus_from_native_xml): Take an environment in parameter. (build_function_parameter): Get variadic parameter type from the environment. * src/abg-comparison.cc (compute_diff): Add asserts in all the overloads to ensure that the artifact being compared come from the same environment. * tests/print-diff-tree.cc (main): Create an env for the ABI artifacts to use. * tests/test-abidiff.cc (main): Likewise. * tests/test-diff-dwarf.cc (main): Likewise. * tests/test-ir-walker.cc (main): Likewise. * tests/test-read-dwarf.cc (main): Likewise. * tests/test-read-write.cc (main): Likewise. * tools/abicompat.cc (main): Likewise. * tools/abidiff.cc (main): Likewise. * tools/abidw.cc (main): Likewise. * tools/abilint.cc (main): Likewise. * tools/abipkgdiff.cc (main): Likewise. Signed-off-by: Dodji Seketeli --- include/abg-corpus.h | 11 +- include/abg-dwarf-reader.h | 22 +- include/abg-fwd.h | 3 +- include/abg-ir.h | 169 +++++++-- include/abg-reader.h | 18 +- src/abg-comparison.cc | 126 ++++++- src/abg-corpus.cc | 103 ++++-- src/abg-dwarf-reader.cc | 267 ++++++++------ src/abg-hash.cc | 27 +- src/abg-ir.cc | 702 +++++++++++++++++++++++-------------- src/abg-reader.cc | 80 +++-- tests/print-diff-tree.cc | 7 +- tests/test-abidiff.cc | 11 +- tests/test-diff-dwarf.cc | 5 + tests/test-ir-walker.cc | 4 +- tests/test-read-dwarf.cc | 12 +- tests/test-read-write.cc | 7 +- tools/abicompat.cc | 12 +- tools/abidiff.cc | 19 +- tools/abidw.cc | 6 +- tools/abilint.cc | 17 +- tools/abipkgdiff.cc | 5 +- 22 files changed, 1110 insertions(+), 523 deletions(-) diff --git a/include/abg-corpus.h b/include/abg-corpus.h index ee0dcf1a..09ee4481 100644 --- a/include/abg-corpus.h +++ b/include/abg-corpus.h @@ -78,7 +78,16 @@ private: public: - corpus(const string&); + corpus(const string&, ir::environment*); + + environment* + get_environment(); + + const environment* + get_environment() const; + + void + set_environment(environment*) const; void add(const translation_unit_sptr); diff --git a/include/abg-dwarf-reader.h b/include/abg-dwarf-reader.h index bdc71fe9..c72dbf9d 100644 --- a/include/abg-dwarf-reader.h +++ b/include/abg-dwarf-reader.h @@ -87,9 +87,9 @@ typedef shared_ptr read_context_sptr; read_context_sptr create_read_context(const std::string& elf_path, char** debug_info_root_path, + ir::environment* environment, bool read_all_types = false); - corpus_sptr read_corpus_from_elf(read_context& ctxt, status&); @@ -97,6 +97,7 @@ read_corpus_from_elf(read_context& ctxt, corpus_sptr read_corpus_from_elf(const std::string& elf_path, char** debug_info_root_path, + ir::environment* environment, bool load_all_types, status&); @@ -129,13 +130,30 @@ bool get_type_of_elf_file(const string& path, elf_type& type); +void +set_debug_info_root_path(read_context& ctxt, + char** path); + +char** +get_debug_info_root_path(read_context& ctxt, + char**& path); + bool get_show_stats(read_context_sptr& ctxt); void set_show_stats(read_context_sptr& ctxt, - bool f); + bool f); + +void +set_environment(read_context& ctxt, + ir::environment*); + +const environment_sptr& +get_environment(const read_context& ctxt); +environment_sptr& +get_environment(read_context& ctxt); }// end namespace dwarf_reader }// end namespace abigail diff --git a/include/abg-fwd.h b/include/abg-fwd.h index 38d9a900..27917832 100644 --- a/include/abg-fwd.h +++ b/include/abg-fwd.h @@ -77,6 +77,7 @@ namespace ir class corpus; // Forward declarations for ir. +class environment; class location; class location_manager; class translation_unit; @@ -662,7 +663,7 @@ string demangle_cplus_mangled_name(const string&); shared_ptr -type_or_void(const shared_ptr); +type_or_void(const shared_ptr, const environment*); shared_ptr canonicalize(shared_ptr); diff --git a/include/abg-ir.h b/include/abg-ir.h index f193eba5..5e9bab9d 100644 --- a/include/abg-ir.h +++ b/include/abg-ir.h @@ -57,13 +57,13 @@ /// abigail::type_base_sptr is added to the scope using the function /// abigail::add_decl_to_scope(). /// -/// There is a kind of type that is usually not syntactically owned by a -/// scope: it's function type. In libabigail function types are -/// represented by abigail::function_type and abigail::method_type. These -/// types must be owned by the translation unit they originate from. -/// Adding them to the translation unit must be done by a call to the -/// method function abigail::translation::get_canonical_function_type(). -/// The type returned by that function is the one to use. +/// There is a kind of type that is usually not syntactically owned by +/// a scope: it's function type. In libabigail, function types are +/// represented by abigail::function_type and abigail::method_type. +/// These types must be owned by the translation unit they originate +/// from. Adding them to the translation unit must be done by a call +/// to the method function +/// abigail::translation::bind_function_type_life_time(). /// /// A declaration that has a type does NOT own the type /// @@ -82,6 +82,12 @@ /// Likewise, data members, function and template parameters similarly /// have weak pointers on their type. /// +/// If, for a reason, you really need to keep a type alive for the +/// entire lifetime of the type system, then you can bind the life +/// time of that type to the life time of the @ref environment that is +/// supposed to outlive the type system. You do that by passing the +/// type to the function environment::keep_type_alive(). +/// /// @} namespace abigail @@ -95,6 +101,69 @@ namespace ir // Inject some std::tr1 types in here. using std::tr1::unordered_map; +/// Convenience typedef for a shared pointer on a @ref type_base +typedef shared_ptr type_base_sptr; + +/// Convenience typedef for a shared pointer on a @ref type_decl. +typedef shared_ptr type_decl_sptr; + +/// Convenience typedef for a shared pointer to an @ref environment +typedef shared_ptr environment_sptr; + +/// This is an abstraction of the set of resources necessary to manage +/// several aspects of the internal representations of the Abigail +/// library. +/// +/// An environment can be seen as the boundaries in which all related +/// Abigail artifacts live. So before doing anything using this +/// library, the first thing to create is, well, you know it now, an +/// environment. +/// +/// Note that the lifetime of environment objects must be longer than +/// the lifetime of any other type in the Abigail system. So a given +/// instance of @ref environment must stay around as long as you are +/// using libabigail. It's only when you are done using the library +/// that you can de-allocate the environment instance. +class environment +{ +public: + + // A convenience typedef for a map of canonical types. The a map + /// entry key is the hash value of a particular type and the value + /// is the list of canonical types that have the same hash value. + typedef std::tr1::unordered_map > canonical_types_map_type; + +private: + struct priv; + typedef shared_ptr priv_sptr; + + priv_sptr priv_; +public: + + environment(); + virtual ~environment(); + + canonical_types_map_type& + get_canonical_types_map(); + + const type_decl_sptr& + get_void_type_decl() const; + + const type_decl_sptr& + get_variadic_parameter_type_decl() const; + + bool + canonicalization_is_done() const; + + void + canonicalization_is_done(bool); + + friend class class_decl; + + friend void keep_type_alive(type_base_sptr); +}; // end class environment + /// @brief The source location of a token. /// /// This represents the location of a token coming from a given @@ -164,9 +233,6 @@ typedef shared_ptr translation_unit_sptr; /// Convenience typedef for a vector of @ref translation_unit_sptr. typedef std::vector translation_units; -/// Convenience typedef for a shared pointer on a @ref type_base -typedef shared_ptr type_base_sptr; - /// Convenience typedef for a weak pointer on a @ref type_base typedef weak_ptr type_base_wptr; @@ -255,11 +321,21 @@ public: }; public: - translation_unit(const std::string& path, - char address_size = 0); + translation_unit(const std::string& path, + ir::environment* env, + char address_size = 0); virtual ~translation_unit(); + const environment* + get_environment() const; + + environment* + get_environment(); + + void + set_environment(environment*); + language get_language() const; @@ -719,8 +795,40 @@ typedef shared_ptr type_or_decl_base_sptr; /// The base class of both types and declarations. class type_or_decl_base : public ir_traversable_base { + struct priv; + typedef shared_ptr priv_sptr; + mutable priv_sptr priv_; + +protected: + + size_t get_cached_hash_value() const; + + void set_cached_hash_value(size_t) const; + + bool hashing_started() const; + + void hashing_started(bool) const; + public: + + type_or_decl_base(); + + type_or_decl_base(const type_or_decl_base&); + virtual ~type_or_decl_base(); + + const environment* + get_environment() const; + + environment* + get_environment(); + + void + set_environment(environment*); + + virtual bool + traverse(ir_node_visitor&); + virtual string get_pretty_representation() const = 0; }; // end class type_or_decl_base @@ -731,6 +839,14 @@ operator==(const type_or_decl_base&, const type_or_decl_base&); bool operator==(const type_or_decl_base_sptr&, const type_or_decl_base_sptr&); +void +set_environment_for_artifact(type_or_decl_base* artifact, + environment* env); + +void +set_environment_for_artifact(type_or_decl_base_sptr artifact, + environment* env); + /// The base type of all declarations. class decl_base : public virtual type_or_decl_base { @@ -740,15 +856,6 @@ class decl_base : public virtual type_or_decl_base protected: mutable priv_sptr priv_; - bool - hashing_started() const; - - void - hashing_started(bool b) const; - - size_t - peek_hash_value() const; - const string& peek_qualified_name() const; @@ -823,9 +930,6 @@ public: virtual const string& get_qualified_name() const; - void - set_hash(size_t) const; - bool get_is_in_public_symbol_table() const; @@ -962,7 +1066,8 @@ public: scope_decl(const std::string& name, location locus, visibility vis = VISIBILITY_DEFAULT) - : decl_base(name, locus, /*mangled_name=*/name, vis) + : type_or_decl_base(), + decl_base(name, locus, /*mangled_name=*/name, vis) {} scope_decl(location l) : decl_base("", l) @@ -1074,7 +1179,6 @@ private: // Forbid this. type_base(); - static type_base_sptr get_canonical_type_for(type_base_sptr); @@ -1127,8 +1231,8 @@ public: /// Hash functor for instances of @ref type_base. struct type_base::hash { - size_t - operator()(const type_base& t) const; + size_t + operator()(const type_base& t) const; size_t operator()(const type_base* t) const; @@ -1180,9 +1284,6 @@ struct type_shared_ptr_equal bool equals(const type_decl&, const type_decl&, change_kind*); -/// Convenience typedef for a shared pointer on a @ref type_decl. -typedef shared_ptr type_decl_sptr; - /// A basic type declaration that introduces no scope. class type_decl : public virtual decl_base, public virtual type_base { @@ -1199,12 +1300,6 @@ public: location locus, const std::string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); - static type_decl_sptr& - get_void_type_decl(); - - static type_decl_sptr& - get_variadic_parameter_type_decl(); - virtual bool operator==(const type_base&) const; diff --git a/include/abg-reader.h b/include/abg-reader.h index 62f46d4e..eda20b8d 100644 --- a/include/abg-reader.h +++ b/include/abg-reader.h @@ -41,28 +41,34 @@ namespace xml_reader using namespace abigail::ir; translation_unit_sptr -read_translation_unit_from_file(const std::string& file_path); +read_translation_unit_from_file(const std::string& file_path, + environment* env); translation_unit_sptr -read_translation_unit_from_buffer(const std::string& file_path); +read_translation_unit_from_buffer(const std::string& file_path, + environment* env); translation_unit_sptr -read_translation_unit_from_istream(std::istream* in); +read_translation_unit_from_istream(std::istream* in, + environment* env); abigail::corpus_sptr read_corpus_from_file(const string& path); int -read_corpus_from_file(corpus_sptr& corp, const string& path); +read_corpus_from_file(corpus_sptr& corp, + const string& path); int read_corpus_from_file(corpus_sptr& corp); corpus_sptr -read_corpus_from_native_xml(std::istream* in); +read_corpus_from_native_xml(std::istream* in, + environment* env); corpus_sptr -read_corpus_from_native_xml_file(const string& path); +read_corpus_from_native_xml_file(const string& path, + environment* env); }//end xml_reader }//end namespace abigail diff --git a/src/abg-comparison.cc b/src/abg-comparison.cc index 854d8dc7..28b4ce99 100644 --- a/src/abg-comparison.cc +++ b/src/abg-comparison.cc @@ -6018,6 +6018,9 @@ compute_diff_for_decls(const decl_base_sptr first, /// Compute the difference between two decls. The decls can represent /// either type declarations, or non-type declaration. /// +/// Note that the two decls must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first decl to consider. /// /// @param second the second decl to consider. @@ -6034,6 +6037,8 @@ compute_diff(const decl_base_sptr first, if (!first || !second) return diff_sptr(); + assert(first->get_environment() == second->get_environment()); + diff_sptr d; if (is_type(first) && is_type(second)) d = compute_diff_for_types(first, second, ctxt); @@ -6045,6 +6050,9 @@ compute_diff(const decl_base_sptr first, /// Compute the difference between two types. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first type to consider. /// /// @param second the second type to consider. @@ -6060,6 +6068,10 @@ compute_diff(const type_base_sptr first, { decl_base_sptr f = get_type_declaration(first), s = get_type_declaration(second); + + if (first && second) + assert(first->get_environment() == second->get_environment()); + diff_sptr d = compute_diff_for_types(f,s, ctxt); assert(d); return d; @@ -6708,6 +6720,9 @@ var_diff::report(ostream& out, const string& indent) const /// Compute the diff between two instances of @ref var_decl. /// +/// Note that the two decls must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first @ref var_decl to consider for the diff. /// /// @param second the second @ref var_decl to consider for the diff. @@ -6720,6 +6735,9 @@ compute_diff(const var_decl_sptr first, const var_decl_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + var_diff_sptr d(new var_diff(first, second, diff_sptr(), ctxt)); ctxt->initialize_canonical_diff(d); return d; @@ -6921,6 +6939,9 @@ pointer_diff::report(ostream& out, const string& indent) const /// Compute the diff between between two pointers. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the pointer to consider for the diff. /// /// @param second the pointer to consider for the diff. @@ -6933,6 +6954,9 @@ compute_diff(pointer_type_def_sptr first, pointer_type_def_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + diff_sptr d = compute_diff_for_types(first->get_pointed_to_type(), second->get_pointed_to_type(), ctxt); @@ -7111,6 +7135,9 @@ array_diff::report(ostream& out, const string& indent) const /// Compute the diff between two arrays. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first array to consider for the diff. /// /// @param second the second array to consider for the diff. @@ -7121,6 +7148,9 @@ compute_diff(array_type_def_sptr first, array_type_def_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + diff_sptr d = compute_diff_for_types(first->get_element_type(), second->get_element_type(), ctxt); @@ -7288,6 +7318,9 @@ reference_diff::report(ostream& out, const string& indent) const /// Compute the diff between two references. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first reference to consider for the diff. /// /// @param second the second reference to consider for the diff. @@ -7298,6 +7331,9 @@ compute_diff(reference_type_def_sptr first, reference_type_def_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + diff_sptr d = compute_diff_for_types(first->get_pointed_to_type(), second->get_pointed_to_type(), ctxt); @@ -7514,6 +7550,9 @@ qualified_type_diff::report(ostream& out, const string& indent) const /// Compute the diff between two qualified types. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first qualified type to consider for the diff. /// /// @param second the second qualified type to consider for the diff. @@ -7524,6 +7563,9 @@ compute_diff(const qualified_type_def_sptr first, const qualified_type_def_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + diff_sptr d = compute_diff_for_types(first->get_underlying_type(), second->get_underlying_type(), ctxt); @@ -7883,6 +7925,9 @@ enum_diff::report(ostream& out, const string& indent) const /// Compute the set of changes between two instances of @ref /// enum_type_decl. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first a pointer to the first enum_type_decl to consider. /// /// @param second a pointer to the second enum_type_decl to consider. @@ -7896,6 +7941,9 @@ compute_diff(const enum_type_decl_sptr first, const enum_type_decl_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + diff_sptr ud = compute_diff_for_types(first->get_underlying_type(), second->get_underlying_type(), ctxt); @@ -9658,6 +9706,9 @@ class_diff::report(ostream& out, const string& indent) const /// Compute the set of changes between two instances of class_decl. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first class_decl to consider. /// /// @param second the second class_decl to consider. @@ -9670,6 +9721,9 @@ compute_diff(const class_decl_sptr first, const class_decl_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + class_decl_sptr f = look_through_decl_only_class(first), s = look_through_decl_only_class(second); @@ -9931,6 +9985,9 @@ base_diff::report(ostream& out, const string& indent) const /// Constructs the diff object representing a diff between two base /// class specifications. /// +/// Note that the two artifacts must have been created in the same +/// @ref environment, otherwise, this function aborts. +/// /// @param first the first base class specification. /// /// @param second the second base class specification. @@ -9943,6 +10000,9 @@ compute_diff(const class_decl::base_spec_sptr first, const class_decl::base_spec_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + class_diff_sptr cl = compute_diff(first->get_base_class(), second->get_base_class(), ctxt); @@ -10571,6 +10631,9 @@ scope_diff::report(ostream& out, const string& indent) const /// Compute the diff between two scopes. /// +/// Note that the two decls must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first scope to consider in computing the diff. /// /// @param second the second scope to consider in the diff @@ -10591,6 +10654,9 @@ compute_diff(const scope_decl_sptr first, { assert(d->first_scope() == first && d->second_scope() == second); + if (first && second) + assert(first->get_environment() == second->get_environment()); + compute_diff(first->get_member_decls().begin(), first->get_member_decls().end(), second->get_member_decls().begin(), @@ -10605,6 +10671,9 @@ compute_diff(const scope_decl_sptr first, /// Compute the diff between two scopes. /// +/// Note that the two decls must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first_scope the first scope to consider in computing the diff. /// /// @param second_scope the second scope to consider in the diff @@ -10618,6 +10687,10 @@ compute_diff(const scope_decl_sptr first_scope, const scope_decl_sptr second_scope, diff_context_sptr ctxt) { + if (first_scope && second_scope) + assert(first_scope->get_environment() + == second_scope->get_environment()); + scope_diff_sptr d(new scope_diff(first_scope, second_scope, ctxt)); d = compute_diff(first_scope, second_scope, d, ctxt); ctxt->initialize_canonical_diff(d); @@ -10779,6 +10852,9 @@ fn_parm_diff::chain_into_hierarchy() /// that is, between two function parameters. Return a resulting /// fn_parm_diff_sptr that represents the changes. /// +/// Note that the two decls must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first subject of the diff. /// /// @param second the second subject of the diff. @@ -10794,6 +10870,8 @@ compute_diff(const function_decl::parameter_sptr first, if (!first || !second) return fn_parm_diff_sptr(); + assert(first->get_environment() == second->get_environment()); + fn_parm_diff_sptr result(new fn_parm_diff(first, second, ctxt)); ctxt->initialize_canonical_diff(result); @@ -11189,6 +11267,9 @@ function_type_diff::chain_into_hierarchy() /// Compute the diff between two instances of @ref function_type. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first @ref function_type to consider for the diff. /// /// @param second the second @ref function_type to consider for the diff. @@ -11207,6 +11288,8 @@ compute_diff(const function_type_sptr first, return function_type_diff_sptr(); } + assert(first->get_environment() == second->get_environment()); + function_type_diff_sptr result(new function_type_diff(first, second, ctxt)); diff_utils::compute_diff(first->get_first_non_implicit_parm(), @@ -11672,6 +11755,9 @@ function_decl_diff::report(ostream& out, const string& indent) const /// Compute the diff between two function_decl. /// +/// Note that the two decls must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first the first function_decl to consider for the diff /// /// @param second the second function_decl to consider for the diff @@ -11690,6 +11776,8 @@ compute_diff(const function_decl_sptr first, return function_decl_diff_sptr(); } + assert(first->get_environment() == second->get_environment()); + function_type_diff_sptr type_diff = compute_diff(first->get_type(), second->get_type(), ctxt); @@ -11819,6 +11907,9 @@ type_decl_diff::report(ostream& out, const string& indent) const /// Compute a diff between two type_decl. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// This function doesn't actually compute a diff. As a type_decl is /// very simple (unlike compound constructs like function_decl or /// class_decl) it's easy to just compare the components of the @@ -11840,6 +11931,9 @@ compute_diff(const type_decl_sptr first, const type_decl_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + type_decl_diff_sptr result(new type_decl_diff(first, second, ctxt)); // We don't need to actually compute a diff here as a type_decl @@ -12013,6 +12107,9 @@ typedef_diff::report(ostream& out, const string& indent) const /// Compute a diff between two typedef_decl. /// +/// Note that the two types must have been created in the same @ref +/// environment, otherwise, this function aborts. +/// /// @param first a pointer to the first typedef_decl to consider. /// /// @param second a pointer to the second typedef_decl to consider. @@ -12025,6 +12122,9 @@ compute_diff(const typedef_decl_sptr first, const typedef_decl_sptr second, diff_context_sptr ctxt) { + if (first && second) + assert(first->get_environment() == second->get_environment()); + diff_sptr d = compute_diff_for_types(first->get_underlying_type(), second->get_underlying_type(), ctxt); @@ -12128,6 +12228,9 @@ translation_unit_diff::report(ostream& out, const string& indent) const /// Compute the diff between two translation_units. /// +/// Note that the two translation units must have been created in the +/// same @ref environment, otherwise, this function aborts. +/// /// @param first the first translation_unit to consider. /// /// @param second the second translation_unit to consider. @@ -12141,6 +12244,10 @@ compute_diff(const translation_unit_sptr first, const translation_unit_sptr second, diff_context_sptr ctxt) { + assert(first && second); + + assert(first->get_environment() == second->get_environment()); + if (!ctxt) ctxt.reset(new diff_context); @@ -14909,7 +15016,10 @@ corpus_diff::traverse(diff_node_visitor& v) return true; } -/// Compute the diff between two instances fo the @ref corpus +/// Compute the diff between two instances of @ref corpus. +/// +/// Note that the two corpora must have been created in the same @ref +/// environment, otherwise, this function aborts. /// /// @param f the first @ref corpus to consider for the diff. /// @@ -14928,6 +15038,12 @@ compute_diff(const corpus_sptr f, typedef elf_symbols::const_iterator symbols_it_type; typedef diff_utils::deep_ptr_eq_functor eq_type; + assert(f && s); + + // We can only compare two corpora that were built out of the same + // environment. + assert(f->get_environment() == s->get_environment()); + if (!ctxt) ctxt.reset(new diff_context); @@ -15920,11 +16036,15 @@ is_diff_of_variadic_parameter_type(const diff* d) return false; type_base_sptr t = is_type(d->first_subject()); - if (t && t.get() == type_decl::get_variadic_parameter_type_decl().get()) + if (t + && (t.get() + == t->get_environment()->get_variadic_parameter_type_decl().get())) return true; t = is_type(d->second_subject()); - if (t && t.get() == type_decl::get_variadic_parameter_type_decl().get()) + if (t + && (t.get() + == t->get_environment()->get_variadic_parameter_type_decl().get())) return true; return false; diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc index f5b34310..0e49e098 100644 --- a/src/abg-corpus.cc +++ b/src/abg-corpus.cc @@ -750,38 +750,41 @@ corpus::exported_decls_builder::maybe_add_var_to_exported_vars(var_decl* var) struct corpus::priv { - corpus::exported_decls_builder_sptr exported_decls_builder; - origin origin_; - vector regex_patterns_fns_to_suppress; - vector regex_patterns_vars_to_suppress; - vector regex_patterns_fns_to_keep; - vector regex_patterns_vars_to_keep; - vector sym_id_fns_to_keep; - vector sym_id_vars_to_keep; - string path; - vector needed; - string soname; - string architecture_name; - translation_units members; - vector fns; - vector vars; - string_elf_symbols_map_sptr var_symbol_map; - string_elf_symbols_map_sptr undefined_var_symbol_map; - elf_symbols sorted_var_symbols; - elf_symbols sorted_undefined_var_symbols; - string_elf_symbols_map_sptr fun_symbol_map; - string_elf_symbols_map_sptr undefined_fun_symbol_map; - elf_symbols sorted_fun_symbols; - elf_symbols sorted_undefined_fun_symbols; - elf_symbols unrefed_fun_symbols; - elf_symbols unrefed_var_symbols; + environment* env; + corpus::exported_decls_builder_sptr exported_decls_builder; + origin origin_; + vector regex_patterns_fns_to_suppress; + vector regex_patterns_vars_to_suppress; + vector regex_patterns_fns_to_keep; + vector regex_patterns_vars_to_keep; + vector sym_id_fns_to_keep; + vector sym_id_vars_to_keep; + string path; + vector needed; + string soname; + string architecture_name; + translation_units members; + vector fns; + vector vars; + string_elf_symbols_map_sptr var_symbol_map; + string_elf_symbols_map_sptr undefined_var_symbol_map; + elf_symbols sorted_var_symbols; + elf_symbols sorted_undefined_var_symbols; + string_elf_symbols_map_sptr fun_symbol_map; + string_elf_symbols_map_sptr undefined_fun_symbol_map; + elf_symbols sorted_fun_symbols; + elf_symbols sorted_undefined_fun_symbols; + elf_symbols unrefed_fun_symbols; + elf_symbols unrefed_var_symbols; private: priv(); public: - priv(const string &p) - : origin_(ARTIFICIAL_ORIGIN), + priv(const string & p, + environment* e) + : env(e), + origin_(ARTIFICIAL_ORIGIN), path(p) {} @@ -1027,19 +1030,51 @@ corpus::priv::build_unreferenced_symbols_tables() } } +/// Constructor of the @ref corpus type. +/// /// @param path the path to the file containing the ABI corpus. -corpus::corpus(const string& path) -{priv_.reset(new priv(path));} +/// +/// @param env the environment of the corpus. +corpus::corpus(const string& path, ir::environment* env) +{priv_.reset(new priv(path, env));} + +/// Getter of the enviroment of the corpus. +/// +/// @return the environment of this corpus. +const environment* +corpus::get_environment() const +{return priv_->env;} -/// Add a translation unit to the current ABI Corpus. Next time -/// corpus::save is called, all the translation unit that got added -/// to the corpus are going to be serialized on disk in the file +/// Getter of the enviroment of the corpus. +/// +/// @return the environment of this corpus. +environment* +corpus::get_environment() +{return priv_->env;} + +/// Setter of the environment of this corpus. +/// +/// @param e the new environment. +void +corpus::set_environment(environment* e) const +{priv_->env = e;} + +/// Add a translation unit to the current ABI Corpus. Next time +/// corpus::save is called, all the translation unit that got added to +/// the corpus are going to be serialized on disk in the file /// associated to the current corpus. /// /// @param tu the new translation unit to add. void corpus::add(const translation_unit_sptr tu) -{priv_->members.push_back(tu);} +{ + if (!tu->get_environment()) + tu->set_environment(get_environment()); + + assert(tu->get_environment() == get_environment()); + + priv_->members.push_back(tu); +} /// Return the list of translation units of the current corpus. /// @@ -1076,7 +1111,7 @@ corpus::set_origin(origin o) /// the abi file expected at this path; likewise, a call to /// corpus::write will serialize the translation units contained in /// the corpus object into the on-disk file at this path. - +/// /// @return the file path associated to the current corpus. string& corpus::get_path() const diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc index 0d59f7d0..7aa2eeb9 100644 --- a/src/abg-dwarf-reader.cc +++ b/src/abg-dwarf-reader.cc @@ -1713,7 +1713,9 @@ lookup_public_variable_symbol_from_elf(Elf* elf, /// get some important data from it. class read_context { + environment* env_; unsigned short dwarf_version_; + Dwfl_Callbacks offline_callbacks_; dwfl_sptr handle_; Dwarf* dwarf_; // The alternate debug info. Alternate debug info sections are a @@ -1778,16 +1780,16 @@ class read_context read_context(); public: - read_context(dwfl_sptr handle, - const string& elf_path) - : dwarf_version_(0), - handle_(handle), - dwarf_(0), - alt_dwarf_(0), - elf_module_(0), - elf_handle_(0), + read_context(const string& elf_path) + : env_(), + dwarf_version_(), + handle_(), + dwarf_(), + alt_dwarf_(), + elf_module_(), + elf_handle_(), elf_path_(elf_path), - cur_tu_die_(0), + cur_tu_die_(), symtab_section_(), symbol_versionning_sections_loaded_(), symbol_versionning_sections_found_(), @@ -1797,7 +1799,9 @@ public: exported_decls_builder_(), load_all_types_(), show_stats_() - {} + { + memset(&offline_callbacks_, 0, sizeof(offline_callbacks_)); + } /// Clear the data that is relevant only for the current translation /// unit being read. The rest of the data is relevant for the @@ -1808,7 +1812,6 @@ public: while (!scope_stack().empty()) scope_stack().pop(); var_decls_to_re_add_to_tree().clear(); - type_decl::get_void_type_decl()->set_scope(0); } /// Clear the data that is relevant for the current corpus being @@ -1824,6 +1827,67 @@ public: types_to_canonicalize(/*in_alt_di=*/false).clear(); } + /// Getter for the current environment. + /// + /// @return the current environment. + const ir::environment* + env() const + {return env_;} + + /// Getter for the current environment. + /// + /// @return the current environment. + ir::environment* + env() + {return env_;} + + /// Setter for the current environment. + /// + /// @param env the new current environment. + void + env(ir::environment* env) + {env_ = env;} + + /// Getter for the callbacks of the Dwarf Front End library of + /// elfutils that is used by this reader to read dwarf. + /// + /// @return the callbacks. + const Dwfl_Callbacks* + offline_callbacks() const + {return &offline_callbacks_;} + + /// Getter for the callbacks of the Dwarf Front End library of + /// elfutils that is used by this reader to read dwarf. + /// @returnthe callbacks + Dwfl_Callbacks* + offline_callbacks() + {return &offline_callbacks_;} + + /// Constructor for a default Dwfl handle that knows how to load debug + /// info from a library or executable elf file. + /// + /// @param debug_info_root_path a pointer to the root path under which + /// to look for the debug info of the elf files that are later handled + /// by the Dwfl. This for cases where the debug info is split into a + /// different file from the binary we want to inspect. On Red Hat + /// compatible systems, this root path is usually /usr/lib/debug by + /// default. If this argument is set to NULL, then "./debug" and + /// /usr/lib/debug will be searched for sub-directories containing the + /// debug info file. Note that for now, elfutils wants this path to + /// be absolute otherwise things just don't work and the debug info is + /// not found. + /// + /// @return the constructed Dwfl handle. + void + create_default_dwfl(char** debug_info_root_path) + { + offline_callbacks()->find_debuginfo = dwfl_standard_find_debuginfo; + offline_callbacks()->section_address = dwfl_offline_section_address; + offline_callbacks()->debuginfo_path = debug_info_root_path; + handle_.reset(dwfl_begin(offline_callbacks()), + dwfl_deleter()); + } + unsigned short dwarf_version() const {return dwarf_version_;} @@ -1832,10 +1896,22 @@ public: dwarf_version(unsigned short v) {dwarf_version_ = v;} + /// Getter for a smart pointer to a handle on the dwarf front end + /// library that we use to read dwarf. + /// + /// @return the dwfl handle. dwfl_sptr dwfl_handle() const {return handle_;} + /// Setter for a smart pointer to a handle on the dwarf front end + /// library that we use to read dwarf. + /// + /// @param h the new dwfl handle. + void + dwfl_handle(dwfl_sptr& h) + {handle_ = h;} + Dwfl_Module* elf_module() const {return elf_module_;} @@ -3706,6 +3782,28 @@ finish_member_function_reading(Dwarf_Die* die, function_decl_sptr f, class_decl_sptr klass); +/// Setter of the debug info root path for a dwarf reader context. +/// +/// @param ctxt the dwarf reader context to consider. +/// +/// @param path the new debug info root path. This must be a pointer to a +/// character string which life time should be greater than the life +/// time of the read context. +void +set_debug_info_root_path(read_context& ctxt, char** path) +{ctxt.offline_callbacks()->debuginfo_path = path;} + +/// Setter of the debug info root path for a dwarf reader context. +/// +/// @param ctxt the dwarf reader context to consider. +/// +/// @return a pointer to the the debug info root path. +/// +/// time of the read context. +char** +get_debug_info_root_path(read_context& ctxt) +{return ctxt.offline_callbacks()->debuginfo_path;} + /// Getter of the "show_stats" flag. /// /// This flag tells if we should emit statistics about various @@ -3715,12 +3813,8 @@ finish_member_function_reading(Dwarf_Die* die, /// /// @return the value of the flag. bool -get_show_stats(read_context_sptr& ctxt) -{ - if(!ctxt) - return false; - return ctxt->show_stats(); -} +get_show_stats(read_context& ctxt) +{return ctxt.show_stats();} /// Setter of the "show_stats" flag. /// @@ -3731,68 +3825,8 @@ get_show_stats(read_context_sptr& ctxt) /// /// @param f the value of the flag. void -set_show_stats(read_context_sptr& ctxt, - bool f) -{ - if (ctxt) - ctxt->show_stats(f); -} - -/// Constructor for a default Dwfl handle that knows how to load debug -/// info from a library or executable elf file. -/// -/// @param debug_info_root_path a pointer to the root path under which -/// to look for the debug info of the elf files that are later handled -/// by the Dwfl. This for cases where the debug info is split into a -/// different file from the binary we want to inspect. On Red Hat -/// compatible systems, this root path is usually /usr/lib/debug by -/// default. If this argument is set to NULL, then "./debug" and -/// /usr/lib/debug will be searched for sub-directories containing the -/// debug info file. Note that for now, elfutils wants this path to -/// be absolute otherwise things just don't work and the debug info is -/// not found. -/// -/// @return the constructed Dwfl handle. -static Dwfl* -create_default_dwfl(char** debug_info_root_path) -{ - static Dwfl_Callbacks offline_callbacks; - - memset(&offline_callbacks, 0, sizeof(offline_callbacks)); - offline_callbacks.find_debuginfo = dwfl_standard_find_debuginfo; - offline_callbacks.section_address = dwfl_offline_section_address; - offline_callbacks.debuginfo_path = debug_info_root_path; - return dwfl_begin(&offline_callbacks); -} - -/// Create a shared pointer for a pointer to Dwfl. -/// -/// @param dwfl the pointer to Dwfl to create the shared pointer for. -/// -/// @return the newly created shared pointer. -static dwfl_sptr -create_dwfl_sptr(Dwfl* dwfl) -{ - dwfl_sptr result(dwfl, dwfl_deleter()); - return result; -} - -/// Create a shared pointer to a default Dwfl handle. This uses the -/// create_default_dwfl() function. -/// -/// @param di_path a pointer to the root path under which to look for -/// the debug info of the elf files that are later handled by the -/// Dwfl. This for cases where the debug info is split into a -/// different file from the binary we want to inspect. On Red Hat -/// compatible systems, this root path is usually /usr/lib/debug by -/// default. If this argument is set to NULL, then "./debug" and -/// /usr/lib/debug will be searched for sub-directories containing the -/// debug info file. -/// -/// @return the created shared pointer. -static dwfl_sptr -create_default_dwfl_sptr(char** di_path) -{return create_dwfl_sptr(create_default_dwfl(di_path));} +set_show_stats(read_context& ctxt, bool f) +{ctxt.show_stats(f);} /// Get the value of an attribute that is supposed to be a string, or /// an empty string if the attribute could not be found. @@ -6059,7 +6093,9 @@ build_translation_unit_and_add_to_ir(read_context& ctxt, ctxt.cur_tu_die(die); string path = die_string_attribute(die, DW_AT_name); - result.reset(new translation_unit(path, address_size)); + result.reset(new translation_unit(path, + ctxt.env(), + address_size)); size_t l = 0; die_unsigned_constant_attribute(die, DW_AT_language, l); @@ -6756,8 +6792,8 @@ build_qualified_type(read_context& ctxt, /// Strip qualification from a qualified type, when it makes sense. /// /// DWARF constructs "const reference". This is redundant because a -/// reference is always const. The issue is these redundant type then -/// leaks into the IR and makes for bad diagnostics. +/// reference is always const. The issue is these redundant types then +/// leak into the IR and make for bad diagnostics. /// /// This function thus strips the const qualifier from the type in /// that case. It might contain code to strip other cases like this @@ -7329,8 +7365,9 @@ build_function_decl(read_context& ctxt, { // This is a variadic function parameter. bool is_artificial = die_is_artificial(&child); - type_decl_sptr parm_type = - type_decl::get_variadic_parameter_type_decl(); + ir::environment* env = ctxt.env(); + assert(env); + type_decl_sptr parm_type = env->get_variadic_parameter_type_decl(); function_decl::parameter_sptr p (new function_decl::parameter(parm_type, /*name=*/"", @@ -7396,8 +7433,6 @@ build_function_decl(read_context& ctxt, is_in_alt_di, result->get_type()); - maybe_canonicalize_type(dwarf_dieoffset(die), is_in_alt_di, ctxt); - return result; } @@ -7416,8 +7451,10 @@ read_debug_info_into_corpus(read_context& ctxt) if (!ctxt.current_corpus()) { - corpus_sptr corp (new corpus(ctxt.elf_path())); + corpus_sptr corp (new corpus(ctxt.elf_path(), ctxt.env())); ctxt.current_corpus(corp); + if (!ctxt.env()) + ctxt.env(corp->get_environment()); } if (!ctxt.dwarf()) @@ -8046,7 +8083,9 @@ build_ir_node_from_die(read_context& ctxt, static decl_base_sptr build_ir_node_for_void_type(read_context& ctxt) { - decl_base_sptr t = type_decl::get_void_type_decl(); + ir::environment* env = ctxt.env(); + assert(env); + decl_base_sptr t = env->get_void_type_decl(); if (!has_scope(t)) add_decl_to_scope(t, ctxt.cur_tu()->get_global_scope()); canonicalize(is_type(t)); @@ -8134,6 +8173,17 @@ operator&=(status& l, status r) /// debug info is to be found for @p elf_path. Leave this to NULL if /// the debug info is not in a split file. /// +/// @param environment the environment used by the current context. +/// This environment contains resources needed by the reader and by +/// the types and declarations that are to be created later. Note +/// that ABI artifacts that are to be compared all need to be created +/// within the same environment. +/// +/// Please also note that the life time of this environment object +/// must be greater than the life time of the resulting @ref +/// read_context the context uses resources that are allocated in the +/// environment. +/// /// @param load_all_types if set to false only the types that are /// reachable from publicly exported declarations (of functions and /// variables) are read. If set to true then all types found in the @@ -8141,15 +8191,17 @@ operator&=(status& l, status r) /// /// @return a smart pointer to the resulting dwarf_reader::read_context. read_context_sptr -create_read_context(const std::string& elf_path, - char** debug_info_root_path, - bool load_all_types) +create_read_context(const std::string& elf_path, + char** debug_info_root_path, + ir::environment* environment, + bool load_all_types) { // Create a DWARF Front End Library handle to be used by functions // of that library. - dwfl_sptr handle = create_default_dwfl_sptr(debug_info_root_path); - read_context_sptr result(new read_context(handle, elf_path)); + read_context_sptr result(new read_context(elf_path)); + result->create_default_dwfl(debug_info_root_path); result->load_all_types(load_all_types); + result->env(environment); return result; } @@ -8214,6 +8266,15 @@ read_corpus_from_elf(read_context& ctxt, status& status) /// /usr/lib/debug will be searched for sub-directories containing the /// debug info file. /// +/// @param environment the environment used by the current context. +/// This environment contains resources needed by the reader and by +/// the types and declarations that are to be created later. Note +/// that ABI artifacts that are to be compared all need to be created +/// within the same environment. Also, the lifetime of the +/// environment must be greater than the lifetime of the resulting +/// corpus because the corpus uses resources that are allocated in the +/// environment. +/// /// @param load_all_types if set to false only the types that are /// reachable from publicly exported declarations (of functions and /// variables) are read. If set to true then all types found in the @@ -8224,18 +8285,16 @@ read_corpus_from_elf(read_context& ctxt, status& status) /// @return the resulting status. corpus_sptr read_corpus_from_elf(const std::string& elf_path, - char** debug_info_root_path, - bool load_all_types, - status& status) + char** debug_info_root_path, + ir::environment* environment, + bool load_all_types, + status& status) { - // Create a DWARF Front End Library handle to be used by functions - // of that library. - dwfl_sptr handle = create_default_dwfl_sptr(debug_info_root_path); - - read_context_sptr c = create_read_context(elf_path, debug_info_root_path); - c->load_all_types(load_all_types); + read_context_sptr c = create_read_context(elf_path, + debug_info_root_path, + environment, + load_all_types); read_context& ctxt = *c; - return read_corpus_from_elf(ctxt, status); } @@ -8390,7 +8449,7 @@ has_alt_debug_info(const string& elf_path, bool& has_alt_di, string& alt_debug_info_path) { - read_context_sptr c = create_read_context(elf_path, debug_info_root_path); + read_context_sptr c = create_read_context(elf_path, debug_info_root_path, 0); read_context& ctxt = *c; // Load debug info from the elf path. diff --git a/src/abg-hash.cc b/src/abg-hash.cc index 01261dd5..d20afead 100644 --- a/src/abg-hash.cc +++ b/src/abg-hash.cc @@ -145,18 +145,15 @@ struct type_decl::hash size_t scope_decl::hash::operator()(const scope_decl& d) const { - if (d.peek_hash_value() == 0 || d.hashing_started()) - { - std::tr1::hash hash_string; - size_t v = hash_string(typeid(d).name()); - for (scope_decl::declarations::const_iterator i = - d.get_member_decls().begin(); - i != d.get_member_decls().end(); - ++i) - v = hashing::combine_hashes(v, (*i)->get_hash()); - d.set_hash(v); - } - return d.peek_hash_value(); + std::tr1::hash hash_string; + size_t v = hash_string(typeid(d).name()); + for (scope_decl::declarations::const_iterator i = + d.get_member_decls().begin(); + i != d.get_member_decls().end(); + ++i) + v = hashing::combine_hashes(v, (*i)->get_hash()); + + return v; } /// Hashing operator for the @ref scope_decl type. @@ -375,9 +372,6 @@ var_decl::hash::operator()(const var_decl* t) const size_t function_decl::hash::operator()(const function_decl& t) const { - if (t.peek_hash_value() != 0) - return t.peek_hash_value(); - std::tr1::hash hash_int; std::tr1::hash hash_size_t; std::tr1::hash hash_bool; @@ -406,9 +400,6 @@ function_decl::hash::operator()(const function_decl& t) const v = hashing::combine_hashes(v, hash_size_t(voffset)); } - if (t.get_type() && (t.get_type()->get_canonical_type() != 0)) - t.set_hash(v); - return v; } diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 81a49a98..b7485d6b 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -36,109 +36,78 @@ #include "abg-sptr-utils.h" #include "abg-ir.h" -namespace abigail +namespace { - -namespace ir +/// This internal type is a tree walker that walks the sub-tree of a +/// type and sets the environment of the type (including its sub-type) +/// to a new environment. +class environment_setter : public abigail::ir::ir_node_visitor { + abigail::ir::type_or_decl_base* artifact_; + abigail::ir::environment* env_; -// Inject. -using std::string; -using std::list; -using std::vector; -using std::tr1::unordered_map; -using std::tr1::dynamic_pointer_cast; -using std::tr1::static_pointer_cast; - -// A convenience typedef for a map of canonical types. The a map -/// entry key is the hash value of a particular type and the value -/// is the list of canonical types that have the same hash value. -typedef std::tr1::unordered_map > canonical_types_map_type; - -static canonical_types_map_type& get_canonical_types_map(); +public: + environment_setter(abigail::ir::type_or_decl_base* a, + abigail::ir::environment* env) + : artifact_(a), + env_(env) + {} -/// This is a type which instance is referenced by relevant users -/// (types) of the type system, so that we can know when the type -/// system is 'used' or not. -/// -/// It can then serve to detect when the type system is not used -/// anymore, so that resources that should stay live only during the -/// life time of *users* of the type system can be deallocated. -/// -/// A kind of canary in a coal mine, so to speak. -class usage_watchdog -{}; + /// This function is called on each sub-tree node that is a + /// declaration. Note that it's also called on some types because + /// most types that have a declarations also inherit the type @ref + /// decl_base. + /// + /// @param d the declaration being visited. + bool + visit_begin(abigail::ir::decl_base* d) + { + if (abigail::ir::environment* env = d->get_environment()) + { + assert(env == env_); + return false; + } + else + d->set_environment(env_); -/// A convenience typedef for a shared pointer to @ref usage_watchdog. -typedef shared_ptr usage_watchdog_sptr; + return true; -/// A convenience typedef for a weak pointer to @ref usage_watchdog. -typedef weak_ptr usage_watchdog_wptr; + } -/// Getter of the usage watchdog. -/// -/// Note that this getter does *not* increment the usage count of the -/// watchdog. -/// -/// @return a reference on the usage watchdog. -static usage_watchdog_sptr& -get_usage_watchdog() -{ - static usage_watchdog_sptr watchdog; - return watchdog; + /// This function is called on each sub-tree node that is a type. + /// + /// @param t the type being visited. + bool + visit_begin(abigail::ir::type_base* t) + { + if (abigail::ir::environment* env = t->get_environment()) + { + assert(env == env_); + return false; + } + else + { + assert(!t->get_environment()); + t->set_environment(env_); + } + return true; + } +}; } -/// Getter of a weak pointer to the usage watchdog. -/// -/// This weak pointer on the usage watchdog allows users to test if -/// the usage watchdog is referenced by someone else or not. This -/// test is done via the method weak_ptr::expired(). What a wonderful -/// method ... -/// -/// @return a reference to the weak pointer to the usage watchdog. -static usage_watchdog_wptr& -get_usage_watchdog_wptr() +namespace abigail { - static usage_watchdog_wptr watchdog; - return watchdog; -} -/// Increase the reference count of the usage watchdog. -/// -/// Actually this function returns a shared pointer to the usage -/// pointer. Storing that shared pointer is what increases the -/// reference count of the watchdog. When the shared pointer that -/// stores the returned usage watchdog is destroyed, the reference -/// count goes down. -/// -/// @return a shared pointer to the usage watchdog so that its -/// reference count can be increased by the simple fact of storing it. -static usage_watchdog_sptr -ref_usage_watchdog() +namespace ir { - usage_watchdog_sptr result; - if (!get_usage_watchdog()) - { - usage_watchdog_sptr w(new usage_watchdog); - get_usage_watchdog() = w; - get_usage_watchdog_wptr() = w; - } - result = get_usage_watchdog(); - - return result; -} -/// Test if the reference count of the usage watchdog shared point -/// reached zero. If yes, cleanup the data of the type system that is -/// supposed to stay live only as long as the usage watchdog shared -/// pointer is live. -static void -maybe_cleanup_type_system_data() -{ - if (!get_usage_watchdog_wptr().expired()) - get_canonical_types_map().clear(); -} +// Inject. +using std::string; +using std::list; +using std::vector; +using std::tr1::unordered_map; +using std::tr1::dynamic_pointer_cast; +using std::tr1::static_pointer_cast; /// @brief the location of a token represented in its simplest form. /// Instances of this type are to be stored in a sorted vector, so the @@ -249,7 +218,7 @@ typedef unordered_map synthesized_types_; - priv() - : is_constructed_(), + priv(environment* env) + : env_(env), + is_constructed_(), address_size_(), language_(LANG_UNKNOWN) - { - // Note that translation units own types. - // - // There is data in the type system that is global and that should - // have the same lifetime as the type system itself. So when the - // type system has no more users, its global data should be - // de-allocated. - // - // So let's say that we are using the type system. We say this by - // increasing the reference count of the shared pointer to the - // usage watchdog of the type system. When that ref-count goes to - // zero, that means the type system has no more use. At that - // point the global data of the type system needs to be - // de-allocated. This is done in the destructor of this - // translation_unit::priv type. - usage_watchdog_ = ref_usage_watchdog(); - } + {} ~priv() - { - // So when the translation unit is de-allocated, let's de-allocate - // type system data that should not outlive translation units. - maybe_cleanup_type_system_data(); - } + {} }; // end translation_unit::priv // @@ -295,11 +245,17 @@ struct translation_unit::priv /// /// @param path the location of the translation unit. /// +/// @param env the environment of this translation unit. Please note +/// that the life time of the environment must be greater than the +/// life time of the translation unit because the translation uses +/// resources that are allocated in the environment. +/// /// @param address_size the size of addresses in the translation unit, /// in bits. -translation_unit::translation_unit(const std::string& path, - char address_size) - : priv_(new priv) +translation_unit::translation_unit(const std::string& path, + environment* env, + char address_size) + : priv_(new priv(env)) { priv_->path_ = path; priv_->address_size_ = address_size; @@ -314,11 +270,38 @@ const shared_ptr translation_unit::get_global_scope() const { if (!priv_->global_scope_) - priv_->global_scope_.reset - (new global_scope(const_cast(this))); + { + priv_->global_scope_.reset + (new global_scope(const_cast(this))); + // The global scope must be out of the same environment as its + // translation unit. + priv_->global_scope_-> + set_environment(const_cast(get_environment())); + } return priv_->global_scope_; } +/// Getter of the environment of the current @ref translation_unit. +/// +/// @return the translation unit of the current translation unit. +const environment* +translation_unit::get_environment() const +{return priv_->env_;} + +/// Getter of the environment of the current @ref translation_unit. +/// +/// @return the translation unit of the current translation unit. +environment* +translation_unit::get_environment() +{return priv_->env_;} + +/// Setter of the environment of the current @ref translation_unit. +/// +/// @param env the environment. +void +translation_unit::set_environment(environment* env) +{priv_->env_ = env;} + /// Getter of the language of the source code of the translation unit. /// /// @return the language of the source code. @@ -441,7 +424,16 @@ translation_unit::operator==(const translation_unit& other)const /// function type can be destroyed to. void translation_unit::bind_function_type_life_time(function_type_sptr ftype) const -{priv_->function_types_.push_back(ftype);} +{ + priv_->function_types_.push_back(ftype); + + // The function type must be ouf of the same environment as its + // translation unit. + if (const environment* env = get_environment()) + assert(env == get_environment()); + + ftype->set_environment(const_cast(get_environment())); +} /// This implements the ir_traversable_base::traverse virtual /// function. @@ -1571,13 +1563,218 @@ elf_symbol::version::operator=(const elf_symbol::version& o) dm_context_rel::~dm_context_rel() {} +// + +/// The private data of the @ref environment type. +struct environment::priv +{ + bool canonicalization_is_done_; + canonical_types_map_type canonical_types_; + type_decl_sptr void_type_decl_; + type_decl_sptr variadic_marker_type_decl_; + unordered_map classes_being_compared_; + vector extra_live_types_; + + priv() + : canonicalization_is_done_() + {} +};// end struct environment::priv + +/// Default constructor of the @ref environment type. +environment::environment() + :priv_(new priv) +{} + +/// Destructor for the @ref environment type. +environment::~environment() +{} + +/// Getter the map of canonical types. +/// +/// @return the map of canonical types. The key of the map is the +/// hash of the canonical type and its value if the canonical type. +environment::canonical_types_map_type& +environment::get_canonical_types_map() +{return priv_->canonical_types_;} + +/// Get a @ref type_decl that represents a "void" type for the current +/// environment. +/// +/// @return the @ref type_decl that represents a "void" type. +const type_decl_sptr& +environment::get_void_type_decl() const +{ + if (!priv_->void_type_decl_) + { + priv_->void_type_decl_.reset(new type_decl("void", 0, 0, location())); + priv_->void_type_decl_->set_environment(const_cast(this)); + } + return priv_->void_type_decl_; +} + +/// Get a @ref type_decl instance that represents a the type of a +/// variadic function parameter. +/// +/// @return the Get a @ref type_decl instance that represents a the +/// type of a variadic function parameter. +const type_decl_sptr& +environment::get_variadic_parameter_type_decl() const +{ + if (!priv_->variadic_marker_type_decl_) + { + priv_->variadic_marker_type_decl_. + reset(new type_decl("variadic parameter type", + 0, 0, location())); + priv_->variadic_marker_type_decl_-> + set_environment(const_cast(this)); + } + return priv_->variadic_marker_type_decl_; +} + +/// Test if the canonicalization of types created out of the current +/// environment is done. +/// +/// @return true iff the canonicalization of types created out of the current +/// environment is done. +bool +environment::canonicalization_is_done() const +{return priv_->canonicalization_is_done_;} + +/// Set a flag saying if the canonicalization of types created out of +/// the current environment is done or not. +/// +/// Note that this function must only be called by internal code of +/// the library that creates ABI artifacts (e.g, read an abi corpus +/// from elf or from our own xml format and creates representations of +/// types out of it) and thus needs to canonicalize types to speed-up +/// further type comparison. +/// +/// @param f the new value of the flag. +void +environment::canonicalization_is_done(bool f) +{priv_->canonicalization_is_done_ = f;} + +// // +/// The private data of @ref type_or_decl_base. +struct type_or_decl_base::priv +{ + // If a non-scalar data member is added, please think about adding a + // copy operator for this type. + size_t hash_; + bool hashing_started_; + environment* env_; + + priv() + : hash_(), + hashing_started_(), + env_() + {} +}; // end struct type_or_decl_base + +/// Default constructor of @ref type_or_decl_base. +type_or_decl_base::type_or_decl_base() + :priv_(new priv) +{} + +/// Copy constructor of @ref type_or_decl_base. +type_or_decl_base::type_or_decl_base(const type_or_decl_base& o) +{*priv_ = *o.priv_;} + /// The destructor of the @ref type_or_decl_base type. type_or_decl_base::~type_or_decl_base() {} +/// Getter for the 'hashing_started' property. +/// +/// @return the 'hashing_started' property. +bool +type_or_decl_base::hashing_started() const +{return priv_->hashing_started_;} + +/// Setter for the 'hashing_started' property. +/// +/// @param b the value to set the 'hashing_property' to. +void +type_or_decl_base::hashing_started(bool b) const +{priv_->hashing_started_ = b;} + +/// Getter of the cached hash value of this ABI artifact. +/// +/// @return cached hash value of this ABI artifact. +size_t +type_or_decl_base::get_cached_hash_value() const +{return priv_->hash_;} + +/// Setter of the cached hash value of this ABI artifact. +/// +/// @param v the new cached value. +void +type_or_decl_base::set_cached_hash_value(size_t v) const +{priv_->hash_ = v;} + +/// Setter of the environment of the current ABI artifact. +/// +/// This just sets the environment artifact of the current ABI +/// artifact, not on its sub-trees. If you want to set the +/// environment of an ABI artifact including its sub-tree, use the +/// abigail::ir::set_environment_for_artifact() function. +/// +/// @param env the new environment. +void +type_or_decl_base::set_environment(environment* env) +{priv_->env_ = env;} + +/// Getter of the environment of the current ABI artifact. +/// +/// @return the environment of the artifact. +const environment* +type_or_decl_base::get_environment() const +{return priv_->env_;} + +/// Getter of the environment of the current ABI artifact. +/// +/// @return the environment of the artifact. +environment* +type_or_decl_base::get_environment() +{return priv_->env_;} + +/// Traverse the the ABI artifact. +/// +/// @param v the visitor used to traverse the sub-tree nodes of the +/// artifact. +bool +type_or_decl_base::traverse(ir_node_visitor&) +{return true;} + +/// Set the environment of a given ABI artifact, including recursively +/// setting the environment on the sub-trees of the artifact. +/// +/// @param artifact the artifact to set the environment for. +/// +/// @param env the new environment. +void +set_environment_for_artifact(type_or_decl_base* artifact, environment* env) +{ + assert(artifact && env); + + ::environment_setter s(artifact, env); + artifact->traverse(s); +} + +/// Set the environment of a given ABI artifact, including recursively +/// setting the environment on the sub-trees of the artifact. +/// +/// @param artifact the artifact to set the environment for. +/// +/// @param env the new environment. +void +set_environment_for_artifact(type_or_decl_base_sptr artifact, + environment* env) +{set_environment_for_artifact(artifact.get(), env);} + /// Non-member equality operator for the @type_or_decl_base type. /// /// @param lr the left-hand operand of the equality. @@ -1637,8 +1834,6 @@ operator==(const type_or_decl_base_sptr& l, const type_or_decl_base_sptr& r) struct decl_base::priv { - size_t hash_; - bool hashing_started_; bool in_pub_sym_tab_; location location_; context_rel_sptr context_; @@ -1649,17 +1844,13 @@ struct decl_base::priv visibility visibility_; priv() - : hash_(0), - hashing_started_(false), - in_pub_sym_tab_(false), + : in_pub_sym_tab_(false), visibility_(VISIBILITY_DEFAULT) {} priv(const std::string& name, location locus, const std::string& linkage_name, visibility vis) - : hash_(0), - hashing_started_(false), - in_pub_sym_tab_(false), + : in_pub_sym_tab_(false), location_(locus), name_(name), linkage_name_(linkage_name), @@ -1667,9 +1858,7 @@ struct decl_base::priv {} priv(location l) - : hash_(0), - hashing_started_(0), - in_pub_sym_tab_(false), + : in_pub_sym_tab_(false), location_(l), visibility_(VISIBILITY_DEFAULT) {} @@ -1687,9 +1876,8 @@ decl_base::decl_base(location l) {} decl_base::decl_base(const decl_base& d) + : type_or_decl_base(d) { - priv_->hash_ = d.priv_->hash_; - priv_->hashing_started_ = d.priv_->hashing_started_; priv_->in_pub_sym_tab_ = d.priv_->in_pub_sym_tab_; priv_->location_ = d.priv_->location_; priv_->name_ = d.priv_->name_; @@ -1700,30 +1888,6 @@ decl_base::decl_base(const decl_base& d) priv_->visibility_ = d.priv_->visibility_; } -/// Getter for the 'hashing_started' property. -/// -/// @return the 'hashing_started' property. -bool -decl_base::hashing_started() const -{return priv_->hashing_started_;} - -/// Setter for the 'hashing_started' property. -/// -/// @param b the value to set the 'hashing_property' to. -void -decl_base::hashing_started(bool b) const -{priv_->hashing_started_ = b;} - -/// Getter for the hash value. -/// -/// unlike decl_base::get_hash() this does not try to update the hash -/// value. -/// -/// @return the hash value. -size_t -decl_base::peek_hash_value() const -{return priv_->hash_;} - /// Getter for the qualified name. /// /// Unlike decl_base::get_qualified_name() this doesn't try to update @@ -1781,13 +1945,6 @@ decl_base::get_hash() const return result; } -/// Set a new hash for the type. -/// -/// @param h the new hash. -void -decl_base::set_hash(size_t h) const -{priv_->hash_ = h;} - /// Test if the decl is defined in a ELF symbol table as a public /// symbol. /// @@ -2897,13 +3054,16 @@ strip_typedef(const type_base_sptr type) return type; } + environment* env = type->get_environment(); + assert(env); type_base_sptr t = type; if (const typedef_decl_sptr ty = is_typedef(t)) - t = strip_typedef(type_or_void(ty->get_underlying_type())); + t = strip_typedef(type_or_void(ty->get_underlying_type(), env)); else if (const reference_type_def_sptr ty = is_reference_type(t)) { - type_base_sptr p = strip_typedef(type_or_void(ty->get_pointed_to_type())); + type_base_sptr p = strip_typedef(type_or_void(ty->get_pointed_to_type(), + env)); assert(p); t.reset(new reference_type_def(p, ty->is_lvalue(), @@ -2913,7 +3073,8 @@ strip_typedef(const type_base_sptr type) } else if (const pointer_type_def_sptr ty = is_pointer_type(t)) { - type_base_sptr p = strip_typedef(type_or_void(ty->get_pointed_to_type())); + type_base_sptr p = strip_typedef(type_or_void(ty->get_pointed_to_type(), + env)); assert(p); t.reset(new pointer_type_def(p, ty->get_size_in_bits(), @@ -2922,7 +3083,8 @@ strip_typedef(const type_base_sptr type) } else if (const qualified_type_def_sptr ty = is_qualified_type(t)) { - type_base_sptr p = strip_typedef(type_or_void(ty->get_underlying_type())); + type_base_sptr p = strip_typedef(type_or_void(ty->get_underlying_type(), + env)); assert(p); t.reset(new qualified_type_def(p, ty->get_cv_quals(), @@ -2989,6 +3151,9 @@ strip_typedef(const type_base_sptr type) ty->get_alignment_in_bits())); } + if (!t->get_environment()) + set_environment_for_artifact(t, env); + if (!canonicalize(t)) keep_type_alive(t); @@ -3211,13 +3376,18 @@ peel_typedef_pointer_or_reference_type(const type_base* type) /// /// @param member the new member decl to add to this scope. decl_base_sptr -scope_decl::add_member_decl(const shared_ptr member) +scope_decl::add_member_decl(const decl_base_sptr member) { members_.push_back(member); if (scope_decl_sptr m = dynamic_pointer_cast(member)) member_scopes_.push_back(m); + member->priv_->qualified_name_.clear(); + + if (environment* env = get_environment()) + set_environment_for_artifact(member, env); + return member; } @@ -3239,6 +3409,10 @@ scope_decl::insert_member_decl(const decl_base_sptr member, member_scopes_.push_back(m); member->priv_->qualified_name_.clear(); + + if (environment* env = get_environment()) + set_environment_for_artifact(member, env); + return member; } @@ -3487,8 +3661,10 @@ scope_decl::~scope_decl() /// /// @param scope the scope to append the declaration to decl_base_sptr -add_decl_to_scope(shared_ptr decl, scope_decl* scope) +add_decl_to_scope(decl_base_sptr decl, scope_decl* scope) { + assert(scope); + if (scope && decl && !decl->get_scope()) { decl = scope->add_member_decl(decl); @@ -4918,11 +5094,17 @@ synthesize_type_from_translation_unit(const type_base_sptr& type, if (qualified_type_def_sptr qual = is_qualified_type(type)) { type_base_sptr underlying_type = - synthesize_type_from_translation_unit(qual->get_underlying_type(), tu); + synthesize_type_from_translation_unit(qual->get_underlying_type(), + tu); if (underlying_type) - result.reset(new qualified_type_def(underlying_type, - qual->get_cv_quals(), - qual->get_location())); + { + result.reset(new qualified_type_def(underlying_type, + qual->get_cv_quals(), + qual->get_location())); + // The new qualified type must be in the same environment + // as its underlying type. + result->set_environment(underlying_type->get_environment()); + } tu.priv_->synthesized_types_.push_back(result); } @@ -4954,11 +5136,14 @@ synthesize_function_type_from_translation_unit(const function_type& fn_type, { function_type_sptr nil = function_type_sptr(); + environment* env = tu.get_environment(); + assert(env); + type_base_sptr return_type = fn_type.get_return_type(); type_base_sptr result_return_type; if (!return_type - || return_type.get() == type_decl::get_void_type_decl().get()) - result_return_type = type_base_sptr(type_decl::get_void_type_decl()); + || return_type.get() == env->get_void_type_decl().get()) + result_return_type = type_base_sptr(env->get_void_type_decl()); else result_return_type = synthesize_type_from_translation_unit(return_type, tu); if (!result_return_type) @@ -4990,6 +5175,9 @@ synthesize_function_type_from_translation_unit(const function_type& fn_type, fn_type.get_alignment_in_bits())); tu.priv_->synthesized_types_.push_back(result_fn_type); + // The new synthesized type must be in the same environment as its + // translation unit. + result_fn_type->set_environment(tu.get_environment()); return result_fn_type; } @@ -5395,10 +5583,25 @@ demangle_cplus_mangled_name(const string& mangled_name) /// /// @param t the type to consider. /// +/// @param env the environment to use. If NULL, just abort the +/// process. +/// /// @return either @p t if it is non-null, or the void type. type_base_sptr -type_or_void(const type_base_sptr t) -{return t ? t : type_base_sptr(type_decl::get_void_type_decl());} +type_or_void(const type_base_sptr t, const environment* env) +{ + type_base_sptr r; + + if (t) + r = t; + else + { + assert(env); + r = type_base_sptr(env->get_void_type_decl()); + } + + return r; +} global_scope::~global_scope() { @@ -5427,25 +5630,6 @@ struct type_base::priv {} }; // end struct type_base::priv -/// Getter of the map that contains the canonical types of all the -/// types known to libabigail at a certain point in time. -/// -/// That map is a global value that is initialized at the first -/// invocation of this function and that is freed when the containing -/// process is shut down. -/// -/// The key of the map is the hash value of the type and the value a -/// list of canonical types that have the same map as the key. -/// -/// @return the map that contains the canonical types of all the types -/// known the running instance of libabigail in a given process. -static canonical_types_map_type& -get_canonical_types_map() -{ - static canonical_types_map_type m; - return m; -} - /// Compute the canonical type for a given instance of @ref type_base. /// /// Consider two types T and T'. The canonical type of T, denoted @@ -5474,6 +5658,9 @@ type_base::get_canonical_type_for(type_base_sptr t) if (!t) return t; + environment* env = t->get_environment(); + assert(env); + // Look through declaration-only classes if (class_decl_sptr class_declaration = is_class_type(t)) if (class_declaration->get_is_declaration_only()) @@ -5485,8 +5672,8 @@ type_base::get_canonical_type_for(type_base_sptr t) type_base::dynamic_hash hash; size_t h = hash(t.get()); - canonical_types_map_type& m = get_canonical_types_map(); - canonical_types_map_type::iterator i = m.find(h); + environment::canonical_types_map_type& m = env->get_canonical_types_map(); + environment::canonical_types_map_type::iterator i = m.find(h); type_base_sptr result; @@ -5674,30 +5861,6 @@ type_decl::type_decl(const std::string& name, { } -/// Get a singleton representing a void type node. -/// -/// @return the void type node. -type_decl_sptr& -type_decl::get_void_type_decl() -{ - static type_decl_sptr void_type_decl; - if (!void_type_decl) - void_type_decl.reset(new type_decl("void", 0, 0, location())); - return void_type_decl; -} - -/// Get a singleton representing the type of a variadic parameter. -/// -/// @return the variadic parameter type. -type_decl_sptr& -type_decl::get_variadic_parameter_type_decl() -{ - static type_decl_sptr variadic_parm_type_decl; - if (!variadic_parm_type_decl) - variadic_parm_type_decl.reset(new type_decl("variadic parameter type", - 0, 0, location())); - return variadic_parm_type_decl; -} /// Compares two instances of @ref type_decl. /// /// If the two intances are different, set a bitfield to give some @@ -6350,8 +6513,9 @@ pointer_type_def::pointer_type_def(const type_base_sptr& pointed_to, location locus) : type_base(size_in_bits, align_in_bits), decl_base("", locus, "", - get_type_declaration(type_or_void(pointed_to))->get_visibility()), - pointed_to_type_(type_or_void(pointed_to)) + get_type_declaration(type_or_void(pointed_to, + 0))->get_visibility()), + pointed_to_type_(type_or_void(pointed_to, 0)) { try { @@ -6502,8 +6666,9 @@ reference_type_def::reference_type_def(const type_base_sptr pointed_to, location locus) : type_base(size_in_bits, align_in_bits), decl_base("", locus, "", - dynamic_pointer_cast(type_or_void(pointed_to))->get_visibility()), - pointed_to_type_(type_or_void(pointed_to)), + dynamic_pointer_cast(type_or_void(pointed_to, + 0))->get_visibility()), + pointed_to_type_(type_or_void(pointed_to, 0)), is_lvalue_(lvalue) { try @@ -6611,7 +6776,8 @@ reference_type_def::get_qualified_name() const || !get_canonical_type()) { decl_base_sptr td = - get_type_declaration(type_or_void(get_pointed_to_type())); + get_type_declaration(type_or_void(get_pointed_to_type(), + get_environment())); string name; td->get_qualified_name(name); if (is_lvalue()) @@ -9177,13 +9343,16 @@ function_decl::parameter::get_qualified_name(string& qualified_name) const string function_decl::parameter::get_pretty_representation() const { + const environment* env = get_environment(); + string type_repr; type_base_sptr t = get_type(); if (!t) type_repr = "void"; - else if (t == - dynamic_pointer_cast - (type_decl::get_variadic_parameter_type_decl())) + else if (env + && (t == + dynamic_pointer_cast + (env->get_variadic_parameter_type_decl()))) type_repr = "..."; else type_repr = ir::get_pretty_representation(t); @@ -9207,19 +9376,18 @@ sort_virtual_member_functions(class_decl::member_functions& mem_fns); /// The private data for the class_decl type. struct class_decl::priv { - static unordered_map classes_being_compared_; - bool is_declaration_only_; - bool is_struct_; - decl_base_sptr declaration_; - class_decl_sptr definition_of_declaration_; - base_specs bases_; - member_types member_types_; - data_members data_members_; - data_members non_static_data_members_; - member_functions member_functions_; - member_functions virtual_mem_fns_; - member_function_templates member_function_templates_; - member_class_templates member_class_templates_; + bool is_declaration_only_; + bool is_struct_; + decl_base_sptr declaration_; + class_decl_sptr definition_of_declaration_; + base_specs bases_; + member_types member_types_; + data_members data_members_; + data_members non_static_data_members_; + member_functions member_functions_; + member_functions virtual_mem_fns_; + member_function_templates member_function_templates_; + member_class_templates member_class_templates_; priv() : is_declaration_only_(false), @@ -9257,11 +9425,6 @@ struct class_decl::priv /// Mark a class as being currently compared using the class_decl== /// operator. /// - /// This method is not thread safe because it uses the static data - /// member classes_being_compared_. If you wish to use it in a - /// multi-threaded environment you should probably protect the - /// access to that static data member with a mutex or somesuch. - /// /// Note that is marking business is to avoid infinite loop when /// comparing a class. If via the comparison of a data member or a /// member function a recursive re-comparison of the class is @@ -9271,7 +9434,11 @@ struct class_decl::priv /// @param klass the class to mark as being currently compared. void mark_as_being_compared(const class_decl& klass) const - {classes_being_compared_[klass.get_qualified_name()] = true;} + { + const environment* env = klass.get_environment(); + assert(env); + env->priv_->classes_being_compared_[klass.get_qualified_name()] = true; + } /// Mark a class as being currently compared using the class_decl== /// operator. @@ -9313,7 +9480,11 @@ struct class_decl::priv /// @param klass the instance of class_decl to unmark. void unmark_as_being_compared(const class_decl& klass) const - {classes_being_compared_.erase(klass.get_qualified_name());} + { + const environment* env = klass.get_environment(); + assert(env); + env->priv_->classes_being_compared_.erase(klass.get_qualified_name()); + } /// If the instance of class_decl has been previously marked as /// being compared -- via an invocation of mark_as_being_compared() @@ -9322,7 +9493,11 @@ struct class_decl::priv /// @param klass the instance of class_decl to unmark. void unmark_as_being_compared(const class_decl* klass) const - {classes_being_compared_.erase(klass->get_qualified_name());} + { + const environment* env = klass->get_environment(); + assert(env); + env->priv_->classes_being_compared_.erase(klass->get_qualified_name()); + } /// Test if a given instance of class_decl is being currently /// compared. @@ -9333,8 +9508,10 @@ struct class_decl::priv bool comparison_started(const class_decl& klass) const { - return (classes_being_compared_.find(klass.get_qualified_name()) - != classes_being_compared_.end()); + const environment* env = klass.get_environment(); + assert(env); + unordered_map& c = env->priv_->classes_being_compared_; + return (c.find(klass.get_qualified_name()) != c.end()); } /// Test if a given instance of class_decl is being currently @@ -9348,8 +9525,6 @@ struct class_decl::priv {return comparison_started(*klass);} };// end struct class_decl::priv -unordered_map class_decl::priv::classes_being_compared_; - /// A Constructor for instances of \ref class_decl /// /// @param name the identifier of the class. @@ -9782,12 +9957,12 @@ class_decl::base_spec::base_spec(shared_ptr base, size_t class_decl::base_spec::get_hash() const { - if (peek_hash_value() == 0) + if (get_cached_hash_value() == 0) { base_spec::hash h; - set_hash(h(*this)); + set_cached_hash_value(h(*this)); } - return peek_hash_value(); + return get_cached_hash_value(); } /// Traverses an instance of @ref class_decl::base_spec, visiting all @@ -11753,8 +11928,9 @@ type_has_sub_type_changes(const type_base_sptr t_v1, void keep_type_alive(type_base_sptr t) { - static vector extra_live_types; - extra_live_types.push_back(t); + environment* env = t->get_environment(); + assert(env); + env->priv_->extra_live_types_.push_back(t); } /// Hash an ABI artifact that is either a type or a decl. @@ -11979,7 +12155,7 @@ ir_node_visitor::visit_end(class_decl::member_class_template* d) static string get_next_string() { - static size_t counter; + static __thread size_t counter; ++counter; std::ostringstream o; o << counter; diff --git a/src/abg-reader.cc b/src/abg-reader.cc index 0e22a2d7..f874e583 100644 --- a/src/abg-reader.cc +++ b/src/abg-reader.cc @@ -96,6 +96,7 @@ public: typedef unordered_map xml_node_decl_base_sptr_map; private: + environment* m_env; unordered_map > m_types_map; unordered_map > m_fn_tmpl_map; unordered_map > m_class_tmpl_map; @@ -112,12 +113,35 @@ private: read_context(); public: - read_context(xml::reader_sptr reader) - : m_reader(reader), + read_context(xml::reader_sptr reader, + environment* env) + : m_env(env), + m_reader(reader), m_corp_node(), m_exported_decls_builder_() {} + /// Getter for the environment of this reader. + /// + /// @return the environment of this reader. + const environment* + get_environment() const + {return m_env;} + + /// Getter for the environment of this reader. + /// + /// @return the environment of this reader. + environment* + get_environment() + {return m_env;} + + /// Setter for the environment of this reader. + /// + /// @param env the environment of this reader. + void + set_environment(environment* env) + {m_env = env;} + xml::reader_sptr get_reader() const {return m_reader;} @@ -1085,7 +1109,7 @@ read_translation_unit(read_context& ctxt, xmlNodePtr node) ctxt.set_corpus_node(node); - tu.reset(new translation_unit("")); + tu.reset(new translation_unit("", ctxt.get_environment())); xml::xml_char_sptr addrsize_str = XML_NODE_GET_ATTRIBUTE(node, "address-size"); @@ -1422,7 +1446,7 @@ read_corpus_from_input(read_context& ctxt) if (!ctxt.get_corpus()) { - corpus_sptr c(new corpus("")); + corpus_sptr c(new corpus("", ctxt.get_environment())); ctxt.set_corpus(c); } @@ -1498,12 +1522,15 @@ read_corpus_from_input(read_context& ctxt) /// @param input_file a path to the file containing the xml document /// to parse. /// +/// @param env the environment to use. +/// /// @return the translation unit resulting from the parsing upon /// successful completion, or nil. translation_unit_sptr -read_translation_unit_from_file(const string& input_file) +read_translation_unit_from_file(const string& input_file, + environment* env) { - read_context read_ctxt(xml::new_reader_from_file(input_file)); + read_context read_ctxt(xml::new_reader_from_file(input_file), env); return read_translation_unit_from_input(read_ctxt); } @@ -1513,12 +1540,15 @@ read_translation_unit_from_file(const string& input_file) /// @param buffer the in-memory buffer containing the xml document to /// parse. /// +/// @param env the environment to use. +/// /// @return the translation unit resulting from the parsing upon /// successful completion, or nil. translation_unit_sptr -read_translation_unit_from_buffer(const string& buffer) +read_translation_unit_from_buffer(const string& buffer, + environment* env) { - read_context read_ctxt(xml::new_reader_from_buffer(buffer)); + read_context read_ctxt(xml::new_reader_from_buffer(buffer), env); return read_translation_unit_from_input(read_ctxt); } @@ -2206,6 +2236,8 @@ build_function_parameter(read_context& ctxt, const xmlNodePtr node) if (!node || !xmlStrEqual(node->name, BAD_CAST("parameter"))) return nil; + assert(ctxt.get_environment()); + bool is_variadic = false; string is_variadic_str; if (xml_char_sptr s = @@ -2230,7 +2262,7 @@ build_function_parameter(read_context& ctxt, const xmlNodePtr node) shared_ptr type; if (is_variadic) - type = type_decl::get_variadic_parameter_type_decl(); + type = ctxt.get_environment()->get_variadic_parameter_type_decl(); else { assert(!type_id.empty()); @@ -4077,12 +4109,14 @@ handle_class_tdecl(read_context& ctxt, /// /// @param in a pointer to the input stream. /// +/// @param env the environment to use. +/// /// @return the translation unit resulting from the parsing upon /// successful completion, or nil. translation_unit_sptr -read_translation_unit_from_istream(istream* in) +read_translation_unit_from_istream(istream* in, environment* env) { - read_context read_ctxt(xml::new_reader_from_istream(in)); + read_context read_ctxt(xml::new_reader_from_istream(in), env); return read_translation_unit_from_input(read_ctxt); } template @@ -4245,16 +4279,19 @@ read_corpus_from_file(const string& path) /// /// @param in the input stream to read the XML document from. /// -/// @param corp the corpus de-serialized from the parsing. This is -/// set iff the function returns true. +/// @param env the environment to use. Note that the life time of +/// this environment must be greater than the lifetime of the +/// resulting corpus as the corpus uses resources that are allocated +/// in the environment. /// /// @return the resulting corpus de-serialized from the parsing. This /// is non-null iff the parsing resulted in a valid corpus. corpus_sptr -read_corpus_from_native_xml(std::istream* in) +read_corpus_from_native_xml(std::istream* in, + environment* env) { - read_context read_ctxt(xml::new_reader_from_istream(in)); - corpus_sptr corp(new corpus("")); + read_context read_ctxt(xml::new_reader_from_istream(in), env); + corpus_sptr corp(new corpus("", read_ctxt.get_environment())); read_ctxt.set_corpus(corp); return read_corpus_from_input(read_ctxt); } @@ -4265,15 +4302,18 @@ read_corpus_from_native_xml(std::istream* in) /// @param path the path to the input file to read the XML document /// from. /// -/// @param corp the corpus de-serialized from the parsing. This is -/// set iff the function returns true. +/// @param env the environment to use. Note that the life time of +/// this environment must be greater than the lifetime of the +/// resulting corpus as the corpus uses resources that are allocated +/// in the environment. /// /// @return the resulting corpus de-serialized from the parsing. This /// is non-null if the parsing successfully resulted in a corpus. corpus_sptr -read_corpus_from_native_xml_file(const string& path) +read_corpus_from_native_xml_file(const string& path, + environment* env) { - read_context read_ctxt(xml::new_reader_from_file(path)); + read_context read_ctxt(xml::new_reader_from_file(path), env); corpus_sptr corp = read_corpus_from_input(read_ctxt); if (corp) { diff --git a/tests/print-diff-tree.cc b/tests/print-diff-tree.cc index d0126bd9..349ae3b5 100644 --- a/tests/print-diff-tree.cc +++ b/tests/print-diff-tree.cc @@ -33,6 +33,8 @@ using std::string; using abigail::comparison::diff; using abigail::comparison::diff_sptr; +using abigail::ir::environment; +using abigail::ir::environment_sptr; using abigail::comparison::corpus_diff_sptr; using abigail::comparison::compute_diff; using abigail::comparison::print_diff_tree; @@ -118,7 +120,8 @@ main(int argc, char* argv[]) dwarf_reader::status c1_status, c2_status; corpus_sptr c1, c2; - c1 = dwarf_reader::read_corpus_from_elf(opts.elf1, 0, + environment_sptr env(new environment); + c1 = dwarf_reader::read_corpus_from_elf(opts.elf1, 0, env.get(), /*load_all_types=*/false, c1_status); if (c1_status != dwarf_reader::STATUS_OK) @@ -127,7 +130,7 @@ main(int argc, char* argv[]) return 1; } - c2 = dwarf_reader::read_corpus_from_elf(opts.elf2, 0, + c2 = dwarf_reader::read_corpus_from_elf(opts.elf2, 0, env.get(), /*load_all_types=*/false, c2_status); if (c2_status != dwarf_reader::STATUS_OK) diff --git a/tests/test-abidiff.cc b/tests/test-abidiff.cc index 433e5442..63e31f97 100644 --- a/tests/test-abidiff.cc +++ b/tests/test-abidiff.cc @@ -114,6 +114,8 @@ using std::ofstream; using abigail::tools_utils::file_type; using abigail::tools_utils::check_file; using abigail::tools_utils::guess_file_type; +using abigail::ir::environment; +using abigail::ir::environment_sptr; using abigail::corpus_sptr; using abigail::translation_unit; using abigail::translation_unit_sptr; @@ -154,13 +156,14 @@ main(int, char*[]) continue; } + environment_sptr env(new environment); translation_unit_sptr tu1, tu2; corpus_sptr corpus1, corpus2; file_type t = guess_file_type(first_in_path); if (t == abigail::tools_utils::FILE_TYPE_NATIVE_BI) - tu1 = read_translation_unit_from_file(first_in_path); + tu1 = read_translation_unit_from_file(first_in_path, env.get()); else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS) - corpus1 = read_corpus_from_native_xml_file(first_in_path); + corpus1 = read_corpus_from_native_xml_file(first_in_path, env.get()); else abort(); if (!tu1 && !corpus1) @@ -172,9 +175,9 @@ main(int, char*[]) t = guess_file_type(second_in_path); if (t == abigail::tools_utils::FILE_TYPE_NATIVE_BI) - tu2 = read_translation_unit_from_file(second_in_path); + tu2 = read_translation_unit_from_file(second_in_path, env.get()); else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS) - corpus2 = read_corpus_from_native_xml_file(second_in_path); + corpus2 = read_corpus_from_native_xml_file(second_in_path, env.get()); else abort(); if (!tu2 && !corpus2) diff --git a/tests/test-diff-dwarf.cc b/tests/test-diff-dwarf.cc index e2220ce3..eb4fcbbe 100644 --- a/tests/test-diff-dwarf.cc +++ b/tests/test-diff-dwarf.cc @@ -267,6 +267,8 @@ main() using abigail::dwarf_reader::read_corpus_from_elf; using abigail::comparison::compute_diff; using abigail::comparison::corpus_diff_sptr; + using abigail::ir::environment; + using abigail::ir::environment_sptr; bool is_ok = true; string in_elfv0_path, in_elfv1_path, @@ -289,15 +291,18 @@ main() abigail::dwarf_reader::status status = abigail::dwarf_reader::STATUS_UNKNOWN; + environment_sptr env(new environment); abigail::corpus_sptr corp0 = read_corpus_from_elf(in_elfv0_path, /*debug_info_root_path=*/0, + env.get(), /*load_all_types=*/false, status); abigail::corpus_sptr corp1 = read_corpus_from_elf(in_elfv1_path, /*debug_info_root_path=*/0, + env.get(), /*load_all_types=*/false, status); diff --git a/tests/test-ir-walker.cc b/tests/test-ir-walker.cc index 2df2d428..b5b302f1 100644 --- a/tests/test-ir-walker.cc +++ b/tests/test-ir-walker.cc @@ -136,8 +136,10 @@ main(int argc, char **argv) string file_name = argv[1]; + abigail::ir::environment_sptr env(new abigail::ir::environment); abigail::translation_unit_sptr tu; - if (!(tu = abigail::xml_reader::read_translation_unit_from_file(file_name))) + if (!(tu = abigail::xml_reader::read_translation_unit_from_file(file_name, + env.get()))) { cerr << "failed to read " << file_name << "\n"; return 1; diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc index 7d4c69a1..10884113 100644 --- a/tests/test-read-dwarf.cc +++ b/tests/test-read-dwarf.cc @@ -143,21 +143,25 @@ InOutSpec in_out_specs[] = int main() { + using abigail::dwarf_reader::read_corpus_from_elf; unsigned result = 1; bool is_ok = true; string in_elf_path, in_abi_path, out_abi_path; + abigail::ir::environment_sptr env; abigail::corpus_sptr corp; for (InOutSpec* s = in_out_specs; s->in_elf_path; ++s) { in_elf_path = abigail::tests::get_src_dir() + "/tests/" + s->in_elf_path; + env.reset(new abigail::ir::environment); abigail::dwarf_reader::status status = abigail::dwarf_reader::STATUS_UNKNOWN; - corp = abigail::dwarf_reader::read_corpus_from_elf(in_elf_path, - /*debug_info_root_path=*/0, - /*load_all_types=*/false, - status); + corp = read_corpus_from_elf(in_elf_path, + /*debug_info_root_path=*/0, + env.get(), + /*load_all_types=*/false, + status); if (!corp) { cerr << "failed to read " << in_elf_path << "\n"; diff --git a/tests/test-read-write.cc b/tests/test-read-write.cc index 32b0420a..ccf918cf 100644 --- a/tests/test-read-write.cc +++ b/tests/test-read-write.cc @@ -40,6 +40,8 @@ using abigail::tools_utils::file_type; using abigail::tools_utils::check_file; using abigail::tools_utils::guess_file_type; using abigail::tests::get_build_dir; +using abigail::ir::environment; +using abigail::ir::environment_sptr; using abigail::translation_unit_sptr; using abigail::corpus_sptr; using abigail::xml_reader::read_translation_unit_from_file; @@ -187,15 +189,16 @@ main() if (!check_file(in_path, cerr)) return true; + environment_sptr env(new environment); translation_unit_sptr tu; corpus_sptr corpus; bool read = false; file_type t = guess_file_type(in_path); if (t == abigail::tools_utils::FILE_TYPE_NATIVE_BI) - read = (tu = read_translation_unit_from_file(in_path)); + read = (tu = read_translation_unit_from_file(in_path, env.get())); else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS) - read = (corpus = read_corpus_from_native_xml_file(in_path)); + read = (corpus = read_corpus_from_native_xml_file(in_path, env.get())); else abort(); if (!read) diff --git a/tools/abicompat.cc b/tools/abicompat.cc index b406a337..09b0bff2 100644 --- a/tools/abicompat.cc +++ b/tools/abicompat.cc @@ -213,6 +213,8 @@ parse_command_line(int argc, char* argv[], options& opts) using abigail::tools_utils::check_file; using abigail::tools_utils::base_name; using abigail::tools_utils::abidiff_status; +using abigail::ir::environment; +using abigail::ir::environment_sptr; using abigail::corpus; using abigail::corpus_sptr; using abigail::ir::elf_symbols; @@ -606,9 +608,10 @@ main(int argc, char* argv[]) // Read the application ELF file. char * app_di_root = opts.app_di_root_path.get(); status status = abigail::dwarf_reader::STATUS_UNKNOWN; + environment_sptr env(new environment); corpus_sptr app_corpus= read_corpus_from_elf(opts.app_path, - &app_di_root, + &app_di_root, env.get(), /*load_all_types=*/opts.weak_mode, status); @@ -654,9 +657,9 @@ main(int argc, char* argv[]) char * lib1_di_root = opts.lib1_di_root_path.get(); corpus_sptr lib1_corpus = read_corpus_from_elf(opts.lib1_path, - &lib1_di_root, - /*load_all_types=*/false, - status); + &lib1_di_root, env.get(), + /*load_all_types=*/false, + status); if (status & abigail::dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND) cerr << "could not read debug info for " << opts.lib1_path << "\n"; if (status & abigail::dwarf_reader::STATUS_NO_SYMBOLS_FOUND) @@ -678,6 +681,7 @@ main(int argc, char* argv[]) char * lib2_di_root = opts.lib2_di_root_path.get(); lib2_corpus = read_corpus_from_elf(opts.lib2_path, &lib2_di_root, + env.get(), /*load_all_types=*/false, status); if (status & abigail::dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND) diff --git a/tools/abidiff.cc b/tools/abidiff.cc index c78a1dc8..5b29f39c 100644 --- a/tools/abidiff.cc +++ b/tools/abidiff.cc @@ -37,6 +37,8 @@ using std::ostream; using std::cout; using std::cerr; using std::tr1::shared_ptr; +using abigail::ir::environment; +using abigail::ir::environment_sptr; using abigail::translation_unit; using abigail::translation_unit_sptr; using abigail::corpus_sptr; @@ -524,6 +526,7 @@ main(int argc, char* argv[]) return abigail::tools_utils::ABIDIFF_ERROR; } + environment_sptr env(new environment); translation_unit_sptr t1, t2; abigail::dwarf_reader::status c1_status = abigail::dwarf_reader::STATUS_OK, @@ -538,7 +541,8 @@ main(int argc, char* argv[]) return abigail::tools_utils::ABIDIFF_ERROR; break; case abigail::tools_utils::FILE_TYPE_NATIVE_BI: - t1 = abigail::xml_reader::read_translation_unit_from_file(opts.file1); + t1 = abigail::xml_reader::read_translation_unit_from_file(opts.file1, + env.get()); break; case abigail::tools_utils::FILE_TYPE_ELF: case abigail::tools_utils::FILE_TYPE_AR: @@ -546,7 +550,7 @@ main(int argc, char* argv[]) di_dir1 = opts.di_root_path1.get(); abigail::dwarf_reader::read_context_sptr ctxt = abigail::dwarf_reader::create_read_context(opts.file1, - &di_dir1, + &di_dir1, env.get(), /*read_all_types=*/false); assert(ctxt); abigail::dwarf_reader::set_show_stats @@ -557,7 +561,8 @@ main(int argc, char* argv[]) break; case abigail::tools_utils::FILE_TYPE_XML_CORPUS: c1 = - abigail::xml_reader::read_corpus_from_native_xml_file(opts.file1); + abigail::xml_reader::read_corpus_from_native_xml_file(opts.file1, + env.get()); break; case abigail::tools_utils::FILE_TYPE_ZIP_CORPUS: #ifdef WITH_ZIP_ARCHIVE @@ -579,7 +584,8 @@ main(int argc, char* argv[]) return abigail::tools_utils::ABIDIFF_ERROR; break; case abigail::tools_utils::FILE_TYPE_NATIVE_BI: - t2 = abigail::xml_reader::read_translation_unit_from_file(opts.file2); + t2 = abigail::xml_reader::read_translation_unit_from_file(opts.file2, + env.get()); break; case abigail::tools_utils::FILE_TYPE_ELF: case abigail::tools_utils::FILE_TYPE_AR: @@ -587,7 +593,7 @@ main(int argc, char* argv[]) di_dir2 = opts.di_root_path2.get(); abigail::dwarf_reader::read_context_sptr ctxt = abigail::dwarf_reader::create_read_context(opts.file2, - &di_dir2, + &di_dir2, env.get(), /*read_all_types=*/false); assert(ctxt); abigail::dwarf_reader::set_show_stats @@ -597,7 +603,8 @@ main(int argc, char* argv[]) break; case abigail::tools_utils::FILE_TYPE_XML_CORPUS: c2 = - abigail::xml_reader::read_corpus_from_native_xml_file(opts.file2); + abigail::xml_reader::read_corpus_from_native_xml_file(opts.file2, + env.get()); break; case abigail::tools_utils::FILE_TYPE_ZIP_CORPUS: #ifdef WITH_ZIP_ARCHIVE diff --git a/tools/abidw.cc b/tools/abidw.cc index 87a80588..871e0746 100644 --- a/tools/abidw.cc +++ b/tools/abidw.cc @@ -182,6 +182,8 @@ main(int argc, char* argv[]) return 1; } + using abigail::ir::environment_sptr; + using abigail::ir::environment; using abigail::corpus; using abigail::corpus_sptr; using abigail::translation_units; @@ -192,8 +194,10 @@ main(int argc, char* argv[]) using namespace abigail; char* p = opts.di_root_path.get(); + environment_sptr env(new environment); corpus_sptr corp; - read_context_sptr c = create_read_context(opts.in_file_path, &p, + read_context_sptr c = create_read_context(opts.in_file_path, + &p, env.get(), opts.load_all_types); set_show_stats(c, opts.show_stats); read_context& ctxt = *c; diff --git a/tools/abilint.cc b/tools/abilint.cc index 6b7dd82f..c4e4e2e6 100644 --- a/tools/abilint.cc +++ b/tools/abilint.cc @@ -160,6 +160,7 @@ main(int argc, char* argv[]) return true; } + abigail::ir::environment_sptr env(new abigail::ir::environment); if (opts.read_from_stdin) { if (!cin.good()) @@ -168,7 +169,7 @@ main(int argc, char* argv[]) if (opts.read_tu) { abigail::translation_unit_sptr tu = - read_translation_unit_from_istream(&cin); + read_translation_unit_from_istream(&cin, env.get()); if (!tu) { @@ -182,7 +183,7 @@ main(int argc, char* argv[]) } else { - corpus_sptr corp = read_corpus_from_native_xml(&cin); + corpus_sptr corp = read_corpus_from_native_xml(&cin, env.get()); if (!opts.noout) write_corpus_to_native_xml(corp, /*indent=*/0, cout); return false; @@ -192,7 +193,6 @@ main(int argc, char* argv[]) { if (!check_file(opts.file_path, cerr)) return true; - abigail::translation_unit_sptr tu; abigail::corpus_sptr corp; abigail::dwarf_reader::status s = abigail::dwarf_reader::STATUS_OK; @@ -205,18 +205,19 @@ main(int argc, char* argv[]) cerr << "Unknown file type given in input: " << opts.file_path; return true; case abigail::tools_utils::FILE_TYPE_NATIVE_BI: - tu = read_translation_unit_from_file(opts.file_path); + tu = read_translation_unit_from_file(opts.file_path, env.get()); break; case abigail::tools_utils::FILE_TYPE_ELF: case abigail::tools_utils::FILE_TYPE_AR: di_root_path = opts.di_root_path.get(); corp = read_corpus_from_elf(opts.file_path, - &di_root_path, - /*load_all_types=*/false, - s); + &di_root_path, + env.get(), + /*load_all_types=*/false, + s); break; case abigail::tools_utils::FILE_TYPE_XML_CORPUS: - corp = read_corpus_from_native_xml_file(opts.file_path); + corp = read_corpus_from_native_xml_file(opts.file_path, env.get()); break; case abigail::tools_utils::FILE_TYPE_ZIP_CORPUS: #if WITH_ZIP_ARCHIVE diff --git a/tools/abipkgdiff.cc b/tools/abipkgdiff.cc index 417853f3..30a2eba3 100644 --- a/tools/abipkgdiff.cc +++ b/tools/abipkgdiff.cc @@ -715,13 +715,14 @@ compare(const elf_file& elf1, abigail::dwarf_reader::status c1_status = abigail::dwarf_reader::STATUS_OK, c2_status = abigail::dwarf_reader::STATUS_OK; + abigail::ir::environment_sptr env(new abigail::ir::environment); if (verbose) cerr << " Reading file " << elf1.path << " ..."; - corpus_sptr corpus1 = read_corpus_from_elf(elf1.path, &di_dir1, + corpus_sptr corpus1 = read_corpus_from_elf(elf1.path, &di_dir1, env.get(), /*load_all_types=*/false, c1_status); if (!(c1_status & abigail::dwarf_reader::STATUS_OK)) @@ -753,7 +754,7 @@ compare(const elf_file& elf1, << elf2.path << " ..."; - corpus_sptr corpus2 = read_corpus_from_elf(elf2.path, &di_dir2, + corpus_sptr corpus2 = read_corpus_from_elf(elf2.path, &di_dir2, env.get(), /*load_all_types=*/false, c2_status); if (!(c2_status & abigail::dwarf_reader::STATUS_OK)) -- 2.43.5