From patchwork Tue Oct 25 15:19:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 59399 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C5B34385AC24 for ; Tue, 25 Oct 2022 15:20:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C5B34385AC24 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1666711217; bh=gVhhwC9gYTNZ2pRNd5PvrbVHdoSkzI+1ACGfqFn143w=; h=To:Subject:References:Date:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Help:List-Subscribe:From:Reply-To:Cc:From; b=Rm3WOitw35xLLT6hc80ND+wefH7SnTxBNIBUtaHYW7VYGSZmwjTUf6hrlaJCjtL5X zsU4WE6+U7p3POkSoDRFRDUksO2Grlnbr2lGfyyHwnf42V1PTgnBTxjYG05jQIlDhy GmW8KDChSM4w3lk9BoNHvfEWi4M+wM6A+EWyi0I0= X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 65B17385AC33 for ; Tue, 25 Oct 2022 15:19:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 65B17385AC33 Received: from mail-qk1-f200.google.com (mail-qk1-f200.google.com [209.85.222.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-250-UkJgVy3EO7qbq0iJgOABVw-1; Tue, 25 Oct 2022 11:19:26 -0400 X-MC-Unique: UkJgVy3EO7qbq0iJgOABVw-1 Received: by mail-qk1-f200.google.com with SMTP id bm16-20020a05620a199000b006ee95743ad2so11789433qkb.14 for ; Tue, 25 Oct 2022 08:19:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:message-id:in-reply-to:date:references :organization:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gVhhwC9gYTNZ2pRNd5PvrbVHdoSkzI+1ACGfqFn143w=; b=NJ8rXy04PpMNa4qqnQCeuKlGP0iaajQ4G0taCjbbOyLhWZZKY82UeTYgCzqmbIRAV4 et7WiNf1V8SnT9M2VhJksaKPdKaLXOKX2l61u6akO63e7LfuISHY6ofAdgTmW8urifUJ 1gAoeKGi4On1TfUIO0ipRlxNYEeUSVvu4jy4bAg3TmlQK+YcKqn+5rTz+K5lQgEYmnR4 y6lrB1I4lIFwpMOljyTSGgWj6uwFlrL0/QVU/0V3KULogTIzXubpGTQoMWg3ijg/3zoJ gTyXemWcIXloQz7p7MOZPfgfnEOohqWcExZ3kVqeplkZ2+YsfX5uEOu5iSqygv2cOvDT Tc8g== X-Gm-Message-State: ACrzQf0vSkC0g+Pu/ybpP0baru+NMgp3YGOtgmBLVhdoIoHrkCooIcV1 X/MkDuH73mhDFeyMxekZRzDRhW47GN8Sgnmks8a1B7ULkFr6yPUpsRnibLRKdrsSYG0N9A6AK24 PRAqGjvcz5vERr1iRHOtv X-Received: by 2002:a05:622a:449:b0:39c:d73a:e7d5 with SMTP id o9-20020a05622a044900b0039cd73ae7d5mr32323687qtx.276.1666711162143; Tue, 25 Oct 2022 08:19:22 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4dV6vBG/LSDsFFuMMcVT/DGCqNP8m59iWS3hcQMKGcYMvGcaThSijyD1Bo+bEtCVMI3j4DiQ== X-Received: by 2002:a05:622a:449:b0:39c:d73a:e7d5 with SMTP id o9-20020a05622a044900b0039cd73ae7d5mr32323547qtx.276.1666711160444; Tue, 25 Oct 2022 08:19:20 -0700 (PDT) Received: from localhost ([88.120.130.27]) by smtp.gmail.com with ESMTPSA id u6-20020a37ab06000000b006eed094dcdasm2142164qke.70.2022.10.25.08.19.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Oct 2022 08:19:19 -0700 (PDT) Received: by localhost (Postfix, from userid 1000) id 099D2581C59; Tue, 25 Oct 2022 17:19:16 +0200 (CEST) To: "Guillermo E. Martinez" Subject: [PATCH 1/1, RFC] Make Front Ends first class citizens Organization: Red Hat / France References: <87lep4os22.fsf@redhat.com> X-Operating-System: Fedora 38 X-URL: http://www.redhat.com Date: Tue, 25 Oct 2022 17:19:16 +0200 In-Reply-To: <87lep4os22.fsf@redhat.com> (Dodji Seketeli's message of "Tue, 25 Oct 2022 17:12:53 +0200") Message-ID: <87h6zsorrf.fsf@redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP, T_FILL_THIS_FORM_SHORT autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libabigail@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list of the Libabigail project List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-Patchwork-Original-From: Dodji Seketeli via Libabigail From: Dodji Seketeli Reply-To: Dodji Seketeli Cc: libabigail@sourceware.org Errors-To: libabigail-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libabigail" Hello, This patch is a reorganization of the code to better support the need for having several different front-ends. In the libabigail pipeline of operation, a front-end is the part of the pipeline that analyses the input file. For instance, to analyse an ELF file, there is going to be one front-end. To analyse an ABIXML file, there is going to be another front-end. The middle-end is the part of the pipeline that interacts with the internal representation of ABIs. The middle-end knows how to analyse, compare ABI corpora provide an internal representation of the comparison result and analyse it as well. The back-end would be the part of the front-end that knows how to serialize internal representations of ABIs and ABI comparison results. One could thus imagine a front-end that understands the DWARF debug info format, embedded in an ELF file. Another front-end would be dedicated to the CTF debug infor format, and so on. Front-ends can share capabilities. For instance, DWARF and CTF front-ends are ELF based front end. As such, they share capabilities to understand the ELF format. They don't share much with the ABIBXML front-end, however, as it's based on XML, which has almost nothing in common with ELF. To support this organization of concepts, this patch introduces a new hierarchy of types in the form of C++ classes. All front-ends implements the "Front End Interface". As such, they all inherits from the abigail::fe_iface class. That class provides properties and behaviours that are shared by all front-ends that libabigail supports today. Namely, that class provides access to (properties of) the ABI corpus, corpus groups, associated suppression specifications. It also provides an abstract interface to perform the actual loading of the ABI corpus. That abstract interface has be implemented by every single concrete front-end that is provided in libabigail. Then, there is the "ELF Reader" front-end. Its class name is abigail::elf_reader. It inherits the abigail::fe_iface class and implements the fe_iface::load_corpus() so that the ELF properties of the ELF file be loaded and exposed in the ABI corpus as returned by the fe_iface::corpus() accessor. This ELF reader front-end also provides lots of capabilities that are specific to accessing ELF content. Then, there is a common base class for ELF-based front-ends to come, named abigail::elf_based_reader, which inherits the abigail::fe_iface class. The purpose of this base class is to provide common properties and behaviours that are necessary to implement things like a DWARF or a CTF front-end, or any other front-end to support an ELF-based debug info format. Then, there is a CTF front-end which class is named abigail::ctf_reader::reader. It inherits the abigail::elf_based_reader class and implements the fe_iface::load_corpus() interface to load and analyse the CTF-specific properties of the ELF file. To do this, abigail::ctf_reader::reader re-uses the abigail::elf_reader::load_corpus() member function to load the generic ELF parts of the ABI corpus. This reader then constructs the internal representation of the ABI corpus and passes it to the middle-end for further analysis. Then, there is a DWARF front-end which class is named abigail::dwarf_reader::reader. It inherits the abigail::elf_based_reader class and implements the fe_iface::load_corpus() interface to load and analyse the DWARF-specific properties of the ELF file. To do this, abigail::dwarf_reader::reader re-uses the abigail::elf_reader::load_corpus() member function to load the generic ELF parts of the ABI corpus, just like what the CTF front-end does. And then, just like the CTF front-end, this reader then constructs the internal representation of the ABI corpus and passes it to the middle-end for further analysis. Lastly, there is an ABIXML front-end which class is named abigail::abixml_reader::reader. It inherits the abigail::fe_iface class directly. Note that unlike the two previous front-ends, this one doesn't inherit the elf_based_reader base class, for reasons that should be obvious to the astute reader by now. So, this front-end implements the abigail::fe_iface::load_corpus() abstract interface to load the properties for the ABI corpus represented in the ABIXML format, construct the internal representation and pass it to the middle-end for further analysis. The code of the tools got adapted to use these front-ends. The support of CTF is still guarded by #ifdef WITH_CTF pre-processor macros, but the one cool side effect is that the amount of guarded code is reduced. Basically, it's only the creation of the CTF front-end that is guarded. After its creation, what is returned is an instance of abigail::elf_based_reader::reader, exactly like what is returned by the creation of a DWARF front-end. Thus, the rest of the code is exactly the same, regardless of the kind of front-end. I believe this results in a more elegant and maintainable code. As a proof-of-concept, this patch also provides the create_best_elf_based_reader function. This function analyses the ELF file and depending on the kind of debug info it provides, returns the right front-end for it. Maybe at some point, all the #ifdef WITH_CTF guard pre-processing macros will be constrained in a single function like this one that will take the decision of instantiating the right front-end. The rest of the code will be as generic as it gets. The patch also simplifies how the environment is created and passed around the functions that create front ends. Basically, the environment can simply be allocated on the stack and passed by reference to the libabigail pipeline: For instance: vector debug_info_paths; fe_iface::status result_status; abigail::ir::environment env; corpus_sptr abi_corpus = dwarf_reader::read_corpus_from_elf("/path/to/elf-binary", debug_info_paths, env, /*load_all_types=*/false, result_status); /* then do something with the resulting abi_corpus*/ Note how, you don't need to use the "new" operator to instantiate the "env" object, of type environment. It can sit on the stack, and it's passed to the read_corpus_from_elf function by reference. So, the internal representation types have been changed to refer to the environment by reference, rather than requiring a pointer to it. The patch passes 'make distcheck' on all the supported platforms. * include/abg-elf-reader-common.h: Delete this file. Its content is going to be put in the new include/abg-elf-reader.h. * src/abg-elf-reader-common.cc: Likewise. * include/abg-{elf-based-reader, elf-reader, fe-iface}.h: Add new files. * src/abg-fe-iface.cc: Likewise. * include/Makefile.am: Add the new file abg-fe-iface.h, abg-elf-based-reader.h and abg-elf-reader.h to source distribution and remove include/abg-elf-reader-common.h from source distribution. * abg-fwd.h (type_or_void): Take a reference to the environment, not a pointer. * include/abg-ir.h (translation::translation): Take a reference to the environment, not a pointer. (translation::{g,s}et_environment): Return or take a reference to the environment, not a pointer. (elf_symbol::{elf_symbol, create, get_environment, set_environment}): Likewise. (type_or_decl_base::type_or_decl_base): Make the copy constructor private to prevent copy. (type_or_decl_base::operator=): Make this protected. (type_or_decl_base::{type_or_decl_base, get_environment, set_environment}): Return or take a reference to the environment, not a pointer. (set_environment_for_artifact): Remove this. The environment is not set anymore after the artifact is created anymore. (decl_base::decl_base): Make the copy constructor protected. (decl_base::decl_base): In constructors, pass a reference to the environment, not a pointer. (scope_decl::scope_decl, type_base::type_base) (type_decl::type_decl, scope_type_decl::scope_type_decl) (namespace_decl::namespace_decl) (qualified_type_def::qualified_type_def) (pointer_type_def::pointer_type_def) (reference_type_def::reference_type_def) (array_type_def::subrange_type::subrange_type) (array_type_def::array_type_def) (enum_type_decl::enumerator::enumerator) (typedef_decl::typedef_decl, function_type::function_type) (method_type::method_type, template_decl::template_decl) (class_tdecl::class_tdecl, class_or_union::class_or_union) (class_decl::class_decl, union_decl::union_decl): Likewise. (enum_type_decl::enumerator::enumerator): Don't take a pointer to an environment anymore. (enum_type_decl::enumerator::get_environment): Remove. (enum_type_decl::enumerator::get_{name, qualified_name}): Return a string, no more an interned_string. This is because the enumerator no more contains a pointer to an environment as no environment pointer is passed to ABI artifacts anymore. The enumerator type can't have a reference to an environment because the enumerator is one of the rare types that is copyable in the IR, and the environment is not. The sole purpose of the environment in the enumerator was to interning strings. So enumerator are not the sole ABI artifact for which strings are not interned. We'll see what the impact on performance is, but I expect it to be minimal. * src/abg-ir-priv.h (translation_unit::priv::env_): Turn the type of this into a reference to environment. (translation_unit::priv::priv): adjust. (environment::priv::{confirm_ct_propagation_for_types_dependant_on, confirm_ct_propagation, cancel_ct_propagation, mark_as_being_compared, unmark_as_being_compared, comparison_started, mark_as_being_compared, comparison_started}): * src/abg-ir.cc (class environment_setter): Remove. This is now useless as the environment of ABI artifacts can no longer be modified. (push_composite_type_comparison_operands) (pop_composite_type_comparison_operands) (mark_dependant_types_compared_until, try_canonical_compare) (return_comparison_result, translation_unit::translation_unit) (translation_unit::{get_global_scope, get_environment, bind_function_type_life_time}): Adjust to use a reference to the environment, not a pointer. (translation_unit::set_environment): Remove. (elf_symbol::priv::env_): Turn the type of this into a reference to environment. (elf_symbol::priv::priv): Adjust to take a reference to the environment, not a pointer. (elf_symbol::elf_symbol): Remove the default constructor as it can't take a reference to an environment. Adjust the other constructor to make it take a reference to the environment, not a pointer. (elf_symbol::create): Remove the default one. Adjust the other overload to make it take reference to the environment, not a pointer. (elf_symbol::get_environment): Adjust to return a reference to the environment, not a pointer. (elf_symbol::set_environment): Remove. (environment::get_void_type): Adjust. (type_or_decl_base::priv::env_): Make the type of this data member be reference to environment, not a pointer. (type_or_decl_base::{priv::priv, type_or_decl_base, get_environment, }): Adjust. (type_or_decl_base::{set_environment, operator=}): Remove. (set_environment_for_artifact): Remove. (decl_base::{decl_base, set_base, set_naming_typedef, set_linkage_name}, get_decl_name_for_comparison, strip_typedef) (strip_useless_const_qualification, scope_decl::{scope_decl, add_member_decl, get_generic_anonymous_internal_type_name}) (get_type_name, get_name_of_pointer_to_type) (get_name_of_reference_to_type, get_name_of_qualified_type) (get_function_type_name, get_method_type_name) (is_void_pointer_type, lookup_basic_type) (lookup_union_type_per_location, lookup_enum_type) (lookup_typedef_type, lookup_pointer_type, lookup_type) (lookup_basic_type_per_location, lookup_class_type) (lookup_class_type_per_location, lookup_union_type) (lookup_enum_type, lookup_enum_types) (lookup_enum_type_per_location, lookup_typedef_type) (lookup_typedef_type_per_location, maybe_update_types_lookup_map) (maybe_update_types_lookup_map) (synthesize_type_from_translation_unit) (synthesize_function_type_from_translation_unit, type_or_void) (types_defined_same_linux_kernel_corpus_public) (compare_types_during_canonicalization) (type_base::{get_canonical_type_for, type_base::type_base, get_cached_pretty_representation}, type_decl::{type_decl, get_qualified_name}, scope_type_decl::scope_type_decl) (namespace_decl::namespace_decl, qualified_type_def::{build_name, qualified_type_def, get_qualified_name, set_underlying_type}) (pointer_type_def::{priv::priv, pointer_type_def, set_pointed_to_type}, reference_type_def::reference_type_def) (array_type_def::{subrange_type::subrange_type, array_type_def, update_size, set_element_type, append_subranges, set_element_type, append_subranges, get_qualified_name, typedef_decl::typedef_decl}) (equals, var_decl::{get_id, get_qualified_name}) (function_type::function_type, method_type::method_type) (function_decl::{get_pretty_representation_of_declarator, set_symbol, get_id, parameter::get_type_name, parameter::get_type_pretty_representation, parameter::get_pretty_representation}) (class_or_union::class_or_union, dump_classes_being_compared) (dump_fn_types_being_compared, copy_member_function) (maybe_propagate_canonical_type, class_decl::{class_decl, add_base_specifier}, maybe_cancel_propagated_canonical_type) (union_decl::union_decl, template_decl::template_decl) (function_tdecl::function_tdecl, class_tdecl::class_tdecl) (keep_type_alive, is_non_canonicalized_type) (qualified_name_setter::do_update): Adjust to take or use a reference of environment, not a pointer. (enum_type_decl::enumerator::priv::env_): Remove. This can't have a reference to an environment because the enum_type_decl::enumerator type is copyable and the environment type is not. So I am removing the environment data member from here. The only reason why we had an environment as a data member here is so that the strings used by the enumerator type could be interned. So for now, we are not interning those strings. That seems to incur no measurable speed cost so far. (enum_type_decl::enumerator::{priv::{name_, qualified_name}): Turn these into std::string, as opposed to interned_string. (enum_type_decl::enumerator::{priv::priv, enumerator, operator=, operator!=, get_name, get_qualified_name}): Adjust. (enum_type_decl::enumerator::get_environment): Remove. * include/abg-reader.h (abigail::abixml_reader): Rename the namespace abigail::xml_reader into this one. (read_context, create_native_xml_read_context) (read_context_get_path, read_corpus_from_native_xml) (read_corpus_from_native_xml_file) (read_corpus_group_from_native_xml) (read_corpus_group_from_native_xml_file): Remove. (read_translation_unit_from_file) (read_translation_unit_from_buffer) (read_translation_unit_from_istream) (read_corpus_group_from_input): Take a reference to an environment, not a pointer. (read_translation_unit) (consider_types_not_reachable_from_public_interfaces) (get_types_from_type_id, get_artifact_used_by_relation_map) (load_canonical_type_ids): Take an fe_iface&, not a read_context. (create_abixml_reader): Declare new function that returns a fe_iface_sptr. (read_corpus_from_abixml, read_corpus_from_abixml_file) (read_corpus_group_from_abixml) (read_corpus_group_from_abixml_file): Declare new functions that take a reference to environment. * src/abg-reader.cc (namespace abixml_reader): Rename the xml_reader namespace into this. (abixml_reader::reader_sptr): New typedef. (abixml_reader::reader): Rename read_context into this. Make it inherit the fe_iface interface. (abixml_reader::reader::{m_path, m_env, m_corpus, m_corpus_group, m_exported_decls_builder, m_supprs}): Remove these data members that are now part of the fe_iface parent type. (abixml_reader::reader::{reader, get_path, set_path, get_environment, get_exported_decls_builder, set_exported_decls_builder, get_suppressions, corpus_is_suppressed_by_soname_or_filename, suppression_can_match}): Adjust. (abixml_reader::reader::{set_environment, get_corpus, set_corpus, set_corpus_group, maybe_add_fn_to_exported_decls, maybe_add_var_to_exported_decls, maybe_check_abixml_canonical_type_stability, suppression_matches_function_sym_name, suppression_matches_variable_name, suppression_matches_variable_sym_name}): Remove. (read_corpus_from_input): Remove. Actually the code of this went into abixml_reader::reader::read_context(). (abixml_reader::reader::get_libxml_reader): Rename the get_reader member function into this. (abixml_reader::add_reader_suppressions): Rename add_read_context_suppressions into this. (abixml_reader::reader::read_corpus): Implement this virtual member function if the fe_iface parent interface. (maybe_set_naming_typedef, advance_cursor) (handle_version_attribute, walk_xml_node_to_map_type_ids) (read_elf_needed_from_input, read_symbol_db_from_input) (get_or_read_and_add_translation_unit, build_needed) (read_elf_needed_from_input, add_read_context_suppressions) (maybe_set_artificial_location, maybe_set_naming_typedef) (build_namespace_decl, build_elf_symbol) (build_elf_symbol_from_reference, build_elf_symbol_db) (build_function_parameter, build_function_decl) (build_function_decl_if_not_suppressed, function_is_suppressed) (type_is_suppressed, build_var_decl_if_not_suppressed) (variable_is_suppressed, variable_is_suppressed, build_var_decl) (build_type_decl, build_qualified_type_decl) (build_pointer_type_def, build_reference_type_def) (build_function_type, build_subrange_type, build_array_type_def) (build_enum_type_decl_if_not_suppressed, build_enum_type_decl) (build_typedef_decl, build_class_decl_if_not_suppressed) (build_union_decl_if_not_suppressed, build_class_decl) (build_union_decl, build_function_tdecl, build_class_tdecl) (build_type_tparameter, build_type_composition) (build_non_type_tparameter, build_non_type_tparameter) (build_template_tparameter, build_template_parameter, build_type) (handle_type_decl, handle_namespace_decl) (handle_qualified_type_decl, handle_pointer_type_def) (handle_reference_type_def, handle_function_type) (handle_array_type_def, handle_enum_type_decl) (handle_typedef_decl, handle_var_decl, handle_function_decl) (handle_class_decl, handle_union_decl, handle_function_tdecl) (read_translation_unit_from_istream): Take or use an abixml_reader::reader rather than a read_context. (read_translation_unit, read_translation_unit_from_input) (consider_types_not_reachable_from_public_interfaces) (get_types_from_type_id, get_artifact_used_by_relation_map) (read_corpus_group_from_input, read_translation_unit) (handle_element_node, read_location, read_artificial_location) (load_canonical_type_ids) : Take an fe_iface&, not a read_context. (create_abixml_reader): Rename create_native_xml_read_context into this. Make it return a fe_iface_sptr. (read_corpus_from_abixml): Rename read_corpus_from_abixml into this. (read_corpus_from_abixml_file): Rename read_corpus_from_native_xml_file into this. (read_corpus_group_from_abixml) (read_corpus_group_from_abixml_file) (read_translation_unit_from_buffer, maybe_map_type_with_type_id): Adjust. (read_context_get_path): Remove. * include/abg-tools-utils.h (abigail::tools_utils::{file_has_dwarf_debug_info, file_has_ctf_debug_info}): Declare new functions. (build_corpus_group_from_kernel_dist_under): Take a reference to environment, not a pointer. (create_best_elf_based_reader): Declare new function. * include/abg-writer.h (create_write_context): Take a reference to environment, not a pointer. * src/abg-comparison.cc (compute_diff): Stop asserting that artifacts being compared come from the same environment because now, it's less likely that things come from different environment, given that ABI artifacts can't see their environment changed. * include/abg-corpus.h (corpus::add): Pass the translation unit by reference. (corpus::exported_decls_builder::maybe_add_{fn,var}_to_exported_fns): Take a const parameter. (corpus::{corpus,get_environment, set_environment}) (corpus_group::{corpus_group}): Pass a reference to the environment, not a pointer. * src/abg-corpus-priv.h (corpus::exported_decls_builder::priv::add_{fn,var}_to_exported): Take a const parameter and adjust. (corpus::priv::env): Change the type of this from environment* to environment&. (corpus::priv::priv): Take a reference to environment, not a pointer. * src/abg-corpus.cc (corpus::exported_decls_builder::maybe_add_{fn,var}_to_exported_fns): Take a const parameter. (corpus::corpus): Take a reference to environment, not a pointer. (corpus::get_environment): Return a reference to environment, not a pointer. (corpus::set_environment): Remove. (corpus::add): Take a reference to translation_unit_sptr. (corpus::{record_type_as_reachable_from_public_interfaces, type_is_reachable_from_public_interfaces, init_format_version, is_empty}): Adjust use of reference to environment, rather than pointer. (corpus_group::corpus_group): Take a reference to environment, not a pointer. (corpus_group::add_corpus): Adjust use of reference to environment, rather than pointer. * include/abg-suppression.h (abigail::fe_iface): Forward-declare this. (abigail::{suppression_sptr, suppressions_type}): Declare these types here. (abigail::suppr::{suppression_can_match, suppression_matches_function_name, suppression_matches_function_sym_name, suppression_matches_variable_name, suppression_matches_variable_sym_name, suppression_matches_type_name_or_location, is_elf_symbol_suppressed, is_elf_symbol_suppressed, is_function_suppressed, is_variable_suppressed, is_type_suppressed}): Declare these functions here. * src/abg-suppression-priv.h (function_is_suppressed) (variable_is_suppressed, type_is_suppressed) (is_elf_symbol_suppressed): Remove these template functions. * src/abg-suppression.cc (suppression_matches_function_name) (suppression_matches_function_sym_name): Remove. (variable_is_suppressed, suppression_can_match) (suppression_matches_function_name) (suppression_matches_function_sym_name) (suppression_matches_variable_name) (suppression_matches_variable_sym_name) (suppression_matches_type_name_or_location) (is_elf_symbol_suppressed, is_elf_symbol_suppressed) (is_function_suppressed, is_variable_suppressed) (is_type_suppressed): New functions. * include/abg-ctf-reader.h (abigail::ctf_reader::{read_context, create_read_context, read_corpus, read_and_add_corpus_to_group_from_elf, set_read_context_corpus_group, reset_read_context, dic_type_key}): Remove. (ctf_reader::{create_ctf_reader, reset_reader}): Declare new functions. * src/abg-ctf-reader.cc (read_context): Remove. (process_ctf_typedef, process_ctf_base_type) (build_ir_node_for_variadic_parameter_type) (process_ctf_function_type, process_ctf_sou_members) (process_ctf_forward_type, process_ctf_struct_type) (process_ctf_union_type, process_ctf_array_type) (process_ctf_qualified_type, process_ctf_pointer_type) (process_ctf_enum_type, fill_ctf_section) (lookup_symbol_in_ctf_archive, dic_type_key): Forward-declare these static functions. (ctf_reader::reader): New class that is the abstraction of the CTF reader. It extends the abigail::elf_based_reader class. This is a renaming of the abigail::ctf_reader::read_context class. (ctf_reader::reader::{elf_handler, elf_fd, elf_handler_dbg, elf_fd_dbg, symtab, debug_info_root_paths_, debug_info_root_paths_}): Remove these data members as they are now properties of the abigail::elf_reader class, which is a parent class of this abigail::ctf_reader::reader class. (ctf_reader::reader::{exported_decls_builder, maybe_add_fn_to_exported_decls, current_corpus_group, has_corpus_group, main_corpus_from_current_group, current_corpus_is_main_corpus_from_current_group, should_reuse_type_from_corpus_group}): Remove these accessors that can now be used from the parent classes abigail::{elf_reader, elf_based_reader}. (ctf_reader::reader::reader): This now takes a reference to an environment as opposed to a pointer, as far as the previous ctf_reader::read_context::read_context constructor was concerned. (ctf_reader::reader::initialize): Add an overload with no parameter. In the other overload, do not take a pointer to an environment as no new environment can be passed to the instance of reader that is being reset. Adjust the code of the initializer to reflect all the data members that got removed. (ctf_reader::{env, find_ctfa_file, slurp_elf_info, process_ctf_archive, process_ctf_type, lookup_type, read_corpus, ~reader}): New member functions. Most of these were free-form functions that took ctf_reader::read_context as first parameter. (lookup_type): Remove. These are now member functions of the ctf_reader::reader class. (process_ctf_typedef, process_ctf_base_type) (build_ir_node_for_variadic_parameter_type) (process_ctf_function_type, process_ctf_sou_members) (process_ctf_forward_type, process_ctf_struct_type) (process_ctf_union_type, process_ctf_array_type) (process_ctf_qualified_type, process_ctf_pointer_type): Take a ctf_reader::reader rather an ctf_reader::read_context. Adjust the content of the functions. (process_ctf_type, lookup_type, process_ctf_archive): Remove these and turn them into member functions of ctf_reader::reader. (open_elf_handler, close_elf_handler, find_alt_debuginfo): Remove these ELF handling functions as ELF handling is now done by the elf_reader parent class. (fill_ctf_section): Take a const pointer to Elf_Scn. (slurp_elf_info, find_ctfa_file): Remove this and make it be a member of ctf_reader::reader. Also, make it handle only CTF reader specific pieces. (create_read_context, read_corpus, set_read_context_corpus_group) (read_and_add_corpus_to_group_from_elf): Remove these functions. (create_ctf_reader, reset_reader): Create new functions (dic_type_key): Make this static. * include/abg-dwarf-reader.h (abigail::dwarf_reader::elf_type): Move this enum into the namespace abigail::elf_reader in the file include/abg-elf-reader.h. (abigail::dwarf_reader::{read_context, read_context_sptr, create_read_context, read_context_get_path, reset_read_context, add_read_context_suppressions, set_read_context_corpus_group, read_corpus_from_elf, read_and_add_corpus_to_group_from_elf, read_and_add_corpus_to_group_from_elf, add_read_context_suppressions, refers_to_alt_debug_info, has_alt_debug_info, get_soname_of_elf_file, get_type_of_elf_file, set_debug_info_root_path, get_debug_info_root_path, get_show_stats, set_show_stats, set_drop_undefined_syms, set_do_log, set_environment, get_environment}): Remove. * src/abg-dwarf-reader.cc (struct dwfl_deleter, dwfl_sptr) (addr_elf_symbol_sptr_map_type, address_set_type) (address_set_sptr): Delete these types. (read_context::options_type): Remove. The data members of this type got moved to struct fe_iface::options_type. (find_alt_debug_info_link, find_alt_debug_info_path) (find_alt_debug_info, lookup_data_tag_from_dynamic_segment) (elf_file_type, refers_to_alt_debug_info, has_alt_debug_info) (get_soname_of_elf_file, get_type_of_elf_file) : Remove these ELF specific functions from here; move them to the elf_reader namespace. (dwarf_reader::reader): Create new class that extends elf_based_reader. dwarf_reader::read_context is renamed into this type, actually. (dwarf_reader::reader::die_source_dependant_container_set::get_container): Adjust. (dwarf_reader::reader::{supprs_, dwarf_version_, offline_callbacks_, debug_info_root_paths_, handle_, dwarf_, alt_fd_, alt_dwarf_, alt_debug_info_path_, elf_module_, elf_handle_, elf_path_, symtab_section_, cur_corpus_group_, cur_corpus_, dt_needed_, dt_soname_, elf_architecture_, exported_decls_builder_, options_, drop_undefined_syms_}): Remove these ELF-related data members to move them into the elf_reader namespace. (maybe_propagate_canonical_type) (build_translation_unit_and_add_to_ir, build_ir_node_from_die) (add_or_update_class_type, add_or_update_union_type) (build_ir_node_for_void_type) (build_ir_node_for_variadic_parameter_type, build_function_decl) (function_is_suppressed, build_or_get_fn_decl_if_not_suppressed) (build_var_decl, build_or_get_var_decl_if_not_suppressed) (variable_is_suppressed) (propagate_canonical_type) (get_parent_die, get_scope_die, die_is_at_class_scope) (die_location, die_qualified_type_name, die_qualified_name) (die_qualified_type_name_empty) (die_return_and_parm_names_from_fn_type_die) (die_function_signature, die_function_type_is_method_type) (die_pretty_print_type, die_pretty_print_decl, die_pretty_print) (maybe_canonicalize_type, build_subrange_type) (build_subranges_from_array_type_die, compare_dies, die_location) (die_loc_and_name, die_is_effectively_public_decl) (maybe_cache_type_comparison_result) (get_cached_type_comparison_result) (maybe_get_cached_type_comparison_result, die_is_at_class_scope) (die_function_type_is_method_type, die_member_offset) (die_qualified_type_name, die_qualified_decl_name) (die_qualified_name, die_qualified_type_name_empty) (die_return_and_parm_names_from_fn_type_die) (die_function_signature, die_pretty_print_type) (die_pretty_print_decl, die_pretty_print) (at_least_one_decl_only_among_odr_relevant_dies) (compare_as_type_dies, compare_as_decl_and_type_dies) (fn_die_equal_by_linkage_name, try_canonical_die_comparison) (maybe_propagate_canonical_type, propagate_canonical_type) (compare_dies, compare_dies_during_canonicalization) (find_import_unit_point_between_dies, get_parent_die) (get_scope_die, find_lower_bound_in_imported_unit_points) (build_translation_unit_and_add_to_ir) (build_namespace_decl_and_add_to_ir, build_type_decl) (build_enum_underlying_type, build_enum_type) (finish_member_function_reading) (maybe_finish_function_decl_reading) (lookup_class_or_typedef_from_corpus) (is_function_for_die_a_member_of_class) (add_or_update_member_function, add_or_update_class_type) (add_or_update_union_type, build_qualified_type) (schedule_array_tree_for_late_canonicalization) (maybe_strip_qualification, build_pointer_type_def) (build_reference_type, build_function_type, build_subrange_type) (build_subranges_from_array_type_die, build_array_type) (build_typedef_type, build_or_get_var_decl_if_not_suppressed) (build_var_decl, function_is_suppressed) (build_or_get_fn_decl_if_not_suppressed, variable_is_suppressed) (type_is_suppressed, type_is_suppressed) (get_opaque_version_of_type, create_default_fn_sym) (build_function_decl, maybe_canonicalize_type) (build_ir_node_from_die) (build_ir_node_for_variadic_parameter_type): Take a reference to the new dwarf_reader::reader rather than to the previous read_context. Adjust the function body. (return_comparison_result): Adjust. (lookup_symbol_from_sysv_hash_tab) (lookup_symbol_from_gnu_hash_tab) (lookup_symbol_from_elf_hash_tab, lookup_symbol_from_symtab) (lookup_symbol_from_elf, lookup_public_function_symbol_from_elf): Take a reference to environment, rather than a pointer. (dwarf_reader::reader::reader): Adjust this from read_context::read_context. (dwarf_reader::reader::initialize): Adjust from dwarf_reader::read_context::initialize. (dwarf_reader::reader::create): New factory static member function. (dwarf_reader::reader::~reader): This doesn't have to clear anything for now. (dwarf_reader::reader::read_corpus): New virtual member function which implements the fe_iface::read_corpus pure virtual interface. (dwarf_reader::reader::reset_corpus): New member function. (dwarf_reader::reader::read_debug_info_into_corpus): Adjust. This is now a member function. (dwarf_reader::reader::{env, drop_undefined_syms, drop_undefined_syms, dwarf_elf_handle, dwarf_per_die_source, elf_path, compute_canonical_die_offset, get_die_source, get_die_from_offset, get_die_qualified_name, get_die_pretty_type_representation, get_die_qualified_type_name, get_die_pretty_representation, odr_is_relevant, set_canonical_die_offset, get_canonical_die_offset, erase_canonical_die_offset, die_wip_classes_map, die_wip_function_types_map, compare_before_canonicalisation, resolve_declaration_only_classes, resolve_declaration_only_enums, symbol_already_belongs_to_a_function, fixup_functions_with_no_symbols, canonicalize_types_scheduled, tu_die_imported_unit_points_map, die_parent_map, find_symbol_table_section, get_variable_address, exported_decls_builder, load_all_types, load_in_linux_kernel_mode, show_stats, do_log, build_die_parent_maps): Adjust. (offset_pairs_stack_type::rdr_): Changed the ctxt_ into this. (offset_pairs_stack_type::offset_pairs_stack_type): Adjust. (offset_pairs_stack_type::{erase_redundant_type_pair_entry, cancel_canonical_propagated_type}): Adjust. (dwarf_reader::reader::{get_suppressions, offline_callbacks, create_default_dwfl, dwfl_handle, elf_module, elf_handle, add_debug_info_root_paths, add_debug_info_root_path, find_alt_debug_info, dwarf, alt_dwarf, alt_debug_info_path, current_corpus, reset_current_corpus, current_corpus_group, has_corpus_group, main_corpus_from_current_group, current_corpus_is_main_corpus_from_current_group, should_reuse_type_from_corpus_group, function_symbol_is_exported, variable_symbol_is_exported, symtab, dt_needed, dt_soname, elf_architecture, is_elf_symbol_suppressed, load_dt_soname_and_needed, load_elf_architecture, load_elf_properties, maybe_add_fn_to_exported_decls, maybe_add_var_to_exported_decls}): Remove these member functions as they got moved into the elf_reader namespace or into the fe_iface class. (dwarf_reader::read_context::{suppression_can_match, suppression_matches_function_sym_name, suppression_matches_function_name, suppression_matches_variable_name, suppression_matches_variable_sym_name, suppression_matches_type_name_or_location}): Move these into the suppr namespace. Make it take an additional parameter that is reference fe_iface. (dwarf_reader::reader::load_debug_info): Remove. This became merged into dwarf_reader::read_debug_info_into_corpus. (dwarf_reader::{set_debug_info_root_path, get_debug_info_root_path, get_show_stats, set_drop_undefined_syms, set_do_log}): Remove. (add_read_context_suppressions) (set_read_context_corpus_group, read_corpus_from_elf): Remove. (read_debug_info_into_corpus): This became a member function of dwarf_reader::reader. (create_dwarf_reader): Renamed create_read_context into this. Make it return an elf_based_reader_sptr, like the other front-end factory functions. Adjust. (reset_dwarf_reader): Renamed reset_read_context into this. Adjust. (read_corpus_from_elf, lookup_symbol_from_elf) (lookup_public_function_symbol_from_elf): Take a reference to the environment rather than a pointer. Adjust. * src/abg-elf-based-reader.cc: New file. * src/abg-elf-helpers.h (struct dwfl_deleter, dwfl_sptr) (addr_elf_symbol_sptr_map_type, address_set_sptr): Move these types here from abg-dwarf-reader.cc (initialize_dwfl_callbacks, lookup_data_tag_from_dynamic_segment): * src/abg-elf-helpers.cc (lookup_data_tag_from_dynamic_segment) (lookup_data_tag_from_dynamic_segment, initialize_dwfl_callbacks) (create_new_dwfl_handle, get_soname_of_elf_file): New functions that got moved here from the factorizing of abg-dwarf-reader.cc and abg-ctf-reader.cc. * src/abg-symtab-reader.h (symtab::{load, load_}): Take a reference to an environment, not a pointer. * src/abg-symtab-reader.cc (symtab::{load, load_}): Likewise. * src/abg-tools-utils.cc (file_has_dwarf_debug_info) (file_has_ctf_debug_info): New functions. (load_generate_apply_suppressions): Take an elf_based_reader, not a dwarf_reader::read_context. (maybe_load_vmlinux_dwarf_corpus) (build_corpus_group_from_kernel_dist_under): Take a reference to environment, not a pointer. Adjust the body to use the new front-end types. * rc/abg-writer.cc (id_manger::m_env): Make this a reference to an environment, rather than a pointer. (id_manager::{id_manager, get_environment, get_id}): Adjust. (write_context::m_env): Make this a reference to an environment rather than a pointer. (write_context::{write_context, get_environment, get_config, get_id_for_type, decl_is_emitted, record_decl_as_emitted}): Adjust. (create_write_context, write_class_decl): Take a reference to an environment, rather than a pointer. Adjust the body. * src/Makefile.am: Add the new files src/abg-{fe-iface, elf-based-reader, elf-reader}.cc to source distribution. Remove src/abg-elf-reader-common.cc. * tools/Makefile.am: Factorize linking to libabigail.so by using LDADD. * tools/abicompat.cc (read_corpus, main): Adjust. * tools/abidiff.cc (set_suppressions) (set_native_xml_reader_options, handle_error, main): Adjust. * tools/abidw.cc (set_suppressions, load_corpus_and_write_abixml) (load_kernel_corpus_group_and_write_abixml): Adjust. * tools/abilint.cc (build_type_use_tree, show_how_type_is_used) (set_suppressions, main): Adjust. * tools/abipkgdiff.cc (elf_file::type, compare, compare_to_self) (create_maps_of_package_content) (compare_prepared_userspace_packages) (self_compare_prepared_userspace_package) (compare_prepared_linux_kernel_packages): Adjust. * tools/abisym.cc (main): Adjust. * tools/kmidiff.cc (main): Adjust. * tests/print-diff-tree.cc (main): Adjust. * tests/test-abidiff.cc (main): Likewise. * tests/test-diff-dwarf.cc (main): Likewise. * tests/test-ir-walker.cc (main): Likewise. * tests/test-read-ctf.cc (test_task_ctf::perform): Likewise. * tests/test-read-dwarf.cc: Remove the useless "using" statements. * tests/test-read-write.cc: Likewise. * tests/test-symtab.cc (read_corpus, TEST_CASE) (assert_symbol_count): Adjust. * tests/data/test-read-ctf/test0.abi: Adjust. * tests/data/test-read-ctf/test0.hash.abi: Likewise. * tests/data/test-read-ctf/test1.so.abi: Likewise. * tests/data/test-read-ctf/test1.so.hash.abi: Likewise. * tests/data/test-read-ctf/test2.so.abi: Likewise. * tests/data/test-read-ctf/test2.so.hash.abi: Likewise. * tests/data/test-read-ctf/test3.so.abi: Likewise. * tests/data/test-read-ctf/test3.so.hash.abi: Likewise. * tests/data/test-read-ctf/test4.so.abi: Likewise. * tests/data/test-read-ctf/test4.so.hash.abi: Likewise. Signed-off-by: Dodji Seketeli --- include/Makefile.am | 4 +- include/abg-corpus.h | 18 +- include/abg-ctf-reader.h | 33 +- include/abg-dwarf-reader.h | 124 +- include/abg-elf-based-reader.h | 63 + include/abg-elf-reader-common.h | 70 - include/abg-elf-reader.h | 155 + include/abg-fe-iface.h | 166 + include/abg-fwd.h | 2 +- include/abg-ir.h | 156 +- include/abg-reader.h | 62 +- include/abg-suppression.h | 67 + include/abg-tools-utils.h | 13 +- include/abg-writer.h | 2 +- src/Makefile.am | 4 +- src/abg-comparison.cc | 67 +- src/abg-corpus-priv.h | 18 +- src/abg-corpus.cc | 73 +- src/abg-ctf-reader.cc | 1545 ++++---- src/abg-dwarf-reader.cc | 3849 +++++++------------- src/abg-elf-based-reader.cc | 102 + src/abg-elf-helpers.cc | 183 +- src/abg-elf-helpers.h | 38 + src/abg-elf-reader-common.cc | 90 - src/abg-elf-reader.cc | 890 +++++ src/abg-fe-iface.cc | 411 +++ src/abg-ir-priv.h | 57 +- src/abg-ir.cc | 817 ++--- src/abg-reader.cc | 1974 +++++----- src/abg-suppression-priv.h | 179 - src/abg-suppression.cc | 479 ++- src/abg-symtab-reader.cc | 5 +- src/abg-symtab-reader.h | 6 +- src/abg-tools-utils.cc | 163 +- src/abg-writer.cc | 39 +- tests/data/test-read-ctf/test0.abi | 3 + tests/data/test-read-ctf/test0.hash.abi | 3 + tests/data/test-read-ctf/test1.so.abi | 3 + tests/data/test-read-ctf/test1.so.hash.abi | 3 + tests/data/test-read-ctf/test2.so.abi | 3 + tests/data/test-read-ctf/test2.so.hash.abi | 3 + tests/data/test-read-ctf/test3.so.abi | 5 +- tests/data/test-read-ctf/test3.so.hash.abi | 5 +- tests/data/test-read-ctf/test4.so.abi | 3 + tests/data/test-read-ctf/test4.so.hash.abi | 3 + tests/print-diff-tree.cc | 12 +- tests/test-abidiff.cc | 24 +- tests/test-diff-dwarf.cc | 20 +- tests/test-ir-walker.cc | 7 +- tests/test-read-ctf.cc | 20 +- tests/test-read-dwarf.cc | 3 - tests/test-read-write.cc | 3 - tests/test-symtab.cc | 42 +- tools/Makefile.am | 13 +- tools/abicompat.cc | 63 +- tools/abidiff.cc | 222 +- tools/abidw.cc | 178 +- tools/abilint.cc | 128 +- tools/abipkgdiff.cc | 222 +- tools/abisym.cc | 5 +- tools/kmidiff.cc | 14 +- 61 files changed, 6365 insertions(+), 6569 deletions(-) create mode 100644 include/abg-elf-based-reader.h delete mode 100644 include/abg-elf-reader-common.h create mode 100644 include/abg-elf-reader.h create mode 100644 include/abg-fe-iface.h create mode 100644 src/abg-elf-based-reader.cc delete mode 100644 src/abg-elf-reader-common.cc create mode 100644 src/abg-elf-reader.cc create mode 100644 src/abg-fe-iface.cc diff --git a/include/Makefile.am b/include/Makefile.am index b3b9148f..6b7f1e49 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -4,8 +4,10 @@ abg-sptr-utils.h \ abg-interned-str.h \ abg-ir.h \ abg-corpus.h \ +abg-fe-iface.h \ +abg-elf-based-reader.h \ +abg-elf-reader.h \ abg-reader.h \ -abg-elf-reader-common.h \ abg-dwarf-reader.h \ abg-writer.h \ abg-comparison.h \ diff --git a/include/abg-corpus.h b/include/abg-corpus.h index 27de8c2f..20ec4f41 100644 --- a/include/abg-corpus.h +++ b/include/abg-corpus.h @@ -60,21 +60,15 @@ public: struct priv; std::unique_ptr priv_; - corpus(ir::environment*, const string& path= ""); + corpus(const ir::environment&, const string& path= ""); virtual ~corpus(); - const environment* + const environment& get_environment() const; - environment* - get_environment(); - - void - set_environment(environment*); - void - add(const translation_unit_sptr); + add(const translation_unit_sptr&); const translation_units& get_translation_units() const; @@ -332,10 +326,10 @@ public: exported_variables(); void - maybe_add_fn_to_exported_fns(function_decl*); + maybe_add_fn_to_exported_fns(const function_decl*); void - maybe_add_var_to_exported_vars(var_decl*); + maybe_add_var_to_exported_vars(const var_decl*); }; //corpus::exported_decls_builder /// Abstraction of a group of corpora. @@ -355,7 +349,7 @@ class corpus_group : public corpus public: typedef vector corpora_type; - corpus_group(ir::environment*, const string&); + corpus_group(const ir::environment&, const string&); virtual ~corpus_group(); diff --git a/include/abg-ctf-reader.h b/include/abg-ctf-reader.h index 0f49b5eb..ea19683e 100644 --- a/include/abg-ctf-reader.h +++ b/include/abg-ctf-reader.h @@ -17,7 +17,7 @@ #include #include "abg-corpus.h" #include "abg-suppression.h" -#include "abg-elf-reader-common.h" +#include "abg-elf-based-reader.h" #include "ctf-api.h" @@ -26,32 +26,15 @@ namespace abigail namespace ctf_reader { -class read_context; -typedef shared_ptr read_context_sptr; - -read_context_sptr -create_read_context(const std::string& elf_path, - const vector& debug_info_root_paths, - ir::environment *env); -corpus_sptr -read_corpus(read_context *ctxt, elf_reader::status& status); - -corpus_sptr -read_corpus(const read_context_sptr &ctxt, elf_reader::status &status); - -corpus_sptr -read_and_add_corpus_to_group_from_elf(read_context*, corpus_group&, elf_reader::status&); - -void -set_read_context_corpus_group(read_context& ctxt, corpus_group_sptr& group); +elf_based_reader_sptr +create_ctf_reader(const std::string& elf_path, + const vector& debug_info_root_paths, + environment& env); void -reset_read_context(read_context_sptr &ctxt, - const std::string& elf_path, - const vector& debug_info_root_path, - ir::environment* environment); -std::string -dic_type_key(ctf_dict_t *dic, ctf_id_t ctf_type); +reset_reader(elf_based_reader& ctxt, + const std::string& elf_path, + const vector& debug_info_root_path); } // end namespace ctf_reader } // end namespace abigail diff --git a/include/abg-dwarf-reader.h b/include/abg-dwarf-reader.h index 5766f906..f325da32 100644 --- a/include/abg-dwarf-reader.h +++ b/include/abg-dwarf-reader.h @@ -18,7 +18,7 @@ #include #include "abg-corpus.h" #include "abg-suppression.h" -#include "abg-elf-reader-common.h" +#include "abg-elf-based-reader.h" namespace abigail { @@ -29,131 +29,39 @@ namespace dwarf_reader using namespace abigail::ir; -/// The kind of ELF file we are looking at. -enum elf_type -{ - /// A normal executable binary - ELF_TYPE_EXEC, - /// A Position Independant Executable binary - ELF_TYPE_PI_EXEC, - /// A dynamic shared object, a.k.a shared library binrary. - ELF_TYPE_DSO, - /// A relocatalbe binary. - ELF_TYPE_RELOCATABLE, - /// An unknown kind of binary. - ELF_TYPE_UNKNOWN -}; - -class read_context; - -/// A convenience typedef for a smart pointer to a -/// dwarf_reader::read_context. -typedef shared_ptr read_context_sptr; - -read_context_sptr -create_read_context(const std::string& elf_path, +elf_based_reader_sptr +create_dwarf_reader(const std::string& elf_path, const vector& debug_info_root_paths, - ir::environment* environment, + environment& environment, bool read_all_types = false, bool linux_kernel_mode = false); -const string& -read_context_get_path(const read_context&); - void -reset_read_context(read_context_sptr &ctxt, - const std::string& elf_path, - const vector& debug_info_root_paths, - ir::environment* environment, - bool read_all_types = false, - bool linux_kernel_mode = false); - -void -add_read_context_suppressions(read_context& ctxt, - const suppr::suppressions_type& supprs); - -void -set_read_context_corpus_group(read_context& ctxt, corpus_group_sptr& group); +reset_dwarf_reader(elf_based_reader& rdr, + const std::string& elf_path, + const vector& debug_info_root_paths, + bool read_all_types = false, + bool linux_kernel_mode = false); corpus_sptr -read_corpus_from_elf(read_context& ctxt, elf_reader::status& stat); - -corpus_sptr -read_corpus_from_elf(const std::string& elf_path, - const vector& debug_info_root_paths, - ir::environment* environment, - bool load_all_types, - elf_reader::status&); - -corpus_sptr -read_and_add_corpus_to_group_from_elf(read_context&, corpus_group&, elf_reader::status&); +read_corpus_from_elf(const std::string& elf_path, + const vector& debug_info_root_paths, + environment& environment, + bool load_all_types, + fe_iface::status& status); bool -lookup_symbol_from_elf(const environment* env, +lookup_symbol_from_elf(environment& env, const string& elf_path, const string& symbol_name, bool demangle, vector& symbols); bool -lookup_public_function_symbol_from_elf(const environment* env, +lookup_public_function_symbol_from_elf(environment& env, const string& path, const string& symname, vector& func_syms); - -bool -refers_to_alt_debug_info(const read_context& ctxt, - string& alt_di_path); - -elf_reader::status -has_alt_debug_info(read_context& ctxt, - bool& has_alt_di, - string& alt_debug_info_path); - -elf_reader::status -has_alt_debug_info(const string& elf_path, - char** debug_info_root_path, - bool& has_alt_di, - string& alt_debug_info_path); - -bool -get_soname_of_elf_file(const string& path, string& soname); - -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& ctxt); - -void -set_show_stats(read_context& ctxt, - bool f); - -void -set_drop_undefined_syms(read_context& ctxt, - bool f); - -void -set_do_log(read_context& ctxt, 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-elf-based-reader.h b/include/abg-elf-based-reader.h new file mode 100644 index 00000000..8916822f --- /dev/null +++ b/include/abg-elf-based-reader.h @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// -*- Mode: C++ -*- +// +// Copyright (C) 2022 Red Hat, Inc. +// +// Author: Dodji Seketeli + +/// @file +/// +/// This file contains the declarations for an elf-based. DWARF and +/// CTF readers can inherit this one. + + +#ifndef __ABG_ELF_BASED_READER_H__ +#define __ABG_ELF_BASED_READER_H__ + +#include +#include + +#include "abg-elf-reader.h" +#include "abg-corpus.h" + +namespace abigail +{ + +/// The common interface of readers based on ELF. +/// +/// These are for readers like DWARF and CTF readers that read debug +/// information describing binaries in the ELF format. +/// +/// This interface extends the elf_reader::reader interface and thus +/// also provides facilities for reading ELF binaries. +class elf_based_reader : public elf_reader::reader +{ + struct priv; + priv* priv_; + + elf_based_reader() = delete; + +protected: + + /// Readers that implement this interface must provide a factory + /// method to create a reader instance as this constructor is + /// protected. + elf_based_reader(const std::string& elf_path, + const vector& debug_info_root_paths, + environment& env); +public: + + ~elf_based_reader(); + + virtual void + reset(const std::string& elf_path, + const vector& debug_info_root_paths); + + virtual ir::corpus_sptr + read_and_add_corpus_to_group(ir::corpus_group& group, + fe_iface::status& status); +};//end class elf_based_reader + +typedef std::shared_ptr elf_based_reader_sptr; +}// namespace +#endif diff --git a/include/abg-elf-reader-common.h b/include/abg-elf-reader-common.h deleted file mode 100644 index 3f4d49b0..00000000 --- a/include/abg-elf-reader-common.h +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -*- Mode: C++ -*- -// -// Copyright (C) 2021-2022 Oracle, Inc. -// -// Author: Jose E. Marchesi - -/// @file -/// -/// This file contains declarations implementing the different status -/// in which a corpus read from an ELF file can result. It is used by -/// the readers based on ELF files, such as DWARF and CTF. -/// -/// More generally, this file contains declarations related to -/// facilities shared by the various readers that handle the ELF -/// format, e.g, the DWARF and CTF realder. - -#ifndef __ABG_ELF_READER_COMMON_H__ -#define __ABG_ELF_READER_COMMON_H__ - -#include - -namespace abigail -{ - -/// The namespace for an ELF based reader. -namespace elf_reader -{ - -/// The status of the @ref read_corpus_from_elf() call. -enum status -{ - /// The status is in an unknown state - STATUS_UNKNOWN = 0, - - /// This status is for when the call went OK. - STATUS_OK = 1, - - /// This status is for when the debug info could not be read. - STATUS_DEBUG_INFO_NOT_FOUND = 1 << 1, - - /// This status is for when the alternate debug info could not be - /// found. - STATUS_ALT_DEBUG_INFO_NOT_FOUND = 1 << 2, - - /// This status is for when the symbols of the ELF binaries could - /// not be read. - STATUS_NO_SYMBOLS_FOUND = 1 << 3, -}; - -std::string -status_to_diagnostic_string(status s); - -status -operator|(status, status); - -status -operator&(status, status); - -status& -operator|=(status&, status); - -status& -operator&=(status&, status); - -}// end namespace elf_reader - -}// end namespace abigail - -#endif //__ABG_ELF_READER_COMMON_H__ diff --git a/include/abg-elf-reader.h b/include/abg-elf-reader.h new file mode 100644 index 00000000..c6cecf0f --- /dev/null +++ b/include/abg-elf-reader.h @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// -*- Mode: C++ -*- +// +// Copyright (C) 2022 Red Hat, Inc. +// +// Author: Dodji Seketeli + +/// @file +/// +/// This file contains the declarations for the @ref fe_iface a.k.a +/// "Front End Interface". + +#ifndef __ABG_ELF_READER_H__ +#define __ABG_ELF_READER_H__ + +#include +#include + +#include + +#include "abg-fe-iface.h" +#include "abg-ir.h" +#include "abg-suppression.h" + +namespace abigail +{ + +/// The namespace for the ELF Reader. +namespace elf_reader +{ + +/// The kind of ELF file we are looking at. +enum elf_type : unsigned +{ + /// A normal executable binary + ELF_TYPE_EXEC, + /// A Position Independant Executable binary + ELF_TYPE_PI_EXEC, + /// A dynamic shared object, a.k.a shared library binary. + ELF_TYPE_DSO, + /// A relocatalbe binary. + ELF_TYPE_RELOCATABLE, + /// An unknown kind of binary. + ELF_TYPE_UNKNOWN +}; + +/// This is the interface an ELF reader. +/// +/// It knows how to open an ELF file, read its content and expose an +/// interface for its symbol table and other properties. +/// +/// Note that the ABI corpus returned by the elf_reader::read_corpus() +/// member function doesn't contain any type representation. It only +/// contains the representations of the the ELF symbols found in the +/// ELF file. +/// +/// To construct the type representations for the functions and global +/// variables present in the ELF file, please use the implementations +/// of the @ref elf_based_reader interface. Those know how to read +/// the debug information from the ELF file to build type +/// representation in the @ref abigail::ir::corpus instance. +class reader : public fe_iface +{ + struct priv; + priv *priv_; + + public: + + reader(const std::string& elf_path, + const vector& debug_info_roots, + environment& env); + + ~reader(); + + void + reset(const std::string& elf_path, + const vector& debug_info_roots); + + const vector& + debug_info_root_paths() const; + + const Dwfl_Callbacks& + dwfl_offline_callbacks() const; + + Dwfl_Callbacks& + dwfl_offline_callbacks(); + + Elf* + elf_handle() const; + + const Dwarf* + dwarf_debug_info() const; + + const Dwarf* + alternate_dwarf_debug_info() const; + + const string& + alternate_dwarf_debug_info_path() const; + + bool + refers_to_alt_debug_info(string& alt_di_path) const; + + const Elf_Scn* + find_symbol_table_section() const; + + void + reset_symbol_table_section(); + + const Elf_Scn* + find_ctf_section() const; + + const Elf_Scn* + find_alternate_ctf_section() const; + + const vector& + dt_needed()const; + + const string& + elf_architecture() const; + + symtab_reader::symtab_sptr& + symtab() const; + + elf_symbol_sptr + function_symbol_is_exported(GElf_Addr symbol_address) const; + + elf_symbol_sptr + variable_symbol_is_exported(GElf_Addr symbol_address) const; + + void + load_dt_soname_and_needed(); + + void + load_elf_architecture(); + + void + load_elf_properties(); + + virtual ir::corpus_sptr + read_corpus(status& status); +};//end class reader. + +/// A convenience typedef for a smart pointer to a +/// elf_reader::reader. +typedef shared_ptr reader_sptr; + +bool +get_soname_of_elf_file(const string& path, string &soname); + +bool +get_type_of_elf_file(const string& path, elf_type& type); +} // end namespace elf_reader. +} // end namespace abigail + +#endif // __ABG_ELF_READER_H__ diff --git a/include/abg-fe-iface.h b/include/abg-fe-iface.h new file mode 100644 index 00000000..5e6cf26f --- /dev/null +++ b/include/abg-fe-iface.h @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// -*- Mode: C++ -*- +// +// Copyright (C) 2022 Red Hat, Inc. +// +// Author: Dodji Seketeli + +/// @file +/// +/// This file contains the declarations for the @ref fe_iface a.k.a +/// "Front End Interface". + +#ifndef __ABG_FE_IFACE_H__ +#define __ABG_FE_IFACE_H__ + +#include "abg-ir.h" +#include "abg-suppression.h" + +namespace abigail +{ + +/// The base class of all libabigail front-ends: The Front End Interface. +/// +/// A front end reads a given type of binary format and constructs a +/// libagbigail internal representation from it. +/// +/// The middle-end then manipulates that IR. +class fe_iface +{ +protected: + struct priv; + priv* priv_; + + public: + + /// The status of the @ref fe_iface::read_corpus call. + enum status + { + /// The status is in an unknown state + STATUS_UNKNOWN = 0, + + /// This status is for when the call went OK. + STATUS_OK = 1, + + /// This status is for when the debug info could not be read. + STATUS_DEBUG_INFO_NOT_FOUND = 1 << 1, + + /// This status is for when the alternate debug info could not be + /// found. + STATUS_ALT_DEBUG_INFO_NOT_FOUND = 1 << 2, + + /// This status is for when the symbols of the ELF binaries could + /// not be read. + STATUS_NO_SYMBOLS_FOUND = 1 << 3, + }; + + /// The generic options that control the behaviour of all Front-End + /// interfaces. + struct options_type + { + environment& env; + bool load_in_linux_kernel_mode = false; + bool load_all_types = false; + bool drop_undefined_syms = false; + bool show_stats = false; + bool do_log = false;; + options_type(environment&); + + };// font_end_iface::options_type + + fe_iface(const std::string& corpus_path, environment& e); + + ~fe_iface(); + + void + reset(const std::string& corpus_path, environment& e); + + const options_type& + options() const; + + options_type& + options(); + + const std::string& + corpus_path() const; + + void + corpus_path(const std::string&); + + const string& + dt_soname() const; + + void + dt_soname(const string&); + + bool + load_in_linux_kernel_mode() const; + + suppr::suppressions_type& + suppressions(); + + const suppr::suppressions_type& + suppressions() const; + + void + suppressions(suppr::suppressions_type&); + + void + add_suppressions(const suppr::suppressions_type&); + + corpus_sptr + corpus(); + + const corpus_sptr + corpus() const; + + corpus_group_sptr& + corpus_group(); + + const corpus_group_sptr& + corpus_group() const; + + void + corpus_group(const ir::corpus_group_sptr& cg); + + bool + has_corpus_group() const; + + corpus_sptr + main_corpus_from_current_group(); + + bool + current_corpus_is_main_corpus_from_current_group(); + + corpus_sptr + should_reuse_type_from_corpus_group(); + + void + maybe_add_fn_to_exported_decls(const function_decl* fn); + + void + maybe_add_var_to_exported_decls(const var_decl* var); + + virtual ir::corpus_sptr + read_corpus(status& status) = 0; +}; //end class fe_iface + +typedef shared_ptr fe_iface_sptr; + +std::string +status_to_diagnostic_string(fe_iface::status s); + +fe_iface::status +operator|(fe_iface::status, fe_iface::status); + +fe_iface::status +operator&(fe_iface::status, fe_iface::status); + +fe_iface::status& +operator|=(fe_iface::status&, fe_iface::status); + +fe_iface::status& +operator&=(fe_iface::status&, fe_iface::status); + +}// end namespace abigail +#endif // __ABG_FE_IFAC_H__ diff --git a/include/abg-fwd.h b/include/abg-fwd.h index 1dbe99bb..33087b90 100644 --- a/include/abg-fwd.h +++ b/include/abg-fwd.h @@ -1384,7 +1384,7 @@ string demangle_cplus_mangled_name(const string&); type_base_sptr -type_or_void(const type_base_sptr, const environment*); +type_or_void(const type_base_sptr, const environment&); type_base_sptr canonicalize(type_base_sptr); diff --git a/include/abg-ir.h b/include/abg-ir.h index 4892f0e2..4272a13c 100644 --- a/include/abg-ir.h +++ b/include/abg-ir.h @@ -649,7 +649,7 @@ class translation_unit : public traversable_base std::unique_ptr priv_; // Forbidden - translation_unit() = delete; + translation_unit(); public: /// Convenience typedef for a shared pointer on a @ref global_scope. @@ -689,21 +689,15 @@ public: }; public: - translation_unit(const ir::environment* env, + translation_unit(const ir::environment& env, const std::string& path, char address_size = 0); virtual ~translation_unit(); - const environment* + const environment& get_environment() const; - environment* - get_environment(); - - void - set_environment(const environment*); - language get_language() const; @@ -929,7 +923,7 @@ private: elf_symbol(); - elf_symbol(const environment* e, + elf_symbol(const environment& e, size_t i, size_t s, const string& n, @@ -952,30 +946,24 @@ private: public: static elf_symbol_sptr - create(); - - static elf_symbol_sptr - create(const environment* e, - size_t i, - size_t s, - const string& n, - type t, - binding b, - bool d, - bool c, - const version& ve, - visibility vi, - bool is_in_ksymtab = false, + create(const environment& e, + size_t i, + size_t s, + const string& n, + type t, + binding b, + bool d, + bool c, + const version& ve, + visibility vi, + bool is_in_ksymtab = false, const abg_compat::optional& crc = {}, const abg_compat::optional& ns = {}, - bool is_suppressed = false); + bool is_suppressed = false); - const environment* + const environment& get_environment() const; - void - set_environment(const environment*) const; - size_t get_index() const; @@ -1340,6 +1328,7 @@ class type_or_decl_base : public ir_traversable_base mutable std::unique_ptr priv_; type_or_decl_base(); + type_or_decl_base(const type_or_decl_base&); protected: @@ -1399,13 +1388,14 @@ protected: void hashing_started(bool) const; + type_or_decl_base& + operator=(const type_or_decl_base&); + public: - type_or_decl_base(const environment*, + type_or_decl_base(const environment&, enum type_or_decl_kind k = ABSTRACT_TYPE_OR_DECL); - type_or_decl_base(const type_or_decl_base&); - virtual ~type_or_decl_base(); bool @@ -1414,15 +1404,9 @@ public: void set_is_artificial(bool); - const environment* + const environment& get_environment() const; - environment* - get_environment(); - - void - set_environment(const environment*); - void set_artificial_location(const location &); @@ -1447,9 +1431,6 @@ public: translation_unit* get_translation_unit(); - type_or_decl_base& - operator=(const type_or_decl_base&); - virtual bool traverse(ir_node_visitor&); @@ -1511,14 +1492,6 @@ operator==(const type_or_decl_base_sptr&, const type_or_decl_base_sptr&); bool operator!=(const type_or_decl_base_sptr&, const type_or_decl_base_sptr&); -void -set_environment_for_artifact(type_or_decl_base* artifact, - const environment* env); - -void -set_environment_for_artifact(type_or_decl_base_sptr artifact, - const environment* env); - /// The base type of all declarations. class decl_base : public virtual type_or_decl_base { @@ -1591,23 +1564,22 @@ protected: void set_context_rel(context_rel *c); + decl_base(const decl_base&); public: - decl_base(const environment* e, + decl_base(const environment& e, const string& name, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); - decl_base(const environment* e, + decl_base(const environment& e, const interned_string& name, const location& locus, const interned_string& mangled_name = interned_string(), visibility vis = VISIBILITY_DEFAULT); - decl_base(const environment*, const location&); - - decl_base(const decl_base&); + decl_base(const environment&, const location&); virtual bool operator==(const decl_base&) const; @@ -1821,11 +1793,11 @@ protected: public: struct hash; - scope_decl(const environment* env, + scope_decl(const environment& env, const string& name, const location& locus, visibility vis = VISIBILITY_DEFAULT); - scope_decl(const environment* env, location& l); + scope_decl(const environment& env, location& l); virtual size_t get_hash() const; @@ -2000,7 +1972,7 @@ public: /// runtime type of the type pointed to. struct shared_ptr_hash; - type_base(const environment* e, size_t s, size_t a); + type_base(const environment& e, size_t s, size_t a); friend type_base_sptr canonicalize(type_base_sptr); @@ -2104,7 +2076,7 @@ public: /// Facility to hash instance of type_decl struct hash; - type_decl(const environment* env, + type_decl(const environment& env, const string& name, size_t size_in_bits, size_t alignment_in_bits, @@ -2159,7 +2131,7 @@ public: /// Hasher for instances of scope_type_decl struct hash; - scope_type_decl(const environment* env, const string& name, + scope_type_decl(const environment& env, const string& name, size_t size_in_bits, size_t alignment_in_bits, const location& locus, visibility vis = VISIBILITY_DEFAULT); @@ -2180,7 +2152,7 @@ class namespace_decl : public scope_decl { public: - namespace_decl(const environment* env, const string& name, + namespace_decl(const environment& env, const string& name, const location& locus, visibility vis = VISIBILITY_DEFAULT); virtual string @@ -2234,7 +2206,7 @@ public: qualified_type_def(type_base_sptr type, CV quals, const location& locus); - qualified_type_def(environment* env, CV quals, const location& locus); + qualified_type_def(const environment& env, CV quals, const location& locus); virtual size_t get_size_in_bits() const; @@ -2335,10 +2307,9 @@ public: pointer_type_def(const type_base_sptr& pointed_to_type, size_t size_in_bits, size_t alignment_in_bits, const location& locus); - pointer_type_def(environment* env, size_t size_in_bits, + pointer_type_def(const environment& env, size_t size_in_bits, size_t alignment_in_bits, const location& locus); - void set_pointed_to_type(const type_base_sptr&); @@ -2400,7 +2371,7 @@ public: bool lvalue, size_t size_in_bits, size_t alignment_in_bits, const location& locus); - reference_type_def(const environment* env, bool lvalue, size_t size_in_bits, + reference_type_def(const environment& env, bool lvalue, size_t size_in_bits, size_t alignment_in_bits, const location& locus); void @@ -2522,7 +2493,7 @@ public: /// Hasher for an instance of array::subrange struct hash; - subrange_type(const environment* env, + subrange_type(const environment& env, const string& name, bound_value lower_bound, bound_value upper_bound, @@ -2530,14 +2501,14 @@ public: const location& loc, translation_unit::language l = translation_unit::LANG_C11); - subrange_type(const environment* env, + subrange_type(const environment& env, const string& name, bound_value lower_bound, bound_value upper_bound, const location& loc, translation_unit::language l = translation_unit::LANG_C11); - subrange_type(const environment* env, + subrange_type(const environment& env, const string& name, bound_value upper_bound, const location& loc, @@ -2603,7 +2574,7 @@ public: const std::vector& subs, const location& locus); - array_type_def(environment* env, + array_type_def(const environment& env, const std::vector& subs, const location& locus); @@ -2761,7 +2732,7 @@ public: ~enumerator(); - enumerator(const environment* env, const string& name, int64_t value); + enumerator(const string& name, int64_t value); enumerator(const enumerator&); @@ -2774,13 +2745,10 @@ public: bool operator!=(const enumerator& other) const; - const environment* - get_environment() const; - - const interned_string& + const string& get_name() const; - const interned_string& + const string& get_qualified_name(bool internal = false) const; void @@ -2823,7 +2791,7 @@ public: visibility vis = VISIBILITY_DEFAULT); typedef_decl(const string& name, - environment* env, + const environment& env, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); @@ -3320,7 +3288,7 @@ public: size_t size_in_bits, size_t alignment_in_bits); - function_type(const environment* env, + function_type(const environment& env, size_t size_in_bits, size_t alignment_in_bits); @@ -3415,7 +3383,7 @@ public: size_t size_in_bits, size_t alignment_in_bits); - method_type(const environment* env, + method_type(const environment& env, size_t size_in_bits, size_t alignment_in_bits); @@ -3452,7 +3420,7 @@ public: /// Hasher. struct hash; - template_decl(const environment* env, + template_decl(const environment& env, const string& name, const location& locus, visibility vis = VISIBILITY_DEFAULT); @@ -3683,7 +3651,7 @@ public: struct hash; struct shared_ptr_hash; - function_tdecl(const environment* env, + function_tdecl(const environment& env, const location& locus, visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_NONE); @@ -3732,7 +3700,7 @@ public: struct hash; struct shared_ptr_hash; - class_tdecl(const environment* env, const location& locus, + class_tdecl(const environment& env, const location& locus, visibility vis = VISIBILITY_DEFAULT); class_tdecl(class_decl_sptr pattern, @@ -3953,17 +3921,17 @@ public: typedef unordered_map string_mem_fn_sptr_map_type; /// @} - class_or_union(const environment* env, const string& name, + class_or_union(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, const location& locus, visibility vis, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns); - class_or_union(const environment* env, const string& name, + class_or_union(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, const location& locus, visibility vis); - class_or_union(const environment* env, const string& name, + class_or_union(const environment& env, const string& name, bool is_declaration_only = true); virtual void @@ -4159,30 +4127,30 @@ private: public: - class_decl(const environment* env, const string& name, + class_decl(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis, base_specs& bases, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns); - class_decl(const environment* env, const string& name, + class_decl(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis, base_specs& bases, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns, bool is_anonymous); - class_decl(const environment* env, const string& name, + class_decl(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis); - class_decl(const environment* env, const string& name, + class_decl(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis, bool is_anonymous); - class_decl(const environment* env, const string& name, bool is_struct, + class_decl(const environment& env, const string& name, bool is_struct, bool is_declaration_only = true); virtual string @@ -4376,26 +4344,26 @@ class union_decl : public class_or_union public: - union_decl(const environment* env, const string& name, + union_decl(const environment& env, const string& name, size_t size_in_bits, const location& locus, visibility vis, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns); - union_decl(const environment* env, const string& name, + union_decl(const environment& env, const string& name, size_t size_in_bits, const location& locus, visibility vis, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns, bool is_anonymous); - union_decl(const environment* env, const string& name, + union_decl(const environment& env, const string& name, size_t size_in_bits, const location& locus, visibility vis); - union_decl(const environment* env, const string& name, + union_decl(const environment& env, const string& name, size_t size_in_bits, const location& locus, visibility vis, bool is_anonymous); - union_decl(const environment* env, const string& name, + union_decl(const environment& env, const string& name, bool is_declaration_only = true); virtual string diff --git a/include/abg-reader.h b/include/abg-reader.h index 624311bc..d89c6458 100644 --- a/include/abg-reader.h +++ b/include/abg-reader.h @@ -17,86 +17,72 @@ #include #include "abg-corpus.h" #include "abg-suppression.h" +#include "abg-fe-iface.h" namespace abigail { -namespace xml_reader +namespace abixml_reader { using namespace abigail::ir; -class read_context; - translation_unit_sptr read_translation_unit_from_file(const std::string& file_path, - environment* env); + environment& env); translation_unit_sptr read_translation_unit_from_buffer(const std::string& file_path, - environment* env); + environment& env); translation_unit_sptr read_translation_unit_from_istream(std::istream* in, - environment* env); + environment& env); translation_unit_sptr -read_translation_unit(read_context&); - -/// A convenience typedef for a shared pointer to read_context. -typedef shared_ptr read_context_sptr; +read_translation_unit(fe_iface&); -read_context_sptr -create_native_xml_read_context(const string& path, environment *env); + abigail::fe_iface_sptr +create_abixml_reader(const string& path, environment& env); -read_context_sptr -create_native_xml_read_context(std::istream* in, environment* env); - -const string& -read_context_get_path(const read_context&); +fe_iface_sptr +create_abixml_reader(std::istream* in, environment& env); corpus_sptr -read_corpus_from_native_xml(std::istream* in, - environment* env); +read_corpus_from_abixml(std::istream* in, + environment& env); corpus_sptr -read_corpus_from_native_xml_file(const string& path, - environment* env); - -corpus_sptr -read_corpus_from_input(read_context& ctxt); +read_corpus_from_abixml_file(const string& path, + environment& env); corpus_group_sptr -read_corpus_group_from_input(read_context& ctxt); +read_corpus_group_from_input(fe_iface& ctxt); corpus_group_sptr -read_corpus_group_from_native_xml(std::istream* in, - environment* env); +read_corpus_group_from_abixml(std::istream* in, + environment& env); corpus_group_sptr -read_corpus_group_from_native_xml_file(const string& path, - environment* env); - -void -add_read_context_suppressions(read_context& ctxt, - const suppr::suppressions_type& supprs); +read_corpus_group_from_abixml_file(const string& path, + environment& env); void -consider_types_not_reachable_from_public_interfaces(read_context& ctxt, +consider_types_not_reachable_from_public_interfaces(fe_iface& ctxt, bool flag); #ifdef WITH_SHOW_TYPE_USE_IN_ABILINT vector* -get_types_from_type_id(read_context&, const string&); +get_types_from_type_id(fe_iface&, const string&); unordered_map>* -get_artifact_used_by_relation_map(read_context&); +get_artifact_used_by_relation_map(fe_iface&); #endif -}//end xml_reader +}//end abixml_reader #ifdef WITH_DEBUG_SELF_COMPARISON bool -load_canonical_type_ids(xml_reader::read_context& ctxt, +load_canonical_type_ids(fe_iface& ctxt, const string& file_path); #endif }//end namespace abigail diff --git a/include/abg-suppression.h b/include/abg-suppression.h index 609fba75..90575f73 100644 --- a/include/abg-suppression.h +++ b/include/abg-suppression.h @@ -16,6 +16,8 @@ namespace abigail { +class fe_iface; + /// @brief an engine to suppress the parts of the result of comparing /// two sets of ABI artifacts. /// @@ -116,6 +118,12 @@ public: const suppression_base& suppr); }; // end class suppression_base +/// Convenience typedef for a shared pointer to a @ref suppression. +typedef shared_ptr suppression_sptr; + +/// Convenience typedef for a vector of @ref suppression_sptr +typedef vector suppressions_type; + void read_suppressions(std::istream& input, suppressions_type& suppressions); @@ -821,8 +829,67 @@ is_private_type_suppr_spec(const type_suppression&); bool is_private_type_suppr_spec(const suppression_sptr& s); + +bool +suppression_can_match(const fe_iface&, + const suppression_base&); + +bool +suppression_matches_function_name(const fe_iface&, + const suppr::function_suppression&, + const string&); + +bool +suppression_matches_function_sym_name(const fe_iface&, + const suppr::function_suppression& s, + const string& fn_linkage_name); + +bool +suppression_matches_variable_name(const fe_iface&, + const suppr::variable_suppression& s, + const string& var_name); + +bool +suppression_matches_variable_sym_name(const fe_iface&, + const suppr::variable_suppression&, + const string&); + +bool +suppression_matches_type_name_or_location(const fe_iface&, + const suppr::type_suppression&, + const string&, + const location&); + +bool +is_elf_symbol_suppressed(const fe_iface&, + const elf_symbol_sptr& symbol); + +bool +is_elf_symbol_suppressed(const fe_iface&, + const string& sym_name, + elf_symbol::type sym_type); + +bool +is_function_suppressed(const fe_iface& fe, + const string& fn_name, + const string& fn_linkage_name, + bool require_drop_property = false); + +bool +is_variable_suppressed(const fe_iface& fe, + const string& var_name, + const string& var_linkage_name, + bool require_drop_property = false); + +bool +is_type_suppressed(const fe_iface& fe, + const string& type_name, + const location& type_location, + bool& type_is_private, + bool require_drop_property = false); } // end namespace suppr + } // end namespace abigail #endif //__ABG_SUPPRESSION_H__ diff --git a/include/abg-tools-utils.h b/include/abg-tools-utils.h index 27bbfefe..9dc9b8d3 100644 --- a/include/abg-tools-utils.h +++ b/include/abg-tools-utils.h @@ -15,6 +15,7 @@ #include #include #include "abg-suppression.h" +#include "abg-elf-based-reader.h" namespace abigail { @@ -36,6 +37,10 @@ const char* get_anonymous_enum_internal_name_prefix(); bool file_exists(const string&); bool is_regular_file(const string&); +bool file_has_dwarf_debug_info(const string& elf_file_path, + const vector& debug_info_root_paths); +bool file_has_ctf_debug_info(const string& elf_file_path, + const vector& debug_info_root_paths); bool is_dir(const string&); bool dir_exists(const string&); bool dir_is_empty(const string &); @@ -311,8 +316,14 @@ build_corpus_group_from_kernel_dist_under(const string& root, vector& kabi_wl_paths, suppr::suppressions_type& supprs, bool verbose, - environment_sptr& env, + environment& env, corpus::origin origin = corpus::DWARF_ORIGIN); + +elf_based_reader_sptr +create_best_elf_based_reader(const string& elf_file_path, + const vector& debug_info_root_paths, + environment& env); + }// end namespace tools_utils /// A macro that expands to aborting the program when executed. diff --git a/include/abg-writer.h b/include/abg-writer.h index ab01b486..58f60b74 100644 --- a/include/abg-writer.h +++ b/include/abg-writer.h @@ -36,7 +36,7 @@ class write_context; typedef shared_ptr write_context_sptr; write_context_sptr -create_write_context(const environment *env, +create_write_context(const environment& env, ostream& output_stream); void diff --git a/src/Makefile.am b/src/Makefile.am index 1748f0b8..70cc04a5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,8 +26,10 @@ abg-suppression-priv.h \ abg-suppression.cc \ abg-comp-filter.cc \ abg-reader.cc \ -abg-elf-reader-common.cc \ abg-dwarf-reader.cc \ +abg-fe-iface.cc \ +abg-elf-based-reader.cc \ +abg-elf-reader.cc \ abg-libxml-utils.cc \ abg-hash.cc \ abg-writer.cc \ diff --git a/src/abg-comparison.cc b/src/abg-comparison.cc index 6e3b2b55..0868d384 100644 --- a/src/abg-comparison.cc +++ b/src/abg-comparison.cc @@ -3133,8 +3133,6 @@ compute_diff(const decl_base_sptr first, if (!first || !second) return diff_sptr(); - ABG_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); @@ -3165,9 +3163,6 @@ compute_diff(const type_base_sptr first, decl_base_sptr f = get_type_declaration(first), s = get_type_declaration(second); - if (first && second) - ABG_ASSERT(first->get_environment() == second->get_environment()); - diff_sptr d = compute_diff_for_types(f,s, ctxt); ABG_ASSERT(d); return d; @@ -3317,9 +3312,6 @@ compute_diff(const var_decl_sptr first, const var_decl_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_ASSERT(first->get_environment() == second->get_environment()); - var_diff_sptr d(new var_diff(first, second, diff_sptr(), ctxt)); ctxt->initialize_canonical_diff(d); @@ -3451,9 +3443,6 @@ compute_diff(pointer_type_def_sptr first, pointer_type_def_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_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); @@ -3607,9 +3596,6 @@ compute_diff(array_type_def_sptr first, array_type_def_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_ASSERT(first->get_environment() == second->get_environment()); - diff_sptr d = compute_diff_for_types(first->get_element_type(), second->get_element_type(), ctxt); @@ -3742,9 +3728,6 @@ compute_diff(reference_type_def_sptr first, reference_type_def_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_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); @@ -3892,9 +3875,6 @@ compute_diff(const qualified_type_def_sptr first, const qualified_type_def_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_ASSERT(first->get_environment() == second->get_environment()); - diff_sptr d = compute_diff_for_types(first->get_underlying_type(), second->get_underlying_type(), ctxt); @@ -4110,9 +4090,6 @@ compute_diff(const enum_type_decl_sptr first, const enum_type_decl_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_ASSERT(first->get_environment() == second->get_environment()); - diff_sptr ud = compute_diff_for_types(first->get_underlying_type(), second->get_underlying_type(), ctxt); @@ -5596,9 +5573,6 @@ compute_diff(const class_decl_sptr first, const class_decl_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_ASSERT(first->get_environment() == second->get_environment()); - class_decl_sptr f = is_class_type(look_through_decl_only_class(first)), s = is_class_type(look_through_decl_only_class(second)); @@ -5821,15 +5795,6 @@ compute_diff(const class_decl::base_spec_sptr first, const class_decl::base_spec_sptr second, diff_context_sptr ctxt) { - if (first && second) - { - ABG_ASSERT(first->get_environment() == second->get_environment()); - ABG_ASSERT(first->get_base_class()->get_environment() - == second->get_base_class()->get_environment()); - ABG_ASSERT(first->get_environment() - == first->get_base_class()->get_environment()); - } - class_diff_sptr cl = compute_diff(first->get_base_class(), second->get_base_class(), ctxt); @@ -5945,9 +5910,6 @@ compute_diff(const union_decl_sptr first, const union_decl_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_ASSERT(first->get_environment() == second->get_environment()); - union_diff_sptr changes(new union_diff(first, second, ctxt)); ctxt->initialize_canonical_diff(changes); @@ -6449,9 +6411,6 @@ compute_diff(const scope_decl_sptr first, { ABG_ASSERT(d->first_scope() == first && d->second_scope() == second); - if (first && second) - ABG_ASSERT(first->get_environment() == second->get_environment()); - compute_diff(first->get_member_decls().begin(), first->get_member_decls().end(), second->get_member_decls().begin(), @@ -6482,10 +6441,6 @@ compute_diff(const scope_decl_sptr first_scope, const scope_decl_sptr second_scope, diff_context_sptr ctxt) { - if (first_scope && second_scope) - ABG_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); @@ -6632,8 +6587,6 @@ compute_diff(const function_decl::parameter_sptr first, if (!first || !second) return fn_parm_diff_sptr(); - ABG_ASSERT(first->get_environment() == second->get_environment()); - fn_parm_diff_sptr result(new fn_parm_diff(first, second, ctxt)); ctxt->initialize_canonical_diff(result); @@ -6930,8 +6883,6 @@ compute_diff(const function_type_sptr first, return function_type_diff_sptr(); } - ABG_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_parm(), @@ -7072,8 +7023,6 @@ compute_diff(const function_decl_sptr first, return function_decl_diff_sptr(); } - ABG_ASSERT(first->get_environment() == second->get_environment()); - function_type_diff_sptr type_diff = compute_diff(first->get_type(), second->get_type(), ctxt); @@ -7196,9 +7145,6 @@ compute_diff(const type_decl_sptr first, const type_decl_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_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 @@ -7349,9 +7295,6 @@ compute_diff(const typedef_decl_sptr first, const typedef_decl_sptr second, diff_context_sptr ctxt) { - if (first && second) - ABG_ASSERT(first->get_environment() == second->get_environment()); - diff_sptr d = compute_diff_for_types(first->get_underlying_type(), second->get_underlying_type(), ctxt); @@ -7470,8 +7413,6 @@ compute_diff(const translation_unit_sptr first, { ABG_ASSERT(first && second); - ABG_ASSERT(first->get_environment() == second->get_environment()); - if (!ctxt) ctxt.reset(new diff_context); @@ -10929,10 +10870,6 @@ compute_diff(const corpus_sptr f, ABG_ASSERT(f && s); - // We can only compare two corpora that were built out of the same - // environment. - ABG_ASSERT(f->get_environment() == s->get_environment()); - if (!ctxt) ctxt.reset(new diff_context); @@ -12272,11 +12209,11 @@ is_diff_of_variadic_parameter_type(const diff* d) return false; type_base_sptr t = is_type(d->first_subject()); - if (t && t->get_environment()->is_variadic_parameter_type(t)) + if (t && t->get_environment().is_variadic_parameter_type(t)) return true; t = is_type(d->second_subject()); - if (t && t->get_environment()->is_variadic_parameter_type(t)) + if (t && t->get_environment().is_variadic_parameter_type(t)) return true; return false; diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h index 8719be56..0b40d800 100644 --- a/src/abg-corpus-priv.h +++ b/src/abg-corpus-priv.h @@ -403,12 +403,12 @@ public: /// /// @param fn the function to add to the set of exported functions. void - add_fn_to_exported(function_decl* fn) + add_fn_to_exported(const function_decl* fn) { if (!fn_is_in_id_fns_map(fn)) { - fns_.push_back(fn); - add_fn_to_id_fns_map(fn); + fns_.push_back(const_cast(fn)); + add_fn_to_id_fns_map(const_cast(fn)); } } @@ -416,13 +416,13 @@ public: /// /// @param fn the variable to add to the set of exported variables. void - add_var_to_exported(var_decl* var) + add_var_to_exported(const var_decl* var) { const string& id = get_id(*var); if (!var_id_is_in_id_var_map(id)) { - vars_.push_back(var); - add_var_to_map(var); + vars_.push_back(const_cast(var)); + add_var_to_map(const_cast(var)); } } @@ -667,7 +667,7 @@ struct corpus::priv mutable unordered_map canonical_types_; string format_major_version_number_; string format_minor_version_number_; - environment* env; + const environment& env; corpus_group* group; corpus::exported_decls_builder_sptr exported_decls_builder; corpus::origin origin_; @@ -717,8 +717,8 @@ private: mutable abg_compat::optional unrefed_fun_symbols; public: - priv(const string & p, - environment* e) + priv(const string & p, + const environment& e) : env(e), group(), origin_(ARTIFICIAL_ORIGIN), diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc index 0b23667f..8c1e6158 100644 --- a/src/abg-corpus.cc +++ b/src/abg-corpus.cc @@ -133,7 +133,7 @@ corpus::exported_decls_builder::exported_variables() /// /// @param fn the function to add the set of exported functions. void -corpus::exported_decls_builder::maybe_add_fn_to_exported_fns(function_decl* fn) +corpus::exported_decls_builder::maybe_add_fn_to_exported_fns(const function_decl* fn) { if (!fn->get_is_in_public_symbol_table()) return; @@ -156,7 +156,7 @@ corpus::exported_decls_builder::maybe_add_fn_to_exported_fns(function_decl* fn) /// /// @param fn the variable to add the set of exported variables. void -corpus::exported_decls_builder::maybe_add_var_to_exported_vars(var_decl* var) +corpus::exported_decls_builder::maybe_add_var_to_exported_vars(const var_decl* var) { if (!var->get_is_in_public_symbol_table()) return; @@ -596,7 +596,7 @@ corpus::priv::~priv() /// @param env the environment of the corpus. /// /// @param path the path to the file containing the ABI corpus. -corpus::corpus(ir::environment* env, const string& path) +corpus::corpus(const ir::environment& env, const string& path) { priv_.reset(new priv(path, env)); init_format_version(); @@ -607,31 +607,11 @@ corpus::~corpus() = default; /// Getter of the enviroment of the corpus. /// /// @return the environment of this corpus. -const environment* +const environment& corpus::get_environment() const {return priv_->env;} -/// 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) -{ - priv_->env = e; - init_format_version(); -} - -/// 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. +/// Add a translation unit to the current ABI Corpus. /// /// Note that two translation units with the same path (as returned by /// translation_unit::get_path) cannot be added to the same @ref @@ -639,13 +619,8 @@ corpus::set_environment(environment* e) /// /// @param tu the new translation unit to add. void -corpus::add(const translation_unit_sptr tu) +corpus::add(const translation_unit_sptr& tu) { - if (!tu->get_environment()) - tu->set_environment(get_environment()); - - ABG_ASSERT(tu->get_environment() == get_environment()); - ABG_ASSERT(priv_->members.insert(tu).second); if (!tu->get_absolute_path().empty()) @@ -741,7 +716,7 @@ void corpus::record_type_as_reachable_from_public_interfaces(const type_base& t) { string repr = get_pretty_representation(&t, /*internal=*/true); - interned_string s = t.get_environment()->intern(repr); + interned_string s = t.get_environment().intern(repr); priv_->get_public_types_pretty_representations()->insert(s); } @@ -759,7 +734,7 @@ bool corpus::type_is_reachable_from_public_interfaces(const type_base& t) const { string repr = get_pretty_representation(&t, /*internal=*/true); - interned_string s = t.get_environment()->intern(repr); + interned_string s = t.get_environment().intern(repr); return (priv_->get_public_types_pretty_representations()->find(s) != priv_->get_public_types_pretty_representations()->end()); @@ -839,13 +814,10 @@ corpus::set_group(corpus_group* g) void corpus::init_format_version() { - if (priv_->env) - { - set_format_major_version_number - (priv_->env->get_config().get_format_major_version_number()); - set_format_minor_version_number - (priv_->env->get_config().get_format_minor_version_number()); - } + set_format_major_version_number + (priv_->env.get_config().get_format_major_version_number()); + set_format_minor_version_number + (priv_->env.get_config().get_format_minor_version_number()); } /// Getter for the origin of the corpus. @@ -1013,7 +985,9 @@ corpus::is_empty() const return (members_empty && (!get_symtab() || !get_symtab()->has_symbols()) && priv_->soname.empty() - && priv_->needed.empty()); + && priv_->needed.empty() + && priv_->architecture_name.empty() + && !priv_->group); } /// Compare the current @ref corpus against another one. @@ -1690,8 +1664,12 @@ struct corpus_group::priv } }; // end corpus_group::priv -/// Default constructor of the @ref corpus_group type. -corpus_group::corpus_group(environment* env, const string& path = "") +/// Constructor of the @ref corpus_group type. +/// +/// @param env the environment of the @ref corpus_group. +/// +/// @param path the path to the file represented by the corpus group. +corpus_group::corpus_group(const environment& env, const string& path = "") : corpus(env, path), priv_(new priv) {} @@ -1708,15 +1686,6 @@ corpus_group::add_corpus(const corpus_sptr& corp) if (!corp) return; - // Ensure the new environment patches the current one. - if (const environment* cur_env = get_environment()) - { - if (environment* corp_env = corp->get_environment()) - ABG_ASSERT(cur_env == corp_env); - } - else - set_environment(corp->get_environment()); - // Ensure the new architecture name matches the current one. string cur_arch = get_architecture_name(), corp_arch = corp->get_architecture_name(); diff --git a/src/abg-ctf-reader.cc b/src/abg-ctf-reader.cc index e307fcd7..cabb919e 100644 --- a/src/abg-ctf-reader.cc +++ b/src/abg-ctf-reader.cc @@ -23,17 +23,18 @@ #include "abg-internal.h" #include "abg-ir-priv.h" -#include "abg-elf-helpers.h" +#include "abg-symtab-reader.h" + +#include "abg-internal.h" // ABG_BEGIN_EXPORT_DECLARATIONS #include "abg-ctf-reader.h" -#include "abg-libxml-utils.h" -#include "abg-reader.h" +#include "abg-elf-based-reader.h" #include "abg-corpus.h" -#include "abg-symtab-reader.h" #include "abg-tools-utils.h" +#include "abg-elf-helpers.h" ABG_END_EXPORT_DECLARATIONS // @@ -46,16 +47,104 @@ using std::dynamic_pointer_cast; using abigail::tools_utils::dir_name; using abigail::tools_utils::file_exists; -class read_context -{ -public: - /// The name of the ELF file from which the CTF archive got - /// extracted. - string filename; +class reader; + +static typedef_decl_sptr +process_ctf_typedef(reader *rdr, + corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); + +static type_decl_sptr +process_ctf_base_type(reader *rdr, + corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); + +static decl_base_sptr +build_ir_node_for_variadic_parameter_type(reader &rdr, + translation_unit_sptr tunit); + +static function_type_sptr +process_ctf_function_type(reader *rdr, + corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); + +static void +process_ctf_sou_members(reader *rdr, + corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type, + class_or_union_sptr sou); + +static type_base_sptr +process_ctf_forward_type(reader *rdr, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); + +static class_decl_sptr +process_ctf_struct_type(reader *rdr, + corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); + +static union_decl_sptr +process_ctf_union_type(reader *rdr, + corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); + +static array_type_def_sptr +process_ctf_array_type(reader *rdr, + corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); + +static type_base_sptr +process_ctf_qualified_type(reader *rdr, + corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); + +static pointer_type_def_sptr +process_ctf_pointer_type(reader *rdr, + corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); + +static enum_type_decl_sptr +process_ctf_enum_type(reader *rdr, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type); - /// The IR environment. - ir::environment *ir_env; +static void +fill_ctf_section(const Elf_Scn *elf_section, ctf_sect_t *ctf_section); +static ctf_id_t +lookup_symbol_in_ctf_archive(ctf_archive_t *ctfa, ctf_dict_t **ctf_dict, + const char *sym_name); + +static std::string +dic_type_key(ctf_dict_t *dic, ctf_id_t ctf_type); + +/// The abstraction of a CTF reader. +/// +/// It groks the type information contains the CTF-specific part of +/// the ELF file and builds an ABI corpus out of it. +class reader : public elf_based_reader +{ /// The CTF archive read from FILENAME. If an archive couldn't /// be read from the file then this is NULL. ctf_archive_t *ctfa; @@ -67,140 +156,20 @@ public: /// A set associating unknown CTF type ids std::set unknown_types_set; - /// libelf handler for the ELF file from which we read the CTF data, - /// and the corresponding file descriptor. - Elf *elf_handler; - int elf_fd; - - /// libelf handler for the ELF file from which we read the CTF data, - /// and the corresponding file descriptor found in external .debug file - Elf *elf_handler_dbg; - int elf_fd_dbg; - - /// The symtab read from the ELF file. - symtab_reader::symtab_sptr symtab; - /// Raw contents of several sections from the ELF file. These are /// used by libctf. ctf_sect_t ctf_sect; ctf_sect_t symtab_sect; ctf_sect_t strtab_sect; - corpus_sptr cur_corpus_; - corpus_group_sptr cur_corpus_group_; - corpus::exported_decls_builder* exported_decls_builder_; - // The set of directories under which to look for debug info. - vector debug_info_root_paths_; - - /// Setter of the exported decls builder object. - /// - /// Note that this @ref read_context is not responsible for the live - /// time of the exported_decls_builder object. The corpus is. - /// - /// @param b the new builder. - void - exported_decls_builder(corpus::exported_decls_builder* b) - {exported_decls_builder_ = b;} +public: /// Getter of the exported decls builder object. /// /// @return the exported decls builder. corpus::exported_decls_builder* exported_decls_builder() - {return exported_decls_builder_;} - - /// If a given function decl is suitable for the set of exported - /// functions of the current corpus, this function adds it to that - /// set. - /// - /// @param fn the function to consider for inclusion into the set of - /// exported functions of the current corpus. - void - maybe_add_fn_to_exported_decls(function_decl* fn) - { - if (fn) - if (corpus::exported_decls_builder* b = exported_decls_builder()) - b->maybe_add_fn_to_exported_fns(fn); - } - - /// If a given variable decl is suitable for the set of exported - /// variables of the current corpus, this variable adds it to that - /// set. - /// - /// @param fn the variable to consider for inclusion into the set of - /// exported variables of the current corpus. - void - maybe_add_var_to_exported_decls(var_decl* var) - { - if (var) - if (corpus::exported_decls_builder* b = exported_decls_builder()) - b->maybe_add_var_to_exported_vars(var); - } - - /// Getter of the current corpus group being constructed. - /// - /// @return current the current corpus being constructed, if any, or - /// nil. - const corpus_group_sptr - current_corpus_group() const - {return cur_corpus_group_;} - - /// Test if there is a corpus group being built. - /// - /// @return if there is a corpus group being built, false otherwise. - bool - has_corpus_group() const - {return bool(cur_corpus_group_);} - - /// Return the main corpus from the current corpus group, if any. - /// - /// @return the main corpus of the current corpus group, if any, nil - /// if no corpus group is being constructed. - corpus_sptr - main_corpus_from_current_group() - { - if (cur_corpus_group_) - return cur_corpus_group_->get_main_corpus(); - return corpus_sptr(); - } - - /// Test if the current corpus being built is the main corpus of the - /// current corpus group. - /// - /// @return return true iff the current corpus being built is the - /// main corpus of the current corpus group. - bool - current_corpus_is_main_corpus_from_current_group() - { - corpus_sptr main_corpus = main_corpus_from_current_group(); - - if (main_corpus && main_corpus.get() == cur_corpus_.get()) - return true; - - return false; - } - - /// Return true if the current corpus is part of a corpus group - /// being built and if it's not the main corpus of the group. - /// - /// For instance, this would return true if we are loading a linux - /// kernel *module* that is part of the current corpus group that is - /// being built. In this case, it means we should re-use types - /// coming from the "vmlinux" binary that is the main corpus of the - /// group. - /// - /// @return the corpus group the current corpus belongs to, if the - /// current corpus is part of a corpus group being built. Nil otherwise. - corpus_sptr - should_reuse_type_from_corpus_group() - { - if (has_corpus_group()) - if (corpus_sptr main_corpus = main_corpus_from_current_group()) - if (!current_corpus_is_main_corpus_from_current_group()) - return current_corpus_group(); - - return corpus_sptr(); - } + {return corpus()->get_exported_decls_builder().get();} /// Associate a given CTF type ID with a given libabigail IR type. /// @@ -269,67 +238,490 @@ public: /// 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. - read_context(const string& elf_path, - const vector& debug_info_root_paths, - ir::environment *env) : - ctfa(NULL) + reader(const string& elf_path, + const vector& debug_info_root_paths, + environment& env) + : elf_based_reader(elf_path, debug_info_root_paths, env) { - initialize(elf_path, debug_info_root_paths, env); + initialize(); } - /// Initializer of read_context. + /// Initializer of the reader. /// - /// @param elf_path the path to the elf file the context is to be - /// used for. + /// This is useful to clear out the data used by the reader and get + /// it ready to be used again. /// - /// @param debug_info_root_paths vector with the paths - /// to directories where .debug file is located. + /// Note that the reader eeps the same environment it has been + /// originally created with. /// - /// @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 + /// reader the context uses resources that are allocated in + /// the environment. + void + initialize() + { + ctfa = nullptr; + types_map.clear(); + corpus_group().reset(); + } + + /// Initializer of the reader. + /// + /// + /// @param elf_path the new path to the new ELF file to use. + /// + /// @param debug_info_root_paths a vector of paths to use to look + /// for debug info that is split out into a separate file. + /// + /// This is useful to clear out the data used by the reader and get + /// it ready to be used again. + /// + /// Note that the reader eeps the same environment it has been + /// originally created with. /// /// 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 + /// reader the context uses resources that are allocated in /// the environment. void initialize(const string& elf_path, - const vector& debug_info_root_paths, - ir::environment *env) + const vector& debug_info_root_paths) { - types_map.clear(); - filename = elf_path; - ir_env = env; - elf_handler = NULL; - elf_handler_dbg = NULL; - elf_fd = -1; - elf_fd_dbg = -1; - symtab.reset(); - cur_corpus_group_.reset(); - exported_decls_builder_ = 0; - debug_info_root_paths_ = debug_info_root_paths; + reset(elf_path, debug_info_root_paths); + } + + /// Getter of the environment of the current CTF reader. + /// + /// @return the environment of the current CTF reader. + const environment& + env() const + {return options().env;} + + /// Getter of the environment of the current CTF reader. + /// + /// @return the environment of the current CTF reader. + environment& + env() + {return options().env;} + + /// Look for vmlinux.ctfa file in default directory or in + /// directories provided by debug-info-dir command line option, + /// it stores location path in @ref ctfa_file. + /// + /// @param ctfa_file file name found. + /// @return true if file is found. + bool + find_ctfa_file(std::string& ctfa_file) + { + std::string ctfa_dirname; + dir_name(corpus_path(), ctfa_dirname, false); + + // In corpus group we assume vmlinux as first file to + // be processed, so default location for vmlinux.cfa + // is vmlinux dirname. + ctfa_file = ctfa_dirname + "/vmlinux.ctfa"; + if (file_exists(ctfa_file)) + return true; + + // If it's proccessing a module, then location directory + // for vmlinux.ctfa should be provided with --debug-info-dir + // option. + for (const auto& path : debug_info_root_paths()) + { + ctfa_dirname = *path; + ctfa_file = ctfa_dirname + "/vmlinux.ctfa"; + if (file_exists(ctfa_file)) + return true; + } + + return false; + } + + /// Slurp certain information from the underlying ELF file, and + /// install it the current libabigail corpus associated to the + /// current CTF reader. + /// + /// @param status the resulting status flags. + void + slurp_elf_info(fe_iface::status& status) + { + // Read the ELF-specific parts of the corpus. + elf_reader::reader::read_corpus(status); + + if ((status & STATUS_NO_SYMBOLS_FOUND) + || !(status & STATUS_OK)) + // Either we couldn't find ELF symbols or something went badly + // wrong. There is nothing we can do with this ELF file. Bail + // out. + return; + + corpus_sptr corp = corpus(); + if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN) + && corpus_group()) + { + status |= fe_iface::STATUS_OK; + return; + } + + /* Get the raw ELF section contents for libctf. */ + if (!find_ctf_section()) + { + status |= fe_iface::STATUS_DEBUG_INFO_NOT_FOUND; + return; + } + + GElf_Ehdr *ehdr, eh_mem; + if (!(ehdr = gelf_getehdr(elf_handle(), &eh_mem))) + return; + + // ET_{EXEC,DYN} needs .dyn{sym,str} in ctf_arc_bufopen + const char *symtab_name = ".dynsym"; + const char *strtab_name = ".dynstr"; + + if (ehdr->e_type == ET_REL) + { + symtab_name = ".symtab"; + strtab_name = ".strtab"; + } + + const Elf_Scn* ctf_scn = find_ctf_section(); + fill_ctf_section(ctf_scn, &ctf_sect); + + const Elf_Scn* symtab_scn = + elf_helpers::find_section_by_name(elf_handle(), symtab_name); + fill_ctf_section(symtab_scn, &symtab_sect); + + const Elf_Scn* strtab_scn = + elf_helpers::find_section_by_name(elf_handle(), strtab_name); + fill_ctf_section(strtab_scn, &strtab_sect); + + status |= fe_iface::STATUS_OK; + } + + /// Process a CTF archive and create libabigail IR for the types, + /// variables and function declarations found in the archive, iterating + /// over public symbols. The IR is added to the given corpus. + /// + /// @param corp the IR corpus to which add the new contents. + void + process_ctf_archive(corpus_sptr corp) + { + /* We only have a translation unit. */ + translation_unit_sptr ir_translation_unit = + std::make_shared(env(), "", 64); + ir_translation_unit->set_language(translation_unit::LANG_C); + corp->add(ir_translation_unit); + + int ctf_err; + ctf_dict_t *ctf_dict, *dict_tmp; + const auto symt = symtab(); + symtab_reader::symtab_filter filter = symt->make_filter(); + filter.set_public_symbols(); + std::string dict_name; + + if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN) + && corpus_group()) + { + tools_utils::base_name(corpus_path(), dict_name); + + if (dict_name != "vmlinux") + // remove .ko suffix + dict_name.erase(dict_name.length() - 3, 3); + + std::replace(dict_name.begin(), dict_name.end(), '-', '_'); + } + + if ((ctf_dict = ctf_dict_open(ctfa, + dict_name.empty() ? NULL : dict_name.c_str(), + &ctf_err)) == NULL) + { + fprintf(stderr, "ERROR dictionary not found\n"); + abort(); + } + + dict_tmp = ctf_dict; + + for (const auto& symbol : symtab_reader::filtered_symtab(*symt, filter)) + { + std::string sym_name = symbol->get_name(); + ctf_id_t ctf_sym_type; + + ctf_sym_type = lookup_symbol_in_ctf_archive(ctfa, &ctf_dict, + sym_name.c_str()); + if (ctf_sym_type == CTF_ERR) + continue; + + if (ctf_type_kind(ctf_dict, ctf_sym_type) != CTF_K_FUNCTION) + { + const char *var_name = sym_name.c_str(); + type_base_sptr var_type = lookup_type(corp, ir_translation_unit, + ctf_dict, ctf_sym_type); + if (!var_type) + /* Ignore variable if its type can't be sorted out. */ + continue; + + var_decl_sptr var_declaration; + var_declaration.reset(new var_decl(var_name, + var_type, + location(), + var_name)); + + var_declaration->set_symbol(symbol); + add_decl_to_scope(var_declaration, + ir_translation_unit->get_global_scope()); + var_declaration->set_is_in_public_symbol_table(true); + maybe_add_var_to_exported_decls(var_declaration.get()); + } + else + { + const char *func_name = sym_name.c_str(); + ctf_id_t ctf_sym = ctf_sym_type; + type_base_sptr func_type = lookup_type(corp, ir_translation_unit, + ctf_dict, ctf_sym); + if (!func_type) + /* Ignore function if its type can't be sorted out. */ + continue; + + function_decl_sptr func_declaration; + func_declaration.reset(new function_decl(func_name, + func_type, + 0 /* is_inline */, + location())); + func_declaration->set_symbol(symbol); + add_decl_to_scope(func_declaration, + ir_translation_unit->get_global_scope()); + func_declaration->set_is_in_public_symbol_table(true); + maybe_add_fn_to_exported_decls(func_declaration.get()); + } + + ctf_dict = dict_tmp; + } + + ctf_dict_close(ctf_dict); + /* Canonicalize all the types generated above. This must be + done "a posteriori" because the processing of types may + require other related types to not be already + canonicalized. */ + canonicalize_all_types(); + } + + /// Add a new type declaration to the given libabigail IR corpus CORP. + /// + /// @param corp the libabigail IR corpus being constructed. + /// @param tunit the current IR translation unit. + /// @param ctf_dictionary the CTF dictionary being read. + /// @param ctf_type the CTF type ID of the source type. + /// + /// Note that if @ref ctf_type can't reliably be translated to the IR + /// then it is simply ignored. + /// + /// @return a shared pointer to the IR node for the type. + type_base_sptr + process_ctf_type(corpus_sptr corp, + translation_unit_sptr tunit, + ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type) + { + int type_kind = ctf_type_kind(ctf_dictionary, ctf_type); + type_base_sptr result; + + if (lookup_unknown_type(ctf_type)) + return nullptr; + + if ((result = lookup_type(ctf_dictionary, ctf_type))) + return result; + + switch (type_kind) + { + case CTF_K_INTEGER: + case CTF_K_FLOAT: + { + type_decl_sptr type_decl + = process_ctf_base_type(this, corp, tunit, ctf_dictionary, ctf_type); + result = is_type(type_decl); + break; + } + case CTF_K_TYPEDEF: + { + typedef_decl_sptr typedef_decl + = process_ctf_typedef(this, corp, tunit, ctf_dictionary, ctf_type); + result = is_type(typedef_decl); + break; + } + case CTF_K_POINTER: + { + pointer_type_def_sptr pointer_type + = process_ctf_pointer_type(this, corp, tunit, ctf_dictionary, ctf_type); + result = pointer_type; + break; + } + case CTF_K_CONST: + case CTF_K_VOLATILE: + case CTF_K_RESTRICT: + { + type_base_sptr qualified_type + = process_ctf_qualified_type(this, corp, tunit, ctf_dictionary, ctf_type); + result = qualified_type; + break; + } + case CTF_K_ARRAY: + { + array_type_def_sptr array_type + = process_ctf_array_type(this, corp, tunit, ctf_dictionary, ctf_type); + result = array_type; + break; + } + case CTF_K_ENUM: + { + enum_type_decl_sptr enum_type + = process_ctf_enum_type(this, tunit, ctf_dictionary, ctf_type); + result = enum_type; + break; + } + case CTF_K_FUNCTION: + { + function_type_sptr function_type + = process_ctf_function_type(this, corp, tunit, ctf_dictionary, ctf_type); + result = function_type; + break; + } + case CTF_K_STRUCT: + { + class_decl_sptr struct_decl + = process_ctf_struct_type(this, corp, tunit, ctf_dictionary, ctf_type); + result = is_type(struct_decl); + break; + } + case CTF_K_FORWARD: + { + result = process_ctf_forward_type(this, tunit, + ctf_dictionary, + ctf_type); + } + break; + case CTF_K_UNION: + { + union_decl_sptr union_decl + = process_ctf_union_type(this, corp, tunit, ctf_dictionary, ctf_type); + result = is_type(union_decl); + break; + } + case CTF_K_UNKNOWN: + /* Unknown types are simply ignored. */ + default: + break; + } + + if (!result) + { + fprintf(stderr, "NOT PROCESSED TYPE %lu\n", ctf_type); + add_unknown_type(ctf_type); + } + + return result; + } + + /// Given a CTF type id, lookup the corresponding libabigail IR type. + /// If the IR type hasn't been generated yet, generate it. + /// + /// @param corp the libabigail IR corpus being constructed. + /// @param tunit the current IR translation unit. + /// @param ctf_dictionary the CTF dictionary being read. + /// @param ctf_type the CTF type ID of the looked type. + /// + /// Note that if @ref ctf_type can't reliably be translated to the IR + /// then a NULL shared pointer is returned. + /// + /// @return a shared pointer to the IR node for the type. + type_base_sptr + lookup_type(corpus_sptr corp, + translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, + ctf_id_t ctf_type) + { + type_base_sptr result = lookup_type(ctf_dictionary, ctf_type); + + if (!result) + result = process_ctf_type(corp, tunit, ctf_dictionary, ctf_type); + return result; + } + + /// Read the CTF information in the binary and construct an ABI + /// corpus from it. + /// + /// @param status output parameter. Contains the status of the ABI + /// corpus construction. + /// + /// @return the corpus created as a result of processing the debug + /// information. + corpus_sptr + read_corpus(fe_iface::status &status) + { + corpus_sptr corp = corpus(); + status = fe_iface::STATUS_UNKNOWN; + + bool is_linux_kernel = elf_helpers::is_linux_kernel(elf_handle()); + corpus::origin origin = corpus::CTF_ORIGIN; + + if (is_linux_kernel) + origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN; + corp->set_origin(origin); + + if (corpus_group()) + corpus_group()->add_corpus(corpus()); + + slurp_elf_info(status); + if (!is_linux_kernel + && ((status & fe_iface::STATUS_DEBUG_INFO_NOT_FOUND) | + (status & fe_iface::STATUS_NO_SYMBOLS_FOUND))) + return corp; + + int errp; + if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN) + && corpus_group()) + { + if (ctfa == NULL) + { + std::string ctfa_filename; + if (find_ctfa_file(ctfa_filename)) + ctfa = ctf_arc_open(ctfa_filename.c_str(), &errp); + } + } + else + /* Build the ctfa from the contents of the relevant ELF sections, + and process the CTF archive in the read context, if any. + Information about the types, variables, functions, etc contained + in the archive are added to the given corpus. */ + ctfa = ctf_arc_bufopen(&ctf_sect, &symtab_sect, + &strtab_sect, &errp); + + env().canonicalization_is_done(false); + if (ctfa == NULL) + status |= fe_iface::STATUS_DEBUG_INFO_NOT_FOUND; + else + { + process_ctf_archive(corp); + corpus()->sort_functions(); + corpus()->sort_variables(); + } + + env().canonicalization_is_done(true); + + return corp; } - ~read_context() + /// Destructor of the CTF reader. + ~reader() { ctf_close(ctfa); } -}; // end class read_context. +}; // end class reader. -/// Forward reference, needed because several of the process_ctf_* -/// functions below are indirectly recursive through this call. -static type_base_sptr lookup_type(read_context *ctxt, - corpus_sptr corp, - translation_unit_sptr tunit, - ctf_dict_t *ctf_dictionary, - ctf_id_t ctf_type); +typedef shared_ptr reader_sptr; /// Build and return a typedef libabigail IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. @@ -338,7 +730,7 @@ static type_base_sptr lookup_type(read_context *ctxt, /// @return a shared pointer to the IR node for the typedef. static typedef_decl_sptr -process_ctf_typedef(read_context *ctxt, +process_ctf_typedef(reader *rdr, corpus_sptr corp, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, @@ -351,17 +743,17 @@ process_ctf_typedef(read_context *ctxt, return result; const char *typedef_name = ctf_type_name_raw(ctf_dictionary, ctf_type); - if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group()) if (result = lookup_typedef_type(typedef_name, *corp)) return result; - type_base_sptr utype = lookup_type(ctxt, corp, tunit, - ctf_dictionary, ctf_utype); + type_base_sptr utype = rdr->lookup_type(corp, tunit, + ctf_dictionary, ctf_utype); if (!utype) return result; - result = dynamic_pointer_cast(ctxt->lookup_type(ctf_dictionary, + result = dynamic_pointer_cast(rdr->lookup_type(ctf_dictionary, ctf_type)); if (result) return result; @@ -383,7 +775,7 @@ process_ctf_typedef(read_context *ctxt, if (result) { add_decl_to_scope(result, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, result); + rdr->add_type(ctf_dictionary, ctf_type, result); } return result; @@ -392,7 +784,7 @@ process_ctf_typedef(read_context *ctxt, /// Build and return an integer or float type declaration libabigail /// IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param ctf_dictionary the CTF dictionary being read. /// @param ctf_type the CTF type ID of the source type. @@ -400,7 +792,7 @@ process_ctf_typedef(read_context *ctxt, /// @return a shared pointer to the IR node for the type. static type_decl_sptr -process_ctf_base_type(read_context *ctxt, +process_ctf_base_type(reader *rdr, corpus_sptr corp, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, @@ -425,14 +817,14 @@ process_ctf_base_type(read_context *ctxt, && type_encoding.cte_format == CTF_INT_SIGNED) { /* This is the `void' type. */ - type_base_sptr void_type = ctxt->ir_env->get_void_type(); + type_base_sptr void_type = rdr->env().get_void_type(); decl_base_sptr type_declaration = get_type_declaration(void_type); result = is_type_decl(type_declaration); canonicalize(result); } else { - if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group()) { string normalized_type_name = type_name; integral_type int_type; @@ -444,7 +836,7 @@ process_ctf_base_type(read_context *ctxt, result = lookup_basic_type(type_name, *corp); if (!result) - result.reset(new type_decl(ctxt->ir_env, + result.reset(new type_decl(rdr->env(), type_name, type_encoding.cte_bits, type_alignment * 8 /* in bits */, @@ -456,7 +848,7 @@ process_ctf_base_type(read_context *ctxt, if (result) { add_decl_to_scope(result, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, result); + rdr->add_type(ctf_dictionary, ctf_type, result); } return result; @@ -464,17 +856,16 @@ process_ctf_base_type(read_context *ctxt, /// Build the IR node for a variadic parameter type. /// -/// @param ctxt the read context to use. +/// @param rdr the read context to use. /// /// @return the variadic parameter type. static decl_base_sptr -build_ir_node_for_variadic_parameter_type(read_context &ctxt, +build_ir_node_for_variadic_parameter_type(reader &rdr, translation_unit_sptr tunit) { - ir::environment* env = ctxt.ir_env; - ABG_ASSERT(env); - type_base_sptr t = env->get_variadic_parameter_type(); + const ir::environment& env = rdr.env(); + type_base_sptr t = env.get_variadic_parameter_type(); decl_base_sptr type_declaration = get_type_declaration(t); if (!has_scope(type_declaration)) add_decl_to_scope(type_declaration, tunit->get_global_scope()); @@ -484,7 +875,7 @@ build_ir_node_for_variadic_parameter_type(read_context &ctxt, /// Build and return a function type libabigail IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. @@ -493,7 +884,7 @@ build_ir_node_for_variadic_parameter_type(read_context &ctxt, /// @return a shared pointer to the IR node for the function type. static function_type_sptr -process_ctf_function_type(read_context *ctxt, +process_ctf_function_type(reader *rdr, corpus_sptr corp, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, @@ -508,8 +899,8 @@ process_ctf_function_type(read_context *ctxt, /* Take care first of the result type. */ ctf_id_t ctf_ret_type = funcinfo.ctc_return; - type_base_sptr ret_type = lookup_type(ctxt, corp, tunit, - ctf_dictionary, ctf_ret_type); + type_base_sptr ret_type = rdr->lookup_type(corp, tunit, + ctf_dictionary, ctf_ret_type); if (!ret_type) return result; @@ -524,8 +915,8 @@ process_ctf_function_type(read_context *ctxt, for (int i = 0; i < argc; i++) { ctf_id_t ctf_arg_type = argv[i]; - type_base_sptr arg_type = lookup_type(ctxt, corp, tunit, - ctf_dictionary, ctf_arg_type); + type_base_sptr arg_type = rdr->lookup_type(corp, tunit, + ctf_dictionary, ctf_arg_type); if (!arg_type) return result; @@ -540,7 +931,7 @@ process_ctf_function_type(read_context *ctxt, if (vararg_p) { type_base_sptr arg_type = - is_type(build_ir_node_for_variadic_parameter_type(*ctxt, tunit)); + is_type(build_ir_node_for_variadic_parameter_type(*rdr, tunit)); function_decl::parameter_sptr parm (new function_decl::parameter(arg_type, "", @@ -550,7 +941,7 @@ process_ctf_function_type(read_context *ctxt, function_parms.push_back(parm); } - result = dynamic_pointer_cast(ctxt->lookup_type(ctf_dictionary, + result = dynamic_pointer_cast(rdr->lookup_type(ctf_dictionary, ctf_type)); if (result) return result; @@ -567,7 +958,7 @@ process_ctf_function_type(read_context *ctxt, result->set_is_artificial(true); decl_base_sptr function_type_decl = get_type_declaration(result); add_decl_to_scope(function_type_decl, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, result); + rdr->add_type(ctf_dictionary, ctf_type, result); } return result; @@ -575,7 +966,7 @@ process_ctf_function_type(read_context *ctxt, /// Add member information to a IR struct or union type. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. @@ -583,7 +974,7 @@ process_ctf_function_type(read_context *ctxt, /// @param sou the IR struct or union type to which add the members. static void -process_ctf_sou_members(read_context *ctxt, +process_ctf_sou_members(reader *rdr, corpus_sptr corp, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, @@ -609,9 +1000,9 @@ process_ctf_sou_members(read_context *ctxt, return; /* Build the IR for the member's type. */ - type_base_sptr member_type = lookup_type(ctxt, corp, tunit, - ctf_dictionary, - member_ctf_type); + type_base_sptr member_type = rdr->lookup_type(corp, tunit, + ctf_dictionary, + member_ctf_type); if (!member_type) /* Ignore this member. */ continue; @@ -635,14 +1026,14 @@ process_ctf_sou_members(read_context *ctxt, /// Create a declaration-only union or struct type and add it to the /// IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. /// @param ctf_type the CTF type ID of the source type. /// @return the resulting IR node created. static type_base_sptr -process_ctf_forward_type(read_context *ctxt, +process_ctf_forward_type(reader *rdr, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, ctf_id_t ctf_type) @@ -656,24 +1047,24 @@ process_ctf_forward_type(read_context *ctxt, if (kind == CTF_K_UNION) { union_decl_sptr - union_fwd(new union_decl(ctxt->ir_env, - type_name, - /*alignment=*/0, - location(), - decl_base::VISIBILITY_DEFAULT, - type_is_anonymous)); + union_fwd(new union_decl(rdr->env(), + type_name, + /*alignment=*/0, + location(), + decl_base::VISIBILITY_DEFAULT, + type_is_anonymous)); union_fwd->set_is_declaration_only(true); result = union_fwd; } else { if (!type_is_anonymous) - if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group()) if (result = lookup_class_type(type_name, *corp)) return is_type(result); class_decl_sptr - struct_fwd(new class_decl(ctxt->ir_env, type_name, + struct_fwd(new class_decl(rdr->env(), type_name, /*alignment=*/0, /*size=*/0, true /* is_struct */, location(), @@ -687,14 +1078,14 @@ process_ctf_forward_type(read_context *ctxt, return is_type(result); add_decl_to_scope(result, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, is_type(result)); + rdr->add_type(ctf_dictionary, ctf_type, is_type(result)); return is_type(result); } /// Build and return a struct type libabigail IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. @@ -703,7 +1094,7 @@ process_ctf_forward_type(read_context *ctxt, /// @return a shared pointer to the IR node for the struct type. static class_decl_sptr -process_ctf_struct_type(read_context *ctxt, +process_ctf_struct_type(reader *rdr, corpus_sptr corp, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, @@ -715,12 +1106,12 @@ process_ctf_struct_type(read_context *ctxt, bool struct_type_is_anonymous = (struct_type_name == ""); if (!struct_type_is_anonymous) - if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group()) if (result = lookup_class_type(struct_type_name, *corp)) return result; /* The libabigail IR encodes C struct types in `class' IR nodes. */ - result.reset(new class_decl(ctxt->ir_env, + result.reset(new class_decl(rdr->env(), struct_type_name, ctf_type_size(ctf_dictionary, ctf_type) * 8, ctf_type_align(ctf_dictionary, ctf_type) * 8, @@ -737,12 +1128,12 @@ process_ctf_struct_type(read_context *ctxt, at this point even if the members haven't been added to the IR node yet. */ add_decl_to_scope(result, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, result); + rdr->add_type(ctf_dictionary, ctf_type, result); /* Now add the struct members as specified in the CTF type description. This is C, so named types can only be defined in the global scope. */ - process_ctf_sou_members(ctxt, corp, tunit, ctf_dictionary, ctf_type, + process_ctf_sou_members(rdr, corp, tunit, ctf_dictionary, ctf_type, result); return result; @@ -750,7 +1141,7 @@ process_ctf_struct_type(read_context *ctxt, /// Build and return an union type libabigail IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. @@ -759,7 +1150,7 @@ process_ctf_struct_type(read_context *ctxt, /// @return a shared pointer to the IR node for the union type. static union_decl_sptr -process_ctf_union_type(read_context *ctxt, +process_ctf_union_type(reader *rdr, corpus_sptr corp, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, @@ -771,12 +1162,12 @@ process_ctf_union_type(read_context *ctxt, bool union_type_is_anonymous = (union_type_name == ""); if (!union_type_is_anonymous) - if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group()) if (result = lookup_union_type(union_type_name, *corp)) return result; /* Create the corresponding libabigail union IR node. */ - result.reset(new union_decl(ctxt->ir_env, + result.reset(new union_decl(rdr->env(), union_type_name, ctf_type_size(ctf_dictionary, ctf_type) * 8, location(), @@ -791,12 +1182,12 @@ process_ctf_union_type(read_context *ctxt, at this point even if the members haven't been added to the IR node yet. */ add_decl_to_scope(result, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, result); + rdr->add_type(ctf_dictionary, ctf_type, result); /* Now add the union members as specified in the CTF type description. This is C, so named types can only be defined in the global scope. */ - process_ctf_sou_members(ctxt, corp, tunit, ctf_dictionary, ctf_type, + process_ctf_sou_members(rdr, corp, tunit, ctf_dictionary, ctf_type, result); return result; @@ -804,7 +1195,7 @@ process_ctf_union_type(read_context *ctxt, /// Build and return an array type libabigail IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. @@ -813,7 +1204,7 @@ process_ctf_union_type(read_context *ctxt, /// @return a shared pointer to the IR node for the array type. static array_type_def_sptr -process_ctf_array_type(read_context *ctxt, +process_ctf_array_type(reader *rdr, corpus_sptr corp, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, @@ -834,20 +1225,20 @@ process_ctf_array_type(read_context *ctxt, uint64_t nelems = ctf_ainfo.ctr_nelems; /* Make sure the element type is generated. */ - type_base_sptr element_type = lookup_type(ctxt, corp, tunit, - ctf_dictionary, - ctf_element_type); + type_base_sptr element_type = rdr->lookup_type(corp, tunit, + ctf_dictionary, + ctf_element_type); if (!element_type) return result; /* Ditto for the index type. */ - type_base_sptr index_type = lookup_type(ctxt, corp, tunit, - ctf_dictionary, - ctf_index_type); + type_base_sptr index_type = rdr->lookup_type(corp, tunit, + ctf_dictionary, + ctf_index_type); if (!index_type) return result; - result = dynamic_pointer_cast(ctxt->lookup_type(ctf_dictionary, + result = dynamic_pointer_cast(rdr->lookup_type(ctf_dictionary, ctf_type)); if (result) return result; @@ -866,7 +1257,7 @@ process_ctf_array_type(read_context *ctxt, if (upper_bound.get_unsigned_value() == 0) is_infinite = true; - subrange.reset(new array_type_def::subrange_type(ctxt->ir_env, + subrange.reset(new array_type_def::subrange_type(rdr->env(), "", lower_bound, upper_bound, @@ -887,7 +1278,7 @@ process_ctf_array_type(read_context *ctxt, { decl_base_sptr array_type_decl = get_type_declaration(result); add_decl_to_scope(array_type_decl, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, result); + rdr->add_type(ctf_dictionary, ctf_type, result); } return result; @@ -895,14 +1286,14 @@ process_ctf_array_type(read_context *ctxt, /// Build and return a qualified type libabigail IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. /// @param ctf_type the CTF type ID of the source type. static type_base_sptr -process_ctf_qualified_type(read_context *ctxt, +process_ctf_qualified_type(reader *rdr, corpus_sptr corp, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, @@ -911,12 +1302,12 @@ process_ctf_qualified_type(read_context *ctxt, type_base_sptr result; int type_kind = ctf_type_kind(ctf_dictionary, ctf_type); ctf_id_t ctf_utype = ctf_type_reference(ctf_dictionary, ctf_type); - type_base_sptr utype = lookup_type(ctxt, corp, tunit, - ctf_dictionary, ctf_utype); + type_base_sptr utype = rdr->lookup_type(corp, tunit, + ctf_dictionary, ctf_utype); if (!utype) return result; - result = dynamic_pointer_cast(ctxt->lookup_type(ctf_dictionary, + result = dynamic_pointer_cast(rdr->lookup_type(ctf_dictionary, ctf_type)); if (result) return result; @@ -940,7 +1331,7 @@ process_ctf_qualified_type(read_context *ctxt, { decl_base_sptr qualified_type_decl = get_type_declaration(result); add_decl_to_scope(qualified_type_decl, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, result); + rdr->add_type(ctf_dictionary, ctf_type, result); } return result; @@ -948,7 +1339,7 @@ process_ctf_qualified_type(read_context *ctxt, /// Build and return a pointer type libabigail IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. @@ -957,7 +1348,7 @@ process_ctf_qualified_type(read_context *ctxt, /// @return a shared pointer to the IR node for the pointer type. static pointer_type_def_sptr -process_ctf_pointer_type(read_context *ctxt, +process_ctf_pointer_type(reader *rdr, corpus_sptr corp, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, @@ -968,13 +1359,13 @@ process_ctf_pointer_type(read_context *ctxt, if (ctf_target_type == CTF_ERR) return result; - type_base_sptr target_type = lookup_type(ctxt, corp, tunit, - ctf_dictionary, - ctf_target_type); + type_base_sptr target_type = rdr->lookup_type(corp, tunit, + ctf_dictionary, + ctf_target_type); if (!target_type) return result; - result = dynamic_pointer_cast(ctxt->lookup_type(ctf_dictionary, + result = dynamic_pointer_cast(rdr->lookup_type(ctf_dictionary, ctf_type)); if (result) return result; @@ -986,7 +1377,7 @@ process_ctf_pointer_type(read_context *ctxt, if (result) { add_decl_to_scope(result, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, result); + rdr->add_type(ctf_dictionary, ctf_type, result); } return result; @@ -994,7 +1385,7 @@ process_ctf_pointer_type(read_context *ctxt, /// Build and return an enum type libabigail IR. /// -/// @param ctxt the read context. +/// @param rdr the read context. /// @param corp the libabigail IR corpus being constructed. /// @param tunit the current IR translation unit. /// @param ctf_dictionary the CTF dictionary being read. @@ -1003,7 +1394,7 @@ process_ctf_pointer_type(read_context *ctxt, /// @return a shared pointer to the IR node for the enum type. static enum_type_decl_sptr -process_ctf_enum_type(read_context *ctxt, +process_ctf_enum_type(reader *rdr, translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, ctf_id_t ctf_type) @@ -1012,7 +1403,7 @@ process_ctf_enum_type(read_context *ctxt, std::string enum_name = ctf_type_name_raw(ctf_dictionary, ctf_type); if (!enum_name.empty()) - if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group()) if (result = lookup_enum_type(enum_name, *corp)) return result; @@ -1022,7 +1413,7 @@ process_ctf_enum_type(read_context *ctxt, size_t utype_size_in_bits = ctf_type_size(ctf_dictionary, ctf_type) * 8; type_decl_sptr utype; - utype.reset(new type_decl(ctxt->ir_env, + utype.reset(new type_decl(rdr->env(), "", utype_size_in_bits, utype_size_in_bits, @@ -1041,7 +1432,7 @@ process_ctf_enum_type(read_context *ctxt, int evalue; while ((ename = ctf_enum_next(ctf_dictionary, ctf_type, &enum_next, &evalue))) - enms.push_back(enum_type_decl::enumerator(ctxt->ir_env, ename, evalue)); + enms.push_back(enum_type_decl::enumerator(ename, evalue)); if (ctf_errno(ctf_dictionary) != ECTF_NEXT_END) { fprintf(stderr, "ERROR from ctf_enum_next\n"); @@ -1053,154 +1444,9 @@ process_ctf_enum_type(read_context *ctxt, if (result) { add_decl_to_scope(result, tunit->get_global_scope()); - ctxt->add_type(ctf_dictionary, ctf_type, result); - } - - return result; -} - -/// Add a new type declaration to the given libabigail IR corpus CORP. -/// -/// @param ctxt the read context. -/// @param corp the libabigail IR corpus being constructed. -/// @param tunit the current IR translation unit. -/// @param ctf_dictionary the CTF dictionary being read. -/// @param ctf_type the CTF type ID of the source type. -/// -/// Note that if @ref ctf_type can't reliably be translated to the IR -/// then it is simply ignored. -/// -/// @return a shared pointer to the IR node for the type. - -static type_base_sptr -process_ctf_type(read_context *ctxt, - corpus_sptr corp, - translation_unit_sptr tunit, - ctf_dict_t *ctf_dictionary, - ctf_id_t ctf_type) -{ - int type_kind = ctf_type_kind(ctf_dictionary, ctf_type); - type_base_sptr result; - - if (ctxt->lookup_unknown_type(ctf_type)) - return nullptr; - - if ((result = ctxt->lookup_type(ctf_dictionary, ctf_type))) - return result; - - switch (type_kind) - { - case CTF_K_INTEGER: - case CTF_K_FLOAT: - { - type_decl_sptr type_decl - = process_ctf_base_type(ctxt, corp, tunit, ctf_dictionary, ctf_type); - result = is_type(type_decl); - break; - } - case CTF_K_TYPEDEF: - { - typedef_decl_sptr typedef_decl - = process_ctf_typedef(ctxt, corp, tunit, ctf_dictionary, ctf_type); - result = is_type(typedef_decl); - break; - } - case CTF_K_POINTER: - { - pointer_type_def_sptr pointer_type - = process_ctf_pointer_type(ctxt, corp, tunit, ctf_dictionary, ctf_type); - result = pointer_type; - break; - } - case CTF_K_CONST: - case CTF_K_VOLATILE: - case CTF_K_RESTRICT: - { - type_base_sptr qualified_type - = process_ctf_qualified_type(ctxt, corp, tunit, ctf_dictionary, ctf_type); - result = qualified_type; - break; - } - case CTF_K_ARRAY: - { - array_type_def_sptr array_type - = process_ctf_array_type(ctxt, corp, tunit, ctf_dictionary, ctf_type); - result = array_type; - break; - } - case CTF_K_ENUM: - { - enum_type_decl_sptr enum_type - = process_ctf_enum_type(ctxt, tunit, ctf_dictionary, ctf_type); - result = enum_type; - break; - } - case CTF_K_FUNCTION: - { - function_type_sptr function_type - = process_ctf_function_type(ctxt, corp, tunit, ctf_dictionary, ctf_type); - result = function_type; - break; - } - case CTF_K_STRUCT: - { - class_decl_sptr struct_decl - = process_ctf_struct_type(ctxt, corp, tunit, ctf_dictionary, ctf_type); - result = is_type(struct_decl); - break; - } - case CTF_K_FORWARD: - { - result = process_ctf_forward_type(ctxt, tunit, - ctf_dictionary, - ctf_type); - } - break; - case CTF_K_UNION: - { - union_decl_sptr union_decl - = process_ctf_union_type(ctxt, corp, tunit, ctf_dictionary, ctf_type); - result = is_type(union_decl); - break; - } - case CTF_K_UNKNOWN: - /* Unknown types are simply ignored. */ - default: - break; + rdr->add_type(ctf_dictionary, ctf_type, result); } - if (!result) - { - fprintf(stderr, "NOT PROCESSED TYPE %lu\n", ctf_type); - ctxt->add_unknown_type(ctf_type); - } - - return result; -} - -/// Given a CTF type id, lookup the corresponding libabigail IR type. -/// If the IR type hasn't been generated yet, generate it. -/// -/// @param ctxt the read context. -/// @param corp the libabigail IR corpus being constructed. -/// @param tunit the current IR translation unit. -/// @param ctf_dictionary the CTF dictionary being read. -/// @param ctf_type the CTF type ID of the looked type. -/// -/// Note that if @ref ctf_type can't reliably be translated to the IR -/// then a NULL shared pointer is returned. -/// -/// @return a shared pointer to the IR node for the type. - -static type_base_sptr -lookup_type(read_context *ctxt, corpus_sptr corp, - translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary, - ctf_id_t ctf_type) -{ - type_base_sptr result = ctxt->lookup_type(ctf_dictionary, ctf_type); - - if (!result) - result = process_ctf_type(ctxt, corp, tunit, ctf_dictionary, ctf_type); return result; } @@ -1259,162 +1505,6 @@ lookup_symbol_in_ctf_archive(ctf_archive_t *ctfa, ctf_dict_t **ctf_dict, return ctf_type; } -/// Process a CTF archive and create libabigail IR for the types, -/// variables and function declarations found in the archive, iterating -/// over public symbols. The IR is added to the given corpus. -/// -/// @param ctxt the read context containing the CTF archive to -/// process. -/// @param corp the IR corpus to which add the new contents. - -static void -process_ctf_archive(read_context *ctxt, corpus_sptr corp) -{ - /* We only have a translation unit. */ - translation_unit_sptr ir_translation_unit = - std::make_shared(ctxt->ir_env, "", 64); - ir_translation_unit->set_language(translation_unit::LANG_C); - corp->add(ir_translation_unit); - - int ctf_err; - ctf_dict_t *ctf_dict, *dict_tmp; - const auto symtab = ctxt->symtab; - symtab_reader::symtab_filter filter = symtab->make_filter(); - filter.set_public_symbols(); - std::string dict_name; - - if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN) - && ctxt->cur_corpus_group_) - { - tools_utils::base_name(ctxt->filename, dict_name); - - if (dict_name != "vmlinux") - // remove .ko suffix - dict_name.erase(dict_name.length() - 3, 3); - - std::replace(dict_name.begin(), dict_name.end(), '-', '_'); - } - - if ((ctf_dict = ctf_dict_open(ctxt->ctfa, - dict_name.empty() ? NULL : dict_name.c_str(), - &ctf_err)) == NULL) - { - fprintf(stderr, "ERROR dictionary not found\n"); - abort(); - } - - dict_tmp = ctf_dict; - - for (const auto& symbol : symtab_reader::filtered_symtab(*symtab, filter)) - { - std::string sym_name = symbol->get_name(); - ctf_id_t ctf_sym_type; - - ctf_sym_type = lookup_symbol_in_ctf_archive(ctxt->ctfa, &ctf_dict, - sym_name.c_str()); - if (ctf_sym_type == CTF_ERR) - continue; - - if (ctf_type_kind(ctf_dict, ctf_sym_type) != CTF_K_FUNCTION) - { - const char *var_name = sym_name.c_str(); - type_base_sptr var_type = lookup_type(ctxt, corp, ir_translation_unit, - ctf_dict, ctf_sym_type); - if (!var_type) - /* Ignore variable if its type can't be sorted out. */ - continue; - - var_decl_sptr var_declaration; - var_declaration.reset(new var_decl(var_name, - var_type, - location(), - var_name)); - - var_declaration->set_symbol(symbol); - add_decl_to_scope(var_declaration, - ir_translation_unit->get_global_scope()); - var_declaration->set_is_in_public_symbol_table(true); - ctxt->maybe_add_var_to_exported_decls(var_declaration.get()); - } - else - { - const char *func_name = sym_name.c_str(); - ctf_id_t ctf_sym = ctf_sym_type; - type_base_sptr func_type = lookup_type(ctxt, corp, ir_translation_unit, - ctf_dict, ctf_sym); - if (!func_type) - /* Ignore function if its type can't be sorted out. */ - continue; - - function_decl_sptr func_declaration; - func_declaration.reset(new function_decl(func_name, - func_type, - 0 /* is_inline */, - location())); - func_declaration->set_symbol(symbol); - add_decl_to_scope(func_declaration, - ir_translation_unit->get_global_scope()); - func_declaration->set_is_in_public_symbol_table(true); - ctxt->maybe_add_fn_to_exported_decls(func_declaration.get()); - } - - ctf_dict = dict_tmp; - } - - ctf_dict_close(ctf_dict); - /* Canonicalize all the types generated above. This must be - done "a posteriori" because the processing of types may - require other related types to not be already - canonicalized. */ - ctxt->canonicalize_all_types(); -} - -/// Open the ELF file described by the given read context. -/// -/// @param ctxt the read context. -/// @return 0 if the ELF file can't be opened. -/// @return 1 otherwise. - -static int -open_elf_handler(read_context *ctxt) -{ - /* libelf requires to negotiate/set the version of ELF. */ - if (elf_version(EV_CURRENT) == EV_NONE) - return 0; - - /* Open an ELF handler. */ - ctxt->elf_fd = open(ctxt->filename.c_str(), O_RDONLY); - if (ctxt->elf_fd == -1) - return 0; - - ctxt->elf_handler = elf_begin(ctxt->elf_fd, ELF_C_READ, NULL); - if (ctxt->elf_handler == NULL) - { - fprintf(stderr, "cannot open %s: %s\n", - ctxt->filename.c_str(), elf_errmsg(elf_errno())); - close(ctxt->elf_fd); - return 0; - } - - return 1; -} - -/// Close the ELF file described by the given read context. -/// -/// @param ctxt the read context. - -static void -close_elf_handler (read_context *ctxt) -{ - /* Finish the ELF handler and close the associated file. */ - elf_end(ctxt->elf_handler); - close(ctxt->elf_fd); - - /* Finish the ELF handler and close the associated debug file. */ - elf_end(ctxt->elf_handler_dbg); - close(ctxt->elf_fd_dbg); -} - /// Fill a CTF section description with the information in a given ELF /// section. /// @@ -1422,13 +1512,14 @@ close_elf_handler (read_context *ctxt) /// @param ctf_section the CTF section to fill with the raw data. static void -fill_ctf_section(Elf_Scn *elf_section, ctf_sect_t *ctf_section) +fill_ctf_section(const Elf_Scn *elf_section, ctf_sect_t *ctf_section) { GElf_Shdr section_header_mem, *section_header; Elf_Data *section_data; - section_header = gelf_getshdr(elf_section, §ion_header_mem); - section_data = elf_getdata(elf_section, 0); + section_header = gelf_getshdr(const_cast(elf_section), + §ion_header_mem); + section_data = elf_getdata(const_cast(elf_section), 0); ABG_ASSERT (section_header != NULL); ABG_ASSERT (section_data != NULL); @@ -1439,326 +1530,27 @@ fill_ctf_section(Elf_Scn *elf_section, ctf_sect_t *ctf_section) ctf_section->cts_entsize = section_header->sh_entsize; } -/// Find a CTF section and debug symbols in a given ELF using -/// .gnu_debuglink section. -/// -/// @param ctxt the read context. -/// @param ctf_dbg_section the CTF section to fill with the raw data. -static void -find_alt_debuginfo(read_context *ctxt, Elf_Scn **ctf_dbg_scn) -{ - std::string name; - Elf_Data *data; - - Elf_Scn *section = elf_helpers::find_section - (ctxt->elf_handler, ".gnu_debuglink", SHT_PROGBITS); - - if (section - && (data = elf_getdata(section, NULL)) - && data->d_size != 0) - name = (char *) data->d_buf; - - int fd = -1; - Elf *hdlr = NULL; - *ctf_dbg_scn = NULL; - - if (!name.empty()) - for (vector::const_iterator i = ctxt->debug_info_root_paths_.begin(); - i != ctxt->debug_info_root_paths_.end(); - ++i) - { - std::string file_path; - if (!tools_utils::find_file_under_dir(**i, name, file_path)) - continue; - - if ((fd = open(file_path.c_str(), O_RDONLY)) == -1) - continue; - - if ((hdlr = elf_begin(fd, ELF_C_READ, NULL)) == NULL) - { - close(fd); - continue; - } - - ctxt->symtab = - symtab_reader::symtab::load(hdlr, ctxt->ir_env, nullptr); - - // unlikely .ctf was designed to be present in stripped file - *ctf_dbg_scn = - elf_helpers::find_section(hdlr, ".ctf", SHT_PROGBITS); - break; - - elf_end(hdlr); - close(fd); - } - - // If we don't have a symbol table, use current one in ELF file - if (!ctxt->symtab) - ctxt->symtab = - symtab_reader::symtab::load(ctxt->elf_handler, ctxt->ir_env, nullptr); - - ctxt->elf_handler_dbg = hdlr; - ctxt->elf_fd_dbg = fd; -} - -/// Slurp certain information from the ELF file described by a given -/// read context and install it in a libabigail corpus. -/// -/// @param ctxt the read context -/// @param corp the libabigail corpus in which to install the info. -/// @param status the resulting status flags. -static void -slurp_elf_info(read_context *ctxt, - corpus_sptr corp, - elf_reader::status& status) -{ - /* Set the ELF architecture. */ - GElf_Ehdr *ehdr, eh_mem; - Elf_Scn *symtab_scn; - Elf_Scn *ctf_scn, *ctf_dbg_scn; - Elf_Scn *strtab_scn; - - if (!(ehdr = gelf_getehdr(ctxt->elf_handler, &eh_mem))) - return; - - corp->set_architecture_name(elf_helpers::e_machine_to_string(ehdr->e_machine)); - - find_alt_debuginfo(ctxt, &ctf_dbg_scn); - ABG_ASSERT(ctxt->symtab); - corp->set_symtab(ctxt->symtab); - - if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN) - && ctxt->cur_corpus_group_) - { - status |= elf_reader::STATUS_OK; - return; - } - - /* Get the raw ELF section contents for libctf. */ - const char *ctf_name = ".ctf"; - ctf_scn = elf_helpers::find_section_by_name(ctxt->elf_handler, ctf_name); - if (ctf_scn == NULL) - { - if (ctf_dbg_scn) - ctf_scn = ctf_dbg_scn; - else - { - status |= elf_reader::STATUS_DEBUG_INFO_NOT_FOUND; - return; - } - } - - // ET_{EXEC,DYN} needs .dyn{sym,str} in ctf_arc_bufopen - const char *symtab_name = ".dynsym"; - const char *strtab_name = ".dynstr"; - - if (ehdr->e_type == ET_REL) - { - symtab_name = ".symtab"; - strtab_name = ".strtab"; - } - - symtab_scn = elf_helpers::find_section_by_name(ctxt->elf_handler, symtab_name); - strtab_scn = elf_helpers::find_section_by_name(ctxt->elf_handler, strtab_name); - if (symtab_scn == NULL || strtab_scn == NULL) - { - status |= elf_reader::STATUS_NO_SYMBOLS_FOUND; - return; - } - - fill_ctf_section(ctf_scn, &ctxt->ctf_sect); - fill_ctf_section(symtab_scn, &ctxt->symtab_sect); - fill_ctf_section(strtab_scn, &ctxt->strtab_sect); - - status |= elf_reader::STATUS_OK; -} - -/// Looks for vmlinux.ctfa file in default directory or in -/// directories provided by debug-info-dir command line option, -/// it stores location path in @ref ctfa_file. -/// -/// @param ctxt the read context. -/// @param ctfa_file file name found. -/// @return true if file is found. -static bool -find_ctfa_file(read_context *ctxt, std::string& ctfa_file) -{ - std::string ctfa_dirname; - dir_name(ctxt->filename, ctfa_dirname, false); - - // In corpus group we assume vmlinux as first file to - // be processed, so default location for vmlinux.cfa - // is vmlinux dirname. - ctfa_file = ctfa_dirname + "/vmlinux.ctfa"; - if (file_exists(ctfa_file)) - return true; - - // If it's proccessing a module, then location directory - // for vmlinux.ctfa should be provided with --debug-info-dir - // option. - for (vector::const_iterator i = ctxt->debug_info_root_paths_.begin(); - i != ctxt->debug_info_root_paths_.end(); - ++i) - { - ctfa_dirname = **i; - ctfa_file = ctfa_dirname + "/vmlinux.ctfa"; - if (file_exists(ctfa_file)) - return true; - } - - return false; -} - /// Create and return a new read context to process CTF information /// from a given ELF file. /// /// @param elf_path the patch of some ELF file. /// @param env a libabigail IR environment. -read_context_sptr -create_read_context(const std::string& elf_path, - const vector& debug_info_root_paths, - ir::environment *env) -{ - read_context_sptr result(new read_context(elf_path, - debug_info_root_paths, - env)); - return result; -} - -/// Read the CTF information from some source described by a given -/// read context and process it to create a libabigail IR corpus. -/// Store the corpus in the same read context. -/// -/// @param ctxt the read context to use. -/// -/// @param status the resulting status of the corpus read. -/// -/// @return a shared pointer to the read corpus. - -corpus_sptr -read_corpus(read_context *ctxt, elf_reader::status &status) -{ - corpus_sptr corp - = std::make_shared(ctxt->ir_env, ctxt->filename); - ctxt->cur_corpus_ = corp; - status = elf_reader::STATUS_UNKNOWN; - - /* Open the ELF file. */ - if (!open_elf_handler(ctxt)) - return corp; - - bool is_linux_kernel = elf_helpers::is_linux_kernel(ctxt->elf_handler); - corpus::origin origin = corpus::CTF_ORIGIN; - - if (is_linux_kernel) - origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN; - corp->set_origin(origin); - - if (ctxt->cur_corpus_group_) - ctxt->cur_corpus_group_->add_corpus(ctxt->cur_corpus_); - - slurp_elf_info(ctxt, corp, status); - if (!is_linux_kernel - && ((status & elf_reader::STATUS_DEBUG_INFO_NOT_FOUND) | - (status & elf_reader::STATUS_NO_SYMBOLS_FOUND))) - return corp; - - // Set the set of exported declaration that are defined. - ctxt->exported_decls_builder - (ctxt->cur_corpus_->get_exported_decls_builder().get()); - - int errp; - if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN) - && ctxt->cur_corpus_group_) - { - if (ctxt->ctfa == NULL) - { - std::string ctfa_filename; - if (find_ctfa_file(ctxt, ctfa_filename)) - ctxt->ctfa = ctf_arc_open(ctfa_filename.c_str(), &errp); - } - } - else - /* Build the ctfa from the contents of the relevant ELF sections, - and process the CTF archive in the read context, if any. - Information about the types, variables, functions, etc contained - in the archive are added to the given corpus. */ - ctxt->ctfa = ctf_arc_bufopen(&ctxt->ctf_sect, &ctxt->symtab_sect, - &ctxt->strtab_sect, &errp); - - ctxt->ir_env->canonicalization_is_done(false); - if (ctxt->ctfa == NULL) - status |= elf_reader::STATUS_DEBUG_INFO_NOT_FOUND; - else - { - process_ctf_archive(ctxt, corp); - ctxt->cur_corpus_->sort_functions(); - ctxt->cur_corpus_->sort_variables(); - } - - ctxt->ir_env->canonicalization_is_done(true); - - /* Cleanup and return. */ - close_elf_handler(ctxt); - return corp; -} - -/// Read the CTF information from some source described by a given -/// read context and process it to create a libabigail IR corpus. -/// Store the corpus in the same read context. -/// -/// @param ctxt the read context to use. -/// -/// @param status the resulting status of the corpus read. -/// -/// @return a shared pointer to the read corpus. - -corpus_sptr -read_corpus(const read_context_sptr &ctxt, elf_reader::status &status) -{return read_corpus(ctxt.get(), status);} - -/// Set the @ref corpus_group being created to the current read context. -/// -/// @param ctxt the read_context to consider. -/// -/// @param group the @ref corpus_group to set. -void -set_read_context_corpus_group(read_context& ctxt, - corpus_group_sptr& group) -{ - ctxt.cur_corpus_group_ = group; -} - -/// Read a corpus and add it to a given @ref corpus_group. -/// -/// @param ctxt the reading context to consider. -/// -/// @param group the @ref corpus_group to add the new corpus to. -/// -/// @param status output parameter. The status of the read. It is set -/// by this function upon its completion. -corpus_sptr -read_and_add_corpus_to_group_from_elf(read_context* ctxt, - corpus_group& group, - elf_reader::status& status) +elf_based_reader_sptr +create_ctf_reader(const std::string& elf_path, + const vector& debug_info_root_paths, + environment& env) { - corpus_sptr result; - corpus_sptr corp = read_corpus(ctxt, status); - if (status & elf_reader::STATUS_OK) - { - if (!corp->get_group()) - group.add_corpus(corp); - result = corp; - } - + reader_sptr result(new reader(elf_path, + debug_info_root_paths, + env)); return result; } -/// Re-initialize a read_context so that it can re-used to read +/// Re-initialize a reader so that it can re-used to read /// another binary. /// -/// @param ctxt the context to re-initialize. +/// @param rdr the context to re-initialize. /// /// @param elf_path the path to the elf file the context is to be used /// for. @@ -1771,16 +1563,15 @@ read_and_add_corpus_to_group_from_elf(read_context* ctxt, /// /// 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 +/// reader the context uses resources that are allocated in the /// environment. void -reset_read_context(read_context_sptr &ctxt, - const std::string& elf_path, - const vector& debug_info_root_path, - ir::environment* environment) +reset_reader(elf_based_reader& rdr, + const std::string& elf_path, + const vector& debug_info_root_path) { - if (ctxt) - ctxt->initialize(elf_path, debug_info_root_path, environment); + ctf_reader::reader& r = dynamic_cast(rdr); + r.initialize(elf_path, debug_info_root_path); } /// Returns a key to be use in types_map dict conformed by @@ -1796,7 +1587,7 @@ reset_read_context(read_context_sptr &ctxt, /// was found. /// /// @param type the id for given CTF type. -std::string +static std::string dic_type_key(ctf_dict_t *dic, ctf_id_t ctf_type) { std::stringstream key; diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc index ddd040e1..70c85161 100644 --- a/src/abg-dwarf-reader.cc +++ b/src/abg-dwarf-reader.cc @@ -11,7 +11,7 @@ /// de-serialize an instance of @ref abigail::corpus from a file in /// elf format, containing dwarf information. -#include "config.h" +#include "abg-internal.h" #include #include #include @@ -37,16 +37,16 @@ #include "abg-ir-priv.h" #include "abg-suppression-priv.h" #include "abg-corpus-priv.h" -#include "abg-elf-helpers.h" -#include "abg-internal.h" +#include "abg-symtab-reader.h" // ABG_BEGIN_EXPORT_DECLARATIONS #include "abg-dwarf-reader.h" +#include "abg-elf-based-reader.h" #include "abg-sptr-utils.h" -#include "abg-symtab-reader.h" #include "abg-tools-utils.h" +#include "abg-elf-helpers.h" ABG_END_EXPORT_DECLARATIONS // @@ -91,16 +91,6 @@ enum die_source // enumerator }; -/// A functor used by @ref dwfl_sptr. -struct dwfl_deleter -{ - void - operator()(Dwfl* dwfl) - {dwfl_end(dwfl);} -};//end struct dwfl_deleter - -/// A convenience typedef for a shared pointer to a Dwfl. -typedef shared_ptr dwfl_sptr; /// A convenience typedef for a vector of Dwarf_Off. typedef vector dwarf_offsets_type; @@ -143,13 +133,6 @@ typedef unordered_map istring_dwarf_offsets_map_type; -/// Convenience typedef for a map which key is an elf address and -/// which value is an elf_symbol_sptr. -typedef unordered_map addr_elf_symbol_sptr_map_type; - -/// Convenience typedef for a set of ELF addresses. -typedef unordered_set address_set_type; - /// A hasher for a pair of Dwarf_Off. This is used as a hasher for /// the type @ref dwarf_offset_pair_set_type. struct dwarf_offset_pair_hash @@ -244,21 +227,23 @@ typedef unordered_map, /// A convenience typedef for a vector of pairs of offset_type. typedef vector> offset_pair_vector_type; -class read_context; +class reader; + +static translation_unit_sptr +build_translation_unit_and_add_to_ir(reader& rdr, + Dwarf_Die* die, + char address_size); static void -maybe_propagate_canonical_type(const read_context& ctxt, +maybe_propagate_canonical_type(const reader& rdr, const Dwarf_Die* l, const Dwarf_Die* r); static void -propagate_canonical_type(const read_context& ctxt, +propagate_canonical_type(const reader& rdr, const Dwarf_Die* l, const Dwarf_Die* r); -/// Convenience typedef for a shared pointer to an @ref address_set_type. -typedef shared_ptr address_set_sptr; - /// Convenience typedef for a shared pointer to an /// addr_elf_symbol_sptr_map_type. typedef shared_ptr addr_elf_symbol_sptr_map_sptr; @@ -379,13 +364,13 @@ operator<(const imported_unit_point& l, const imported_unit_point& r) {return l.offset_of_import < r.offset_of_import;} static bool -get_parent_die(const read_context& ctxt, +get_parent_die(const reader& rdr, const Dwarf_Die* die, Dwarf_Die& parent_die, size_t where_offset); static bool -get_scope_die(const read_context& ctxt, +get_scope_die(const reader& rdr, const Dwarf_Die* die, size_t where_offset, Dwarf_Die& scope_die); @@ -468,7 +453,7 @@ static bool is_type_die_to_be_canonicalized(const Dwarf_Die *die); static bool -die_is_at_class_scope(const read_context& ctxt, +die_is_at_class_scope(const reader& rdr, const Dwarf_Die* die, size_t where_offset, Dwarf_Die& class_scope_die); @@ -510,7 +495,7 @@ static string die_name(const Dwarf_Die* die); static location -die_location(const read_context& ctxt, const Dwarf_Die* die); +die_location(const reader& rdr, const Dwarf_Die* die); static bool die_location_address(Dwarf_Die* die, @@ -540,27 +525,27 @@ build_internal_underlying_enum_type_name(const string &base_name, uint64_t size); static string -die_qualified_type_name(const read_context& ctxt, +die_qualified_type_name(const reader& rdr, const Dwarf_Die* die, size_t where); static string -die_qualified_decl_name(const read_context& ctxt, +die_qualified_decl_name(const reader& rdr, const Dwarf_Die* die, size_t where); static string -die_qualified_name(const read_context& ctxt, +die_qualified_name(const reader& rdr, const Dwarf_Die* die, size_t where); static bool -die_qualified_type_name_empty(const read_context& ctxt, +die_qualified_type_name_empty(const reader& rdr, const Dwarf_Die* die, size_t where, string &qualified_name); static void -die_return_and_parm_names_from_fn_type_die(const read_context& ctxt, +die_return_and_parm_names_from_fn_type_die(const reader& rdr, const Dwarf_Die* die, size_t where_offset, bool pretty_print, @@ -571,7 +556,7 @@ die_return_and_parm_names_from_fn_type_die(const read_context& ctxt, bool& is_static); static string -die_function_signature(const read_context& ctxt, +die_function_signature(const reader& rdr, const Dwarf_Die *die, size_t where_offset); @@ -579,7 +564,7 @@ static bool die_peel_qual_ptr(Dwarf_Die *die, Dwarf_Die& peeled_die); static bool -die_function_type_is_method_type(const read_context& ctxt, +die_function_type_is_method_type(const reader& rdr, const Dwarf_Die *die, size_t where_offset, Dwarf_Die& object_pointer_die, @@ -587,23 +572,23 @@ die_function_type_is_method_type(const read_context& ctxt, bool& is_static); static string -die_pretty_print_type(read_context& ctxt, +die_pretty_print_type(reader& rdr, const Dwarf_Die* die, size_t where_offset); static string -die_pretty_print_decl(read_context& ctxt, +die_pretty_print_decl(reader& rdr, const Dwarf_Die* die, size_t where_offset); static string -die_pretty_print(read_context& ctxt, +die_pretty_print(reader& rdr, const Dwarf_Die* die, size_t where_offset); static void maybe_canonicalize_type(const type_base_sptr& t, - read_context& ctxt); + reader& rdr); static uint64_t get_default_array_lower_bound(translation_unit::language l); @@ -614,234 +599,31 @@ find_lower_bound_in_imported_unit_points(const imported_unit_points_type&, imported_unit_points_type::const_iterator&); static array_type_def::subrange_sptr -build_subrange_type(read_context& ctxt, +build_subrange_type(reader& rdr, const Dwarf_Die* die, size_t where_offset, bool associate_type_to_die = true); static void -build_subranges_from_array_type_die(read_context& ctxt, +build_subranges_from_array_type_die(reader& rdr, const Dwarf_Die* die, array_type_def::subranges_type& subranges, size_t where_offset, bool associate_type_to_die = true); static comparison_result -compare_dies(const read_context& ctxt, +compare_dies(const reader& rdr, const Dwarf_Die *l, const Dwarf_Die *r, bool update_canonical_dies_on_the_fly); static bool -compare_dies_during_canonicalization(read_context& ctxt, +compare_dies_during_canonicalization(reader& rdr, const Dwarf_Die *l, const Dwarf_Die *r, bool update_canonical_dies_on_the_fly); - static bool get_member_child_die(const Dwarf_Die *die, Dwarf_Die *child); -/// Find the file name of the alternate debug info file. -/// -/// @param elf_module the elf module to consider. -/// -/// @param out parameter. Is set to the file name of the alternate -/// debug info file, iff this function returns true. -/// -/// @return true iff the location of the alternate debug info file was -/// found. -static bool -find_alt_debug_info_link(Dwfl_Module *elf_module, - string &alt_file_name) -{ - GElf_Addr bias = 0; - Dwarf *dwarf = dwfl_module_getdwarf(elf_module, &bias); - Elf *elf = dwarf_getelf(dwarf); - GElf_Ehdr ehmem, *elf_header; - elf_header = gelf_getehdr(elf, &ehmem); - - Elf_Scn* section = 0; - while ((section = elf_nextscn(elf, section)) != 0) - { - GElf_Shdr header_mem, *header; - header = gelf_getshdr(section, &header_mem); - if (header->sh_type != SHT_PROGBITS) - continue; - - const char *section_name = elf_strptr(elf, - elf_header->e_shstrndx, - header->sh_name); - - char *alt_name = 0; - char *buildid = 0; - size_t buildid_len = 0; - if (section_name != 0 - && strcmp(section_name, ".gnu_debugaltlink") == 0) - { - Elf_Data *data = elf_getdata(section, 0); - if (data != 0 && data->d_size != 0) - { - alt_name = (char*) data->d_buf; - char *end_of_alt_name = - (char *) memchr(alt_name, '\0', data->d_size); - buildid_len = data->d_size - (end_of_alt_name - alt_name + 1); - if (buildid_len == 0) - return false; - buildid = end_of_alt_name + 1; - } - } - else - continue; - - if (buildid == 0 || alt_name == 0) - return false; - - alt_file_name = alt_name; - return true; - } - - return false; -} - -/// Find alternate debuginfo file of a given "link" under a set of -/// root directories. -/// -/// The link is a string that is read by the function -/// find_alt_debug_info_link(). That link is a path that is relative -/// to a given debug info file, e.g, "../../../.dwz/something.debug". -/// It designates the alternate debug info file associated to a given -/// debug info file. -/// -/// This function will thus try to find the .dwz/something.debug file -/// under some given root directories. -/// -/// @param root_dirs the set of root directories to look from. -/// -/// @param alt_file_name a relative path to the alternate debug info -/// file to look for. -/// -/// @param alt_file_path the resulting absolute path to the alternate -/// debuginfo path denoted by @p alt_file_name and found under one of -/// the directories in @p root_dirs. This is set iff the function -/// returns true. -/// -/// @return true iff the function found the alternate debuginfo file. -static bool -find_alt_debug_info_path(const vector root_dirs, - const string &alt_file_name, - string &alt_file_path) -{ - if (alt_file_name.empty()) - return false; - - string altfile_name = tools_utils::trim_leading_string(alt_file_name, "../"); - - for (vector::const_iterator i = root_dirs.begin(); - i != root_dirs.end(); - ++i) - if (tools_utils::find_file_under_dir(**i, altfile_name, alt_file_path)) - return true; - - return false; -} - -/// Return the alternate debug info associated to a given main debug -/// info file. -/// -/// @param elf_module the elf module to consider. -/// -/// @param debug_root_dirs a set of root debuginfo directories under -/// which too look for the alternate debuginfo file. -/// -/// @param alt_file_name output parameter. This is set to the file -/// path of the alternate debug info file associated to @p elf_module. -/// This is set iff the function returns a non-null result. -/// -/// @param alt_fd the file descriptor used to access the alternate -/// debug info. If this parameter is set by the function, then the -/// caller needs to fclose it, otherwise the file descriptor is going -/// to be leaked. Note however that on recent versions of elfutils -/// where libdw.h contains the function dwarf_getalt(), this parameter -/// is set to 0, so it doesn't need to be fclosed. -/// -/// Note that the alternate debug info file is a DWARF extension as of -/// DWARF 4 ans is decribed at -/// http://www.dwarfstd.org/ShowIssue.php?issue=120604.1. -/// -/// @return the alternate debuginfo, or null. If @p alt_fd is -/// non-zero, then the caller of this function needs to call -/// dwarf_end() on the returned alternate debuginfo pointer, -/// otherwise, it's going to be leaked. -static Dwarf* -find_alt_debug_info(Dwfl_Module *elf_module, - const vector debug_root_dirs, - string& alt_file_name, - int& alt_fd) -{ - if (elf_module == 0) - return 0; - - Dwarf* result = 0; - find_alt_debug_info_link(elf_module, alt_file_name); - -#ifdef LIBDW_HAS_DWARF_GETALT - // We are on recent versions of elfutils where the function - // dwarf_getalt exists, so let's use it. - Dwarf_Addr bias = 0; - Dwarf* dwarf = dwfl_module_getdwarf(elf_module, &bias); - result = dwarf_getalt(dwarf); - alt_fd = 0; -#else - // We are on an old version of elfutils where the function - // dwarf_getalt doesn't exist yet, so let's open code its - // functionality - char *alt_name = 0; - const char *file_name = 0; - void **user_data = 0; - Dwarf_Addr low_addr = 0; - char *alt_file = 0; - - file_name = dwfl_module_info(elf_module, &user_data, - &low_addr, 0, 0, 0, 0, 0); - - alt_fd = dwfl_standard_find_debuginfo(elf_module, user_data, - file_name, low_addr, - alt_name, file_name, - 0, &alt_file); - - result = dwarf_begin(alt_fd, DWARF_C_READ); -#endif - - if (result == 0) - { - // So we didn't find the alternate debuginfo file from the - // information that is in the debuginfo file associated to - // elf_module. Maybe the alternate debuginfo file is located - // under one of the directories in debug_root_dirs. So let's - // look in there. - string alt_file_path; - if (!find_alt_debug_info_path(debug_root_dirs, - alt_file_name, - alt_file_path)) - return result; - - // If we reach this point it means we have found the path to the - // alternate debuginfo file and it's in alt_file_path. So let's - // open it and read it. - int fd = open(alt_file_path.c_str(), O_RDONLY); - if (fd == -1) - return result; - result = dwarf_begin(fd, DWARF_C_READ); - -#ifdef LIBDW_HAS_DWARF_GETALT - Dwarf_Addr bias = 0; - Dwarf* dwarf = dwfl_module_getdwarf(elf_module, &bias); - dwarf_setalt(dwarf, result); -#endif - } - - return result; -} - /// Compare a symbol name against another name, possibly demangling /// the symbol_name before performing the comparison. /// @@ -892,7 +674,7 @@ compare_symbol_name(const string& symbol_name, /// @param syms_found a vector of symbols found with the name @p /// sym_name. table. static bool -lookup_symbol_from_sysv_hash_tab(const environment* env, +lookup_symbol_from_sysv_hash_tab(const environment& env, Elf* elf_handle, const string& sym_name, size_t ht_index, @@ -1169,7 +951,7 @@ setup_gnu_ht(Elf* elf_handle, /// /// @return true if a symbol was actually found. static bool -lookup_symbol_from_gnu_hash_tab(const environment* env, +lookup_symbol_from_gnu_hash_tab(const environment& env, Elf* elf_handle, const string& sym_name, size_t ht_index, @@ -1301,7 +1083,7 @@ lookup_symbol_from_gnu_hash_tab(const environment* env, /// @return true iff the function found the symbol from the elf hash /// table. static bool -lookup_symbol_from_elf_hash_tab(const environment* env, +lookup_symbol_from_elf_hash_tab(const environment& env, Elf* elf_handle, hash_table_kind ht_kind, size_t ht_index, @@ -1358,7 +1140,7 @@ lookup_symbol_from_elf_hash_tab(const environment* env, /// /// @return true iff the symbol was found. static bool -lookup_symbol_from_symtab(const environment* env, +lookup_symbol_from_symtab(environment& env, Elf* elf_handle, const string& sym_name, size_t sym_tab_index, @@ -1449,7 +1231,7 @@ lookup_symbol_from_symtab(const environment* env, /// /// @return true iff a symbol with the name @p symbol_name was found. static bool -lookup_symbol_from_elf(const environment* env, +lookup_symbol_from_elf(environment& env, Elf* elf_handle, const string& symbol_name, bool demangle, @@ -1500,7 +1282,7 @@ lookup_symbol_from_elf(const environment* env, /// /// @return true iff the symbol was found. static bool -lookup_public_function_symbol_from_elf(const environment* env, +lookup_public_function_symbol_from_elf(environment& env, Elf* elf_handle, const string& symbol_name, vector& func_syms) @@ -1533,120 +1315,6 @@ lookup_public_function_symbol_from_elf(const environment* env, return found; } -/// Get data tag information of an ELF file by looking up into its -/// dynamic segment -/// -/// @param elf the elf handle to use for the query. -/// -/// @param dt_tag data tag to look for in dynamic segment -/// @param dt_tag_data vector of found information for a given @p data_tag -/// -/// @return true iff data tag @p data_tag was found - -bool -lookup_data_tag_from_dynamic_segment(Elf* elf, - Elf64_Sxword data_tag, - vector& dt_tag_data) -{ - size_t num_prog_headers = 0; - bool found = false; - if (elf_getphdrnum(elf, &num_prog_headers) < 0) - return found; - - // Cycle through each program header. - for (size_t i = 0; i < num_prog_headers; ++i) - { - GElf_Phdr phdr_mem; - GElf_Phdr *phdr = gelf_getphdr(elf, i, &phdr_mem); - if (phdr == NULL || phdr->p_type != PT_DYNAMIC) - continue; - - // Poke at the dynamic segment like a section, so that we can - // get its section header information; also we'd like to read - // the data of the segment by using elf_getdata() but that - // function needs a Elf_Scn data structure to act on. - // Elfutils doesn't really have any particular function to - // access segment data, other than the functions used to - // access section data. - Elf_Scn *dynamic_section = gelf_offscn(elf, phdr->p_offset); - GElf_Shdr shdr_mem; - GElf_Shdr *dynamic_section_header = gelf_getshdr(dynamic_section, - &shdr_mem); - if (dynamic_section_header == NULL - || dynamic_section_header->sh_type != SHT_DYNAMIC) - continue; - - // Get data of the dynamic segment (seen as a section). - Elf_Data *data = elf_getdata(dynamic_section, NULL); - if (data == NULL) - continue; - - // Get the index of the section headers string table. - size_t string_table_index = 0; - ABG_ASSERT (elf_getshdrstrndx(elf, &string_table_index) >= 0); - - size_t dynamic_section_header_entry_size = gelf_fsize(elf, - ELF_T_DYN, 1, - EV_CURRENT); - - GElf_Shdr link_mem; - GElf_Shdr *link = - gelf_getshdr(elf_getscn(elf, - dynamic_section_header->sh_link), - &link_mem); - ABG_ASSERT(link != NULL); - - size_t num_dynamic_section_entries = - dynamic_section_header->sh_size / dynamic_section_header_entry_size; - - // Now walk through all the DT_* data tags that are in the - // segment/section - for (size_t j = 0; j < num_dynamic_section_entries; ++j) - { - GElf_Dyn dynamic_section_mem; - GElf_Dyn *dynamic_section = gelf_getdyn(data, - j, - &dynamic_section_mem); - if (dynamic_section->d_tag == data_tag) - { - dt_tag_data.push_back(elf_strptr(elf, - dynamic_section_header->sh_link, - dynamic_section->d_un.d_val)); - found = true; - } - } - } - return found; -} - -/// Convert the type of ELF file into @ref elf_type. -/// -/// @param elf the elf handle to use for the query. -/// -/// @return the @ref elf_type for a given elf type. -static elf_type -elf_file_type(Elf* elf) -{ - GElf_Ehdr ehdr_mem; - GElf_Ehdr *header = gelf_getehdr (elf, &ehdr_mem); - vector dt_debug_data; - - switch (header->e_type) - { - case ET_DYN: - if (lookup_data_tag_from_dynamic_segment(elf, DT_DEBUG, dt_debug_data)) - return ELF_TYPE_PI_EXEC; - else - return ELF_TYPE_DSO; - case ET_EXEC: - return ELF_TYPE_EXEC; - case ET_REL: - return ELF_TYPE_RELOCATABLE; - default: - return ELF_TYPE_UNKNOWN; - } -} - // --------------------------------------- // // --------------------------------------- @@ -2004,35 +1672,18 @@ struct dwarf_expr_eval_context // // --------------------------------------- -/// The context used to build ABI corpus from debug info in DWARF -/// format. -/// -/// This context is to be created by create_read_context(). It's then -/// passed to all the routines that read specific dwarf bits as they -/// get some important data from it. +class reader; + +typedef shared_ptr reader_sptr; + +/// The DWARF reader used to build the ABI corpus from debug info in +/// DWARF format. /// -/// When a new data member is added to this context, it must be -/// initiliazed by the read_context::initiliaze() function. So please -/// do not forget. -class read_context +/// This type is to be instanciated +/// abigail::dwarf_reader::reader::create(). +class reader : public elf_based_reader { public: - struct options_type - { - environment* env; - bool load_in_linux_kernel_mode; - bool load_all_types; - bool show_stats; - bool do_log; - - options_type() - : env(), - load_in_linux_kernel_mode(), - load_all_types(), - show_stats(), - do_log() - {} - };// read_context::options_type /// A set of containers that contains one container per kind of @ref /// die_source. This allows to associate DIEs to things, depending @@ -2092,7 +1743,7 @@ public: /// Getter for the container associated to DIEs coming from the /// same source as a given DIE. /// - /// @param ctxt the read context to consider. + /// @param rdr the DWARF reader to consider. /// /// @param die the DIE which should have the same source as the /// source of the container we want. @@ -2100,16 +1751,16 @@ public: /// @return the container that associates DIEs coming from the /// same source as @p die. ContainerType& - get_container(const read_context& ctxt, const Dwarf_Die *die) + get_container(const reader& rdr, const Dwarf_Die *die) { - const die_source source = ctxt.get_die_source(die); + const die_source source = rdr.get_die_source(die); return get_container(source); } /// Getter for the container associated to DIEs coming from the /// same source as a given DIE. /// - /// @param ctxt the read context to consider. + /// @param rdr the DWARF reader to consider. /// /// @param die the DIE which should have the same source as the /// source of the container we want. @@ -2117,10 +1768,10 @@ public: /// @return the container that associates DIEs coming from the /// same source as @p die. const ContainerType& - get_container(const read_context& ctxt, const Dwarf_Die *die) const + get_container(const reader& rdr, const Dwarf_Die *die) const { return const_cast(this)-> - get_container(ctxt, die); + get_container(rdr, die); } /// Clear the container set. @@ -2133,28 +1784,7 @@ public: } }; // end die_dependant_container_set - suppr::suppressions_type supprs_; unsigned short dwarf_version_; - Dwfl_Callbacks offline_callbacks_; - // The set of directories under which to look for debug info. - vector debug_info_root_paths_; - dwfl_sptr handle_; - Dwarf* dwarf_; - // The alternate debug info. Alternate debug info sections are a - // DWARF extension as of DWARF4 and are described at - // http://www.dwarfstd.org/ShowIssue.php?issue=120604.1. Below are - // the file desctor used to access the alternate debug info - // sections, and the representation of the DWARF debug info. Both - // need to be freed after we are done using them, with fclose and - // dwarf_end. - int alt_fd_; - Dwarf* alt_dwarf_; - string alt_debug_info_path_; - // The address range of the offline elf file we are looking at. - Dwfl_Module* elf_module_; - mutable Elf* elf_handle_; - string elf_path_; - mutable Elf_Scn* symtab_section_; Dwarf_Die* cur_tu_die_; mutable dwarf_expr_eval_context dwarf_expr_eval_context_; // A set of maps (one per kind of die source) that associates a decl @@ -2210,8 +1840,6 @@ public: string_classes_map decl_only_classes_map_; string_enums_map decl_only_enums_map_; die_tu_map_type die_tu_map_; - corpus_group_sptr cur_corpus_group_; - corpus_sptr cur_corpus_; translation_unit_sptr cur_tu_; scope_decl_sptr nil_scope_; scope_stack_type scope_stack_; @@ -2228,12 +1856,6 @@ public: offset_offset_map_type alternate_die_parent_map_; offset_offset_map_type type_section_die_parent_map_; list var_decls_to_add_; - vector dt_needed_; - string dt_soname_; - string elf_architecture_; - corpus::exported_decls_builder* exported_decls_builder_; - options_type options_; - bool drop_undefined_syms_; #ifdef WITH_DEBUG_TYPE_CANONICALIZATION bool debug_die_canonicalization_is_on_; bool use_canonical_die_comparison_; @@ -2242,14 +1864,11 @@ public: mutable size_t canonical_propagated_count_; mutable size_t cancelled_propagation_count_; - read_context(); +protected: -private: - mutable symtab_reader::symtab_sptr symtab_; + reader() = delete; -public: - - /// Constructor of read_context. + /// Constructor of reader. /// /// @param elf_path the path to the elf file the context is to be /// used for. @@ -2260,14 +1879,14 @@ public: /// split file. /// /// @param environment the environment used by the current context. - /// This environment contains resources needed by the reader and by + /// This environment contains resources needed by the DWARF 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 + /// reader the context uses resources that are allocated in /// the environment. /// /// @param load_all_types if set to false only the types that are @@ -2278,36 +1897,23 @@ public: /// @param linux_kernel_mode if set to true, then consider the special /// linux kernel symbol tables when determining if a symbol is /// exported or not. - read_context(const string& elf_path, - const vector& debug_info_root_paths, - ir::environment* environment, - bool load_all_types, - bool linux_kernel_mode) + reader(const string& elf_path, + const vector& debug_info_root_paths, + environment& environment, + bool load_all_types, + bool linux_kernel_mode) + : elf_based_reader(elf_path, + debug_info_root_paths, + environment) { - initialize(elf_path, debug_info_root_paths, environment, - load_all_types, linux_kernel_mode); + initialize(load_all_types, linux_kernel_mode); } - /// Initializer of read_context. - /// - /// @param elf_path the path to the elf file the context is to be - /// used for. +public: + + /// Initializer of reader. /// - /// @param debug_info_root_paths a vector of pointers to the path to - /// the root directory under which the debug info is to be found for - /// @p elf_path. Leave this empty 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. + /// Resets the reader so that it can be re-used to read another binary. /// /// @param load_all_types if set to false only the types that are /// reachable from publicly exported declarations (of functions and @@ -2318,27 +1924,10 @@ public: /// special linux kernel symbol tables when determining if a symbol /// is exported or not. void - initialize(const string& elf_path, - const vector& debug_info_root_paths, - ir::environment* environment, - bool load_all_types, - bool linux_kernel_mode) + initialize(bool load_all_types, bool linux_kernel_mode) { dwarf_version_ = 0; - dwarf_ = 0; - handle_.reset(); - alt_fd_ = 0; - alt_dwarf_ = 0; - elf_module_ = 0; - elf_handle_ = 0; - elf_path_ = elf_path; - symtab_section_ = 0; cur_tu_die_ = 0; - exported_decls_builder_ = 0; - - clear_alt_debug_info_data(); - - supprs_.clear(); decl_die_repr_die_offsets_maps_.clear(); type_die_repr_die_offsets_maps_.clear(); die_qualified_name_maps_.clear(); @@ -2358,8 +1947,8 @@ public: types_to_canonicalize_.clear(); decl_only_classes_map_.clear(); die_tu_map_.clear(); - cur_corpus_group_.reset(); - cur_corpus_.reset(); + corpus().reset(); + corpus_group().reset(); cur_tu_.reset(); primary_die_parent_map_.clear(); tu_die_imported_unit_points_map_.clear(); @@ -2368,20 +1957,9 @@ public: alternate_die_parent_map_.clear(); type_section_die_parent_map_.clear(); var_decls_to_add_.clear(); - dt_needed_.clear(); - dt_soname_.clear(); - elf_architecture_.clear(); - - symtab_.reset(); - clear_per_translation_unit_data(); - - memset(&offline_callbacks_, 0, sizeof(offline_callbacks_)); - create_default_dwfl(debug_info_root_paths); - options_.env = environment; - options_.load_in_linux_kernel_mode = linux_kernel_mode; - options_.load_all_types = load_all_types; - drop_undefined_syms_ = false; + options().load_in_linux_kernel_mode = linux_kernel_mode; + options().load_all_types = load_all_types; #ifdef WITH_DEBUG_TYPE_CANONICALIZATION debug_die_canonicalization_is_on_ = environment->debug_die_canonicalization_is_on(); @@ -2393,27 +1971,349 @@ public: load_in_linux_kernel_mode(linux_kernel_mode); } - /// Clear the resources related to the alternate DWARF data. + /// Initializer of reader. + /// + /// Resets the reader so that it can be re-used to read another binary. + /// + /// @param elf_path the path to the new ELF file. + /// + /// @param debug_info_root_paths the vector of debug-info path to + /// look for split debug info. + /// + /// @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 + /// debug information are loaded. + /// + /// @param linux_kernel_mode if set to true, then consider the + /// special linux kernel symbol tables when determining if a symbol + /// is exported or not. void - clear_alt_debug_info_data() + initialize(const string& elf_path, + const vector& debug_info_root_paths, + bool load_all_types, + bool linux_kernel_mode) { - if (alt_fd_) - { - close(alt_fd_); - alt_fd_ = 0; - if (alt_dwarf_) - { - dwarf_end(alt_dwarf_); - alt_dwarf_ = 0; - } - alt_debug_info_path_.clear(); - } + reset(elf_path, debug_info_root_paths); + initialize(load_all_types, linux_kernel_mode); + } + + /// Create an instance of DWARF Reader. + /// + /// @param elf_path the path to the ELF file to read from. + /// + /// @param debug_info_root_paths a vector of paths where to look up + /// split debug info files. + /// + /// @param environment the environment to be used by the reader. + /// + /// @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 + /// debug information are loaded. + /// + /// @param linux_kernel_mode if set to true, then consider the + /// special linux kernel symbol tables when determining if a symbol + /// is exported or not. + static dwarf_reader::reader_sptr + create(const std::string& elf_path, + const vector& debug_info_root_paths, + environment& environment, + bool load_all_types, + bool linux_kernel_mode) + { + reader_sptr result(new reader(elf_path, debug_info_root_paths, + environment, load_all_types, + linux_kernel_mode)); + return result; } - /// Detructor of the @ref read_context type. - ~read_context() + /// Destructor of the @ref reader type. + ~reader() { - clear_alt_debug_info_data(); + } + + /// Read and analyze the ELF and DWARF information associated with + /// the underlying ELF file and build an ABI corpus out of it. + /// + /// @param status output parameter. This is set to the status of + /// the analysis of the debug info. + /// + /// @return the resulting ABI corpus. + corpus_sptr + read_corpus(status& status) + { + status = STATUS_UNKNOWN; + + // Load the generic ELF parts of the corpus. + elf_reader::reader::read_corpus(status); + + if ((status & STATUS_NO_SYMBOLS_FOUND) + || !(status & STATUS_OK)) + // Either we couldn't find ELF symbols or something went badly + // wrong. There is nothing we can do with this ELF file. Bail + // out. + return corpus_sptr(); + + // If we couldn't find debug info from the elf path, then say it. + if (dwarf_debug_info() == nullptr) + status |= STATUS_DEBUG_INFO_NOT_FOUND; + + { + string alt_di_path; + if (refers_to_alt_debug_info(alt_di_path) + && !alternate_dwarf_debug_info()) + status |= STATUS_ALT_DEBUG_INFO_NOT_FOUND; + } + + if (// If debug info was found but not the required alternate debug + // info ... + ((status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) + && !(status & STATUS_DEBUG_INFO_NOT_FOUND))) + // ... then we cannot handle the binary. + return corpus_sptr(); + + // Read the variable and function descriptions from the debug info + // we have, through the dwfl handle. + corpus_sptr corp = read_debug_info_into_corpus(); + + status |= STATUS_OK; + + return corp; + } + + /// Read an analyze the DWARF information. + /// + /// Construct an ABI corpus from it. + /// + /// This is a sub-routine of abigail::dwarf_reader::reader::read_corpus(). + /// + /// @return the resulting ABI corpus. + corpus_sptr + read_debug_info_into_corpus() + { + clear_per_corpus_data(); + + // First set some mundane properties of the corpus gathered from + // ELF. + corpus::origin origin = corpus::DWARF_ORIGIN; + if (is_linux_kernel(elf_handle())) + origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN; + corpus()->set_origin(origin); + + if (origin & corpus::LINUX_KERNEL_BINARY_ORIGIN + && !env().user_set_analyze_exported_interfaces_only()) + // So we are looking at the Linux Kernel and the user has not set + // any particular option regarding the amount of types to analyse. + // In that case, we need to only analyze types that are reachable + // from exported interfaces otherwise we get such a massive amount + // of type DIEs to look at that things are just too slow down the + // road. + env().analyze_exported_interfaces_only(true); + + corpus()->set_soname(dt_soname()); + corpus()->set_needed(dt_needed()); + corpus()->set_architecture_name(elf_architecture()); + if (corpus_group_sptr group = corpus_group()) + group->add_corpus(corpus()); + + // Set symbols information to the corpus. + corpus()->set_symtab(symtab()); + + // Get out now if no debug info is found. + if (!dwarf_debug_info()) + return corpus(); + + uint8_t address_size = 0; + size_t header_size = 0; + +#ifdef WITH_DEBUG_SELF_COMPARISON + if (env().self_comparison_debug_is_on()) + env().set_self_comparison_debug_input(corpus()); +#endif + + // Walk all the DIEs of the debug info to build a DIE -> parent map + // useful for get_die_parent() to work. + { + tools_utils::timer t; + if (do_log()) + { + cerr << "building die -> parent maps ..."; + t.start(); + } + + build_die_parent_maps(); + + if (do_log()) + { + t.stop(); + cerr << " DONE@" << corpus()->get_path() + << ":" + << t + << "\n"; + } + } + + env().canonicalization_is_done(false); + + { + tools_utils::timer t; + if (do_log()) + { + cerr << "building the libabigail internal representation ..."; + t.start(); + } + // And now walk all the DIEs again to build the libabigail IR. + Dwarf_Half dwarf_vers = 0; + for (Dwarf_Off offset = 0, next_offset = 0; + (dwarf_next_unit(const_cast(dwarf_debug_info()), + offset, &next_offset, &header_size, + &dwarf_vers, NULL, &address_size, NULL, + NULL, NULL) == 0); + offset = next_offset) + { + Dwarf_Off die_offset = offset + header_size; + Dwarf_Die unit; + if (!dwarf_offdie(const_cast(dwarf_debug_info()), + die_offset, &unit) + || dwarf_tag(&unit) != DW_TAG_compile_unit) + continue; + + dwarf_version(dwarf_vers); + + address_size *= 8; + + // Build a translation_unit IR node from cu; note that cu must + // be a DW_TAG_compile_unit die. + translation_unit_sptr ir_node = + build_translation_unit_and_add_to_ir(*this, &unit, address_size); + ABG_ASSERT(ir_node); + } + if (do_log()) + { + t.stop(); + cerr << " DONE@" << corpus()->get_path() + << ":" + << t + << "\n"; + + cerr << "Number of aggregate types compared: " + << compare_count_ << "\n" + << "Number of canonical types propagated: " + << canonical_propagated_count_ << "\n" + << "Number of cancelled propagated canonical types:" + << cancelled_propagation_count_ << "\n"; + } + } + + { + tools_utils::timer t; + if (do_log()) + { + cerr << "resolving declaration only classes ..."; + t.start(); + } + resolve_declaration_only_classes(); + if (do_log()) + { + t.stop(); + cerr << " DONE@" << corpus()->get_path() + << ":" + << t + <<"\n"; + } + } + + { + tools_utils::timer t; + if (do_log()) + { + cerr << "resolving declaration only enums ..."; + t.start(); + } + resolve_declaration_only_enums(); + if (do_log()) + { + t.stop(); + cerr << " DONE@" << corpus()->get_path() + << ":" + << t + <<"\n"; + } + } + + { + tools_utils::timer t; + if (do_log()) + { + cerr << "fixing up functions with linkage name but " + << "no advertised underlying symbols ...."; + t.start(); + } + fixup_functions_with_no_symbols(); + if (do_log()) + { + t.stop(); + cerr << " DONE@" << corpus()->get_path() + <<":" + << t + <<"\n"; + } + } + + /// Now, look at the types that needs to be canonicalized after the + /// translation has been constructed (which is just now) and + /// canonicalize them. + /// + /// These types need to be constructed at the end of the translation + /// unit reading phase because some types are modified by some DIEs + /// even after the principal DIE describing the type has been read; + /// this happens for clones of virtual destructors (for instance) or + /// even for some static data members. We need to do that for types + /// are in the alternate debug info section and for types that in + /// the main debug info section. + { + tools_utils::timer t; + if (do_log()) + { + cerr << "perform late type canonicalizing ...\n"; + t.start(); + } + + perform_late_type_canonicalizing(); + if (do_log()) + { + t.stop(); + cerr << "late type canonicalizing DONE@" + << corpus()->get_path() + << ":" + << t + << "\n"; + } + } + + env().canonicalization_is_done(true); + + { + tools_utils::timer t; + if (do_log()) + { + cerr << "sort functions and variables ..."; + t.start(); + } + corpus()->sort_functions(); + corpus()->sort_variables(); + if (do_log()) + { + t.stop(); + cerr << " DONE@" << corpus()->get_path() + << ":" + << t + <<" \n"; + } + } + + return corpus(); } /// Clear the data that is relevant only for the current translation @@ -2442,23 +2342,16 @@ public: /// Getter for the current environment. /// /// @return the current environment. - const ir::environment* - env() const - {return options_.env;} + environment& + env() + {return options().env;} /// Getter for the current environment. /// /// @return the current environment. - ir::environment* - env() - {return options_.env;} - - /// Setter for the current environment. - /// - /// @param env the new current environment. - void - env(ir::environment* env) - {options_.env = env;} + const environment& + env() const + {return const_cast(this)->env();} /// Getter for the flag that tells us if we are dropping functions /// and variables that have undefined symbols. @@ -2467,7 +2360,7 @@ public: /// undefined symbols. bool drop_undefined_syms() const - {return drop_undefined_syms_;} + {return options().drop_undefined_syms;} /// Setter for the flag that tells us if we are dropping functions /// and variables that have undefined symbols. @@ -2475,67 +2368,9 @@ public: /// @param f the new value of the flag. void drop_undefined_syms(bool f) - {drop_undefined_syms_ = f;} - - /// Getter of the suppression specifications to be used during - /// ELF/DWARF parsing. - /// - /// @return the suppression specifications. - const suppr::suppressions_type& - get_suppressions() const - {return supprs_;} - - /// Getter of the suppression specifications to be used during - /// ELF/DWARF parsing. - /// - /// @return the suppression specifications. - suppr::suppressions_type& - get_suppressions() - {return supprs_;} - - /// 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_paths a vector of pointers to the root - /// path under which to look for the debug info of the elf files - /// that are later handled by the Dwfl. This is 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 the empty set, 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(const vector& debug_info_root_paths) - { - offline_callbacks()->find_debuginfo = dwfl_standard_find_debuginfo; - offline_callbacks()->section_address = dwfl_offline_section_address; - offline_callbacks()->debuginfo_path = - debug_info_root_paths.empty() ? 0 : debug_info_root_paths.front(); - handle_.reset(dwfl_begin(offline_callbacks()), - dwfl_deleter()); - debug_info_root_paths_ = debug_info_root_paths; - } + {options().drop_undefined_syms = f;} + /// Getter of the DWARF version. unsigned short dwarf_version() const {return dwarf_version_;} @@ -2544,47 +2379,9 @@ 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_;} - - /// Return the ELF descriptor for the binary we are analizing. - /// - /// @return a pointer to the Elf descriptor representing the binary - /// we are analizing. - Elf* - elf_handle() const - { - if (elf_handle_ == 0) - { - if (elf_module()) - { - GElf_Addr bias = 0; - elf_handle_ = dwfl_module_getelf(elf_module(), &bias); - } - } - return elf_handle_; - } - /// Return the ELF descriptor used for DWARF access. /// - /// This can be the same as read_context::elf_handle() above, if the + /// This can be the same as reader::elf_handle() above, if the /// DWARF info is in the same ELF file as the one of the binary we /// are analizing. It is different if e.g, the debug info is split /// from the ELF file we are analizing. @@ -2593,7 +2390,7 @@ public: /// info. Elf* dwarf_elf_handle() const - {return dwarf_getelf(dwarf());} + {return dwarf_getelf(const_cast(dwarf_debug_info()));} /// Test if the debug information is in a separate ELF file wrt the /// main ELF file of the program (application or shared library) we @@ -2606,122 +2403,24 @@ public: dwarf_is_splitted() const {return dwarf_elf_handle() != elf_handle();} - /// Add paths to the set of paths under which to look for split - /// debuginfo files. - /// - /// @param debug_info_root_paths the paths to add. - void - add_debug_info_root_paths(const vector& debug_info_root_paths) - { - debug_info_root_paths_.insert(debug_info_root_paths_.end(), - debug_info_root_paths.begin(), - debug_info_root_paths.end()); - } - - /// Add a path to the set of paths under which to look for split - /// debuginfo files. - /// - /// @param debug_info_root_path the path to add. - void - add_debug_info_root_path(char** debug_info_root_path) - {debug_info_root_paths_.push_back(debug_info_root_path);} - - /// Find the alternate debuginfo file associated to a given elf file. - /// - /// @param elf_module represents the elf file to consider. - /// - /// @param alt_file_name the resulting path to the alternate - /// debuginfo file found. This is set iff the function returns a - /// non-nil value. - Dwarf* - find_alt_debug_info(Dwfl_Module *elf_module, - string& alt_file_name, - int& alt_fd) - { - Dwarf *result = 0; - result = dwarf_reader::find_alt_debug_info(elf_module, - debug_info_root_paths_, - alt_file_name, alt_fd); - return result; - } - - /// Load the debug info associated with an elf file that is at a - /// given path. - /// - /// @return a pointer to the DWARF debug info pointer upon - /// successful debug info loading, NULL otherwise. - Dwarf* - load_debug_info() - { - if (!dwfl_handle()) - return 0; - - if (dwarf_) - return dwarf_; - - elf_module_ = - dwfl_report_offline(dwfl_handle().get(), - basename(const_cast(elf_path().c_str())), - elf_path().c_str(), - -1); - dwfl_report_end(dwfl_handle().get(), 0, 0); - - Dwarf_Addr bias = 0; - dwarf_ = dwfl_module_getdwarf(elf_module_, &bias); - // Look for split debuginfo files under multiple possible - // debuginfo roots. - for (vector::const_iterator i = debug_info_root_paths_.begin(); - dwarf_ == 0 && i != debug_info_root_paths_.end(); - ++i) - { - offline_callbacks()->debuginfo_path = *i; - dwarf_ = dwfl_module_getdwarf(elf_module_, &bias); - } - - if (!alt_dwarf_) - alt_dwarf_ = find_alt_debug_info(elf_module_, - alt_debug_info_path_, - alt_fd_); - - return dwarf_; - } - - /// Return the main debug info we are looking at. - /// - /// @return the main debug info. - Dwarf* - dwarf() const - {return dwarf_;} - - /// Return the alternate debug info we are looking at. - /// - /// Note that "alternate debug info sections" is a GNU extension as - /// of DWARF4 and is described at - /// http://www.dwarfstd.org/ShowIssue.php?issue=120604.1 - /// - /// @return the alternate debug info. - Dwarf* - alt_dwarf() const - {return alt_dwarf_;} - /// Return the correct debug info, depending on the DIE source we /// are looking at. /// /// @param source the DIE source to consider. /// /// @return the right debug info, depending on @p source. - Dwarf* + const Dwarf* dwarf_per_die_source(die_source source) const { - Dwarf *result = 0; + const Dwarf *result = 0; switch(source) { case PRIMARY_DEBUG_INFO_DIE_SOURCE: case TYPE_UNIT_DIE_SOURCE: - result = dwarf(); + result = dwarf_debug_info(); break; case ALT_DEBUG_INFO_DIE_SOURCE: - result = alt_dwarf(); + result = alternate_dwarf_debug_info(); break; case NO_DEBUG_INFO_DIE_SOURCE: case NUMBER_OF_DIE_SOURCES: @@ -2730,25 +2429,12 @@ public: return result; } - /// Return the path to the alternate debug info as contained in the - /// .gnu_debugaltlink section of the main elf file. - /// - /// Note that "alternate debug info sections" is a GNU extension as - /// of DWARF4 and is described at - /// http://www.dwarfstd.org/ShowIssue.php?issue=120604.1 - /// - /// @return the path to the alternate debug info file, or an empty - /// path if no alternate debug info file is associated. - const string& - alt_debug_info_path() const - {return alt_debug_info_path_;} - /// Return the path to the ELF path we are reading. /// /// @return the elf path. const string& elf_path() const - {return elf_path_;} + {return corpus_path();} const Dwarf_Die* cur_tu_die() const @@ -2815,9 +2501,9 @@ public: { offset_offset_map_type &canonical_dies = die_as_type - ? const_cast(this)->canonical_type_die_offsets_. + ? const_cast(this)->canonical_type_die_offsets_. get_container(*this, die) - : const_cast(this)->canonical_decl_die_offsets_. + : const_cast(this)->canonical_decl_die_offsets_. get_container(*this, die); Dwarf_Die canonical_die; @@ -2882,13 +2568,14 @@ public: // with a vector of offsets of potentially equivalent DIEs. istring_dwarf_offsets_map_type& map = die_as_type - ? (const_cast(this)-> + ? (const_cast(this)-> type_die_repr_die_offsets_maps().get_container(source)) - : (const_cast(this)-> + : (const_cast(this)-> decl_die_repr_die_offsets_maps().get_container(source)); Dwarf_Die die; - ABG_ASSERT(dwarf_offdie(dwarf_per_die_source(source), die_offset, &die)); + ABG_ASSERT(dwarf_offdie(const_cast(dwarf_per_die_source(source)), + die_offset, &die)); // The variable repr is the the string representation of 'die'. // @@ -2963,9 +2650,9 @@ public: offset_offset_map_type &canonical_dies = die_as_type - ? const_cast(this)->canonical_type_die_offsets_. + ? const_cast(this)->canonical_type_die_offsets_. get_container(source) - : const_cast(this)->canonical_decl_die_offsets_. + : const_cast(this)->canonical_decl_die_offsets_. get_container(source); Dwarf_Off die_offset = dwarf_dieoffset(const_cast(die)); @@ -2980,9 +2667,9 @@ public: // with a vector of offsets of potentially equivalent DIEs. istring_dwarf_offsets_map_type& map = die_as_type - ? (const_cast(this)-> + ? (const_cast(this)-> type_die_repr_die_offsets_maps().get_container(*this, die)) - : (const_cast(this)-> + : (const_cast(this)-> decl_die_repr_die_offsets_maps().get_container(*this, die)); // The variable repr is the the string representation of 'die'. @@ -3008,7 +2695,7 @@ public: cur_die_offset = *o; get_die_from_offset(source, cur_die_offset, &canonical_die); // compare die and canonical_die. - if (compare_dies_during_canonicalization(const_cast(*this), + if (compare_dies_during_canonicalization(const_cast(*this), die, &canonical_die, /*update_canonical_dies_on_the_fly=*/true)) { @@ -3055,9 +2742,9 @@ public: offset_offset_map_type &canonical_dies = die_as_type - ? const_cast(this)->canonical_type_die_offsets_. + ? const_cast(this)->canonical_type_die_offsets_. get_container(source) - : const_cast(this)->canonical_decl_die_offsets_. + : const_cast(this)->canonical_decl_die_offsets_. get_container(source); Dwarf_Off initial_die_offset = dwarf_dieoffset(const_cast(die)); @@ -3077,9 +2764,9 @@ public: // with a vector of offsets of potentially equivalent DIEs. istring_dwarf_offsets_map_type& map = die_as_type - ? (const_cast(this)-> + ? (const_cast(this)-> type_die_repr_die_offsets_maps().get_container(*this, die)) - : (const_cast(this)-> + : (const_cast(this)-> decl_die_repr_die_offsets_maps().get_container(*this, die)); // The variable repr is the the string representation of 'die'. @@ -3115,7 +2802,7 @@ public: Dwarf_Off die_offset = i->second[n]; get_die_from_offset(source, die_offset, &canonical_die); // compare die and canonical_die. - if (compare_dies_during_canonicalization(const_cast(*this), + if (compare_dies_during_canonicalization(const_cast(*this), die, &canonical_die, /*update_canonical_dies_on_the_fly=*/true)) { @@ -3198,10 +2885,10 @@ public: if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) { - Dwarf *die_dwarf = dwarf_cu_getdwarf(cu_die.cu); - if (dwarf() == die_dwarf) + const Dwarf *die_dwarf = dwarf_cu_getdwarf(cu_die.cu); + if (dwarf_debug_info() == die_dwarf) source = PRIMARY_DEBUG_INFO_DIE_SOURCE; - else if (alt_dwarf() == die_dwarf) + else if (alternate_dwarf_debug_info() == die_dwarf) source = ALT_DEBUG_INFO_DIE_SOURCE; else ABG_ASSERT_NOT_REACHED; @@ -3226,9 +2913,11 @@ public: get_die_from_offset(die_source source, Dwarf_Off offset, Dwarf_Die *die) const { if (source == TYPE_UNIT_DIE_SOURCE) - ABG_ASSERT(dwarf_offdie_types(dwarf_per_die_source(source), offset, die)); + ABG_ASSERT(dwarf_offdie_types(const_cast(dwarf_per_die_source(source)), + offset, die)); else - ABG_ASSERT(dwarf_offdie(dwarf_per_die_source(source), offset, die)); + ABG_ASSERT(dwarf_offdie(const_cast(dwarf_per_die_source(source)), + offset, die)); } public: @@ -3331,9 +3020,9 @@ public: if (i == map.end()) { - read_context& ctxt = *const_cast(this); - string qualified_name = die_qualified_name(ctxt, die, where_offset); - interned_string istr = env()->intern(qualified_name); + reader& rdr = *const_cast(this); + string qualified_name = die_qualified_name(rdr, die, where_offset); + interned_string istr = env().intern(qualified_name); map[die_offset] = istr; return istr; } @@ -3356,7 +3045,7 @@ public: interned_string get_die_qualified_name(Dwarf_Die *die, size_t where_offset) const { - return const_cast(this)-> + return const_cast(this)-> get_die_qualified_name(die, where_offset); } @@ -3384,10 +3073,10 @@ public: // The name of the translation unit die is "". if (die == cur_tu_die()) - return env()->intern(""); + return env().intern(""); die_istring_map_type& map = - die_qualified_name_maps_.get_container(*const_cast(this), + die_qualified_name_maps_.get_container(*const_cast(this), die); size_t die_offset = dwarf_dieoffset(const_cast(die)); @@ -3396,7 +3085,7 @@ public: if (i == map.end()) { - read_context& ctxt = *const_cast(this); + reader& rdr = *const_cast(this); string qualified_name; int tag = dwarf_tag(const_cast(die)); if ((tag == DW_TAG_structure_type @@ -3410,9 +3099,9 @@ public: } else qualified_name = - die_qualified_type_name(ctxt, die, where_offset); + die_qualified_type_name(rdr, die, where_offset); - interned_string istr = env()->intern(qualified_name); + interned_string istr = env().intern(qualified_name); map[die_offset] = istr; return istr; } @@ -3442,7 +3131,7 @@ public: { ABG_ASSERT(die); die_istring_map_type& map = - die_pretty_type_repr_maps_.get_container(*const_cast(this), + die_pretty_type_repr_maps_.get_container(*const_cast(this), die); size_t die_offset = dwarf_dieoffset(const_cast(die)); @@ -3450,10 +3139,10 @@ public: if (i == map.end()) { - read_context& ctxt = *const_cast(this); + reader& rdr = *const_cast(this); string pretty_representation = - die_pretty_print_type(ctxt, die, where_offset); - interned_string istr = env()->intern(pretty_representation); + die_pretty_print_type(rdr, die, where_offset); + interned_string istr = env().intern(pretty_representation); map[die_offset] = istr; return istr; } @@ -3479,7 +3168,7 @@ public: ABG_ASSERT(die); die_istring_map_type& map = - die_pretty_repr_maps_.get_container(*const_cast(this), + die_pretty_repr_maps_.get_container(*const_cast(this), die); size_t die_offset = dwarf_dieoffset(const_cast(die)); @@ -3487,10 +3176,10 @@ public: if (i == map.end()) { - read_context& ctxt = *const_cast(this); + reader& rdr = *const_cast(this); string pretty_representation = - die_pretty_print(ctxt, die, where_offset); - interned_string istr = env()->intern(pretty_representation); + die_pretty_print(rdr, die, where_offset); + interned_string istr = env().intern(pretty_representation); map[die_offset] = istr; return istr; } @@ -3704,7 +3393,8 @@ public: odr_is_relevant(Dwarf_Off die_offset, die_source source) const { Dwarf_Die die; - ABG_ASSERT(dwarf_offdie(dwarf_per_die_source(source), die_offset, &die)); + ABG_ASSERT(dwarf_offdie(const_cast(dwarf_per_die_source(source)), + die_offset, &die)); return odr_is_relevant(&die); } @@ -3862,9 +3552,9 @@ public: { offset_offset_map_type &canonical_dies = die_as_type - ? const_cast(this)->canonical_type_die_offsets_. + ? const_cast(this)->canonical_type_die_offsets_. get_container(source) - : const_cast(this)->canonical_decl_die_offsets_. + : const_cast(this)->canonical_decl_die_offsets_. get_container(source); set_canonical_die_offset(canonical_dies, @@ -3932,9 +3622,9 @@ public: { offset_offset_map_type &canonical_dies = die_as_type - ? const_cast(this)->canonical_type_die_offsets_. + ? const_cast(this)->canonical_type_die_offsets_. get_container(source) - : const_cast(this)->canonical_decl_die_offsets_. + : const_cast(this)->canonical_decl_die_offsets_. get_container(source); return get_canonical_die_offset(canonical_dies, die_offset); @@ -3958,9 +3648,9 @@ public: { offset_offset_map_type &canonical_dies = die_as_type - ? const_cast(this)->canonical_type_die_offsets_. + ? const_cast(this)->canonical_type_die_offsets_. get_container(source) - : const_cast(this)->canonical_decl_die_offsets_. + : const_cast(this)->canonical_decl_die_offsets_. get_container(source); return canonical_dies.erase(die_offset); @@ -3999,7 +3689,7 @@ public: /// /// Note that the DIE must have been associated to type by a /// previous invocation of the function - /// read_context::associate_die_to_type(). + /// reader::associate_die_to_type(). /// /// @param die the DIE to consider. /// @@ -4020,7 +3710,7 @@ public: /// /// Note that the DIE must have been associated to type by a /// previous invocation of the function - /// read_context::associate_die_to_type(). + /// reader::associate_die_to_type(). /// /// @param die_offset the offset of the DIE to consider. /// @@ -4076,7 +3766,7 @@ public: /// built. const die_class_or_union_map_type& die_wip_classes_map(die_source source) const - {return const_cast(this)->die_wip_classes_map(source);} + {return const_cast(this)->die_wip_classes_map(source);} /// Getter of a map that associates a die that represents a /// class/struct with the declaration of the class, while the class @@ -4113,7 +3803,7 @@ public: /// @return the map of wip function types. const die_function_type_map_type& die_wip_function_types_map(die_source source) const - {return const_cast(this)->die_wip_function_types_map(source);} + {return const_cast(this)->die_wip_function_types_map(source);} /// Getter for a map that associates a die (that represents a /// function type) whith a function type, while the function type is @@ -4262,16 +3952,16 @@ public: if (!l || !r) return !!l == !!r; - const environment* e = l->get_environment(); - ABG_ASSERT(!e->canonicalization_is_done()); + const environment& e = l->get_environment(); + ABG_ASSERT(!e.canonicalization_is_done()); - e->priv_->allow_type_comparison_results_caching(true); - bool s0 = e->decl_only_class_equals_definition(); - e->decl_only_class_equals_definition(true); + e.priv_->allow_type_comparison_results_caching(true); + bool s0 = e.decl_only_class_equals_definition(); + e.decl_only_class_equals_definition(true); bool equal = l == r; - e->decl_only_class_equals_definition(s0); - e->priv_->clear_type_comparison_results_cache(); - e->priv_->allow_type_comparison_results_caching(false); + e.decl_only_class_equals_definition(s0); + e.priv_->clear_type_comparison_results_cache(); + e.priv_->allow_type_comparison_results_caching(false); return equal; } @@ -4329,7 +4019,7 @@ public: // So get the classes that might define the current // declarations which name is i->first. const type_base_wptrs_type *classes = - lookup_class_types(i->first, *current_corpus()); + lookup_class_types(i->first, *corpus()); if (!classes) continue; @@ -4565,7 +4255,7 @@ public: // So get the enums that might define the current // declarations which name is i->first. const type_base_wptrs_type *enums = - lookup_enum_types(i->first, *current_corpus()); + lookup_enum_types(i->first, *corpus()); if (!enums) continue; @@ -4694,7 +4384,7 @@ public: bool symbol_already_belongs_to_a_function(elf_symbol_sptr& fn) { - corpus_sptr corp = current_corpus(); + corpus_sptr corp = corpus(); if (!corp) return false; @@ -4732,7 +4422,7 @@ public: void fixup_functions_with_no_symbols() { - corpus_sptr corp = current_corpus(); + corpus_sptr corp = corpus(); if (!corp) return; @@ -4816,7 +4506,7 @@ public: /// Canonicalize types which DIE offsets are stored in vectors on /// the side. This is a sub-routine of - /// read_context::perform_late_type_canonicalizing(). + /// reader::perform_late_type_canonicalizing(). /// /// @param source where the DIE of the types to canonicalize are /// from. @@ -4827,9 +4517,9 @@ public: if (do_log()) { cerr << "going to canonicalize types"; - corpus_sptr c = current_corpus(); + corpus_sptr c = corpus(); if (c) - cerr << " of corpus " << current_corpus()->get_path(); + cerr << " of corpus " << corpus()->get_path(); cn_timer.start(); } @@ -4850,7 +4540,7 @@ public: cerr << "canonicalizing type " << get_pretty_representation(*it, false) << " [" << i << "/" << total << "]"; - if (corpus_sptr c = current_corpus()) + if (corpus_sptr c = corpus()) cerr << "@" << c->get_path(); cerr << " ..."; single_type_cn_timer.start(); @@ -4870,9 +4560,9 @@ public: { cn_timer.stop(); cerr << "finished canonicalizing types"; - corpus_sptr c = current_corpus(); + corpus_sptr c = corpus(); if (c) - cerr << " of corpus " << current_corpus()->get_path(); + cerr << " of corpus " << corpus()->get_path(); cerr << ": (" << cn_timer << ")\n"; } } @@ -4948,7 +4638,7 @@ public: /// @return the map. const tu_die_imported_unit_points_map_type& tu_die_imported_unit_points_map(die_source source) const - {return const_cast(this)->tu_die_imported_unit_points_map(source);} + {return const_cast(this)->tu_die_imported_unit_points_map(source);} /// Getter for the map that associates a translation unit DIE to the /// vector of imported unit points that it contains. @@ -4975,127 +4665,12 @@ public: return tu_die_imported_unit_points_map_; } - /// Getter of the current corpus being constructed. - /// - /// @return the current corpus. - const corpus_sptr - current_corpus() const - {return cur_corpus_;} - - /// Getter of the current corpus being constructed. - /// - /// @return the current corpus. - corpus_sptr - current_corpus() - {return cur_corpus_;} - - /// Setter of the current corpus being constructed. - /// - /// @param c the new corpus. - void - current_corpus(const corpus_sptr& c) - { - if (c) - cur_corpus_ = c; - } - /// Reset the current corpus being constructed. /// /// This actually deletes the current corpus being constructed. void - reset_current_corpus() - {cur_corpus_.reset();} - - /// Getter of the current corpus group being constructed. - /// - /// @return current the current corpus being constructed, if any, or - /// nil. - const corpus_group_sptr - current_corpus_group() const - {return cur_corpus_group_;} - - /// Getter of the current corpus group being constructed. - /// - /// @return current the current corpus being constructed, if any, or - /// nil. - corpus_group_sptr - current_corpus_group() - {return cur_corpus_group_;} - - /// Setter of the current corpus group being constructed. - /// - /// @param g the new corpus group. - void - current_corpus_group(const corpus_group_sptr& g) - { - if (g) - cur_corpus_group_ = g; - } - - /// Test if there is a corpus group being built. - /// - /// @return if there is a corpus group being built, false otherwise. - bool - has_corpus_group() const - {return bool(cur_corpus_group_);} - - /// Return the main corpus from the current corpus group, if any. - /// - /// @return the main corpus of the current corpus group, if any, nil - /// if no corpus group is being constructed. - corpus_sptr - main_corpus_from_current_group() - { - if (cur_corpus_group_) - return cur_corpus_group_->get_main_corpus(); - return corpus_sptr(); - } - - /// Return the main corpus from the current corpus group, if any. - /// - /// @return the main corpus of the current corpus group, if any, nil - /// if no corpus group is being constructed. - const corpus_sptr - main_corpus_from_current_group() const - {return const_cast(this)->main_corpus_from_current_group();} - - /// Test if the current corpus being built is the main corpus of the - /// current corpus group. - /// - /// @return return true iff the current corpus being built is the - /// main corpus of the current corpus group. - bool - current_corpus_is_main_corpus_from_current_group() const - { - corpus_sptr main_corpus = main_corpus_from_current_group(); - - if (main_corpus && main_corpus.get() == cur_corpus_.get()) - return true; - - return false; - } - - /// Return true if the current corpus is part of a corpus group - /// being built and if it's not the main corpus of the group. - /// - /// For instance, this would return true if we are loading a linux - /// kernel *module* that is part of the current corpus group that is - /// being built. In this case, it means we should re-use types - /// coming from the "vmlinux" binary that is the main corpus of the - /// group. - /// - /// @return the corpus group the current corpus belongs to, if the - /// current corpus is part of a corpus group being built. Nil otherwise. - corpus_sptr - should_reuse_type_from_corpus_group() const - { - if (has_corpus_group() && is_c_language(cur_transl_unit()->get_language())) - if (corpus_sptr main_corpus = main_corpus_from_current_group()) - if (!current_corpus_is_main_corpus_from_current_group()) - return current_corpus_group(); - - return corpus_sptr(); - } + reset_corpus() + {corpus().reset();} /// Get the map that associates each DIE to its parent DIE. This is /// for DIEs coming from the main debug info sections. @@ -5105,7 +4680,7 @@ public: /// @return the DIE -> parent map. const offset_offset_map_type& die_parent_map(die_source source) const - {return const_cast(this)->die_parent_map(source);} + {return const_cast(this)->die_parent_map(source);} /// Get the map that associates each DIE to its parent DIE. This is /// for DIEs coming from the main debug info sections. @@ -5210,11 +4785,7 @@ public: /// @return the symbol table section if found Elf_Scn* find_symbol_table_section() const - { - if (!symtab_section_) - symtab_section_ = elf_helpers::find_symbol_table_section(elf_handle()); - return symtab_section_; - } + {return find_symbol_table_section();} /// Lookup an elf symbol, referred to by its index, from the .symtab /// section. @@ -5245,70 +4816,6 @@ public: return true; } - /// Test if a given function symbol has been exported. - /// - /// @param symbol_address the address of the symbol we are looking - /// for. Note that this address must be a relative offset from the - /// beginning of the .text section, just like the kind of addresses - /// that are present in the .symtab section. - /// - /// @returnthe elf symbol if found, or nil otherwise. - elf_symbol_sptr - function_symbol_is_exported(GElf_Addr symbol_address) const - { - elf_symbol_sptr symbol = symtab()->lookup_symbol(symbol_address); - if (!symbol) - return symbol; - - if (!symbol->is_function() || !symbol->is_public()) - return elf_symbol_sptr(); - - address_set_sptr set; - bool looking_at_linux_kernel_binary = - load_in_linux_kernel_mode() && is_linux_kernel(elf_handle()); - - if (looking_at_linux_kernel_binary) - { - if (symbol->is_in_ksymtab()) - return symbol; - return elf_symbol_sptr(); - } - - return symbol; - } - - /// Test if a given variable symbol has been exported. - /// - /// @param symbol_address the address of the symbol we are looking - /// for. Note that this address must be a relative offset from the - /// beginning of the .text section, just like the kind of addresses - /// that are present in the .symtab section. - /// - /// @returnthe elf symbol if found, or nil otherwise. - elf_symbol_sptr - variable_symbol_is_exported(GElf_Addr symbol_address) const - { - elf_symbol_sptr symbol = symtab()->lookup_symbol(symbol_address); - if (!symbol) - return symbol; - - if (!symbol->is_variable() || !symbol->is_public()) - return elf_symbol_sptr(); - - address_set_sptr set; - bool looking_at_linux_kernel_binary = - load_in_linux_kernel_mode() && is_linux_kernel(elf_handle()); - - if (looking_at_linux_kernel_binary) - { - if (symbol->is_in_ksymtab()) - return symbol; - return elf_symbol_sptr(); - } - - return symbol; - } - /// Test if a DIE represents a decl (function or variable) that has /// a symbol that is exported, whatever that means. This is /// supposed to work for Linux Kernel binaries as well. @@ -5347,94 +4854,6 @@ public: return result; } - /// Getter for the symtab reader. Will load the symtab from the elf handle if - /// not yet set. - /// - /// @return a shared pointer to the symtab object - const symtab_reader::symtab_sptr& - symtab() const - { - if (!symtab_) - symtab_ = symtab_reader::symtab::load - (elf_handle(), options_.env, - [&](const elf_symbol_sptr& symbol) - {return is_elf_symbol_suppressed(symbol);}); - - if (!symtab_) - std::cerr << "Symbol table of '" << elf_path_ - << "' could not be loaded\n"; - return symtab_; - } - - /// Getter for the ELF dt_needed tag. - const vector& - dt_needed() const - {return dt_needed_;} - - /// Getter for the ELF dt_soname tag. - const string& - dt_soname() const - {return dt_soname_;} - - /// Getter for the ELF architecture of the current file. - const string& - elf_architecture() const - {return elf_architecture_;} - - /// Test if a given ELF symbol was suppressed by a suppression - /// specification. - /// - /// @param symbol the ELF symbol to consider. - /// - /// @return true iff @p symbol is suppressed. - bool - is_elf_symbol_suppressed(const elf_symbol_sptr& symbol) const - { - return (symbol - && suppr::is_elf_symbol_suppressed(*this, - symbol->get_name(), - symbol->get_type())); - } - - /// Load the DT_NEEDED and DT_SONAME elf TAGS. - /// - void - load_dt_soname_and_needed() - { - lookup_data_tag_from_dynamic_segment(elf_handle(), DT_NEEDED, dt_needed_); - - vector dt_tag_data; - lookup_data_tag_from_dynamic_segment(elf_handle(), DT_SONAME, dt_tag_data); - if (!dt_tag_data.empty()) - dt_soname_ = dt_tag_data[0]; - } - - /// Read the string representing the architecture of the current ELF - /// file. - void - load_elf_architecture() - { - if (!elf_handle()) - return; - - GElf_Ehdr eh_mem; - GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem); - - elf_architecture_ = e_machine_to_string(elf_header->e_machine); - } - - /// Load various ELF data. - /// - /// This function loads ELF data that are not symbol maps or debug - /// info. That is, things like various tags, elf architecture and - /// so on. - void - load_elf_properties() - { - load_dt_soname_and_needed(); - load_elf_architecture(); - } - /// This is a sub-routine of maybe_adjust_fn_sym_address and /// maybe_adjust_var_sym_address. /// @@ -5660,150 +5079,13 @@ public: get_variable_address(const Dwarf_Die* variable_die, Dwarf_Addr& address) const { - bool is_tls_address = false; - if (!die_location_address(const_cast(variable_die), - address, is_tls_address)) - return false; - if (!is_tls_address) - address = maybe_adjust_var_sym_address(address); - return true; - } - - /// Tests if a suppression specification can match ABI artifacts - /// coming from the binary being analyzed. - /// - /// This tests if the suppression can match the soname of and binary - /// name of the ELF binary being analyzed. More precisely, if there - /// are any soname or file name property in the suppression and if - /// those do *NOT* match the current binary, then the function - /// returns false. - /// - /// @param s the suppression specification to consider. - /// - /// @return true iff either there are no soname/filename related - /// property on the suppression, or if none of the soname/filename - /// properties of the suppression match the current binary. - bool - suppression_can_match(const suppr::suppression_base& s) const - { - if (!s.priv_->matches_soname(dt_soname())) - if (s.has_soname_related_property()) - // The suppression has some SONAME related properties, but - // none of them match the SONAME of the current binary. So - // the suppression cannot match the current binary. - return false; - - if (!s.priv_->matches_binary_name(elf_path())) - if (s.has_file_name_related_property()) - // The suppression has some file_name related properties, but - // none of them match the file name of the current binary. So - // the suppression cannot match the current binary. - return false; - - return true; - } - - /// Test whether if a given function suppression matches a function - /// designated by a regular expression that describes its linkage - /// name (symbol name). - /// - /// @param s the suppression specification to evaluate to see if it - /// matches a given function linkage name - /// - /// @param fn_linkage_name the linkage name of the function of interest. - /// - /// @return true iff the suppression specification @p s matches the - /// function whose linkage name is @p fn_linkage_name. - bool - suppression_matches_function_sym_name(const suppr::function_suppression& s, - const string& fn_linkage_name) const - { - if (!suppression_can_match(s)) - return false; - - return suppr::suppression_matches_function_sym_name(s, fn_linkage_name); - } - - /// Test whether if a given function suppression matches a function - /// designated by a regular expression that describes its name. - /// - /// @param s the suppression specification to evaluate to see if it - /// matches a given function name. - /// - /// @param fn_name the name of the function of interest. Note that - /// this name must be *non* qualified. - /// - /// @return true iff the suppression specification @p s matches the - /// function whose name is @p fn_name. - bool - suppression_matches_function_name(const suppr::function_suppression& s, - const string& fn_name) const - { - if (!suppression_can_match(s)) - return false; - - return suppr::suppression_matches_function_name(s, fn_name); - } - - /// Test whether if a given variable suppression specification - /// matches a variable denoted by its name. - /// - /// @param s the variable suppression specification to consider. - /// - /// @param var_name the name of the variable to consider. - /// - /// @return true iff the suppression specification @p s matches the - /// variable whose name is @p var_name. - bool - suppression_matches_variable_name(const suppr::variable_suppression& s, - const string& var_name) const - { - if (!suppression_can_match(s)) - return false; - - return suppr::suppression_matches_variable_name(s, var_name); - } - - /// Test whether if a given variable suppression specification - /// matches a variable denoted by its linkage name. - /// - /// @param s the variable suppression specification to consider. - /// - /// @param var_linkage_name the linkage name of the variable to consider. - /// - /// @return true iff variable suppression specification @p s matches - /// the variable denoted by linkage name @p var_linkage_name. - bool - suppression_matches_variable_sym_name(const suppr::variable_suppression& s, - const string& var_linkage_name) const - { - if (!suppression_can_match(s)) - return false; - - return suppr::suppression_matches_variable_sym_name(s, var_linkage_name); - } - - /// Test if a given type suppression specification matches a type - /// designated by its name and location. - /// - /// @param s the suppression specification to consider. - /// - /// @param type_name the fully qualified type name to consider. - /// - /// @param type_location the type location to consider. - /// - /// @return true iff the type suppression specification matches a - /// type of a given name and location. - bool - suppression_matches_type_name_or_location(const suppr::type_suppression& s, - const string& type_name, - const location& type_location) const - { - if (!suppression_can_match(s)) + bool is_tls_address = false; + if (!die_location_address(const_cast(variable_die), + address, is_tls_address)) return false; - - return suppr::suppression_matches_type_name_or_location(s, type_name, - type_location); + if (!is_tls_address) + address = maybe_adjust_var_sym_address(address); + return true; } /// Getter of the exported decls builder object. @@ -5811,17 +5093,7 @@ public: /// @return the exported decls builder. corpus::exported_decls_builder* exported_decls_builder() - {return exported_decls_builder_;} - - /// Setter of the exported decls builder object. - /// - /// Note that this @ref read_context is not responsible for the live - /// time of the exported_decls_builder object. The corpus is. - /// - /// @param b the new builder. - void - exported_decls_builder(corpus::exported_decls_builder* b) - {exported_decls_builder_ = b;} + {return corpus()->get_exported_decls_builder().get();} /// Getter of the "load_all_types" flag. This flag tells if all the /// types (including those not reachable by public declarations) are @@ -5830,7 +5102,7 @@ public: /// @return the load_all_types flag. bool load_all_types() const - {return options_.load_all_types;} + {return options().load_all_types;} /// Setter of the "load_all_types" flag. This flag tells if all the /// types (including those not reachable by public declarations) are @@ -5839,15 +5111,15 @@ public: /// @param f the new load_all_types flag. void load_all_types(bool f) - {options_.load_all_types = f;} + {options().load_all_types = f;} bool load_in_linux_kernel_mode() const - {return options_.load_in_linux_kernel_mode;} + {return options().load_in_linux_kernel_mode;} void load_in_linux_kernel_mode(bool f) - {options_.load_in_linux_kernel_mode = f;} + {options().load_in_linux_kernel_mode = f;} /// Getter of the "show_stats" flag. /// @@ -5857,7 +5129,7 @@ public: /// @return the value of the flag. bool show_stats() const - {return options_.show_stats;} + {return options().show_stats;} /// Setter of the "show_stats" flag. /// @@ -5867,7 +5139,7 @@ public: /// @param f the value of the flag. void show_stats(bool f) - {options_.show_stats = f;} + {options().show_stats = f;} /// Getter of the "do_log" flag. /// @@ -5877,7 +5149,7 @@ public: /// return the "do_log" flag. bool do_log() const - {return options_.do_log;} + {return options().do_log;} /// Setter of the "do_log" flag. /// @@ -5886,35 +5158,7 @@ public: /// @param f the new value of the flag. void do_log(bool f) - {options_.do_log = f;} - - /// If a given function decl is suitable for the set of exported - /// functions of the current corpus, this function adds it to that - /// set. - /// - /// @param fn the function to consider for inclusion into the set of - /// exported functions of the current corpus. - void - maybe_add_fn_to_exported_decls(function_decl* fn) - { - if (fn) - if (corpus::exported_decls_builder* b = exported_decls_builder()) - b->maybe_add_fn_to_exported_fns(fn); - } - - /// If a given variable decl is suitable for the set of exported - /// variables of the current corpus, this variable adds it to that - /// set. - /// - /// @param fn the variable to consider for inclusion into the set of - /// exported variables of the current corpus. - void - maybe_add_var_to_exported_decls(var_decl* var) - { - if (var) - if (corpus::exported_decls_builder* b = exported_decls_builder()) - b->maybe_add_var_to_exported_vars(var); - } + {options().do_log = f;} /// Walk the DIEs under a given die and for each child, populate the /// die -> parent map to record the child -> parent relationship @@ -6047,13 +5291,15 @@ public: // the global namespace so we don't need to build the DIE -> // parent map. So we dont build it in that case. for (Dwarf_Off offset = 0, next_offset = 0; - (dwarf_next_unit(dwarf(), offset, &next_offset, &header_size, + (dwarf_next_unit(const_cast(dwarf_debug_info()), + offset, &next_offset, &header_size, NULL, NULL, &address_size, NULL, NULL, NULL) == 0); offset = next_offset) { Dwarf_Off die_offset = offset + header_size; Dwarf_Die cu; - if (!dwarf_offdie(dwarf(), die_offset, &cu)) + if (!dwarf_offdie(const_cast(dwarf_debug_info()), + die_offset, &cu)) continue; uint64_t l = 0; @@ -6070,13 +5316,15 @@ public: // .debug_info section in the alternate debug info file. die_source source = ALT_DEBUG_INFO_DIE_SOURCE; for (Dwarf_Off offset = 0, next_offset = 0; - (dwarf_next_unit(alt_dwarf(), offset, &next_offset, &header_size, + (dwarf_next_unit(const_cast(alternate_dwarf_debug_info()), + offset, &next_offset, &header_size, NULL, NULL, &address_size, NULL, NULL, NULL) == 0); offset = next_offset) { Dwarf_Off die_offset = offset + header_size; Dwarf_Die cu; - if (!dwarf_offdie(alt_dwarf(), die_offset, &cu)) + if (!dwarf_offdie(const_cast(alternate_dwarf_debug_info()), + die_offset, &cu)) continue; cur_tu_die(&cu); @@ -6092,13 +5340,15 @@ public: address_size = 0; header_size = 0; for (Dwarf_Off offset = 0, next_offset = 0; - (dwarf_next_unit(dwarf(), offset, &next_offset, &header_size, + (dwarf_next_unit(const_cast(dwarf_debug_info()), + offset, &next_offset, &header_size, NULL, NULL, &address_size, NULL, NULL, NULL) == 0); offset = next_offset) { Dwarf_Off die_offset = offset + header_size; Dwarf_Die cu; - if (!dwarf_offdie(dwarf(), die_offset, &cu)) + if (!dwarf_offdie(const_cast(dwarf_debug_info()), + die_offset, &cu)) continue; cur_tu_die(&cu); imported_unit_points_type& imported_units = @@ -6115,7 +5365,8 @@ public: uint64_t type_signature = 0; Dwarf_Off type_offset; for (Dwarf_Off offset = 0, next_offset = 0; - (dwarf_next_unit(dwarf(), offset, &next_offset, &header_size, + (dwarf_next_unit(const_cast(dwarf_debug_info()), + offset, &next_offset, &header_size, NULL, NULL, &address_size, NULL, &type_signature, &type_offset) == 0); offset = next_offset) @@ -6123,7 +5374,8 @@ public: Dwarf_Off die_offset = offset + header_size; Dwarf_Die cu; - if (!dwarf_offdie_types(dwarf(), die_offset, &cu)) + if (!dwarf_offdie_types(const_cast(dwarf_debug_info()), + die_offset, &cu)) continue; cur_tu_die(&cu); imported_unit_points_type& imported_units = @@ -6132,7 +5384,7 @@ public: build_die_parent_relations_under(&cu, source, imported_units); } } -};// end class read_context. +};// end class reader. /// The type of the aggregates being compared during a DIE comparison. /// @@ -6146,8 +5398,8 @@ public: /// that takes place during the canonicalization struct offset_pairs_stack_type { - // The DWARF read context that is useful for so many things. - const read_context& ctxt_; + // The DWARF DWARF reader that is useful for so many things. + const reader& rdr_; // The set of types that are being compared. This is to speed up // searches. offset_pair_set_type set_; @@ -6161,8 +5413,8 @@ struct offset_pairs_stack_type // types it depends on. offset_pair_vect_map_type dependant_types_; - offset_pairs_stack_type(const read_context& ctxt) - : ctxt_ (ctxt) + offset_pairs_stack_type(const reader& rdr) + : rdr_ (rdr) {} /// Add a pair of types being compared to the stack of aggregates @@ -6377,13 +5629,13 @@ struct offset_pairs_stack_type if (dependant_types_it->second.empty()) { if (erase_cached_results) - ctxt_.die_comparison_results_.erase(dependant_type); + rdr_.die_comparison_results_.erase(dependant_type); dependant_types_.erase(dependant_types_it); } } } if (erase_cached_results) - ctxt_.die_comparison_results_.erase(p); + rdr_.die_comparison_results_.erase(p); redundant_types_.erase(p); } @@ -6414,32 +5666,32 @@ struct offset_pairs_stack_type { // If this dependant type was canonical-type-propagated then // erase that canonical type. - if (ctxt_.propagated_types_.find(dependant_type) - != ctxt_.propagated_types_.end()) + if (rdr_.propagated_types_.find(dependant_type) + != rdr_.propagated_types_.end()) { - ctxt_.erase_canonical_die_offset(dependant_type.first.offset_, + rdr_.erase_canonical_die_offset(dependant_type.first.offset_, dependant_type.first.source_, /*die_as_type=*/true); - ctxt_.propagated_types_.erase(dependant_type); - ctxt_.cancelled_propagation_count_++; + rdr_.propagated_types_.erase(dependant_type); + rdr_.cancelled_propagation_count_++; } // Update the cached result. We know the comparison result // must now be different. - auto comp_result_it = ctxt_.die_comparison_results_.find(p); - if (comp_result_it != ctxt_.die_comparison_results_.end()) + auto comp_result_it = rdr_.die_comparison_results_.find(p); + if (comp_result_it != rdr_.die_comparison_results_.end()) { ABG_ASSERT(comp_result_it->second == COMPARISON_RESULT_UNKNOWN); comp_result_it->second= COMPARISON_RESULT_DIFFERENT; } } - if (ctxt_.propagated_types_.find(p) != ctxt_.propagated_types_.end()) + if (rdr_.propagated_types_.find(p) != rdr_.propagated_types_.end()) { - ctxt_.erase_canonical_die_offset(p.first.offset_, + rdr_.erase_canonical_die_offset(p.first.offset_, p.first.source_, /*die_as_type=*/true); - ctxt_.propagated_types_.erase(p); - ctxt_.cancelled_propagation_count_++; + rdr_.propagated_types_.erase(p); + rdr_.cancelled_propagation_count_++; } } @@ -6477,7 +5729,7 @@ struct offset_pairs_stack_type }; // end struct offset_pairs_stack_type static type_or_decl_base_sptr -build_ir_node_from_die(read_context& ctxt, +build_ir_node_from_die(reader& rdr, Dwarf_Die* die, scope_decl* scope, bool called_from_public_decl, @@ -6486,13 +5738,13 @@ build_ir_node_from_die(read_context& ctxt, bool is_required_decl_spec = false); static type_or_decl_base_sptr -build_ir_node_from_die(read_context& ctxt, +build_ir_node_from_die(reader& rdr, Dwarf_Die* die, bool called_from_public_decl, size_t where_offset); static class_decl_sptr -add_or_update_class_type(read_context& ctxt, +add_or_update_class_type(reader& rdr, Dwarf_Die* die, scope_decl* scope, bool is_struct, @@ -6502,7 +5754,7 @@ add_or_update_class_type(read_context& ctxt, bool is_declaration_only); static union_decl_sptr -add_or_update_union_type(read_context& ctxt, +add_or_update_union_type(reader& rdr, Dwarf_Die* die, scope_decl* scope, union_decl_sptr union_type, @@ -6511,25 +5763,25 @@ add_or_update_union_type(read_context& ctxt, bool is_declaration_only); static decl_base_sptr -build_ir_node_for_void_type(read_context& ctxt); +build_ir_node_for_void_type(reader& rdr); static decl_base_sptr -build_ir_node_for_variadic_parameter_type(read_context &ctxt); +build_ir_node_for_variadic_parameter_type(reader &rdr); static function_decl_sptr -build_function_decl(read_context& ctxt, +build_function_decl(reader& rdr, Dwarf_Die* die, size_t where_offset, function_decl_sptr fn); static bool -function_is_suppressed(const read_context& ctxt, +function_is_suppressed(const reader& rdr, const scope_decl* scope, Dwarf_Die *function_die, bool is_declaration_only); static function_decl_sptr -build_or_get_fn_decl_if_not_suppressed(read_context& ctxt, +build_or_get_fn_decl_if_not_suppressed(reader& rdr, scope_decl *scope, Dwarf_Die *die, size_t where_offset, @@ -6537,20 +5789,20 @@ build_or_get_fn_decl_if_not_suppressed(read_context& ctxt, function_decl_sptr f); static var_decl_sptr -build_var_decl(read_context& ctxt, +build_var_decl(reader& rdr, Dwarf_Die *die, size_t where_offset, var_decl_sptr result = var_decl_sptr()); static var_decl_sptr -build_or_get_var_decl_if_not_suppressed(read_context& ctxt, +build_or_get_var_decl_if_not_suppressed(reader& rdr, scope_decl *scope, Dwarf_Die *die, size_t where_offset, var_decl_sptr res = var_decl_sptr(), bool is_required_decl_spec = false); static bool -variable_is_suppressed(const read_context& ctxt, +variable_is_suppressed(const reader& rdr, const scope_decl* scope, Dwarf_Die *variable_die, bool is_required_decl_spec = false); @@ -6559,78 +5811,7 @@ static void finish_member_function_reading(Dwarf_Die* die, const function_decl_sptr& f, const class_or_union_sptr klass, - read_context& ctxt); - -/// 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 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 -/// internal stuff. -/// -/// @param ctx the read context to consider for this flag. -/// -/// @return the value of the flag. -bool -get_show_stats(read_context& ctxt) -{return ctxt.show_stats();} - -/// Setter of the "show_stats" flag. -/// -/// This flag tells if we should emit statistics about various -/// internal stuff. -/// -/// @param ctxt the read context to consider for this flag. -/// -/// @param f the value of the flag. -void -set_show_stats(read_context& ctxt, bool f) -{ctxt.show_stats(f);} - -/// Setter of the "drop_undefined_syms" flag. -/// -/// This flag tells if we should drop functions or variables -/// with undefined symbols. -/// -/// @param ctxt the read context to consider for this flag. -/// -/// @param f the value of the flag. -void -set_drop_undefined_syms(read_context& ctxt, bool f) -{ctxt.drop_undefined_syms(f);} - -/// Setter of the "do_log" flag. -/// -/// This flag tells if we should emit verbose logs for various -/// internal things related to DWARF reading. -/// -/// @param ctxt the DWARF reading context to consider. -/// -/// @param f the new value of the flag. -void -set_do_log(read_context& ctxt, bool f) -{ctxt.do_log(f);} - + reader& rdr); /// Test if a given DIE is anonymous /// @@ -6980,13 +6161,13 @@ die_address_attribute(Dwarf_Die* die, unsigned attr_name, Dwarf_Addr& result) /// Returns the source location associated with a decl DIE. /// -/// @param ctxt the @ref read_context to use. +/// @param rdr the @ref reader to use. /// /// @param die the DIE the read the source location from. /// /// @return the location associated with @p die. static location -die_location(const read_context& ctxt, const Dwarf_Die* die) +die_location(const reader& rdr, const Dwarf_Die* die) { if (!die) return location(); @@ -6997,7 +6178,7 @@ die_location(const read_context& ctxt, const Dwarf_Die* die) if (!file.empty() && line != 0) { - translation_unit_sptr tu = ctxt.cur_transl_unit(); + translation_unit_sptr tu = rdr.cur_transl_unit(); location l = tu->get_loc_mgr().create_new_location(file, line, 1); return l; } @@ -7018,7 +6199,7 @@ die_name(const Dwarf_Die* die) /// Return the location, the name and the mangled name of a given DIE. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DIE to read location and names from. /// @@ -7028,13 +6209,13 @@ die_name(const Dwarf_Die* die) /// /// @param linkage_name the linkage_name output parameter to set. static void -die_loc_and_name(const read_context& ctxt, +die_loc_and_name(const reader& rdr, Dwarf_Die* die, location& loc, string& name, string& linkage_name) { - loc = die_location(ctxt, die); + loc = die_location(rdr, die); name = die_name(die); linkage_name = die_linkage_name(die); } @@ -7150,7 +6331,7 @@ die_is_public_decl(const Dwarf_Die* die) /// @return true iff either the DIE is public or is a variable DIE /// that is at (global) namespace level. static bool -die_is_effectively_public_decl(const read_context& ctxt, +die_is_effectively_public_decl(const reader& rdr, const Dwarf_Die* die) { if (die_is_public_decl(die)) @@ -7162,7 +6343,7 @@ die_is_effectively_public_decl(const read_context& ctxt, // The DIE is a variable. Dwarf_Die parent_die; size_t where_offset = 0; - if (!get_parent_die(ctxt, die, parent_die, where_offset)) + if (!get_parent_die(rdr, die, parent_die, where_offset)) return false; tag = dwarf_tag(&parent_die); @@ -7402,7 +6583,7 @@ type_comparison_result_to_be_cached(unsigned tag) /// Cache the result of comparing to type DIEs. /// -/// @param ctxt the context to consider. +/// @param rdr the context to consider. /// /// @param tag the tag of the DIEs to consider. /// @@ -7410,7 +6591,7 @@ type_comparison_result_to_be_cached(unsigned tag) /// /// @param result the comparison result to be cached. static bool -maybe_cache_type_comparison_result(const read_context& ctxt, +maybe_cache_type_comparison_result(const reader& rdr, int tag, const offset_pair_type& p, comparison_result result) @@ -7420,7 +6601,7 @@ maybe_cache_type_comparison_result(const read_context& ctxt, && result != COMPARISON_RESULT_DIFFERENT)) return false; - ctxt.die_comparison_results_[p] = result; + rdr.die_comparison_results_[p] = result; return true; @@ -7428,7 +6609,7 @@ maybe_cache_type_comparison_result(const read_context& ctxt, /// Get the cached result of the comparison of a pair of DIEs. /// -/// @param ctxt the context to consider. +/// @param rdr the context to consider. /// /// @param tag the tag of the pair of DIEs to consider. /// @@ -7440,12 +6621,12 @@ maybe_cache_type_comparison_result(const read_context& ctxt, /// @return true iff a cached result for the comparisonof @p has been /// found and set into @p result. static bool -get_cached_type_comparison_result(const read_context& ctxt, +get_cached_type_comparison_result(const reader& rdr, const offset_pair_type& p, comparison_result& result) { - auto i = ctxt.die_comparison_results_.find(p); - if (i != ctxt.die_comparison_results_.end()) + auto i = rdr.die_comparison_results_.find(p); + if (i != rdr.die_comparison_results_.end()) { result = i->second; return true; @@ -7456,7 +6637,7 @@ get_cached_type_comparison_result(const read_context& ctxt, /// Get the cached result of the comparison of a pair of DIEs, if the /// kind of DIEs ought to have its comparison results cached. /// -/// @param ctxt the context to consider. +/// @param rdr the context to consider. /// /// @param tag the tag of the pair of DIEs to consider. /// @@ -7468,7 +6649,7 @@ get_cached_type_comparison_result(const read_context& ctxt, /// @return true iff a cached result for the comparisonof @p has been /// found and set into @p result. static bool -maybe_get_cached_type_comparison_result(const read_context& ctxt, +maybe_get_cached_type_comparison_result(const reader& rdr, int tag, const offset_pair_type& p, comparison_result& result) @@ -7478,7 +6659,7 @@ maybe_get_cached_type_comparison_result(const read_context& ctxt, // Types of this kind might have their comparison result cached // when they are not canonicalized. So let's see if we have a // cached comparison result. - if (get_cached_type_comparison_result(ctxt, p, result)) + if (get_cached_type_comparison_result(rdr, p, result)) return true; } return false; @@ -7878,7 +7059,7 @@ die_object_pointer_is_for_const_method(Dwarf_Die* die) /// Test if a DIE represents an entity that is at class scope. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DIE to consider. /// @@ -7892,12 +7073,12 @@ die_object_pointer_is_for_const_method(Dwarf_Die* die) /// class_scope_die is set to the DIE of the class that contains @p /// die. static bool -die_is_at_class_scope(const read_context& ctxt, +die_is_at_class_scope(const reader& rdr, const Dwarf_Die* die, size_t where_offset, Dwarf_Die& class_scope_die) { - if (!get_scope_die(ctxt, die, where_offset, class_scope_die)) + if (!get_scope_die(rdr, die, where_offset, class_scope_die)) return false; int tag = dwarf_tag(&class_scope_die); @@ -8028,7 +7209,7 @@ die_peel_pointer_and_typedef(const Dwarf_Die *die, Dwarf_Die& peeled_die) /// Test if a DIE for a function type represents a method type. /// -/// @param ctxt the read context. +/// @param rdr the DWARF reader. /// /// @param die the DIE to consider. /// @@ -8049,7 +7230,7 @@ die_peel_pointer_and_typedef(const Dwarf_Die *die, Dwarf_Die& peeled_die) /// /// @return true iff @p die is a DIE for a method type. static bool -die_function_type_is_method_type(const read_context& ctxt, +die_function_type_is_method_type(const reader& rdr, const Dwarf_Die *die, size_t where_offset, Dwarf_Die& object_pointer_die, @@ -8077,7 +7258,7 @@ die_function_type_is_method_type(const read_context& ctxt, has_object_pointer = true; else { - if (die_is_at_class_scope(ctxt, &spec_or_origin_die, + if (die_is_at_class_scope(rdr, &spec_or_origin_die, where_offset, class_die)) is_static = true; else @@ -8090,7 +7271,7 @@ die_function_type_is_method_type(const read_context& ctxt, has_object_pointer = true; else { - if (die_is_at_class_scope(ctxt, die, where_offset, class_die)) + if (die_is_at_class_scope(rdr, die, where_offset, class_die)) is_static = true; else return false; @@ -9441,14 +8622,14 @@ die_constant_data_member_location(const Dwarf_Die *die, /// the offset of the function in the vtable. In this case this /// function returns that constant. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the DIE to read the information from. /// /// @param offset the resulting constant offset, in bits. This /// argument is set iff the function returns true. static bool -die_member_offset(const read_context& ctxt, +die_member_offset(const reader& rdr, const Dwarf_Die* die, int64_t& offset) { @@ -9489,7 +8670,7 @@ die_member_offset(const read_context& ctxt, bool is_tls_address = false; if (!eval_last_constant_dwarf_sub_expr(expr, expr_len, offset, is_tls_address, - ctxt.dwarf_expr_eval_ctxt())) + rdr.dwarf_expr_eval_ctxt())) return false; } } @@ -9506,7 +8687,7 @@ die_member_offset(const read_context& ctxt, // offset of the bitfield data member it describes. For details // about the conversion, please read the extensive comments of // read_and_convert_DW_at_bit_offset. - bool is_big_endian = architecture_is_big_endian(ctxt.elf_handle()); + bool is_big_endian = architecture_is_big_endian(rdr.elf_handle()); if (read_and_convert_DW_at_bit_offset(die, is_big_endian, bit_offset)) offset += bit_offset; @@ -9725,7 +8906,7 @@ get_internal_anonymous_die_name(Dwarf_Die *die, /// For instance, if the DIE tag is DW_TAG_subprogram then this /// function computes the name of the function *type*. /// -/// @param ctxt the read context. +/// @param rdr the DWARF reader. /// /// @param die the DIE to consider. /// @@ -9734,7 +8915,7 @@ get_internal_anonymous_die_name(Dwarf_Die *die, /// /// @return a copy of the qualified name of the type. static string -die_qualified_type_name(const read_context& ctxt, +die_qualified_type_name(const reader& rdr, const Dwarf_Die* die, size_t where_offset) { @@ -9750,10 +8931,10 @@ die_qualified_type_name(const read_context& ctxt, string name = die_name(die); Dwarf_Die scope_die; - if (!get_scope_die(ctxt, die, where_offset, scope_die)) + if (!get_scope_die(rdr, die, where_offset, scope_die)) return ""; - string parent_name = die_qualified_name(ctxt, &scope_die, where_offset); + string parent_name = die_qualified_name(rdr, &scope_die, where_offset); bool colon_colon = die_is_type(die) || die_is_namespace(die); string separator = colon_colon ? "::" : "."; @@ -9836,7 +9017,7 @@ die_qualified_type_name(const read_context& ctxt, string underlying_type_repr; if (has_underlying_type_die) underlying_type_repr = - die_qualified_type_name(ctxt, &underlying_type_die, where_offset); + die_qualified_type_name(rdr, &underlying_type_die, where_offset); else underlying_type_repr = "void"; @@ -9869,7 +9050,7 @@ die_qualified_type_name(const read_context& ctxt, break; string pointed_type_repr = - die_qualified_type_name(ctxt, &pointed_to_type_die, where_offset); + die_qualified_type_name(rdr, &pointed_to_type_die, where_offset); repr = pointed_type_repr; if (repr.empty()) @@ -9899,7 +9080,7 @@ die_qualified_type_name(const read_context& ctxt, // the ::as_string() method of that type. So we don't add // that type to the current type tree being built. array_type_def::subrange_sptr s = - build_subrange_type(const_cast(ctxt), + build_subrange_type(const_cast(rdr), die, where_offset, /*associate_die_to_type=*/false); repr += s->as_string(); @@ -9912,12 +9093,12 @@ die_qualified_type_name(const read_context& ctxt, if (!die_die_attribute(die, DW_AT_type, element_type_die)) break; string element_type_name = - die_qualified_type_name(ctxt, &element_type_die, where_offset); + die_qualified_type_name(rdr, &element_type_die, where_offset); if (element_type_name.empty()) break; array_type_def::subranges_type subranges; - build_subranges_from_array_type_die(const_cast(ctxt), + build_subranges_from_array_type_die(const_cast(rdr), die, subranges, where_offset, /*associate_type_to_die=*/false); @@ -9935,7 +9116,7 @@ die_qualified_type_name(const read_context& ctxt, bool is_const = false; bool is_static = false; - die_return_and_parm_names_from_fn_type_die(ctxt, die, where_offset, + die_return_and_parm_names_from_fn_type_die(rdr, die, where_offset, /*pretty_print=*/true, return_type_name, class_name, parm_names, is_const, @@ -9985,7 +9166,7 @@ die_qualified_type_name(const read_context& ctxt, /// For instance, for a DIE of tag DW_TAG_subprogram this function /// computes the signature of the function *declaration*. /// -/// @param ctxt the read context. +/// @param rdr the DWARF reader. /// /// @param die the DIE to consider. /// @@ -9993,7 +9174,7 @@ die_qualified_type_name(const read_context& ctxt, /// /// @return a copy of the computed name. static string -die_qualified_decl_name(const read_context& ctxt, +die_qualified_decl_name(const reader& rdr, const Dwarf_Die* die, size_t where_offset) { @@ -10003,10 +9184,10 @@ die_qualified_decl_name(const read_context& ctxt, string name = die_name(die); Dwarf_Die scope_die; - if (!get_scope_die(ctxt, die, where_offset, scope_die)) + if (!get_scope_die(rdr, die, where_offset, scope_die)) return ""; - string scope_name = die_qualified_name(ctxt, &scope_die, where_offset); + string scope_name = die_qualified_name(rdr, &scope_die, where_offset); string separator = "::"; string repr; @@ -10020,7 +9201,7 @@ die_qualified_decl_name(const read_context& ctxt, repr = scope_name.empty() ? name : scope_name + separator + name; break; case DW_TAG_subprogram: - repr = die_function_signature(ctxt, die, where_offset); + repr = die_function_signature(rdr, die, where_offset); break; case DW_TAG_unspecified_parameters: @@ -10046,7 +9227,7 @@ die_qualified_decl_name(const read_context& ctxt, /// DW_TAG_subprogram is going to be considered as a "type" -- just /// like if it was a DW_TAG_subroutine_type. /// -/// @param ctxt the read context. +/// @param rdr the DWARF reader. /// /// @param die the DIE to consider. /// @@ -10054,12 +9235,12 @@ die_qualified_decl_name(const read_context& ctxt, /// /// @return a copy of the computed name. static string -die_qualified_name(const read_context& ctxt, const Dwarf_Die* die, size_t where) +die_qualified_name(const reader& rdr, const Dwarf_Die* die, size_t where) { if (die_is_type(die)) - return die_qualified_type_name(ctxt, die, where); + return die_qualified_type_name(rdr, die, where); else if (die_is_decl(die)) - return die_qualified_decl_name(ctxt, die, where); + return die_qualified_decl_name(rdr, die, where); return ""; } @@ -10070,7 +9251,7 @@ die_qualified_name(const read_context& ctxt, const Dwarf_Die* die, size_t where) /// that tag; or if the DIE's qualified name is built from names of /// sub-types DIEs whose tags are not yet supported. /// -/// @param ctxt the reading context. +/// @param rdr the DWARF reader. /// /// @param die the DIE to consider. /// @@ -10081,7 +9262,7 @@ die_qualified_name(const read_context& ctxt, const Dwarf_Die* die, size_t where) /// /// @return true if the qualified name of the DIE is empty. static bool -die_qualified_type_name_empty(const read_context& ctxt, +die_qualified_type_name_empty(const reader& rdr, const Dwarf_Die* die, size_t where, string &qualified_name) { @@ -10104,19 +9285,19 @@ die_qualified_type_name_empty(const read_context& ctxt, if (die_die_attribute(die, DW_AT_type, underlying_type_die)) { string name = - die_qualified_type_name(ctxt, &underlying_type_die, where); + die_qualified_type_name(rdr, &underlying_type_die, where); if (name.empty()) return true; } } else { - string name = die_qualified_type_name(ctxt, die, where); + string name = die_qualified_type_name(rdr, die, where); if (name.empty()) return true; } - qname = die_qualified_type_name(ctxt, die, where); + qname = die_qualified_type_name(rdr, die, where); if (qname.empty()) return true; @@ -10134,7 +9315,7 @@ die_qualified_type_name_empty(const read_context& ctxt, /// When the function we are looking at is a member function, it also /// tells if it's const. /// -/// @param ctxt the reading context. +/// @param rdr the DWARF reader. /// /// @param die the DIE of the function or function type we are looking /// at. @@ -10160,7 +9341,7 @@ die_qualified_type_name_empty(const read_context& ctxt, /// @param is_static out parameter. If the function is a static /// member function, then this is set to true. static void -die_return_and_parm_names_from_fn_type_die(const read_context& ctxt, +die_return_and_parm_names_from_fn_type_die(const reader& rdr, const Dwarf_Die* die, size_t where_offset, bool pretty_print, @@ -10177,22 +9358,22 @@ die_return_and_parm_names_from_fn_type_die(const read_context& ctxt, else return_type_name = pretty_print - ? ctxt.get_die_pretty_representation(&ret_type_die, where_offset) - : ctxt.get_die_qualified_type_name(&ret_type_die, where_offset); + ? rdr.get_die_pretty_representation(&ret_type_die, where_offset) + : rdr.get_die_qualified_type_name(&ret_type_die, where_offset); if (return_type_name.empty()) return_type_name = "void"; Dwarf_Die object_pointer_die, class_die; bool is_method_type = - die_function_type_is_method_type(ctxt, die, where_offset, + die_function_type_is_method_type(rdr, die, where_offset, object_pointer_die, class_die, is_static); is_const = false; if (is_method_type) { - class_name = ctxt.get_die_qualified_type_name(&class_die, where_offset); + class_name = rdr.get_die_qualified_type_name(&class_die, where_offset); Dwarf_Die this_pointer_die; Dwarf_Die pointed_to_die; @@ -10223,8 +9404,8 @@ die_return_and_parm_names_from_fn_type_die(const read_context& ctxt, continue; string qualified_name = pretty_print - ? ctxt.get_die_pretty_representation(&parm_type_die, where_offset) - : ctxt.get_die_qualified_type_name(&parm_type_die, where_offset); + ? rdr.get_die_pretty_representation(&parm_type_die, where_offset) + : rdr.get_die_qualified_type_name(&parm_type_die, where_offset); if (qualified_name.empty()) continue; @@ -10248,11 +9429,11 @@ die_return_and_parm_names_from_fn_type_die(const read_context& ctxt, if (class_name.empty()) { Dwarf_Die parent_die; - if (get_parent_die(ctxt, die, parent_die, where_offset)) + if (get_parent_die(rdr, die, parent_die, where_offset)) { if (die_is_class_type(&parent_die)) class_name = - ctxt.get_die_qualified_type_name(&parent_die, where_offset); + rdr.get_die_qualified_type_name(&parent_die, where_offset); } } } @@ -10260,7 +9441,7 @@ die_return_and_parm_names_from_fn_type_die(const read_context& ctxt, /// This computes the signature of the a function declaration /// represented by a DIE. /// -/// @param ctxt the reading context. +/// @param rdr the DWARF reader. /// /// @param fn_die the DIE of the function to consider. /// @@ -10269,14 +9450,14 @@ die_return_and_parm_names_from_fn_type_die(const read_context& ctxt, /// /// @return a copy of the computed function signature string. static string -die_function_signature(const read_context& ctxt, +die_function_signature(const reader& rdr, const Dwarf_Die *fn_die, size_t where_offset) { translation_unit::language lang; bool has_lang = false; - if ((has_lang = ctxt.get_die_language(fn_die, lang))) + if ((has_lang = rdr.get_die_language(fn_die, lang))) { // In a binary originating from the C language, it's OK to use // the linkage name of the function as a key for the map which @@ -10299,7 +9480,7 @@ die_function_signature(const read_context& ctxt, string return_type_name; Dwarf_Die ret_type_die; if (die_die_attribute(fn_die, DW_AT_type, ret_type_die)) - return_type_name = ctxt.get_die_qualified_type_name(&ret_type_die, + return_type_name = rdr.get_die_qualified_type_name(&ret_type_die, where_offset); if (return_type_name.empty()) @@ -10307,8 +9488,8 @@ die_function_signature(const read_context& ctxt, Dwarf_Die scope_die; string scope_name; - if (get_scope_die(ctxt, fn_die, where_offset, scope_die)) - scope_name = ctxt.get_die_qualified_name(&scope_die, where_offset); + if (get_scope_die(rdr, fn_die, where_offset, scope_die)) + scope_name = rdr.get_die_qualified_name(&scope_die, where_offset); string fn_name = die_name(fn_die); if (!scope_name.empty()) fn_name = scope_name + "::" + fn_name; @@ -10318,7 +9499,7 @@ die_function_signature(const read_context& ctxt, bool is_const = false; bool is_static = false; - die_return_and_parm_names_from_fn_type_die(ctxt, fn_die, where_offset, + die_return_and_parm_names_from_fn_type_die(rdr, fn_die, where_offset, /*pretty_print=*/false, return_type_name, class_name, parm_names, is_const, is_static); @@ -10373,7 +9554,7 @@ die_function_signature(const read_context& ctxt, /// Note that this function is also used to pretty print functions. /// For functions, it prints the *type* of the function. /// -/// @param ctxt the context to use. +/// @param rdr the context to use. /// /// @param the DIE of the type to pretty print. /// @@ -10383,7 +9564,7 @@ die_function_signature(const read_context& ctxt, /// /// @return the resulting pretty representation. static string -die_pretty_print_type(read_context& ctxt, +die_pretty_print_type(reader& rdr, const Dwarf_Die* die, size_t where_offset) { @@ -10413,17 +9594,17 @@ die_pretty_print_type(read_context& ctxt, break; case DW_TAG_namespace: - repr = "namespace " + ctxt.get_die_qualified_type_name(die, where_offset); + repr = "namespace " + rdr.get_die_qualified_type_name(die, where_offset); break; case DW_TAG_base_type: - repr = ctxt.get_die_qualified_type_name(die, where_offset); + repr = rdr.get_die_qualified_type_name(die, where_offset); break; case DW_TAG_typedef: { string qualified_name; - if (!die_qualified_type_name_empty(ctxt, die, + if (!die_qualified_type_name_empty(rdr, die, where_offset, qualified_name)) repr = "typedef " + qualified_name; @@ -10436,13 +9617,13 @@ die_pretty_print_type(read_context& ctxt, case DW_TAG_pointer_type: case DW_TAG_reference_type: case DW_TAG_rvalue_reference_type: - repr = ctxt.get_die_qualified_type_name(die, where_offset); + repr = rdr.get_die_qualified_type_name(die, where_offset); break; case DW_TAG_enumeration_type: { string qualified_name = - ctxt.get_die_qualified_type_name(die, where_offset); + rdr.get_die_qualified_type_name(die, where_offset); repr = "enum " + qualified_name; } break; @@ -10451,7 +9632,7 @@ die_pretty_print_type(read_context& ctxt, case DW_TAG_class_type: { string qualified_name = - ctxt.get_die_qualified_type_name(die, where_offset); + rdr.get_die_qualified_type_name(die, where_offset); repr = "class " + qualified_name; } break; @@ -10459,7 +9640,7 @@ die_pretty_print_type(read_context& ctxt, case DW_TAG_union_type: { string qualified_name = - ctxt.get_die_qualified_type_name(die, where_offset); + rdr.get_die_qualified_type_name(die, where_offset); repr = "union " + qualified_name; } break; @@ -10470,12 +9651,12 @@ die_pretty_print_type(read_context& ctxt, if (!die_die_attribute(die, DW_AT_type, element_type_die)) break; string element_type_name = - ctxt.get_die_qualified_type_name(&element_type_die, where_offset); + rdr.get_die_qualified_type_name(&element_type_die, where_offset); if (element_type_name.empty()) break; array_type_def::subranges_type subranges; - build_subranges_from_array_type_die(ctxt, die, subranges, where_offset, + build_subranges_from_array_type_die(rdr, die, subranges, where_offset, /*associate_type_to_die=*/false); repr = element_type_name; @@ -10493,7 +9674,7 @@ die_pretty_print_type(read_context& ctxt, // subrange type is its name. We might need something more // advance, should the needs of the users get more // complicated. - repr += die_qualified_type_name(ctxt, die, where_offset); + repr += die_qualified_type_name(rdr, die, where_offset); } break; @@ -10506,7 +9687,7 @@ die_pretty_print_type(read_context& ctxt, bool is_const = false; bool is_static = false; - die_return_and_parm_names_from_fn_type_die(ctxt, die, where_offset, + die_return_and_parm_names_from_fn_type_die(rdr, die, where_offset, /*pretty_print=*/true, return_type_name, class_name, parm_names, is_const, @@ -10515,7 +9696,7 @@ die_pretty_print_type(read_context& ctxt, repr = "function type"; else repr = "method type"; - repr += " " + ctxt.get_die_qualified_type_name(die, where_offset); + repr += " " + rdr.get_die_qualified_type_name(die, where_offset); } break; @@ -10540,7 +9721,7 @@ die_pretty_print_type(read_context& ctxt, /// Note that this function is also used to pretty print functions. /// For functions, it prints the signature of the function. /// -/// @param ctxt the context to use. +/// @param rdr the context to use. /// /// @param the DIE of the declaration to pretty print. /// @@ -10550,7 +9731,7 @@ die_pretty_print_type(read_context& ctxt, /// /// @return the resulting pretty representation. static string -die_pretty_print_decl(read_context& ctxt, +die_pretty_print_decl(reader& rdr, const Dwarf_Die* die, size_t where_offset) { @@ -10563,7 +9744,7 @@ die_pretty_print_decl(read_context& ctxt, switch (tag) { case DW_TAG_namespace: - repr = "namespace " + die_qualified_name(ctxt, die, where_offset); + repr = "namespace " + die_qualified_name(rdr, die, where_offset); break; case DW_TAG_member: @@ -10572,15 +9753,15 @@ die_pretty_print_decl(read_context& ctxt, string type_repr = "void"; Dwarf_Die type_die; if (die_die_attribute(die, DW_AT_type, type_die)) - type_repr = die_qualified_type_name(ctxt, &type_die, where_offset); - repr = die_qualified_name(ctxt, die, where_offset); + type_repr = die_qualified_type_name(rdr, &type_die, where_offset); + repr = die_qualified_name(rdr, die, where_offset); if (!repr.empty()) repr = type_repr + " " + repr; } break; case DW_TAG_subprogram: - repr = die_function_signature(ctxt, die, where_offset); + repr = die_function_signature(rdr, die, where_offset); break; default: @@ -10598,7 +9779,7 @@ die_pretty_print_decl(read_context& ctxt, /// DW_TAG_subprogram DIE is going to be represented as a function /// *type*. /// -/// @param ctxt the reading context. +/// @param rdr the DWARF reader. /// /// @param die the DIE to consider. /// @@ -10606,12 +9787,12 @@ die_pretty_print_decl(read_context& ctxt, /// /// @return a copy of the pretty printed artifact. static string -die_pretty_print(read_context& ctxt, const Dwarf_Die* die, size_t where_offset) +die_pretty_print(reader& rdr, const Dwarf_Die* die, size_t where_offset) { if (die_is_type(die)) - return die_pretty_print_type(ctxt, die, where_offset); + return die_pretty_print_type(rdr, die, where_offset); else if (die_is_decl(die)) - return die_pretty_print_decl(ctxt, die, where_offset); + return die_pretty_print_decl(rdr, die, where_offset); return ""; } @@ -10675,7 +9856,7 @@ compare_as_decl_dies(const Dwarf_Die *l, const Dwarf_Die *r) /// Test if at least one of two ODR-relevant DIEs is decl-only. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param l the first type DIE to consider. /// @@ -10684,11 +9865,11 @@ compare_as_decl_dies(const Dwarf_Die *l, const Dwarf_Die *r) /// @return true iff either @p l or @p r is decl-only and both are /// ODR-relevant. static bool -at_least_one_decl_only_among_odr_relevant_dies(const read_context &ctxt, +at_least_one_decl_only_among_odr_relevant_dies(const reader &rdr, const Dwarf_Die *l, const Dwarf_Die *r) { - if (!(ctxt.odr_is_relevant(l) && ctxt.odr_is_relevant(r))) + if (!(rdr.odr_is_relevant(l) && rdr.odr_is_relevant(r))) return false; if ((die_is_declaration_only(l) && die_has_no_child(l)) @@ -10711,7 +9892,7 @@ at_least_one_decl_only_among_odr_relevant_dies(const read_context &ctxt, /// a declaration of a type compares equal to the definition of the /// type. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param l the left operand of the comparison operator. /// @@ -10719,7 +9900,7 @@ at_least_one_decl_only_among_odr_relevant_dies(const read_context &ctxt, /// /// @return true iff @p l equals @p r. static bool -compare_as_type_dies(const read_context& ctxt, +compare_as_type_dies(const reader& rdr, const Dwarf_Die *l, const Dwarf_Die *r) { @@ -10738,7 +9919,7 @@ compare_as_type_dies(const read_context& ctxt, // DW_TAG_string_type DIEs are different, by default. return false; - if (at_least_one_decl_only_among_odr_relevant_dies(ctxt, l, r)) + if (at_least_one_decl_only_among_odr_relevant_dies(rdr, l, r)) // A declaration of a type compares equal to the definition of the // type. return true; @@ -10753,7 +9934,7 @@ compare_as_type_dies(const read_context& ctxt, /// Compare two DIEs as decls (looking as their names etc) and as /// types (looking at their size etc). /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param l the first DIE to consider. /// @@ -10762,12 +9943,12 @@ compare_as_type_dies(const read_context& ctxt, /// @return TRUE iff @p l equals @p r as far as naming and size is /// concerned. static bool -compare_as_decl_and_type_dies(const read_context &ctxt, +compare_as_decl_and_type_dies(const reader &rdr, const Dwarf_Die *l, const Dwarf_Die *r) { if (!compare_as_decl_dies(l, r) - || !compare_as_type_dies(ctxt, l, r)) + || !compare_as_type_dies(rdr, l, r)) return false; return true; @@ -10782,7 +9963,7 @@ compare_as_decl_and_type_dies(const read_context &ctxt, /// in C++ for instance, that doesn't imply that the two functions are /// equal. /// -/// @param ctxt the @ref read_context to consider. +/// @param rdr the @ref reader to consider. /// /// @param l the first function DIE to consider. /// @@ -10791,7 +9972,7 @@ compare_as_decl_and_type_dies(const read_context &ctxt, /// @return true iff the function represented by @p l have the same /// linkage name as the function represented by @p r. static bool -fn_die_equal_by_linkage_name(const read_context &ctxt, +fn_die_equal_by_linkage_name(const reader &rdr, const Dwarf_Die *l, const Dwarf_Die *r) { @@ -10810,8 +9991,8 @@ fn_die_equal_by_linkage_name(const read_context &ctxt, string llinkage_name = die_linkage_name(l), rlinkage_name = die_linkage_name(r); - if (ctxt.die_is_in_c_or_cplusplus(l) - && ctxt.die_is_in_c_or_cplusplus(r)) + if (rdr.die_is_in_c_or_cplusplus(l) + && rdr.die_is_in_c_or_cplusplus(r)) { if (!llinkage_name.empty() && !rlinkage_name.empty()) return llinkage_name == rlinkage_name; @@ -10832,7 +10013,7 @@ fn_die_equal_by_linkage_name(const read_context &ctxt, /// canonically and structurally. The two types of comparison should /// be equal, of course. /// -/// @param ctxt the read_context. +/// @param rdr the DWARF reader. /// /// @param l_offset the offset of the first canonical DIE to compare. /// @@ -10855,7 +10036,7 @@ fn_die_equal_by_linkage_name(const read_context &ctxt, /// set to the offset of the canonical DIE of the DIE designated by @p /// l_offset. static bool -try_canonical_die_comparison(const read_context& ctxt, +try_canonical_die_comparison(const reader& rdr, Dwarf_Off l_offset, Dwarf_Off r_offset, die_source l_die_source, die_source r_die_source, bool& l_has_canonical_die_offset, @@ -10865,20 +10046,20 @@ try_canonical_die_comparison(const read_context& ctxt, bool& result) { #ifdef WITH_DEBUG_TYPE_CANONICALIZATION - if (ctxt.debug_die_canonicalization_is_on_ - && !ctxt.use_canonical_die_comparison_) + if (rdr.debug_die_canonicalization_is_on_ + && !rdr.use_canonical_die_comparison_) return false; #endif l_has_canonical_die_offset = (l_canonical_die_offset = - ctxt.get_canonical_die_offset(l_offset, l_die_source, + rdr.get_canonical_die_offset(l_offset, l_die_source, /*die_as_type=*/true)); r_has_canonical_die_offset = (r_canonical_die_offset = - ctxt.get_canonical_die_offset(r_offset, r_die_source, + rdr.get_canonical_die_offset(r_offset, r_die_source, /*die_as_type=*/true)); if (l_has_canonical_die_offset && r_has_canonical_die_offset) @@ -11085,7 +10266,7 @@ get_member_child_die(const Dwarf_Die *die, Dwarf_Die *child) /// This optimization is performed only if /// is_canon_type_to_be_propagated_tag returns true. /// -/// @param ctxt the current context to consider. +/// @param rdr the current context to consider. /// /// @param l the left-hand-side DIE of the comparison. It's going to /// receive the canonical type of the other DIE. @@ -11093,7 +10274,7 @@ get_member_child_die(const Dwarf_Die *die, Dwarf_Die *child) /// @param r the right-hand-side DIE of the comparison. Its canonical /// type is propagated to @p l. static void -maybe_propagate_canonical_type(const read_context& ctxt, +maybe_propagate_canonical_type(const reader& rdr, const Dwarf_Die* l, const Dwarf_Die* r) { @@ -11104,7 +10285,7 @@ maybe_propagate_canonical_type(const read_context& ctxt, return; if (is_canon_type_to_be_propagated_tag(l_tag)) - propagate_canonical_type(ctxt, l, r); + propagate_canonical_type(rdr, l, r); } /// Propagate the canonical type of a the right-hand-side DIE to the @@ -11114,7 +10295,7 @@ maybe_propagate_canonical_type(const read_context& ctxt, /// If the right-hand-side DIE is not canonicalized, the function /// performs its canonicalization. /// -/// @param ctxt the current context to consider. +/// @param rdr the current context to consider. /// /// @param l the left-hand-side DIE of the comparison. It's going to /// receive the canonical type of the other DIE. @@ -11122,7 +10303,7 @@ maybe_propagate_canonical_type(const read_context& ctxt, /// @param r the right-hand-side DIE of the comparison. Its canonical /// type is propagated to @p l. static void -propagate_canonical_type(const read_context& ctxt, +propagate_canonical_type(const reader& rdr, const Dwarf_Die* l, const Dwarf_Die* r) { @@ -11133,8 +10314,8 @@ propagate_canonical_type(const read_context& ctxt, // // In case 'r' has no canonical DIE, then compute it, and then // propagate that canonical DIE to 'r'. - const die_source l_source = ctxt.get_die_source(l); - const die_source r_source = ctxt.get_die_source(r); + const die_source l_source = rdr.get_die_source(l); + const die_source r_source = rdr.get_die_source(r); Dwarf_Off l_offset = dwarf_dieoffset(const_cast(l)); Dwarf_Off r_offset = dwarf_dieoffset(const_cast(r)); @@ -11145,12 +10326,12 @@ propagate_canonical_type(const read_context& ctxt, l_has_canonical_die_offset = (l_canonical_die_offset = - ctxt.get_canonical_die_offset(l_offset, l_source, + rdr.get_canonical_die_offset(l_offset, l_source, /*die_as_type=*/true)); r_has_canonical_die_offset = (r_canonical_die_offset = - ctxt.get_canonical_die_offset(r_offset, r_source, + rdr.get_canonical_die_offset(r_offset, r_source, /*die_as_type=*/true)); @@ -11160,14 +10341,14 @@ propagate_canonical_type(const read_context& ctxt, && l_source == r_source) { if (!r_has_canonical_die_offset) - ctxt.compute_canonical_die_offset(r, r_canonical_die_offset, + rdr.compute_canonical_die_offset(r, r_canonical_die_offset, /*die_as_type=*/true); ABG_ASSERT(r_canonical_die_offset); - ctxt.set_canonical_die_offset(l, r_canonical_die_offset, + rdr.set_canonical_die_offset(l, r_canonical_die_offset, /*die_as_type=*/true); offset_type l_off = {l_source, l_offset}, r_off = {r_source, r_offset}; - ctxt.propagated_types_.insert(std::make_pair(l_off,r_off)); - ctxt.canonical_propagated_count_++; + rdr.propagated_types_.insert(std::make_pair(l_off,r_off)); + rdr.canonical_propagated_count_++; } } @@ -11222,7 +10403,7 @@ return_comparison_result(const Dwarf_Die* l, if (do_propagate_canonical_type) { // Propagate canonical type. - maybe_propagate_canonical_type(comparison_stack.ctxt_, l, r); + maybe_propagate_canonical_type(comparison_stack.rdr_, l, r); // TODO: do we need to confirm any tentative canonical // propagation? @@ -11287,7 +10468,7 @@ return_comparison_result(const Dwarf_Die* l, { // We are in the case described above of a redundant type // that has been fully compared. - maybe_propagate_canonical_type(comparison_stack.ctxt_, l, r); + maybe_propagate_canonical_type(comparison_stack.rdr_, l, r); comparison_stack.confirm_canonical_propagated_type(cur_dies); result = COMPARISON_RESULT_EQUAL; @@ -11299,7 +10480,7 @@ return_comparison_result(const Dwarf_Die* l, // the introductory comment above, it must be dependant on a // redundant type. ABG_ASSERT(comparison_stack.depends_on_redundant_types(cur_dies)); - maybe_propagate_canonical_type(comparison_stack.ctxt_, l, r); + maybe_propagate_canonical_type(comparison_stack.rdr_, l, r); // Then pass through. } } @@ -11341,7 +10522,7 @@ return_comparison_result(const Dwarf_Die* l, //and thus hasn't been pushed to the stack yet gain. comparison_stack.erase(cur_dies); - maybe_cache_type_comparison_result(comparison_stack.ctxt_, + maybe_cache_type_comparison_result(comparison_stack.rdr_, l_tag, cur_dies, result); return result; @@ -11349,7 +10530,7 @@ return_comparison_result(const Dwarf_Die* l, /// Compare two DIEs emitted by a C compiler. /// -/// @param ctxt the read context used to load the DWARF information. +/// @param rdr the DWARF reader used to load the DWARF information. /// /// @param l the left-hand-side argument of this comparison operator. /// @@ -11371,7 +10552,7 @@ return_comparison_result(const Dwarf_Die* l, /// /// @return COMPARISON_RESULT_EQUAL iff @p l equals @p r. static comparison_result -compare_dies(const read_context& ctxt, +compare_dies(const reader& rdr, const Dwarf_Die *l, const Dwarf_Die *r, offset_pairs_stack_type& aggregates_being_compared, bool update_canonical_dies_on_the_fly) @@ -11379,8 +10560,8 @@ compare_dies(const read_context& ctxt, ABG_ASSERT(l); ABG_ASSERT(r); - const die_source l_die_source = ctxt.get_die_source(l); - const die_source r_die_source = ctxt.get_die_source(r); + const die_source l_die_source = rdr.get_die_source(l); + const die_source r_die_source = rdr.get_die_source(r); offset_type l_offset = { @@ -11406,7 +10587,7 @@ compare_dies(const read_context& ctxt, return COMPARISON_RESULT_EQUAL; comparison_result result = COMPARISON_RESULT_EQUAL; - if (maybe_get_cached_type_comparison_result(ctxt, l_tag, + if (maybe_get_cached_type_comparison_result(rdr, l_tag, dies_being_compared, result)) return result; @@ -11419,7 +10600,7 @@ compare_dies(const read_context& ctxt, if (is_type_die_to_be_canonicalized(l) && is_type_die_to_be_canonicalized(r)) { bool canonical_compare_result = false; - if (try_canonical_die_comparison(ctxt, l_offset, r_offset, + if (try_canonical_die_comparison(rdr, l_offset, r_offset, l_die_source, r_die_source, l_has_canonical_die_offset, r_has_canonical_die_offset, @@ -11444,7 +10625,7 @@ compare_dies(const read_context& ctxt, case DW_TAG_base_type: case DW_TAG_string_type: case DW_TAG_unspecified_type: - if (!compare_as_decl_and_type_dies(ctxt, l, r)) + if (!compare_as_decl_and_type_dies(rdr, l, r)) SET_RESULT_TO_FALSE(result, l, r); break; @@ -11456,7 +10637,7 @@ compare_dies(const read_context& ctxt, case DW_TAG_volatile_type: case DW_TAG_restrict_type: { - if (!compare_as_type_dies(ctxt, l, r)) + if (!compare_as_type_dies(rdr, l, r)) { SET_RESULT_TO_FALSE(result, l, r); break; @@ -11493,14 +10674,14 @@ compare_dies(const read_context& ctxt, else if (lu_is_void != ru_is_void) SET_RESULT_TO_FALSE(result, l, r); else - result = compare_dies(ctxt, &lu_type_die, &ru_type_die, + result = compare_dies(rdr, &lu_type_die, &ru_type_die, aggregates_being_compared, update_canonical_dies_on_the_fly); } break; case DW_TAG_enumeration_type: - if (!compare_as_decl_and_type_dies(ctxt, l, r)) + if (!compare_as_decl_and_type_dies(rdr, l, r)) SET_RESULT_TO_FALSE(result, l, r); else { @@ -11508,7 +10689,7 @@ compare_dies(const read_context& ctxt, Dwarf_Die l_enumtor, r_enumtor; bool found_l_enumtor = true, found_r_enumtor = true; - if (!at_least_one_decl_only_among_odr_relevant_dies(ctxt, l, r)) + if (!at_least_one_decl_only_among_odr_relevant_dies(rdr, l, r)) for (found_l_enumtor = dwarf_child(const_cast(l), &l_enumtor) == 0, found_r_enumtor = dwarf_child(const_cast(r), @@ -11551,9 +10732,9 @@ compare_dies(const read_context& ctxt, { RETURN_IF_COMPARISON_CYCLE_DETECTED; - ctxt.compare_count_++; + rdr.compare_count_++; - if (!compare_as_decl_and_type_dies(ctxt, l, r)) + if (!compare_as_decl_and_type_dies(rdr, l, r)) SET_RESULT_TO_FALSE(result, l, r); else { @@ -11562,7 +10743,7 @@ compare_dies(const read_context& ctxt, Dwarf_Die l_member, r_member; bool found_l_member = true, found_r_member = true; - if (!at_least_one_decl_only_among_odr_relevant_dies(ctxt, l, r)) + if (!at_least_one_decl_only_among_odr_relevant_dies(rdr, l, r)) for (found_l_member = get_member_child_die(l, &l_member), found_r_member = get_member_child_die(r, &r_member); found_l_member && found_r_member; @@ -11586,7 +10767,7 @@ compare_dies(const read_context& ctxt, || l_tag == DW_TAG_subprogram); comparison_result local_result = - compare_dies(ctxt, &l_member, &r_member, + compare_dies(rdr, &l_member, &r_member, aggregates_being_compared, update_canonical_dies_on_the_fly); @@ -11622,7 +10803,7 @@ compare_dies(const read_context& ctxt, aggregates_being_compared.add(dies_being_compared); - ctxt.compare_count_++; + rdr.compare_count_++; Dwarf_Die l_child, r_child; bool found_l_child, found_r_child; @@ -11639,7 +10820,7 @@ compare_dies(const read_context& ctxt, if (l_child_tag == DW_TAG_subrange_type || r_child_tag == DW_TAG_subrange_type) { - result = compare_dies(ctxt, &l_child, &r_child, + result = compare_dies(rdr, &l_child, &r_child, aggregates_being_compared, update_canonical_dies_on_the_fly); if (!result) @@ -11657,7 +10838,7 @@ compare_dies(const read_context& ctxt, bool found_rtype = die_die_attribute(r, DW_AT_type, rtype_die); ABG_ASSERT(found_ltype && found_rtype); - result = compare_dies(ctxt, <ype_die, &rtype_die, + result = compare_dies(rdr, <ype_die, &rtype_die, aggregates_being_compared, update_canonical_dies_on_the_fly); if (!result) @@ -11707,22 +10888,22 @@ compare_dies(const read_context& ctxt, aggregates_being_compared.add(dies_being_compared); - ctxt.compare_count_++; + rdr.compare_count_++; if (l_tag == DW_TAG_subprogram - && !fn_die_equal_by_linkage_name(ctxt, l, r)) + && !fn_die_equal_by_linkage_name(rdr, l, r)) { SET_RESULT_TO_FALSE(result, l, r); break; } else if (l_tag == DW_TAG_subprogram - && ctxt.die_is_in_c(l) && ctxt.die_is_in_c(r) - /*&& fn_die_equal_by_linkage_name(ctxt, l, r)*/) + && rdr.die_is_in_c(l) && rdr.die_is_in_c(r) + /*&& fn_die_equal_by_linkage_name(rdr, l, r)*/) { result = COMPARISON_RESULT_EQUAL; break; } - else if (!ctxt.die_is_in_c(l) && !ctxt.die_is_in_c(r)) + else if (!rdr.die_is_in_c(l) && !rdr.die_is_in_c(r)) { // In C, we cannot have two different functions with the // same linkage name in a given binary. But here we are @@ -11735,7 +10916,7 @@ compare_dies(const read_context& ctxt, r_return_type); if (l_return_type_is_void != r_return_type_is_void || (!l_return_type_is_void - && !compare_dies(ctxt, + && !compare_dies(rdr, &l_return_type, &r_return_type, aggregates_being_compared, update_canonical_dies_on_the_fly))) @@ -11762,7 +10943,7 @@ compare_dies(const read_context& ctxt, local_result = COMPARISON_RESULT_DIFFERENT; if (l_child_tag == DW_TAG_formal_parameter) local_result = - compare_dies(ctxt, &l_child, &r_child, + compare_dies(rdr, &l_child, &r_child, aggregates_being_compared, update_canonical_dies_on_the_fly); if (local_result == COMPARISON_RESULT_DIFFERENT) @@ -11804,7 +10985,7 @@ compare_dies(const read_context& ctxt, else if (!l_type_is_void) { comparison_result local_result = - compare_dies(ctxt, &l_type, &r_type, + compare_dies(rdr, &l_type, &r_type, aggregates_being_compared, update_canonical_dies_on_the_fly); SET_RESULT_TO(result, local_result, l, r); @@ -11820,8 +11001,8 @@ compare_dies(const read_context& ctxt, if (l_tag == DW_TAG_member) { int64_t l_offset_in_bits = 0, r_offset_in_bits = 0; - die_member_offset(ctxt, l, l_offset_in_bits); - die_member_offset(ctxt, r, r_offset_in_bits); + die_member_offset(rdr, l, l_offset_in_bits); + die_member_offset(rdr, r, r_offset_in_bits); if (l_offset_in_bits != r_offset_in_bits) SET_RESULT_TO_FALSE(result, l, r); } @@ -11832,7 +11013,7 @@ compare_dies(const read_context& ctxt, ABG_ASSERT(die_die_attribute(l, DW_AT_type, l_type)); ABG_ASSERT(die_die_attribute(r, DW_AT_type, r_type)); comparison_result local_result = - compare_dies(ctxt, &l_type, &r_type, + compare_dies(rdr, &l_type, &r_type, aggregates_being_compared, update_canonical_dies_on_the_fly); SET_RESULT_TO(result, local_result, l, r); @@ -11847,7 +11028,7 @@ compare_dies(const read_context& ctxt, Dwarf_Die l_type, r_type; ABG_ASSERT(die_die_attribute(l, DW_AT_type, l_type)); ABG_ASSERT(die_die_attribute(r, DW_AT_type, r_type)); - result = compare_dies(ctxt, &l_type, &r_type, + result = compare_dies(rdr, &l_type, &r_type, aggregates_being_compared, update_canonical_dies_on_the_fly); if (!result) @@ -11865,8 +11046,8 @@ compare_dies(const read_context& ctxt, ABG_RETURN(COMPARISON_RESULT_DIFFERENT); int64_t l_offset_in_bits = 0, r_offset_in_bits = 0; - die_member_offset(ctxt, l, l_offset_in_bits); - die_member_offset(ctxt, r, r_offset_in_bits); + die_member_offset(rdr, l, l_offset_in_bits); + die_member_offset(rdr, r, r_offset_in_bits); if (l_offset_in_bits != r_offset_in_bits) ABG_RETURN(COMPARISON_RESULT_DIFFERENT); } @@ -11882,7 +11063,7 @@ compare_dies(const read_context& ctxt, Dwarf_Die l_type, r_type; ABG_ASSERT(die_die_attribute(l, DW_AT_type, l_type)); ABG_ASSERT(die_die_attribute(r, DW_AT_type, r_type)); - result = compare_dies(ctxt, &l_type, &r_type, + result = compare_dies(rdr, &l_type, &r_type, aggregates_being_compared, update_canonical_dies_on_the_fly); if (!result) @@ -11890,7 +11071,7 @@ compare_dies(const read_context& ctxt, ABG_ASSERT(die_die_attribute(l, DW_AT_containing_type, l_type)); ABG_ASSERT(die_die_attribute(r, DW_AT_containing_type, r_type)); - result = compare_dies(ctxt, &l_type, &r_type, + result = compare_dies(rdr, &l_type, &r_type, aggregates_being_compared, update_canonical_dies_on_the_fly); if (!result) @@ -11949,7 +11130,7 @@ compare_dies(const read_context& ctxt, case DW_TAG_GNU_call_site_parameter: case DW_TAG_hi_user: #ifdef WITH_DEBUG_TYPE_CANONICALIZATION - if (ctxt.debug_die_canonicalization_is_on_) + if (rdr.debug_die_canonicalization_is_on_) ABG_ASSERT_NOT_REACHED; #endif ABG_ASSERT_NOT_REACHED; @@ -11961,7 +11142,7 @@ compare_dies(const read_context& ctxt, /// Compare two DIEs emitted by a C compiler. /// -/// @param ctxt the read context used to load the DWARF information. +/// @param rdr the DWARF reader used to load the DWARF information. /// /// @param l the left-hand-side argument of this comparison operator. /// @@ -11976,25 +11157,25 @@ compare_dies(const read_context& ctxt, /// /// @return COMPARISON_RESULT_EQUAL iff @p l equals @p r. static comparison_result -compare_dies(const read_context& ctxt, +compare_dies(const reader& rdr, const Dwarf_Die *l, const Dwarf_Die *r, bool update_canonical_dies_on_the_fly) { - offset_pairs_stack_type aggregates_being_compared(ctxt); - return compare_dies(ctxt, l, r, aggregates_being_compared, + offset_pairs_stack_type aggregates_being_compared(rdr); + return compare_dies(rdr, l, r, aggregates_being_compared, update_canonical_dies_on_the_fly); } /// Compare two DIEs for the purpose of canonicalization. /// -/// This is a sub-routine of read_context::get_canonical_die. +/// This is a sub-routine of reader::get_canonical_die. /// /// When DIE canonicalization debugging is on, this function performs /// both structural and canonical comparison. It expects that both /// comparison yield the same result. /// -/// @param ctxt the read context. +/// @param rdr the DWARF reader. /// /// @param l the left-hand-side comparison operand DIE. /// @@ -12005,20 +11186,20 @@ compare_dies(const read_context& ctxt, /// /// @return true iff @p l equals @p r. static bool -compare_dies_during_canonicalization(read_context& ctxt, +compare_dies_during_canonicalization(reader& rdr, const Dwarf_Die *l, const Dwarf_Die *r, bool update_canonical_dies_on_the_fly) { #ifdef WITH_DEBUG_TYPE_CANONICALIZATION - if (ctxt.debug_die_canonicalization_is_on_) + if (rdr.debug_die_canonicalization_is_on_) { bool canonical_equality = false, structural_equality = false; - ctxt.use_canonical_die_comparison_ = false; - structural_equality = compare_dies(ctxt, l, r, + rdr.use_canonical_die_comparison_ = false; + structural_equality = compare_dies(rdr, l, r, /*update_canonical_dies_on_the_fly=*/false); - ctxt.use_canonical_die_comparison_ = true; - canonical_equality = compare_dies(ctxt, l, r, + rdr.use_canonical_die_comparison_ = true; + canonical_equality = compare_dies(rdr, l, r, update_canonical_dies_on_the_fly); if (canonical_equality != structural_equality) { @@ -12028,7 +11209,7 @@ compare_dies_during_canonicalization(read_context& ctxt, << ", r: " << dwarf_dieoffset(const_cast(r)) << std::dec << ", repr: '" - << ctxt.get_die_pretty_type_representation(l, 0) + << rdr.get_die_pretty_type_representation(l, 0) << "'" << std::endl; ABG_ASSERT_NOT_REACHED; @@ -12036,7 +11217,7 @@ compare_dies_during_canonicalization(read_context& ctxt, return structural_equality; } #endif - return compare_dies(ctxt, l, r, + return compare_dies(rdr, l, r, update_canonical_dies_on_the_fly); } @@ -12047,7 +11228,7 @@ compare_dies_during_canonicalization(read_context& ctxt, /// Get the point where a DW_AT_import DIE is used to import a given /// (unit) DIE, between two DIEs. /// -/// @param ctxt the dwarf reading context to consider. +/// @param rdr the dwarf reader to consider. /// /// @param partial_unit_offset the imported unit for which we want to /// know the insertion point. This is usually a partial unit (with @@ -12079,7 +11260,7 @@ compare_dies_during_canonicalization(read_context& ctxt, /// @return true iff an imported unit is found between @p /// first_die_offset and @p last_die_offset. static bool -find_import_unit_point_between_dies(const read_context& ctxt, +find_import_unit_point_between_dies(const reader& rdr, size_t partial_unit_offset, Dwarf_Off first_die_offset, Dwarf_Off first_die_cu_offset, @@ -12088,7 +11269,7 @@ find_import_unit_point_between_dies(const read_context& ctxt, size_t& imported_point_offset) { const tu_die_imported_unit_points_map_type& tu_die_imported_unit_points_map = - ctxt.tu_die_imported_unit_points_map(source); + rdr.tu_die_imported_unit_points_map(source); tu_die_imported_unit_points_map_type::const_iterator iter = tu_die_imported_unit_points_map.find(first_die_cu_offset); @@ -12122,7 +11303,7 @@ find_import_unit_point_between_dies(const read_context& ctxt, for (imported_unit_points_type::const_iterator i = e; i >= b; --i) { - if (find_import_unit_point_between_dies(ctxt, + if (find_import_unit_point_between_dies(rdr, partial_unit_offset, i->imported_unit_child_off, i->imported_unit_cu_off, @@ -12143,7 +11324,7 @@ find_import_unit_point_between_dies(const read_context& ctxt, for (imported_unit_points_type::const_iterator i = b; i != e; ++i) { - if (find_import_unit_point_between_dies(ctxt, + if (find_import_unit_point_between_dies(rdr, partial_unit_offset, i->imported_unit_child_off, i->imported_unit_cu_off, @@ -12164,7 +11345,7 @@ find_import_unit_point_between_dies(const read_context& ctxt, /// Said otherwise, this function returns the last import point of a /// unit, before a limit. /// -/// @param ctxt the dwarf reading context to consider. +/// @param rdr the dwarf reader to consider. /// /// @param partial_unit_offset the imported unit for which we want to /// know the insertion point of. This is usually a partial unit (with @@ -12182,7 +11363,7 @@ find_import_unit_point_between_dies(const read_context& ctxt, /// Note that if an imported unit is found after @p die_offset then @p /// imported_point_offset is set and the function return false. static bool -find_import_unit_point_before_die(const read_context& ctxt, +find_import_unit_point_before_die(const reader& rdr, size_t partial_unit_offset, size_t where_offset, size_t& imported_point_offset) @@ -12190,7 +11371,7 @@ find_import_unit_point_before_die(const read_context& ctxt, size_t import_point_offset = 0; Dwarf_Die first_die_of_tu; - if (dwarf_child(const_cast(ctxt.cur_tu_die()), + if (dwarf_child(const_cast(rdr.cur_tu_die()), &first_die_of_tu) != 0) return false; @@ -12200,7 +11381,7 @@ find_import_unit_point_before_die(const read_context& ctxt, cu_die = dwarf_diecu(const_cast(&first_die_of_tu), &cu_die_memory, 0, 0); - if (find_import_unit_point_between_dies(ctxt, partial_unit_offset, + if (find_import_unit_point_between_dies(rdr, partial_unit_offset, dwarf_dieoffset(&first_die_of_tu), dwarf_dieoffset(cu_die), /*source=*/PRIMARY_DEBUG_INFO_DIE_SOURCE, @@ -12226,7 +11407,7 @@ find_import_unit_point_before_die(const read_context& ctxt, /// called before this one can work. This function either succeeds or /// aborts the current process. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the DIE for which we want the parent. /// @@ -12241,16 +11422,16 @@ find_import_unit_point_before_die(const read_context& ctxt, /// @return true if the function could get a parent DIE, false /// otherwise. static bool -get_parent_die(const read_context& ctxt, +get_parent_die(const reader& rdr, const Dwarf_Die* die, Dwarf_Die& parent_die, size_t where_offset) { - ABG_ASSERT(ctxt.dwarf()); + ABG_ASSERT(rdr.dwarf_debug_info()); - const die_source source = ctxt.get_die_source(die); + const die_source source = rdr.get_die_source(die); - const offset_offset_map_type& m = ctxt.die_parent_map(source); + const offset_offset_map_type& m = rdr.die_parent_map(source); offset_offset_map_type::const_iterator i = m.find(dwarf_dieoffset(const_cast(die))); @@ -12260,13 +11441,16 @@ get_parent_die(const read_context& ctxt, switch (source) { case PRIMARY_DEBUG_INFO_DIE_SOURCE: - ABG_ASSERT(dwarf_offdie(ctxt.dwarf(), i->second, &parent_die)); + ABG_ASSERT(dwarf_offdie(const_cast(rdr.dwarf_debug_info()), + i->second, &parent_die)); break; case ALT_DEBUG_INFO_DIE_SOURCE: - ABG_ASSERT(dwarf_offdie(ctxt.alt_dwarf(), i->second, &parent_die)); + ABG_ASSERT(dwarf_offdie(const_cast(rdr.alternate_dwarf_debug_info()), + i->second, &parent_die)); break; case TYPE_UNIT_DIE_SOURCE: - ABG_ASSERT(dwarf_offdie_types(ctxt.dwarf(), i->second, &parent_die)); + ABG_ASSERT(dwarf_offdie_types(const_cast(rdr.dwarf_debug_info()), + i->second, &parent_die)); break; case NO_DEBUG_INFO_DIE_SOURCE: case NUMBER_OF_DIE_SOURCES: @@ -12277,12 +11461,12 @@ get_parent_die(const read_context& ctxt, { if (where_offset == 0) { - parent_die = *ctxt.cur_tu_die(); + parent_die = *rdr.cur_tu_die(); return true; } size_t import_point_offset = 0; bool found = - find_import_unit_point_before_die(ctxt, + find_import_unit_point_before_die(rdr, dwarf_dieoffset(&parent_die), where_offset, import_point_offset); @@ -12291,15 +11475,15 @@ get_parent_die(const read_context& ctxt, // debug info file) hasn't been imported into this TU. So, // Let's assume its logical parent is the DIE of the current // TU. - parent_die = *ctxt.cur_tu_die(); + parent_die = *rdr.cur_tu_die(); else { ABG_ASSERT(import_point_offset); Dwarf_Die import_point_die; - ABG_ASSERT(dwarf_offdie(ctxt.dwarf(), - import_point_offset, - &import_point_die)); - return get_parent_die(ctxt, &import_point_die, + ABG_ASSERT(dwarf_offdie(const_cast(rdr.dwarf_debug_info()), + import_point_offset, + &import_point_die)); + return get_parent_die(rdr, &import_point_die, parent_die, where_offset); } } @@ -12318,7 +11502,7 @@ get_parent_die(const read_context& ctxt, /// Also note that if the current translation unit is from C, then /// this returns the global scope. /// -/// @param ctxt the reading context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DIE to consider. /// @@ -12327,12 +11511,12 @@ get_parent_die(const read_context& ctxt, /// @param scope_die out parameter. This is set to the resulting /// scope DIE iff the function returns true. static bool -get_scope_die(const read_context& ctxt, +get_scope_die(const reader& rdr, const Dwarf_Die* die, size_t where_offset, Dwarf_Die& scope_die) { - if (is_c_language(ctxt.cur_transl_unit()->get_language())) + if (is_c_language(rdr.cur_transl_unit()->get_language())) { ABG_ASSERT(dwarf_tag(const_cast(die)) != DW_TAG_member); return dwarf_diecu(const_cast(die), &scope_die, 0, 0); @@ -12343,15 +11527,15 @@ get_scope_die(const read_context& ctxt, logical_parent_die, false) || die_die_attribute(die, DW_AT_abstract_origin, logical_parent_die, false)) - return get_scope_die(ctxt, &logical_parent_die, where_offset, scope_die); + return get_scope_die(rdr, &logical_parent_die, where_offset, scope_die); - if (!get_parent_die(ctxt, die, scope_die, where_offset)) + if (!get_parent_die(rdr, die, scope_die, where_offset)) return false; if (dwarf_tag(&scope_die) == DW_TAG_subprogram || dwarf_tag(&scope_die) == DW_TAG_subroutine_type || dwarf_tag(&scope_die) == DW_TAG_array_type) - return get_scope_die(ctxt, &scope_die, where_offset, scope_die); + return get_scope_die(rdr, &scope_die, where_offset, scope_die); return true; } @@ -12366,7 +11550,7 @@ get_scope_die(const read_context& ctxt, /// Also note that if the current translation unit is from C, then /// this returns the global scope. /// -/// @param ctxt the dwarf reading context to use. +/// @param rdr the dwarf reader to use. /// /// @param die the DIE to get the scope for. /// @@ -12378,36 +11562,36 @@ get_scope_die(const read_context& ctxt, /// e.g, DW_TAG_partial_unit that can be included in several places in /// the DIE tree. static scope_decl_sptr -get_scope_for_die(read_context& ctxt, +get_scope_for_die(reader& rdr, Dwarf_Die* die, bool called_for_public_decl, size_t where_offset) { - const die_source source_of_die = ctxt.get_die_source(die); + const die_source source_of_die = rdr.get_die_source(die); translation_unit::language die_lang = translation_unit::LANG_UNKNOWN; - ctxt.get_die_language(die, die_lang); + rdr.get_die_language(die, die_lang); if (is_c_language(die_lang) - || ctxt.die_parent_map(source_of_die).empty()) + || rdr.die_parent_map(source_of_die).empty()) { // In units for the C languages all decls belong to the global // namespace. This is generally the case if Libabigail // determined that no DIE -> parent map was needed. ABG_ASSERT(dwarf_tag(die) != DW_TAG_member); - return ctxt.global_scope(); + return rdr.global_scope(); } Dwarf_Die cloned_die; if (die_die_attribute(die, DW_AT_specification, cloned_die, false) || die_die_attribute(die, DW_AT_abstract_origin, cloned_die, false)) - return get_scope_for_die(ctxt, &cloned_die, + return get_scope_for_die(rdr, &cloned_die, called_for_public_decl, where_offset); Dwarf_Die parent_die; - if (!get_parent_die(ctxt, die, parent_die, where_offset)) - return ctxt.nil_scope(); + if (!get_parent_die(rdr, die, parent_die, where_offset)) + return rdr.nil_scope(); if (dwarf_tag(&parent_die) == DW_TAG_compile_unit || dwarf_tag(&parent_die) == DW_TAG_partial_unit @@ -12418,7 +11602,7 @@ get_scope_for_die(read_context& ctxt, { ABG_ASSERT(source_of_die == ALT_DEBUG_INFO_DIE_SOURCE || source_of_die == TYPE_UNIT_DIE_SOURCE); - return ctxt.cur_transl_unit()->get_global_scope(); + return rdr.cur_transl_unit()->get_global_scope(); } // For top level DIEs like DW_TAG_compile_unit, we just want to @@ -12428,10 +11612,10 @@ get_scope_for_die(read_context& ctxt, // build the translation unit of parent_die. Otherwise, just // return the global scope of the current translation unit. die_tu_map_type::const_iterator i = - ctxt.die_tu_map().find(dwarf_dieoffset(&parent_die)); - if (i != ctxt.die_tu_map().end()) + rdr.die_tu_map().find(dwarf_dieoffset(&parent_die)); + if (i != rdr.die_tu_map().end()) return i->second->get_global_scope(); - return ctxt.cur_transl_unit()->get_global_scope(); + return rdr.cur_transl_unit()->get_global_scope(); } scope_decl_sptr s; @@ -12448,7 +11632,7 @@ get_scope_for_die(read_context& ctxt, // an error of the DWARF emitter. We should never see this DIE in // this context. { - scope_decl_sptr s = get_scope_for_die(ctxt, &parent_die, + scope_decl_sptr s = get_scope_for_die(rdr, &parent_die, called_for_public_decl, where_offset); if (is_anonymous_type_die(die)) @@ -12458,23 +11642,23 @@ get_scope_for_die(read_context& ctxt, // or union where it has nothing to do. while (is_class_or_union_type(s)) { - if (!get_parent_die(ctxt, &parent_die, parent_die, where_offset)) - return ctxt.nil_scope(); - s = get_scope_for_die(ctxt, &parent_die, + if (!get_parent_die(rdr, &parent_die, parent_die, where_offset)) + return rdr.nil_scope(); + s = get_scope_for_die(rdr, &parent_die, called_for_public_decl, where_offset); } return s; } else - d = build_ir_node_from_die(ctxt, &parent_die, + d = build_ir_node_from_die(rdr, &parent_die, called_for_public_decl, where_offset); s = dynamic_pointer_cast(d); if (!s) // this is an entity defined in someting that is not a scope. // Let's drop it. - return ctxt.nil_scope(); + return rdr.nil_scope(); class_decl_sptr cl = dynamic_pointer_cast(d); if (cl && cl->get_is_declaration_only()) @@ -12689,7 +11873,7 @@ find_lower_bound_in_imported_unit_points(const imported_unit_points_type& p, /// recursively reads the children dies of the current DIE and /// populates the resulting translation unit. /// -/// @param ctxt the read_context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DW_TAG_compile_unit DIE to consider. /// @@ -12698,7 +11882,7 @@ find_lower_bound_in_imported_unit_points(const imported_unit_points_type& p, /// /// @return a pointer to the resulting translation_unit. static translation_unit_sptr -build_translation_unit_and_add_to_ir(read_context& ctxt, +build_translation_unit_and_add_to_ir(reader& rdr, Dwarf_Die* die, char address_size) { @@ -12710,9 +11894,9 @@ build_translation_unit_and_add_to_ir(read_context& ctxt, // Clear the part of the context that is dependent on the translation // unit we are reading. - ctxt.clear_per_translation_unit_data(); + rdr.clear_per_translation_unit_data(); - ctxt.cur_tu_die(die); + rdr.cur_tu_die(die); string path = die_string_attribute(die, DW_AT_name); if (path == "") @@ -12737,23 +11921,23 @@ build_translation_unit_and_add_to_ir(read_context& ctxt, { const string& abs_path = compilation_dir.empty() ? path : compilation_dir + "/" + path; - result = ctxt.current_corpus()->find_translation_unit(abs_path); + result = rdr.corpus()->find_translation_unit(abs_path); } if (!result) { - result.reset(new translation_unit(ctxt.env(), + result.reset(new translation_unit(rdr.env(), path, address_size)); result->set_compilation_dir_path(compilation_dir); - ctxt.current_corpus()->add(result); + rdr.corpus()->add(result); uint64_t l = 0; die_unsigned_constant_attribute(die, DW_AT_language, l); result->set_language(dwarf_language_to_tu_language(l)); } - ctxt.cur_transl_unit(result); - ctxt.die_tu_map()[dwarf_dieoffset(die)] = result; + rdr.cur_transl_unit(result); + rdr.die_tu_map()[dwarf_dieoffset(die)] = result; Dwarf_Die child; if (dwarf_child(die, &child) != 0) @@ -12764,17 +11948,17 @@ build_translation_unit_and_add_to_ir(read_context& ctxt, do // Analyze all the DIEs we encounter unless we are asked to only // analyze exported interfaces and the types reachables from them. - if (!ctxt.env()->analyze_exported_interfaces_only() - || ctxt.is_decl_die_with_exported_symbol(&child)) - build_ir_node_from_die(ctxt, &child, + if (!rdr.env().analyze_exported_interfaces_only() + || rdr.is_decl_die_with_exported_symbol(&child)) + build_ir_node_from_die(rdr, &child, die_is_public_decl(&child), dwarf_dieoffset(&child)); while (dwarf_siblingof(&child, &child) == 0); - if (!ctxt.var_decls_to_re_add_to_tree().empty()) + if (!rdr.var_decls_to_re_add_to_tree().empty()) for (list::const_iterator v = - ctxt.var_decls_to_re_add_to_tree().begin(); - v != ctxt.var_decls_to_re_add_to_tree().end(); + rdr.var_decls_to_re_add_to_tree().begin(); + v != rdr.var_decls_to_re_add_to_tree().end(); ++v) { if (is_member_decl(*v)) @@ -12795,7 +11979,7 @@ build_translation_unit_and_add_to_ir(read_context& ctxt, { ty_name = components_to_type_name(fqn_comps); class_type = - lookup_class_type(ty_name, *ctxt.cur_transl_unit()); + lookup_class_type(ty_name, *rdr.cur_transl_unit()); } if (class_type) { @@ -12825,7 +12009,7 @@ build_translation_unit_and_add_to_ir(read_context& ctxt, } } } - ctxt.var_decls_to_re_add_to_tree().clear(); + rdr.var_decls_to_re_add_to_tree().clear(); result->set_is_constructed(true); @@ -12839,7 +12023,7 @@ build_translation_unit_and_add_to_ir(read_context& ctxt, /// being currently created, reads the children of the DIE and /// connects them to the IR as well. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DIE to read from. Must be either DW_TAG_namespace /// or DW_TAG_module. @@ -12852,7 +12036,7 @@ build_translation_unit_and_add_to_ir(read_context& ctxt, /// @return the resulting @ref abigail::namespace_decl or NULL if it /// couldn't be created. static namespace_decl_sptr -build_namespace_decl_and_add_to_ir(read_context& ctxt, +build_namespace_decl_and_add_to_ir(reader& rdr, Dwarf_Die* die, size_t where_offset) { @@ -12865,25 +12049,25 @@ build_namespace_decl_and_add_to_ir(read_context& ctxt, if (tag != DW_TAG_namespace && tag != DW_TAG_module) return result; - scope_decl_sptr scope = get_scope_for_die(ctxt, die, + scope_decl_sptr scope = get_scope_for_die(rdr, die, /*called_for_public_decl=*/false, where_offset); string name, linkage_name; location loc; - die_loc_and_name(ctxt, die, loc, name, linkage_name); + die_loc_and_name(rdr, die, loc, name, linkage_name); - result.reset(new namespace_decl(ctxt.env(), name, loc)); + result.reset(new namespace_decl(rdr.env(), name, loc)); add_decl_to_scope(result, scope.get()); - ctxt.associate_die_to_decl(die, result, where_offset); + rdr.associate_die_to_decl(die, result, where_offset); Dwarf_Die child; if (dwarf_child(die, &child) != 0) return result; - ctxt.scope_stack().push(result.get()); + rdr.scope_stack().push(result.get()); do - build_ir_node_from_die(ctxt, &child, + build_ir_node_from_die(rdr, &child, // If this namespace DIE is private // (anonymous) then all its content is // considered private. Otherwise, its @@ -12892,14 +12076,14 @@ build_namespace_decl_and_add_to_ir(read_context& ctxt, die_is_public_decl(die) && die_is_public_decl(&child), where_offset); while (dwarf_siblingof(&child, &child) == 0); - ctxt.scope_stack().pop(); + rdr.scope_stack().pop(); return result; } /// Build a @ref type_decl out of a DW_TAG_base_type DIE. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DW_TAG_base_type to consider. /// @@ -12907,7 +12091,7 @@ build_namespace_decl_and_add_to_ir(read_context& ctxt, /// /// @return the resulting decl_base_sptr. static type_decl_sptr -build_type_decl(read_context& ctxt, Dwarf_Die* die, size_t where_offset) +build_type_decl(reader& rdr, Dwarf_Die* die, size_t where_offset) { type_decl_sptr result; @@ -12926,21 +12110,21 @@ build_type_decl(read_context& ctxt, Dwarf_Die* die, size_t where_offset) string type_name, linkage_name; location loc; - die_loc_and_name(ctxt, die, loc, type_name, linkage_name); + die_loc_and_name(rdr, die, loc, type_name, linkage_name); if (byte_size == 0) { // The size of the type is zero, that must mean that we are // looking at the definition of the void type. if (type_name == "void") - result = is_type_decl(build_ir_node_for_void_type(ctxt)); + result = is_type_decl(build_ir_node_for_void_type(rdr)); else // A type of size zero that is not void? Hmmh, I am not sure // what that means. Return nil for now. return result; } - if (corpus_sptr corp = ctxt.should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr.should_reuse_type_from_corpus_group()) { string normalized_type_name = type_name; integral_type int_type; @@ -12950,19 +12134,19 @@ build_type_decl(read_context& ctxt, Dwarf_Die* die, size_t where_offset) } if (!result) - if (corpus_sptr corp = ctxt.current_corpus()) + if (corpus_sptr corp = rdr.corpus()) result = lookup_basic_type(type_name, *corp); if (!result) - result.reset(new type_decl(ctxt.env(), type_name, bit_size, + result.reset(new type_decl(rdr.env(), type_name, bit_size, /*alignment=*/0, loc, linkage_name)); - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } /// Construct the type that is to be used as the underlying type of an /// enum. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param enum_name the name of the enum that this type is going to /// be the underlying type of. @@ -12973,7 +12157,7 @@ build_type_decl(read_context& ctxt, Dwarf_Die* die, size_t where_offset) /// not. By default, this should be set to true as before c++11 (and /// in C), it's almost the case. static type_decl_sptr -build_enum_underlying_type(read_context& ctxt, +build_enum_underlying_type(reader& rdr, string enum_name, uint64_t enum_size, bool is_anonymous = true) @@ -12982,11 +12166,11 @@ build_enum_underlying_type(read_context& ctxt, build_internal_underlying_enum_type_name(enum_name, is_anonymous, enum_size); - type_decl_sptr result(new type_decl(ctxt.env(), underlying_type_name, + type_decl_sptr result(new type_decl(rdr.env(), underlying_type_name, enum_size, enum_size, location())); result->set_is_anonymous(is_anonymous); result->set_is_artificial(true); - translation_unit_sptr tu = ctxt.cur_transl_unit(); + translation_unit_sptr tu = rdr.cur_transl_unit(); decl_base_sptr d = add_decl_to_scope(result, tu->get_global_scope().get()); result = dynamic_pointer_cast(d); ABG_ASSERT(result); @@ -12996,7 +12180,7 @@ build_enum_underlying_type(read_context& ctxt, /// Build an enum_type_decl from a DW_TAG_enumeration_type DIE. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DIE to read from. /// @@ -13009,7 +12193,7 @@ build_enum_underlying_type(read_context& ctxt, /// /// @return the built enum_type_decl or NULL if it could not be built. static enum_type_decl_sptr -build_enum_type(read_context& ctxt, +build_enum_type(reader& rdr, Dwarf_Die* die, scope_decl* scope, size_t where_offset, @@ -13025,7 +12209,7 @@ build_enum_type(read_context& ctxt, string name, linkage_name; location loc; - die_loc_and_name(ctxt, die, loc, name, linkage_name); + die_loc_and_name(rdr, die, loc, name, linkage_name); bool is_anonymous = false; // If the enum is anonymous, let's give it a name. @@ -13040,7 +12224,7 @@ build_enum_type(read_context& ctxt, name = build_internal_anonymous_die_name(name, s); } - bool use_odr = ctxt.odr_is_relevant(die); + bool use_odr = rdr.odr_is_relevant(die); // If the type has location, then associate it to its // representation. This way, all occurences of types with the same // representation (name) and location can be later detected as being @@ -13051,10 +12235,10 @@ build_enum_type(read_context& ctxt, if (use_odr) { if (enum_type_decl_sptr pre_existing_enum = - is_enum_type(ctxt.lookup_artifact_from_die(die))) + is_enum_type(rdr.lookup_artifact_from_die(die))) result = pre_existing_enum; } - else if (corpus_sptr corp = ctxt.should_reuse_type_from_corpus_group()) + else if (corpus_sptr corp = rdr.should_reuse_type_from_corpus_group()) { if (loc) result = lookup_enum_type_per_location(loc.expand(), *corp); @@ -13062,14 +12246,14 @@ build_enum_type(read_context& ctxt, else if (loc) { if (enum_type_decl_sptr pre_existing_enum = - is_enum_type(ctxt.lookup_artifact_from_die(die))) + is_enum_type(rdr.lookup_artifact_from_die(die))) if (pre_existing_enum->get_location() == loc) result = pre_existing_enum; } if (result) { - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } } @@ -13095,10 +12279,10 @@ build_enum_type(read_context& ctxt, string n, m; location l; - die_loc_and_name(ctxt, &child, l, n, m); + die_loc_and_name(rdr, &child, l, n, m); uint64_t val = 0; die_unsigned_constant_attribute(&child, DW_AT_const_value, val); - enms.push_back(enum_type_decl::enumerator(ctxt.env(), n, val)); + enms.push_back(enum_type_decl::enumerator(n, val)); } while (dwarf_siblingof(&child, &child) == 0); } @@ -13108,7 +12292,7 @@ build_enum_type(read_context& ctxt, // sole purpose is to be passed to the constructor of the // enum_type_decl type. type_decl_sptr t = - build_enum_underlying_type(ctxt, name, size, + build_enum_underlying_type(rdr, name, size, enum_underlying_type_is_anonymous); t->set_is_declaration_only(is_declaration_only); @@ -13116,9 +12300,9 @@ build_enum_type(read_context& ctxt, result->set_is_anonymous(is_anonymous); result->set_is_declaration_only(is_declaration_only); result->set_is_artificial(is_artificial); - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); - ctxt.maybe_schedule_declaration_only_enum_for_resolution(result); + rdr.maybe_schedule_declaration_only_enum_for_resolution(result); return result; } @@ -13135,12 +12319,12 @@ build_enum_type(read_context& ctxt, /// /// @param klass the @ref class_or_union that @p f belongs to. /// -/// @param ctxt the context used to read the ELF/DWARF information. +/// @param rdr the context used to read the ELF/DWARF information. static void finish_member_function_reading(Dwarf_Die* die, const function_decl_sptr& f, const class_or_union_sptr klass, - read_context& ctxt) + reader& rdr) { ABG_ASSERT(klass); @@ -13237,7 +12421,7 @@ finish_member_function_reading(Dwarf_Die* die, // // Let's thus schedule this function for a later fixup pass // (performed by - // read_context::fixup_functions_with_no_symbols()) that will + // reader::fixup_functions_with_no_symbols()) that will // set its underlying symbol. // // Note that if the underying symbol is encountered later in the @@ -13246,7 +12430,7 @@ finish_member_function_reading(Dwarf_Die* die, // de-schedule this function wrt fixup pass. Dwarf_Off die_offset = dwarf_dieoffset(die); die_function_decl_map_type &fns_with_no_symbol = - ctxt.die_function_decl_with_no_symbol_map(); + rdr.die_function_decl_with_no_symbol_map(); die_function_decl_map_type::const_iterator i = fns_with_no_symbol.find(die_offset); if (i == fns_with_no_symbol.end()) @@ -13260,7 +12444,7 @@ finish_member_function_reading(Dwarf_Die* die, /// then read those extra attributes and update the internal /// representation. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the function DIE to consider. /// @@ -13271,12 +12455,12 @@ finish_member_function_reading(Dwarf_Die* die, /// /// @return the updated function representation. static function_decl_sptr -maybe_finish_function_decl_reading(read_context& ctxt, +maybe_finish_function_decl_reading(reader& rdr, Dwarf_Die* die, size_t where_offset, const function_decl_sptr& existing_fn) { - function_decl_sptr result = build_function_decl(ctxt, die, + function_decl_sptr result = build_function_decl(rdr, die, where_offset, existing_fn); @@ -13305,7 +12489,7 @@ lookup_class_or_typedef_from_corpus(scope_decl* scope, const string& type_name) /// /// The type being looked for has the same name as a given DIE. /// -/// @param ctxt the reading context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DIE which has the same name as the type we are /// looking for. @@ -13317,7 +12501,7 @@ lookup_class_or_typedef_from_corpus(scope_decl* scope, const string& type_name) /// /// @return the type found. static type_base_sptr -lookup_class_or_typedef_from_corpus(read_context& ctxt, +lookup_class_or_typedef_from_corpus(reader& rdr, Dwarf_Die* die, bool called_for_public_decl, size_t where_offset) @@ -13329,7 +12513,7 @@ lookup_class_or_typedef_from_corpus(read_context& ctxt, if (class_name.empty()) return class_decl_sptr(); - scope_decl_sptr scope = get_scope_for_die(ctxt, die, + scope_decl_sptr scope = get_scope_for_die(rdr, die, called_for_public_decl, where_offset); if (scope) @@ -13392,7 +12576,7 @@ lookup_class_typedef_or_enum_type_from_corpus(Dwarf_Die* die, /// Test if a DIE represents a function that is a member of a given /// class type. /// -/// @param ctxt the reading context. +/// @param rdr the DWARF reader. /// /// @param function_die the DIE of the function to consider. /// @@ -13404,11 +12588,11 @@ lookup_class_typedef_or_enum_type_from_corpus(Dwarf_Die* die, /// function of @p class_type, iff @p function_die is for a member /// function of @p class_type. static method_decl_sptr -is_function_for_die_a_member_of_class(read_context& ctxt, +is_function_for_die_a_member_of_class(reader& rdr, Dwarf_Die* function_die, const class_or_union_sptr& class_type) { - type_or_decl_base_sptr artifact = ctxt.lookup_artifact_from_die(function_die); + type_or_decl_base_sptr artifact = rdr.lookup_artifact_from_die(function_die); if (!artifact) return method_decl_sptr(); @@ -13443,7 +12627,7 @@ is_function_for_die_a_member_of_class(read_context& ctxt, /// new member function that is not already present in the class then /// add that new member function to the class. /// -/// @param ctxt the reading context. +/// @param rdr the DWARF reader. /// /// @param function_die the DIE of the potential member function to /// consider. @@ -13457,17 +12641,17 @@ is_function_for_die_a_member_of_class(read_context& ctxt, /// /// @return the method decl representing the member function. static method_decl_sptr -add_or_update_member_function(read_context& ctxt, +add_or_update_member_function(reader& rdr, Dwarf_Die* function_die, const class_or_union_sptr& class_type, bool called_from_public_decl, size_t where_offset) { method_decl_sptr method = - is_function_for_die_a_member_of_class(ctxt, function_die, class_type); + is_function_for_die_a_member_of_class(rdr, function_die, class_type); if (!method) - method = is_method_decl(build_ir_node_from_die(ctxt, function_die, + method = is_method_decl(build_ir_node_from_die(rdr, function_die, class_type.get(), called_from_public_decl, where_offset)); @@ -13476,7 +12660,7 @@ add_or_update_member_function(read_context& ctxt, finish_member_function_reading(function_die, is_function_decl(method), - class_type, ctxt); + class_type, rdr); return method; } @@ -13491,7 +12675,7 @@ add_or_update_member_function(read_context& ctxt, /// class_decl node with data members, member functions and other /// properties coming from the DIE. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the DIE to read information from. Must be either a /// DW_TAG_structure_type or a DW_TAG_class_type. @@ -13517,7 +12701,7 @@ add_or_update_member_function(read_context& ctxt, /// /// @return the resulting class_type. static class_decl_sptr -add_or_update_class_type(read_context& ctxt, +add_or_update_class_type(reader& rdr, Dwarf_Die* die, scope_decl* scope, bool is_struct, @@ -13530,7 +12714,7 @@ add_or_update_class_type(read_context& ctxt, if (!die) return result; - const die_source source = ctxt.get_die_source(die); + const die_source source = rdr.get_die_source(die); unsigned tag = dwarf_tag(die); @@ -13539,8 +12723,8 @@ add_or_update_class_type(read_context& ctxt, { die_class_or_union_map_type::const_iterator i = - ctxt.die_wip_classes_map(source).find(dwarf_dieoffset(die)); - if (i != ctxt.die_wip_classes_map(source).end()) + rdr.die_wip_classes_map(source).find(dwarf_dieoffset(die)); + if (i != rdr.die_wip_classes_map(source).end()) { class_decl_sptr class_type = is_class_type(i->second); ABG_ASSERT(class_type); @@ -13550,7 +12734,7 @@ add_or_update_class_type(read_context& ctxt, string name, linkage_name; location loc; - die_loc_and_name(ctxt, die, loc, name, linkage_name); + die_loc_and_name(rdr, die, loc, name, linkage_name); bool is_anonymous = false; if (name.empty()) @@ -13568,7 +12752,7 @@ add_or_update_class_type(read_context& ctxt, if (!is_anonymous) { - if (corpus_sptr corp = ctxt.should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr.should_reuse_type_from_corpus_group()) { if (loc) // TODO: if there is only one class defined in the corpus @@ -13588,7 +12772,7 @@ add_or_update_class_type(read_context& ctxt, || (!result->get_is_declaration_only() && is_declaration_only))) { - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } else @@ -13606,7 +12790,7 @@ add_or_update_class_type(read_context& ctxt, // when they do have a naming typedef. if (!is_anonymous) if (class_decl_sptr pre_existing_class = - is_class_type(ctxt.lookup_type_artifact_from_die(die))) + is_class_type(rdr.lookup_type_artifact_from_die(die))) klass = pre_existing_class; uint64_t size = 0; @@ -13628,7 +12812,7 @@ add_or_update_class_type(read_context& ctxt, } else { - result.reset(new class_decl(ctxt.env(), name, size, + result.reset(new class_decl(rdr.env(), name, size, /*alignment=*/0, is_struct, loc, decl_base::VISIBILITY_DEFAULT, is_anonymous)); @@ -13670,16 +12854,16 @@ add_or_update_class_type(read_context& ctxt, result->set_is_artificial(is_artificial); - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); - ctxt.maybe_schedule_declaration_only_class_for_resolution(result); + rdr.maybe_schedule_declaration_only_class_for_resolution(result); if (!has_child) // TODO: set the access specifier for the declaration-only class // here. return result; - ctxt.die_wip_classes_map(source)[dwarf_dieoffset(die)] = result; + rdr.die_wip_classes_map(source)[dwarf_dieoffset(die)] = result; bool is_incomplete_type = false; if (is_declaration_only && size == 0 && has_child) @@ -13693,13 +12877,13 @@ add_or_update_class_type(read_context& ctxt, // referred to by a pointer. If we later encounter a definition // for this decl-only class type, then this decl-only class will // be resolved to it by the code in - // read_context::resolve_declaration_only_classes. + // reader::resolve_declaration_only_classes. is_incomplete_type = true; scope_decl_sptr scop = dynamic_pointer_cast(res); ABG_ASSERT(scop); - ctxt.scope_stack().push(scop.get()); + rdr.scope_stack().push(scop.get()); if (has_child && !is_incomplete_type) { @@ -13722,12 +12906,12 @@ add_or_update_class_type(read_context& ctxt, type_base_sptr base_type; if (!(base_type = - lookup_class_or_typedef_from_corpus(ctxt, &type_die, + lookup_class_or_typedef_from_corpus(rdr, &type_die, called_from_public_decl, where_offset))) { base_type = - is_type(build_ir_node_from_die(ctxt, &type_die, + is_type(build_ir_node_from_die(rdr, &type_die, called_from_public_decl, where_offset)); } @@ -13747,14 +12931,14 @@ add_or_update_class_type(read_context& ctxt, bool is_virt= die_is_virtual(&child); int64_t offset = 0; bool is_offset_present = - die_member_offset(ctxt, &child, offset); + die_member_offset(rdr, &child, offset); class_decl::base_spec_sptr base(new class_decl::base_spec (b, access, is_offset_present ? offset : -1, is_virt)); if (b->get_is_declaration_only()) - ABG_ASSERT(ctxt.is_decl_only_class_scheduled_for_resolution(b)); + ABG_ASSERT(rdr.is_decl_only_class_scheduled_for_resolution(b)); if (result->find_base_class(b->get_qualified_name())) continue; result->add_base_specifier(base); @@ -13769,7 +12953,7 @@ add_or_update_class_type(read_context& ctxt, string n, m; location loc; - die_loc_and_name(ctxt, &child, loc, n, m); + die_loc_and_name(rdr, &child, loc, n, m); /// For now, we skip the hidden vtable pointer. /// Currently, we're looking for a member starting with /// "_vptr[^0-9a-zA-Z_]", which is what Clang and GCC @@ -13786,19 +12970,19 @@ add_or_update_class_type(read_context& ctxt, continue; int64_t offset_in_bits = 0; - bool is_laid_out = die_member_offset(ctxt, &child, + bool is_laid_out = die_member_offset(rdr, &child, offset_in_bits); // For now, is_static == !is_laid_out. When we have // templates, we'll try to be more specific. For now, // this approximation should do OK. bool is_static = !is_laid_out; - if (is_static && variable_is_suppressed(ctxt, + if (is_static && variable_is_suppressed(rdr, result.get(), &child)) continue; - decl_base_sptr ty = is_decl(build_ir_node_from_die(ctxt, &type_die, + decl_base_sptr ty = is_decl(build_ir_node_from_die(rdr, &type_die, called_from_public_decl, where_offset)); type_base_sptr t = is_type(ty); @@ -13834,18 +13018,18 @@ add_or_update_class_type(read_context& ctxt, result->add_data_member(dm, access, is_laid_out, is_static, offset_in_bits); ABG_ASSERT(has_scope(dm)); - ctxt.associate_die_to_decl(&child, dm, where_offset, + rdr.associate_die_to_decl(&child, dm, where_offset, /*associate_by_repr=*/false); } // Handle member functions; else if (tag == DW_TAG_subprogram) { decl_base_sptr r = - add_or_update_member_function(ctxt, &child, result, + add_or_update_member_function(rdr, &child, result, called_from_public_decl, where_offset); if (function_decl_sptr f = is_function_decl(r)) - ctxt.associate_die_to_decl(&child, f, where_offset, + rdr.associate_die_to_decl(&child, f, where_offset, /*associate_by_repr=*/true); } // Handle member types @@ -13875,34 +13059,34 @@ add_or_update_class_type(read_context& ctxt, && !lookup_class_typedef_or_enum_type_from_corpus (&child, anonymous_member_type_index, result.get())) || !result->find_member_type(die_name(&child))) - build_ir_node_from_die(ctxt, &child, result.get(), + build_ir_node_from_die(rdr, &child, result.get(), called_from_public_decl, where_offset); } } while (dwarf_siblingof(&child, &child) == 0); } - ctxt.scope_stack().pop(); + rdr.scope_stack().pop(); { die_class_or_union_map_type::const_iterator i = - ctxt.die_wip_classes_map(source).find(dwarf_dieoffset(die)); - if (i != ctxt.die_wip_classes_map(source).end()) + rdr.die_wip_classes_map(source).find(dwarf_dieoffset(die)); + if (i != rdr.die_wip_classes_map(source).end()) { if (is_member_type(i->second)) set_member_access_specifier(res, get_member_access_specifier(i->second)); - ctxt.die_wip_classes_map(source).erase(i); + rdr.die_wip_classes_map(source).erase(i); } } - ctxt.maybe_schedule_declaration_only_class_for_resolution(result); + rdr.maybe_schedule_declaration_only_class_for_resolution(result); return result; } /// Build an @ref union_decl from a DW_TAG_union_type DIE. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DIE to read from. /// @@ -13925,7 +13109,7 @@ add_or_update_class_type(read_context& ctxt, /// /// @return the resulting @ref union_decl type. static union_decl_sptr -add_or_update_union_type(read_context& ctxt, +add_or_update_union_type(reader& rdr, Dwarf_Die* die, scope_decl* scope, union_decl_sptr union_type, @@ -13942,11 +13126,11 @@ add_or_update_union_type(read_context& ctxt, if (tag != DW_TAG_union_type) return result; - const die_source source = ctxt.get_die_source(die); + const die_source source = rdr.get_die_source(die); { die_class_or_union_map_type::const_iterator i = - ctxt.die_wip_classes_map(source).find(dwarf_dieoffset(die)); - if (i != ctxt.die_wip_classes_map(source).end()) + rdr.die_wip_classes_map(source).find(dwarf_dieoffset(die)); + if (i != rdr.die_wip_classes_map(source).end()) { union_decl_sptr u = is_union_type(i->second); ABG_ASSERT(u); @@ -13956,7 +13140,7 @@ add_or_update_union_type(read_context& ctxt, string name, linkage_name; location loc; - die_loc_and_name(ctxt, die, loc, name, linkage_name); + die_loc_and_name(rdr, die, loc, name, linkage_name); bool is_anonymous = false; if (name.empty()) @@ -13979,7 +13163,7 @@ add_or_update_union_type(read_context& ctxt, if (!is_anonymous) { - if (corpus_sptr corp = ctxt.should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr.should_reuse_type_from_corpus_group()) { if (loc) result = lookup_union_type_per_location(loc.expand(), *corp); @@ -13988,7 +13172,7 @@ add_or_update_union_type(read_context& ctxt, if (result) { - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } } @@ -14001,7 +13185,7 @@ add_or_update_union_type(read_context& ctxt, // a naming typedef. if (!is_anonymous) if (union_decl_sptr pre_existing_union = - is_union_type(ctxt.lookup_artifact_from_die(die))) + is_union_type(rdr.lookup_artifact_from_die(die))) union_type = pre_existing_union; uint64_t size = 0; @@ -14015,7 +13199,7 @@ add_or_update_union_type(read_context& ctxt, } else { - result.reset(new union_decl(ctxt.env(), name, size, loc, + result.reset(new union_decl(rdr.env(), name, size, loc, decl_base::VISIBILITY_DEFAULT, is_anonymous)); if (is_declaration_only) @@ -14032,23 +13216,23 @@ add_or_update_union_type(read_context& ctxt, result->set_is_artificial(is_artificial); - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); // TODO: maybe schedule declaration-only union for result like we do // for classes: - // ctxt.maybe_schedule_declaration_only_class_for_resolution(result); + // rdr.maybe_schedule_declaration_only_class_for_resolution(result); Dwarf_Die child; bool has_child = (dwarf_child(die, &child) == 0); if (!has_child) return result; - ctxt.die_wip_classes_map(source)[dwarf_dieoffset(die)] = result; + rdr.die_wip_classes_map(source)[dwarf_dieoffset(die)] = result; scope_decl_sptr scop = dynamic_pointer_cast(result); ABG_ASSERT(scop); - ctxt.scope_stack().push(scop.get()); + rdr.scope_stack().push(scop.get()); if (has_child) { @@ -14064,7 +13248,7 @@ add_or_update_union_type(read_context& ctxt, string n, m; location loc; - die_loc_and_name(ctxt, &child, loc, n, m); + die_loc_and_name(rdr, &child, loc, n, m); // Because we can be updating an existing union, let's // make sure we don't already have a member of the same @@ -14075,7 +13259,7 @@ add_or_update_union_type(read_context& ctxt, ssize_t offset_in_bits = 0; decl_base_sptr ty = - is_decl(build_ir_node_from_die(ctxt, &type_die, + is_decl(build_ir_node_from_die(rdr, &type_die, called_from_public_decl, where_offset)); type_base_sptr t = is_type(ty); @@ -14101,14 +13285,14 @@ add_or_update_union_type(read_context& ctxt, /*is_static=*/false, offset_in_bits); ABG_ASSERT(has_scope(dm)); - ctxt.associate_die_to_decl(&child, dm, where_offset, + rdr.associate_die_to_decl(&child, dm, where_offset, /*associate_by_repr=*/false); } // Handle member functions; else if (tag == DW_TAG_subprogram) { decl_base_sptr r = - is_decl(build_ir_node_from_die(ctxt, &child, + is_decl(build_ir_node_from_die(rdr, &child, result.get(), called_from_public_decl, where_offset)); @@ -14118,31 +13302,31 @@ add_or_update_union_type(read_context& ctxt, function_decl_sptr f = dynamic_pointer_cast(r); ABG_ASSERT(f); - finish_member_function_reading(&child, f, result, ctxt); + finish_member_function_reading(&child, f, result, rdr); - ctxt.associate_die_to_decl(&child, f, where_offset, + rdr.associate_die_to_decl(&child, f, where_offset, /*associate_by_repr=*/false); } // Handle member types else if (die_is_type(&child)) decl_base_sptr td = - is_decl(build_ir_node_from_die(ctxt, &child, result.get(), + is_decl(build_ir_node_from_die(rdr, &child, result.get(), called_from_public_decl, where_offset)); } while (dwarf_siblingof(&child, &child) == 0); } - ctxt.scope_stack().pop(); + rdr.scope_stack().pop(); { die_class_or_union_map_type::const_iterator i = - ctxt.die_wip_classes_map(source).find(dwarf_dieoffset(die)); - if (i != ctxt.die_wip_classes_map(source).end()) + rdr.die_wip_classes_map(source).find(dwarf_dieoffset(die)); + if (i != rdr.die_wip_classes_map(source).end()) { if (is_member_type(i->second)) set_member_access_specifier(result, get_member_access_specifier(i->second)); - ctxt.die_wip_classes_map(source).erase(i); + rdr.die_wip_classes_map(source).erase(i); } } @@ -14152,7 +13336,7 @@ add_or_update_union_type(read_context& ctxt, /// build a qualified type from a DW_TAG_const_type, /// DW_TAG_volatile_type or DW_TAG_restrict_type DIE. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the input DIE to read from. /// @@ -14167,7 +13351,7 @@ add_or_update_union_type(read_context& ctxt, /// /// @return the resulting qualified_type_def. static type_base_sptr -build_qualified_type(read_context& ctxt, +build_qualified_type(reader& rdr, Dwarf_Die* die, bool called_from_public_decl, size_t where_offset) @@ -14189,10 +13373,10 @@ build_qualified_type(read_context& ctxt, // So, if no DW_AT_type is present, then this means (if we are // looking at a debug info emitted by GCC) that we are looking // at a qualified void type. - utype_decl = build_ir_node_for_void_type(ctxt); + utype_decl = build_ir_node_for_void_type(rdr); if (!utype_decl) - utype_decl = is_decl(build_ir_node_from_die(ctxt, &underlying_type_die, + utype_decl = is_decl(build_ir_node_from_die(rdr, &underlying_type_die, called_from_public_decl, where_offset)); if (!utype_decl) @@ -14200,10 +13384,10 @@ build_qualified_type(read_context& ctxt, // The call to build_ir_node_from_die() could have triggered the // creation of the type for this DIE. In that case, just return it. - if (type_base_sptr t = ctxt.lookup_type_from_die(die)) + if (type_base_sptr t = rdr.lookup_type_from_die(die)) { result = t; - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } @@ -14223,7 +13407,7 @@ build_qualified_type(read_context& ctxt, if (!result) result.reset(new qualified_type_def(utype, qual, location())); - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } @@ -14239,22 +13423,22 @@ build_qualified_type(read_context& ctxt, /// /// @param t the type node to be scheduled for canonicalization. /// -/// @param ctxt the contexter of the reader to use. +/// @param rdr the DWARF reader to use. static void schedule_array_tree_for_late_canonicalization(const type_base_sptr& t, - read_context &ctxt) + reader &rdr) { if (typedef_decl_sptr type = is_typedef(t)) { schedule_array_tree_for_late_canonicalization(type->get_underlying_type(), - ctxt); - ctxt.schedule_type_for_late_canonicalization(t); + rdr); + rdr.schedule_type_for_late_canonicalization(t); } else if (qualified_type_def_sptr type = is_qualified_type(t)) { schedule_array_tree_for_late_canonicalization(type->get_underlying_type(), - ctxt); - ctxt.schedule_type_for_late_canonicalization(t); + rdr); + rdr.schedule_type_for_late_canonicalization(t); } else if (array_type_def_sptr type = is_array_type(t)) { @@ -14264,13 +13448,13 @@ schedule_array_tree_for_late_canonicalization(const type_base_sptr& t, ++i) { if (!(*i)->get_scope()) - add_decl_to_scope(*i, ctxt.cur_transl_unit()->get_global_scope()); - ctxt.schedule_type_for_late_canonicalization(*i); + add_decl_to_scope(*i, rdr.cur_transl_unit()->get_global_scope()); + rdr.schedule_type_for_late_canonicalization(*i); } schedule_array_tree_for_late_canonicalization(type->get_element_type(), - ctxt); - ctxt.schedule_type_for_late_canonicalization(type); + rdr); + rdr.schedule_type_for_late_canonicalization(type); } } @@ -14286,12 +13470,12 @@ schedule_array_tree_for_late_canonicalization(const type_base_sptr& t, /// /// @param t the type to strip const qualification from. /// -/// @param ctxt the @ref read_context to use. +/// @param rdr the @ref reader to use. /// /// @return the stripped type or just return @p t. static decl_base_sptr maybe_strip_qualification(const qualified_type_def_sptr t, - read_context &ctxt) + reader &rdr) { if (!t) return t; @@ -14313,7 +13497,7 @@ maybe_strip_qualification(const qualified_type_def_sptr t, scope = array->get_scope(); ABG_ASSERT(scope); array = is_array_type(clone_array_tree(array)); - schedule_array_tree_for_late_canonicalization(array, ctxt); + schedule_array_tree_for_late_canonicalization(array, rdr); add_decl_to_scope(array, scope); t->set_underlying_type(array); u = t->get_underlying_type(); @@ -14324,7 +13508,7 @@ maybe_strip_qualification(const qualified_type_def_sptr t, ABG_ASSERT(scope); typedef_decl_sptr typdef = is_typedef(clone_array_tree(is_typedef(u))); - schedule_array_tree_for_late_canonicalization(typdef, ctxt); + schedule_array_tree_for_late_canonicalization(typdef, rdr); ABG_ASSERT(typdef); add_decl_to_scope(typdef, scope); t->set_underlying_type(typdef); @@ -14358,7 +13542,7 @@ maybe_strip_qualification(const qualified_type_def_sptr t, strip_redundant_quals_from_underyling_types(qual_type); add_decl_to_scope(qual_type, is_decl(element_type)->get_scope()); array->set_element_type(qual_type); - ctxt.schedule_type_for_late_canonicalization(is_type(qual_type)); + rdr.schedule_type_for_late_canonicalization(is_type(qual_type)); result = is_decl(u); } } @@ -14368,7 +13552,7 @@ maybe_strip_qualification(const qualified_type_def_sptr t, /// Build a pointer type from a DW_TAG_pointer_type DIE. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the DIE to read information from. /// @@ -14383,7 +13567,7 @@ maybe_strip_qualification(const qualified_type_def_sptr t, /// /// @return the resulting pointer to pointer_type_def. static pointer_type_def_sptr -build_pointer_type_def(read_context& ctxt, +build_pointer_type_def(reader& rdr, Dwarf_Die* die, bool called_from_public_decl, size_t where_offset) @@ -14403,12 +13587,12 @@ build_pointer_type_def(read_context& ctxt, if (!die_die_attribute(die, DW_AT_type, underlying_type_die)) // If the DW_AT_type attribute is missing, that means we are // looking at a pointer to "void". - utype_decl = build_ir_node_for_void_type(ctxt); + utype_decl = build_ir_node_for_void_type(rdr); else has_underlying_type_die = true; if (!utype_decl && has_underlying_type_die) - utype_decl = build_ir_node_from_die(ctxt, &underlying_type_die, + utype_decl = build_ir_node_from_die(rdr, &underlying_type_die, called_from_public_decl, where_offset); if (!utype_decl) @@ -14416,7 +13600,7 @@ build_pointer_type_def(read_context& ctxt, // The call to build_ir_node_from_die() could have triggered the // creation of the type for this DIE. In that case, just return it. - if (type_base_sptr t = ctxt.lookup_type_from_die(die)) + if (type_base_sptr t = rdr.lookup_type_from_die(die)) { result = is_pointer_type(t); ABG_ASSERT(result); @@ -14429,7 +13613,7 @@ build_pointer_type_def(read_context& ctxt, // if the DIE for the pointer type doesn't have a byte_size // attribute then we assume the size of the pointer is the address // size of the current translation unit. - uint64_t size = ctxt.cur_transl_unit()->get_address_size(); + uint64_t size = rdr.cur_transl_unit()->get_address_size(); if (die_unsigned_constant_attribute(die, DW_AT_byte_size, size)) // The size as expressed by DW_AT_byte_size is in byte, so let's // convert it to bits. @@ -14437,19 +13621,19 @@ build_pointer_type_def(read_context& ctxt, // And the size of the pointer must be the same as the address size // of the current translation unit. - ABG_ASSERT((size_t) ctxt.cur_transl_unit()->get_address_size() == size); + ABG_ASSERT((size_t) rdr.cur_transl_unit()->get_address_size() == size); result.reset(new pointer_type_def(utype, size, /*alignment=*/0, location())); ABG_ASSERT(result->get_pointed_to_type()); - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } /// Build a reference type from either a DW_TAG_reference_type or /// DW_TAG_rvalue_reference_type DIE. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the DIE to read from. /// @@ -14464,7 +13648,7 @@ build_pointer_type_def(read_context& ctxt, /// /// @return a pointer to the resulting reference_type_def. static reference_type_def_sptr -build_reference_type(read_context& ctxt, +build_reference_type(reader& rdr, Dwarf_Die* die, bool called_from_public_decl, size_t where_offset) @@ -14484,7 +13668,7 @@ build_reference_type(read_context& ctxt, return result; type_or_decl_base_sptr utype_decl = - build_ir_node_from_die(ctxt, &underlying_type_die, + build_ir_node_from_die(rdr, &underlying_type_die, called_from_public_decl, where_offset); if (!utype_decl) @@ -14492,7 +13676,7 @@ build_reference_type(read_context& ctxt, // The call to build_ir_node_from_die() could have triggered the // creation of the type for this DIE. In that case, just return it. - if (type_base_sptr t = ctxt.lookup_type_from_die(die)) + if (type_base_sptr t = rdr.lookup_type_from_die(die)) { result = is_reference_type(t); ABG_ASSERT(result); @@ -14505,29 +13689,29 @@ build_reference_type(read_context& ctxt, // if the DIE for the reference type doesn't have a byte_size // attribute then we assume the size of the reference is the address // size of the current translation unit. - uint64_t size = ctxt.cur_transl_unit()->get_address_size(); + uint64_t size = rdr.cur_transl_unit()->get_address_size(); if (die_unsigned_constant_attribute(die, DW_AT_byte_size, size)) size *= 8; // And the size of the pointer must be the same as the address size // of the current translation unit. - ABG_ASSERT((size_t) ctxt.cur_transl_unit()->get_address_size() == size); + ABG_ASSERT((size_t) rdr.cur_transl_unit()->get_address_size() == size); bool is_lvalue = tag == DW_TAG_reference_type; result.reset(new reference_type_def(utype, is_lvalue, size, /*alignment=*/0, location())); - if (corpus_sptr corp = ctxt.current_corpus()) + if (corpus_sptr corp = rdr.corpus()) if (reference_type_def_sptr t = lookup_reference_type(*result, *corp)) result = t; - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } /// Build a subroutine type from a DW_TAG_subroutine_type DIE. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the DIE to read from. /// @@ -14542,7 +13726,7 @@ build_reference_type(read_context& ctxt, /// /// @return a pointer to the resulting function_type_sptr. static function_type_sptr -build_function_type(read_context& ctxt, +build_function_type(reader& rdr, Dwarf_Die* die, class_or_union_sptr is_method, size_t where_offset) @@ -14555,12 +13739,12 @@ build_function_type(read_context& ctxt, ABG_ASSERT(dwarf_tag(die) == DW_TAG_subroutine_type || dwarf_tag(die) == DW_TAG_subprogram); - const die_source source = ctxt.get_die_source(die); + const die_source source = rdr.get_die_source(die); { size_t off = dwarf_dieoffset(die); - auto i = ctxt.die_wip_function_types_map(source).find(off); - if (i != ctxt.die_wip_function_types_map(source).end()) + auto i = rdr.die_wip_function_types_map(source).find(off); + if (i != rdr.die_wip_function_types_map(source).end()) { function_type_sptr fn_type = is_function_type(i->second); ABG_ASSERT(fn_type); @@ -14570,21 +13754,21 @@ build_function_type(read_context& ctxt, decl_base_sptr type_decl; - translation_unit_sptr tu = ctxt.cur_transl_unit(); + translation_unit_sptr tu = rdr.cur_transl_unit(); ABG_ASSERT(tu); /// If, inside the current translation unit, we've already seen a /// function type with the same text representation, then reuse that /// one instead. - if (type_base_sptr t = ctxt.lookup_fn_type_from_die_repr_per_tu(die)) + if (type_base_sptr t = rdr.lookup_fn_type_from_die_repr_per_tu(die)) { result = is_function_type(t); ABG_ASSERT(result); - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } - bool odr_is_relevant = ctxt.odr_is_relevant(die); + bool odr_is_relevant = rdr.odr_is_relevant(die); if (odr_is_relevant) { // So we can rely on the One Definition Rule to say that if @@ -14595,9 +13779,9 @@ build_function_type(read_context& ctxt, // representation as the function type 'die', then it's the same // type as the one denoted by 'die'. if (function_type_sptr fn_type = - is_function_type(ctxt.lookup_type_artifact_from_die(die))) + is_function_type(rdr.lookup_type_artifact_from_die(die))) { - ctxt.associate_die_to_type(die, fn_type, where_offset); + rdr.associate_die_to_type(die, fn_type, where_offset); return fn_type; } } @@ -14610,7 +13794,7 @@ build_function_type(read_context& ctxt, Dwarf_Die object_pointer_die; Dwarf_Die class_type_die; bool has_this_parm_die = - die_function_type_is_method_type(ctxt, die, where_offset, + die_function_type_is_method_type(rdr, die, where_offset, object_pointer_die, class_type_die, is_static); @@ -14628,7 +13812,7 @@ build_function_type(read_context& ctxt, // by DIE was *NOT* a member function. But now we know it's // a member function. Let's take that into account. class_or_union_sptr klass_type = - is_class_or_union_type(build_ir_node_from_die(ctxt, &class_type_die, + is_class_or_union_type(build_ir_node_from_die(rdr, &class_type_die, /*called_from_pub_decl=*/true, where_offset)); ABG_ASSERT(klass_type); @@ -14645,20 +13829,20 @@ build_function_type(read_context& ctxt, ? new method_type(is_method, is_const, tu->get_address_size(), /*alignment=*/0) - : new function_type(ctxt.env(), tu->get_address_size(), + : new function_type(rdr.env(), tu->get_address_size(), /*alignment=*/0)); - ctxt.associate_die_to_type(die, result, where_offset); - ctxt.die_wip_function_types_map(source)[dwarf_dieoffset(die)] = result; + rdr.associate_die_to_type(die, result, where_offset); + rdr.die_wip_function_types_map(source)[dwarf_dieoffset(die)] = result; type_base_sptr return_type; Dwarf_Die ret_type_die; if (die_die_attribute(die, DW_AT_type, ret_type_die)) return_type = - is_type(build_ir_node_from_die(ctxt, &ret_type_die, + is_type(build_ir_node_from_die(rdr, &ret_type_die, /*called_from_public_decl=*/true, where_offset)); if (!return_type) - return_type = is_type(build_ir_node_for_void_type(ctxt)); + return_type = is_type(build_ir_node_for_void_type(rdr)); result->set_return_type(return_type); Dwarf_Die child; @@ -14673,7 +13857,7 @@ build_function_type(read_context& ctxt, // This is a "normal" function parameter. string name, linkage_name; location loc; - die_loc_and_name(ctxt, &child, loc, name, linkage_name); + die_loc_and_name(rdr, &child, loc, name, linkage_name); if (!tools_utils::string_is_ascii_identifier(name)) // Sometimes, bogus compiler emit names that are // non-ascii garbage. Let's just ditch that for now. @@ -14683,7 +13867,7 @@ build_function_type(read_context& ctxt, Dwarf_Die parm_type_die; if (die_die_attribute(&child, DW_AT_type, parm_type_die)) parm_type = - is_type(build_ir_node_from_die(ctxt, &parm_type_die, + is_type(build_ir_node_from_die(rdr, &parm_type_die, /*called_from_public_decl=*/true, where_offset)); if (!parm_type) @@ -14698,10 +13882,9 @@ build_function_type(read_context& ctxt, { // This is a variadic function parameter. bool is_artificial = die_is_artificial(&child); - ir::environment* env = ctxt.env(); - ABG_ASSERT(env); + type_base_sptr parm_type = - is_type(build_ir_node_for_variadic_parameter_type(ctxt)); + is_type(build_ir_node_for_variadic_parameter_type(rdr)); function_decl::parameter_sptr p (new function_decl::parameter(parm_type, /*name=*/"", @@ -14726,23 +13909,23 @@ build_function_type(read_context& ctxt, result->set_is_artificial(true); - ctxt.associate_die_repr_to_fn_type_per_tu(die, result); + rdr.associate_die_repr_to_fn_type_per_tu(die, result); { die_function_type_map_type::const_iterator i = - ctxt.die_wip_function_types_map(source). + rdr.die_wip_function_types_map(source). find(dwarf_dieoffset(die)); - if (i != ctxt.die_wip_function_types_map(source).end()) - ctxt.die_wip_function_types_map(source).erase(i); + if (i != rdr.die_wip_function_types_map(source).end()) + rdr.die_wip_function_types_map(source).erase(i); } - maybe_canonicalize_type(result, ctxt); + maybe_canonicalize_type(result, rdr); return result; } /// Build a subrange type from a DW_TAG_subrange_type. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the DIE to read from. /// @@ -14763,7 +13946,7 @@ build_function_type(read_context& ctxt, /// @return the newly built instance of @ref /// array_type_def::subrange_type, or nil if no type could be built. static array_type_def::subrange_sptr -build_subrange_type(read_context& ctxt, +build_subrange_type(reader& rdr, const Dwarf_Die* die, size_t where_offset, bool associate_type_to_die) @@ -14786,7 +13969,7 @@ build_subrange_type(read_context& ctxt, bool is_signed = false; if (die_die_attribute(die, DW_AT_type, underlying_type_die)) underlying_type = - is_type(build_ir_node_from_die(ctxt, + is_type(build_ir_node_from_die(rdr, &underlying_type_die, /*called_from_public_decl=*/true, where_offset)); @@ -14800,7 +13983,7 @@ build_subrange_type(read_context& ctxt, is_signed = (ate == DW_ATE_signed || ate == DW_ATE_signed_char); } - translation_unit::language language = ctxt.cur_transl_unit()->get_language(); + translation_unit::language language = rdr.cur_transl_unit()->get_language(); array_type_def::subrange_type::bound_value lower_bound = get_default_array_lower_bound(language); array_type_def::subrange_type::bound_value upper_bound; @@ -14856,7 +14039,7 @@ build_subrange_type(read_context& ctxt, } result.reset - (new array_type_def::subrange_type(ctxt.env(), + (new array_type_def::subrange_type(rdr.env(), name, lower_bound, upper_bound, @@ -14872,7 +14055,7 @@ build_subrange_type(read_context& ctxt, - result->get_lower_bound() + 1))); if (associate_type_to_die) - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } @@ -14881,7 +14064,7 @@ build_subrange_type(read_context& ctxt, /// /// This is a sub-routine of build_array_type(). /// -/// @param ctxt the context to read from. +/// @param rdr the context to read from. /// /// @param die the DIE of tag DW_TAG_array_type which contains /// children DIEs that represent the sub-ranges. @@ -14894,7 +14077,7 @@ build_subrange_type(read_context& ctxt, /// e.g, DW_TAG_partial_unit that can be included in several places in /// the DIE tree. static void -build_subranges_from_array_type_die(read_context& ctxt, +build_subranges_from_array_type_die(reader& rdr, const Dwarf_Die* die, array_type_def::subranges_type& subranges, size_t where_offset, @@ -14916,7 +14099,7 @@ build_subranges_from_array_type_die(read_context& ctxt, // the current type graph and associate it to the // DIE it's been created from. type_or_decl_base_sptr t = - build_ir_node_from_die(ctxt, &child, + build_ir_node_from_die(rdr, &child, /*called_from_public_decl=*/true, where_offset); s = is_subrange_type(t); @@ -14925,7 +14108,7 @@ build_subranges_from_array_type_die(read_context& ctxt, // We are being called to create the type but *NOT* // add it to the current tyupe tree, *NOR* associate // it to the DIE it's been created from. - s = build_subrange_type(ctxt, &child, + s = build_subrange_type(rdr, &child, where_offset, /*associate_type_to_die=*/false); if (s) @@ -14938,7 +14121,7 @@ build_subranges_from_array_type_die(read_context& ctxt, /// Build an array type from a DW_TAG_array_type DIE. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the DIE to read from. /// @@ -14953,7 +14136,7 @@ build_subranges_from_array_type_die(read_context& ctxt, /// /// @return a pointer to the resulting array_type_def. static array_type_def_sptr -build_array_type(read_context& ctxt, +build_array_type(reader& rdr, Dwarf_Die* die, bool called_from_public_decl, size_t where_offset) @@ -14971,7 +14154,7 @@ build_array_type(read_context& ctxt, Dwarf_Die type_die; if (die_die_attribute(die, DW_AT_type, type_die)) - type_decl = is_decl(build_ir_node_from_die(ctxt, &type_die, + type_decl = is_decl(build_ir_node_from_die(rdr, &type_die, called_from_public_decl, where_offset)); if (!type_decl) @@ -14979,7 +14162,7 @@ build_array_type(read_context& ctxt, // The call to build_ir_node_from_die() could have triggered the // creation of the type for this DIE. In that case, just return it. - if (type_base_sptr t = ctxt.lookup_type_from_die(die)) + if (type_base_sptr t = rdr.lookup_type_from_die(die)) { result = is_array_type(t); ABG_ASSERT(result); @@ -14991,7 +14174,7 @@ build_array_type(read_context& ctxt, array_type_def::subranges_type subranges; - build_subranges_from_array_type_die(ctxt, die, subranges, where_offset); + build_subranges_from_array_type_die(rdr, die, subranges, where_offset); result.reset(new array_type_def(type, subranges, location())); @@ -15000,7 +14183,7 @@ build_array_type(read_context& ctxt, /// Create a typedef_decl from a DW_TAG_typedef DIE. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param die the DIE to read from. /// @@ -15015,7 +14198,7 @@ build_array_type(read_context& ctxt, /// /// @return the newly created typedef_decl. static typedef_decl_sptr -build_typedef_type(read_context& ctxt, +build_typedef_type(reader& rdr, Dwarf_Die* die, bool called_from_public_decl, size_t where_offset) @@ -15031,9 +14214,9 @@ build_typedef_type(read_context& ctxt, string name, linkage_name; location loc; - die_loc_and_name(ctxt, die, loc, name, linkage_name); + die_loc_and_name(rdr, die, loc, name, linkage_name); - if (corpus_sptr corp = ctxt.should_reuse_type_from_corpus_group()) + if (corpus_sptr corp = rdr.should_reuse_type_from_corpus_group()) if (loc) result = lookup_typedef_type_per_location(loc.expand(), *corp); @@ -15044,11 +14227,11 @@ build_typedef_type(read_context& ctxt, if (!die_die_attribute(die, DW_AT_type, underlying_type_die)) // A typedef DIE with no underlying type means a typedef to // void type. - utype = ctxt.env()->get_void_type(); + utype = rdr.env().get_void_type(); if (!utype) utype = - is_type(build_ir_node_from_die(ctxt, + is_type(build_ir_node_from_die(rdr, &underlying_type_die, called_from_public_decl, where_offset)); @@ -15069,20 +14252,20 @@ build_typedef_type(read_context& ctxt, } } - ctxt.associate_die_to_type(die, result, where_offset); + rdr.associate_die_to_type(die, result, where_offset); return result; } /// Build a @ref var_decl out of a DW_TAG_variable DIE if the variable /// denoted by the DIE is not suppressed by a suppression -/// specification associated to the current read context. +/// specification associated to the current DWARF reader. /// /// Note that if a member variable declaration with the same name as /// the name of the DIE we are looking at exists, this function returns /// that existing variable declaration. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DIE representing the variable we are looking at. /// @@ -15103,7 +14286,7 @@ build_typedef_type(read_context& ctxt, /// @return a pointer to the newly created var_decl. If the var_decl /// could not be built, this function returns NULL. static var_decl_sptr -build_or_get_var_decl_if_not_suppressed(read_context& ctxt, +build_or_get_var_decl_if_not_suppressed(reader& rdr, scope_decl *scope, Dwarf_Die *die, size_t where_offset, @@ -15111,7 +14294,7 @@ build_or_get_var_decl_if_not_suppressed(read_context& ctxt, bool is_required_decl_spec) { var_decl_sptr var; - if (variable_is_suppressed(ctxt, scope, die, is_required_decl_spec)) + if (variable_is_suppressed(rdr, scope, die, is_required_decl_spec)) return var; if (class_decl* class_type = is_class_type(scope)) @@ -15121,13 +14304,13 @@ build_or_get_var_decl_if_not_suppressed(read_context& ctxt, if ((var = class_type->find_data_member(var_name))) return var; } - var = build_var_decl(ctxt, die, where_offset, result); + var = build_var_decl(rdr, die, where_offset, result); return var; } /// Build a @ref var_decl out of a DW_TAG_variable DIE. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param die the DIE representing the variable we are looking at. /// @@ -15144,7 +14327,7 @@ build_or_get_var_decl_if_not_suppressed(read_context& ctxt, /// @return a pointer to the newly created var_decl. If the var_decl /// could not be built, this function returns NULL. static var_decl_sptr -build_var_decl(read_context& ctxt, +build_var_decl(reader& rdr, Dwarf_Die *die, size_t where_offset, var_decl_sptr result) @@ -15163,7 +14346,7 @@ build_var_decl(read_context& ctxt, if (die_die_attribute(die, DW_AT_type, type_die)) { decl_base_sptr ty = - is_decl(build_ir_node_from_die(ctxt, &type_die, + is_decl(build_ir_node_from_die(rdr, &type_die, /*called_from_public_decl=*/true, where_offset)); if (!ty) @@ -15177,7 +14360,7 @@ build_var_decl(read_context& ctxt, string name, linkage_name; location loc; - die_loc_and_name(ctxt, die, loc, name, linkage_name); + die_loc_and_name(rdr, die, loc, name, linkage_name); if (!result) result.reset(new var_decl(name, type, loc, linkage_name)); @@ -15197,13 +14380,15 @@ build_var_decl(read_context& ctxt, { elf_symbol_sptr var_sym; Dwarf_Addr var_addr; - if (ctxt.get_variable_address(die, var_addr)) + + if (rdr.get_variable_address(die, var_addr)) { - ctxt.symtab()->update_main_symbol(var_addr, - result->get_linkage_name().empty() - ? result->get_name() - : result->get_linkage_name()); - var_sym = ctxt.variable_symbol_is_exported(var_addr); + rdr.symtab()-> + update_main_symbol(var_addr, + result->get_linkage_name().empty() + ? result->get_name() + : result->get_linkage_name()); + var_sym = rdr.variable_symbol_is_exported(var_addr); } if (var_sym) @@ -15229,7 +14414,7 @@ build_var_decl(read_context& ctxt, /// Note that a non-member function which symbol is not exported is /// also suppressed. /// -/// @param ctxt the ELF/DWARF reading content of interest. +/// @param rdr the ELF/DWARF reading content of interest. /// /// @param scope of the scope of the function. /// @@ -15239,9 +14424,9 @@ build_var_decl(read_context& ctxt, /// a declaration-only DIE. /// /// @return true iff @p function_die is suppressed by at least one -/// suppression specification attached to the @p ctxt. +/// suppression specification attached to the @p rdr. static bool -function_is_suppressed(const read_context& ctxt, +function_is_suppressed(const reader& rdr, const scope_decl* scope, Dwarf_Die *function_die, bool is_declaration_only) @@ -15252,7 +14437,7 @@ function_is_suppressed(const read_context& ctxt, string fname = die_string_attribute(function_die, DW_AT_name); string flinkage_name = die_linkage_name(function_die); - if (flinkage_name.empty() && ctxt.die_is_in_c(function_die)) + if (flinkage_name.empty() && rdr.die_is_in_c(function_die)) flinkage_name = fname; string qualified_name = build_qualified_name(scope, fname); @@ -15263,13 +14448,14 @@ function_is_suppressed(const read_context& ctxt, // symbol, by default, it's not suppressed. Unless we are asked to // drop undefined symbols too. if (!is_class_type(scope) - && (!is_declaration_only || ctxt.drop_undefined_syms())) + && (!is_declaration_only || rdr.drop_undefined_syms())) { Dwarf_Addr fn_addr; - if (!ctxt.get_function_address(function_die, fn_addr)) + if (!rdr.get_function_address(function_die, fn_addr)) return true; - elf_symbol_sptr symbol = ctxt.function_symbol_is_exported(fn_addr); + elf_symbol_sptr symbol = + rdr.function_symbol_is_exported(fn_addr); if (!symbol) return true; if (!symbol->is_suppressed()) @@ -15286,14 +14472,13 @@ function_is_suppressed(const read_context& ctxt, return false; } - return suppr::function_is_suppressed(ctxt, qualified_name, - flinkage_name, + return suppr::is_function_suppressed(rdr, qualified_name, flinkage_name, /*require_drop_property=*/true); } /// Build a @ref function_decl out of a DW_TAG_subprogram DIE if the /// function denoted by the DIE is not suppressed by a suppression -/// specification associated to the current read context. +/// specification associated to the current DWARF reader. /// /// Note that if a member function declaration with the same signature /// (pretty representation) as one of the DIE we are looking at @@ -15309,7 +14494,7 @@ function_is_suppressed(const read_context& ctxt, /// accordingly. This is done to support "updating" a function_decl /// IR with properties scathered across several DIEs. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @param scope the scope of the function we are looking at. /// @@ -15332,7 +14517,7 @@ function_is_suppressed(const read_context& ctxt, /// @return a pointer to the newly created var_decl. If the var_decl /// could not be built, this function returns NULL. static function_decl_sptr -build_or_get_fn_decl_if_not_suppressed(read_context& ctxt, +build_or_get_fn_decl_if_not_suppressed(reader& rdr, scope_decl *scope, Dwarf_Die *fn_die, size_t where_offset, @@ -15340,7 +14525,7 @@ build_or_get_fn_decl_if_not_suppressed(read_context& ctxt, function_decl_sptr result) { function_decl_sptr fn; - if (function_is_suppressed(ctxt, scope, fn_die, is_declaration_only)) + if (function_is_suppressed(rdr, scope, fn_die, is_declaration_only)) return fn; string name = die_name(fn_die); @@ -15364,11 +14549,11 @@ build_or_get_fn_decl_if_not_suppressed(read_context& ctxt, // symbols. So re-using C++ destructors like that can lead to us // missing some destructors. if (!result && (!(is_dtor && is_virtual))) - if ((fn = is_function_decl(ctxt.lookup_artifact_from_die(fn_die)))) + if ((fn = is_function_decl(rdr.lookup_artifact_from_die(fn_die)))) { - fn = maybe_finish_function_decl_reading(ctxt, fn_die, where_offset, fn); - ctxt.associate_die_to_decl(fn_die, fn, /*do_associate_by_repr=*/true); - ctxt.associate_die_to_type(fn_die, fn->get_type(), where_offset); + fn = maybe_finish_function_decl_reading(rdr, fn_die, where_offset, fn); + rdr.associate_die_to_decl(fn_die, fn, /*do_associate_by_repr=*/true); + rdr.associate_die_to_type(fn_die, fn->get_type(), where_offset); return fn; } @@ -15387,7 +14572,7 @@ build_or_get_fn_decl_if_not_suppressed(read_context& ctxt, // any associated symbol will be dropped on the floor by // potential_member_fn_should_be_dropped. So let's build or a new // function IR or complete the existing partial IR. - fn = build_function_decl(ctxt, fn_die, where_offset, result); + fn = build_function_decl(rdr, fn_die, where_offset, result); return fn; } @@ -15396,7 +14581,7 @@ build_or_get_fn_decl_if_not_suppressed(read_context& ctxt, /// suppressed by any of the suppression specifications associated to /// a given context of ELF/DWARF reading. /// -/// @param ctxt the ELF/DWARF reading content of interest. +/// @param rdr the ELF/DWARF reading content of interest. /// /// @param scope of the scope of the variable. /// @@ -15407,9 +14592,9 @@ build_or_get_fn_decl_if_not_suppressed(read_context& ctxt, /// specification for a concrete variable being built. /// /// @return true iff @p variable_die is suppressed by at least one -/// suppression specification attached to the @p ctxt. +/// suppression specification attached to the @p rdr. static bool -variable_is_suppressed(const read_context& ctxt, +variable_is_suppressed(const reader& rdr, const scope_decl* scope, Dwarf_Die *variable_die, bool is_required_decl_spec) @@ -15421,7 +14606,7 @@ variable_is_suppressed(const read_context& ctxt, string name = die_string_attribute(variable_die, DW_AT_name); string linkage_name = die_linkage_name(variable_die); - if (linkage_name.empty() && ctxt.die_is_in_c(variable_die)) + if (linkage_name.empty() && rdr.die_is_in_c(variable_die)) linkage_name = name; string qualified_name = build_qualified_name(scope, name); @@ -15433,10 +14618,11 @@ variable_is_suppressed(const read_context& ctxt, if (!is_class_type(scope) && !is_required_decl_spec) { Dwarf_Addr var_addr = 0; - if (!ctxt.get_variable_address(variable_die, var_addr)) + if (!rdr.get_variable_address(variable_die, var_addr)) return true; - elf_symbol_sptr symbol = ctxt.variable_symbol_is_exported(var_addr); + elf_symbol_sptr symbol = + rdr.variable_symbol_is_exported(var_addr); if (!symbol) return true; if (!symbol->is_suppressed()) @@ -15453,16 +14639,17 @@ variable_is_suppressed(const read_context& ctxt, return false; } - return suppr::variable_is_suppressed(ctxt, qualified_name, + return suppr::is_variable_suppressed(rdr, + qualified_name, linkage_name, /*require_drop_property=*/true); } /// Test if a type (designated by a given DIE) in a given scope is /// suppressed by the suppression specifications that are associated -/// to a given read context. +/// to a given DWARF reader. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param scope of the scope of the type DIE to consider. /// @@ -15475,9 +14662,9 @@ variable_is_suppressed(const read_context& ctxt, /// /// @return true iff the type designated by the DIE @p type_die, in /// the scope @p scope is suppressed by at the suppression -/// specifications associated to the current read context. +/// specifications associated to the current DWARF reader. static bool -type_is_suppressed(const read_context& ctxt, +type_is_suppressed(const reader& rdr, const scope_decl* scope, Dwarf_Die *type_die, bool &type_is_private) @@ -15491,10 +14678,11 @@ type_is_suppressed(const read_context& ctxt, string type_name, linkage_name; location type_location; - die_loc_and_name(ctxt, type_die, type_location, type_name, linkage_name); + die_loc_and_name(rdr, type_die, type_location, type_name, linkage_name); string qualified_name = build_qualified_name(scope, type_name); - return suppr::type_is_suppressed(ctxt, qualified_name, + return suppr::is_type_suppressed(rdr, + qualified_name, type_location, type_is_private, /*require_drop_property=*/true); @@ -15502,9 +14690,9 @@ type_is_suppressed(const read_context& ctxt, /// Test if a type (designated by a given DIE) in a given scope is /// suppressed by the suppression specifications that are associated -/// to a given read context. +/// to a given DWARF reader. /// -/// @param ctxt the read context to consider. +/// @param rdr the DWARF reader to consider. /// /// @param scope of the scope of the type DIE to consider. /// @@ -15512,14 +14700,14 @@ type_is_suppressed(const read_context& ctxt, /// /// @return true iff the type designated by the DIE @p type_die, in /// the scope @p scope is suppressed by at the suppression -/// specifications associated to the current read context. +/// specifications associated to the current DWARF reader. static bool -type_is_suppressed(const read_context& ctxt, +type_is_suppressed(const reader& rdr, const scope_decl* scope, Dwarf_Die *type_die) { bool type_is_private = false; - return type_is_suppressed(ctxt, scope, type_die, type_is_private); + return type_is_suppressed(rdr, scope, type_die, type_is_private); } /// Get the opaque version of a type that was suppressed because it's @@ -15529,7 +14717,7 @@ type_is_suppressed(const read_context& ctxt, /// version of the type (class, union or enum type) denoted by @p /// type_die. /// -/// @param ctxt the read context in use. +/// @param rdr the DWARF reader in use. /// /// @param scope the scope of the type die we are looking at. /// @@ -15543,7 +14731,7 @@ type_is_suppressed(const read_context& ctxt, /// @return the opaque version of the type denoted by @p type_die or /// nil if no opaque version was found. static type_or_decl_base_sptr -get_opaque_version_of_type(read_context &ctxt, +get_opaque_version_of_type(reader &rdr, scope_decl *scope, Dwarf_Die *type_die, size_t where_offset) @@ -15562,7 +14750,7 @@ get_opaque_version_of_type(read_context &ctxt, string type_name, linkage_name; location type_location; - die_loc_and_name(ctxt, type_die, type_location, type_name, linkage_name); + die_loc_and_name(rdr, type_die, type_location, type_name, linkage_name); if (!type_location) return result; @@ -15576,8 +14764,8 @@ get_opaque_version_of_type(read_context &ctxt, if (tag == DW_TAG_structure_type || tag == DW_TAG_class_type) { string_classes_map::const_iterator i = - ctxt.declaration_only_classes().find(qualified_name); - if (i != ctxt.declaration_only_classes().end()) + rdr.declaration_only_classes().find(qualified_name); + if (i != rdr.declaration_only_classes().end()) result = i->second.back(); if (!result) @@ -15587,7 +14775,7 @@ get_opaque_version_of_type(read_context &ctxt, // opaque type. So let's build one. // // TODO: we need to be able to do this for unions too! - class_decl_sptr klass(new class_decl(ctxt.env(), type_name, + class_decl_sptr klass(new class_decl(rdr.env(), type_name, /*alignment=*/0, /*size=*/0, tag == DW_TAG_structure_type, type_location, @@ -15595,8 +14783,8 @@ get_opaque_version_of_type(read_context &ctxt, klass->set_is_declaration_only(true); klass->set_is_artificial(die_is_artificial(type_die)); add_decl_to_scope(klass, scope); - ctxt.associate_die_to_type(type_die, klass, where_offset); - ctxt.maybe_schedule_declaration_only_class_for_resolution(klass); + rdr.associate_die_to_type(type_die, klass, where_offset); + rdr.maybe_schedule_declaration_only_class_for_resolution(klass); result = klass; } } @@ -15604,8 +14792,8 @@ get_opaque_version_of_type(read_context &ctxt, if (tag == DW_TAG_enumeration_type) { string_enums_map::const_iterator i = - ctxt.declaration_only_enums().find(qualified_name); - if (i != ctxt.declaration_only_enums().end()) + rdr.declaration_only_enums().find(qualified_name); + if (i != rdr.declaration_only_enums().end()) result = i->second.back(); if (!result) @@ -15614,7 +14802,7 @@ get_opaque_version_of_type(read_context &ctxt, if (die_unsigned_constant_attribute(type_die, DW_AT_byte_size, size)) size *= 8; type_decl_sptr underlying_type = - build_enum_underlying_type(ctxt, type_name, size, + build_enum_underlying_type(rdr, type_name, size, /*anonymous=*/true); enum_type_decl::enumerators enumeratorz; enum_type_decl_sptr enum_type (new enum_type_decl(type_name, @@ -15639,7 +14827,7 @@ get_opaque_version_of_type(read_context &ctxt, /// /// @return the newly created symbol. elf_symbol_sptr -create_default_fn_sym(const string& sym_name, const environment *env) +create_default_fn_sym(const string& sym_name, const environment& env) { elf_symbol::version ver; elf_symbol_sptr result = @@ -15658,7 +14846,7 @@ create_default_fn_sym(const string& sym_name, const environment *env) /// Build a @ref function_decl our of a DW_TAG_subprogram DIE. /// -/// @param ctxt the read context to use +/// @param rdr the DWARF reader to use /// /// @param die the DW_TAG_subprogram DIE to read from. /// @@ -15670,7 +14858,7 @@ create_default_fn_sym(const string& sym_name, const environment *env) /// @param called_for_public_decl this is set to true if the function /// was called for a public (function) decl. static function_decl_sptr -build_function_decl(read_context& ctxt, +build_function_decl(reader& rdr, Dwarf_Die* die, size_t where_offset, function_decl_sptr fn) @@ -15683,16 +14871,16 @@ build_function_decl(read_context& ctxt, if (!die_is_public_decl(die)) return result; - translation_unit_sptr tu = ctxt.cur_transl_unit(); + translation_unit_sptr tu = rdr.cur_transl_unit(); ABG_ASSERT(tu); string fname, flinkage_name; location floc; - die_loc_and_name(ctxt, die, floc, fname, flinkage_name); + die_loc_and_name(rdr, die, floc, fname, flinkage_name); size_t is_inline = die_is_declared_inline(die); class_or_union_sptr is_method = - is_class_or_union_type(get_scope_for_die(ctxt, die, true, where_offset)); + is_class_or_union_type(get_scope_for_die(rdr, die, true, where_offset)); if (result) { @@ -15713,12 +14901,12 @@ build_function_decl(read_context& ctxt, } else { - function_type_sptr fn_type(build_function_type(ctxt, die, is_method, + function_type_sptr fn_type(build_function_type(rdr, die, is_method, where_offset)); if (!fn_type) return result; - maybe_canonicalize_type(fn_type, ctxt); + maybe_canonicalize_type(fn_type, rdr); result.reset(is_method ? new method_decl(fname, fn_type, @@ -15735,16 +14923,17 @@ build_function_decl(read_context& ctxt, { elf_symbol_sptr fn_sym; Dwarf_Addr fn_addr; - if (ctxt.get_function_address(die, fn_addr)) + if (rdr.get_function_address(die, fn_addr)) { - ctxt.symtab()->update_main_symbol(fn_addr, - result->get_linkage_name().empty() - ? result->get_name() - : result->get_linkage_name()); - fn_sym = ctxt.function_symbol_is_exported(fn_addr); + rdr.symtab()-> + update_main_symbol(fn_addr, + result->get_linkage_name().empty() + ? result->get_name() + : result->get_linkage_name()); + fn_sym = rdr.function_symbol_is_exported(fn_addr); } - if (fn_sym && !ctxt.symbol_already_belongs_to_a_function(fn_sym)) + if (fn_sym && !rdr.symbol_already_belongs_to_a_function(fn_sym)) { result->set_symbol(fn_sym); string linkage_name = result->get_linkage_name(); @@ -15754,7 +14943,7 @@ build_function_decl(read_context& ctxt, } } - ctxt.associate_die_to_type(die, result->get_type(), where_offset); + rdr.associate_die_to_type(die, result->get_type(), where_offset); size_t die_offset = dwarf_dieoffset(die); @@ -15767,250 +14956,10 @@ build_function_decl(read_context& ctxt, // It thus doesn't need any fixup related to elf symbol. So // remove it from the set of virtual member functions with linkage // names and no elf symbol that need to be fixed up. - ctxt.die_function_decl_with_no_symbol_map().erase(die_offset); + rdr.die_function_decl_with_no_symbol_map().erase(die_offset); return result; } -/// Read all @ref abigail::translation_unit possible from the debug info -/// accessible through a DWARF Front End Library handle, and stuff -/// them into a libabigail ABI Corpus. -/// -/// @param ctxt the read context. -/// -/// @return a pointer to the resulting corpus, or NULL if the corpus -/// could not be constructed. -static corpus_sptr -read_debug_info_into_corpus(read_context& ctxt) -{ - ctxt.clear_per_corpus_data(); - ctxt.current_corpus(std::make_shared(ctxt.env(), ctxt.elf_path())); - - // First set some mundane properties of the corpus gathered from - // ELF. - ctxt.current_corpus()->set_path(ctxt.elf_path()); - - corpus::origin origin = corpus::DWARF_ORIGIN; - if (is_linux_kernel(ctxt.elf_handle())) - origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN; - ctxt.current_corpus()->set_origin(origin); - - if (origin & corpus::LINUX_KERNEL_BINARY_ORIGIN - && !ctxt.env()->user_set_analyze_exported_interfaces_only()) - // So we are looking at the Linux Kernel and the user has not set - // any particular option regarding the amount of types to analyse. - // In that case, we need to only analyze types that are reachable - // from exported interfaces otherwise we get such a massive amount - // of type DIEs to look at that things are just too slow down the - // road. - ctxt.env()->analyze_exported_interfaces_only(true); - - ctxt.current_corpus()->set_soname(ctxt.dt_soname()); - ctxt.current_corpus()->set_needed(ctxt.dt_needed()); - ctxt.current_corpus()->set_architecture_name(ctxt.elf_architecture()); - if (corpus_group_sptr group = ctxt.current_corpus_group()) - group->add_corpus(ctxt.current_corpus()); - - // Set symbols information to the corpus. - ctxt.current_corpus()->set_symtab(ctxt.symtab()); - - // Get out now if no debug info is found. - if (!ctxt.dwarf()) - return ctxt.current_corpus(); - - uint8_t address_size = 0; - size_t header_size = 0; - - // Set the set of exported declaration that are defined. - ctxt.exported_decls_builder - (ctxt.current_corpus()->get_exported_decls_builder().get()); - -#ifdef WITH_DEBUG_SELF_COMPARISON - if (ctxt.env()->self_comparison_debug_is_on()) - ctxt.env()->set_self_comparison_debug_input(ctxt.current_corpus()); -#endif - - // Walk all the DIEs of the debug info to build a DIE -> parent map - // useful for get_die_parent() to work. - { - tools_utils::timer t; - if (ctxt.do_log()) - { - cerr << "building die -> parent maps ..."; - t.start(); - } - - ctxt.build_die_parent_maps(); - - if (ctxt.do_log()) - { - t.stop(); - cerr << " DONE@" << ctxt.current_corpus()->get_path() - << ":" - << t - << "\n"; - } - } - - ctxt.env()->canonicalization_is_done(false); - - { - tools_utils::timer t; - if (ctxt.do_log()) - { - cerr << "building the libabigail internal representation ..."; - t.start(); - } - // And now walk all the DIEs again to build the libabigail IR. - Dwarf_Half dwarf_version = 0; - for (Dwarf_Off offset = 0, next_offset = 0; - (dwarf_next_unit(ctxt.dwarf(), offset, &next_offset, &header_size, - &dwarf_version, NULL, &address_size, NULL, - NULL, NULL) == 0); - offset = next_offset) - { - Dwarf_Off die_offset = offset + header_size; - Dwarf_Die unit; - if (!dwarf_offdie(ctxt.dwarf(), die_offset, &unit) - || dwarf_tag(&unit) != DW_TAG_compile_unit) - continue; - - ctxt.dwarf_version(dwarf_version); - - address_size *= 8; - - // Build a translation_unit IR node from cu; note that cu must - // be a DW_TAG_compile_unit die. - translation_unit_sptr ir_node = - build_translation_unit_and_add_to_ir(ctxt, &unit, address_size); - ABG_ASSERT(ir_node); - } - if (ctxt.do_log()) - { - t.stop(); - cerr << " DONE@" << ctxt.current_corpus()->get_path() - << ":" - << t - << "\n"; - - cerr << "Number of aggregate types compared: " - << ctxt.compare_count_ << "\n" - << "Number of canonical types propagated: " - << ctxt.canonical_propagated_count_ << "\n" - << "Number of cancelled propagated canonical types:" - << ctxt.cancelled_propagation_count_ << "\n"; - } - } - - { - tools_utils::timer t; - if (ctxt.do_log()) - { - cerr << "resolving declaration only classes ..."; - t.start(); - } - ctxt.resolve_declaration_only_classes(); - if (ctxt.do_log()) - { - t.stop(); - cerr << " DONE@" << ctxt.current_corpus()->get_path() - << ":" - << t - <<"\n"; - } - } - - { - tools_utils::timer t; - if (ctxt.do_log()) - { - cerr << "resolving declaration only enums ..."; - t.start(); - } - ctxt.resolve_declaration_only_enums(); - if (ctxt.do_log()) - { - t.stop(); - cerr << " DONE@" << ctxt.current_corpus()->get_path() - << ":" - << t - <<"\n"; - } - } - - { - tools_utils::timer t; - if (ctxt.do_log()) - { - cerr << "fixing up functions with linkage name but " - << "no advertised underlying symbols ...."; - t.start(); - } - ctxt.fixup_functions_with_no_symbols(); - if (ctxt.do_log()) - { - t.stop(); - cerr << " DONE@" << ctxt.current_corpus()->get_path() - <<":" - << t - <<"\n"; - } - } - - /// Now, look at the types that needs to be canonicalized after the - /// translation has been constructed (which is just now) and - /// canonicalize them. - /// - /// These types need to be constructed at the end of the translation - /// unit reading phase because some types are modified by some DIEs - /// even after the principal DIE describing the type has been read; - /// this happens for clones of virtual destructors (for instance) or - /// even for some static data members. We need to do that for types - /// are in the alternate debug info section and for types that in - /// the main debug info section. - { - tools_utils::timer t; - if (ctxt.do_log()) - { - cerr << "perform late type canonicalizing ...\n"; - t.start(); - } - - ctxt.perform_late_type_canonicalizing(); - if (ctxt.do_log()) - { - t.stop(); - cerr << "late type canonicalizing DONE@" - << ctxt.current_corpus()->get_path() - << ":" - << t - << "\n"; - } - } - - ctxt.env()->canonicalization_is_done(true); - - { - tools_utils::timer t; - if (ctxt.do_log()) - { - cerr << "sort functions and variables ..."; - t.start(); - } - ctxt.current_corpus()->sort_functions(); - ctxt.current_corpus()->sort_variables(); - if (ctxt.do_log()) - { - t.stop(); - cerr << " DONE@" << ctxt.current_corpus()->get_path() - << ":" - << t - <<" \n"; - } - } - - return ctxt.current_corpus(); -} - /// Canonicalize a type if it's suitable for early canonicalizing, or, /// if it's not, schedule it for late canonicalization, after the /// debug info of the current translation unit has been fully read. @@ -16024,10 +14973,10 @@ read_debug_info_into_corpus(read_context& ctxt) /// /// @param t the type DIE to consider for canonicalization. /// -/// @param ctxt the @ref read_context to use. +/// @param rdr the @ref reader to use. static void maybe_canonicalize_type(const type_base_sptr& t, - read_context& ctxt) + reader& rdr) { if (!t) return; @@ -16049,9 +14998,9 @@ maybe_canonicalize_type(const type_base_sptr& t, // side. We also delay canonicalization for array and qualified // types because they can be edited (in particular by // maybe_strip_qualification) after they are initially built. - ctxt.schedule_type_for_late_canonicalization(t); + rdr.schedule_type_for_late_canonicalization(t); else if (type_has_non_canonicalized_subtype(t)) - ctxt.schedule_type_for_late_canonicalization(t); + rdr.schedule_type_for_late_canonicalization(t); else canonicalize(t); } @@ -16121,10 +15070,10 @@ potential_member_fn_should_be_dropped(const function_decl_sptr& fn, } /// Build an IR node from a given DIE and add the node to the current -/// IR being build and held in the read_context. Doing that is called +/// IR being build and held in the DWARF reader. Doing that is called /// "emitting an IR node for the DIE". /// -/// @param ctxt the read context. +/// @param rdr the DWARF reader. /// /// @param die the DIE to consider. /// @@ -16153,7 +15102,7 @@ potential_member_fn_should_be_dropped(const function_decl_sptr& fn, /// /// @return the resulting IR node. static type_or_decl_base_sptr -build_ir_node_from_die(read_context& ctxt, +build_ir_node_from_die(reader& rdr, Dwarf_Die* die, scope_decl* scope, bool called_from_public_decl, @@ -16170,7 +15119,7 @@ build_ir_node_from_die(read_context& ctxt, if (!called_from_public_decl) { - if (ctxt.load_all_types() && die_is_type(die)) + if (rdr.load_all_types() && die_is_type(die)) /* We were instructed to load debug info for all types, included those that are not reachable from a public declaration. So load the debug info for this type. */; @@ -16181,12 +15130,12 @@ build_ir_node_from_die(read_context& ctxt, return result; } - const die_source source_of_die = ctxt.get_die_source(die); + const die_source source_of_die = rdr.get_die_source(die); - if ((result = ctxt.lookup_decl_from_die_offset(dwarf_dieoffset(die), + if ((result = rdr.lookup_decl_from_die_offset(dwarf_dieoffset(die), source_of_die))) { - if (ctxt.load_all_types()) + if (rdr.load_all_types()) if (called_from_public_decl) if (type_base_sptr t = is_type(result)) if (corpus *abi_corpus = scope->get_corpus()) @@ -16205,10 +15154,10 @@ build_ir_node_from_die(read_context& ctxt, { // Type DIEs we support. case DW_TAG_base_type: - if (type_decl_sptr t = build_type_decl(ctxt, die, where_offset)) + if (type_decl_sptr t = build_type_decl(rdr, die, where_offset)) { result = - add_decl_to_scope(t, ctxt.cur_transl_unit()->get_global_scope()); + add_decl_to_scope(t, rdr.cur_transl_unit()->get_global_scope()); canonicalize(t); } break; @@ -16219,7 +15168,7 @@ build_ir_node_from_die(read_context& ctxt, t = is_typedef(scope->find_member_type(die_name(die))); if (!t) - t = build_typedef_type(ctxt, die, + t = build_typedef_type(rdr, die, called_from_public_decl, where_offset); @@ -16227,7 +15176,7 @@ build_ir_node_from_die(read_context& ctxt, if (result) { maybe_set_member_type_access_specifier(is_decl(result), die); - maybe_canonicalize_type(t, ctxt); + maybe_canonicalize_type(t, rdr); } } break; @@ -16235,15 +15184,15 @@ build_ir_node_from_die(read_context& ctxt, case DW_TAG_pointer_type: { pointer_type_def_sptr p = - build_pointer_type_def(ctxt, die, + build_pointer_type_def(rdr, die, called_from_public_decl, where_offset); if (p) { result = - add_decl_to_scope(p, ctxt.cur_transl_unit()->get_global_scope()); + add_decl_to_scope(p, rdr.cur_transl_unit()->get_global_scope()); ABG_ASSERT(result->get_translation_unit()); - maybe_canonicalize_type(p, ctxt); + maybe_canonicalize_type(p, rdr); } } break; @@ -16252,16 +15201,16 @@ build_ir_node_from_die(read_context& ctxt, case DW_TAG_rvalue_reference_type: { reference_type_def_sptr r = - build_reference_type(ctxt, die, + build_reference_type(rdr, die, called_from_public_decl, where_offset); if (r) { result = - add_decl_to_scope(r, ctxt.cur_transl_unit()->get_global_scope()); + add_decl_to_scope(r, rdr.cur_transl_unit()->get_global_scope()); - ctxt.associate_die_to_type(die, r, where_offset); - maybe_canonicalize_type(r, ctxt); + rdr.associate_die_to_type(die, r, where_offset); + maybe_canonicalize_type(r, rdr); } } break; @@ -16271,7 +15220,7 @@ build_ir_node_from_die(read_context& ctxt, case DW_TAG_restrict_type: { type_base_sptr q = - build_qualified_type(ctxt, die, + build_qualified_type(rdr, die, called_from_public_decl, where_offset); if (q) @@ -16279,7 +15228,7 @@ build_ir_node_from_die(read_context& ctxt, // Strip some potentially redundant type qualifiers from // the qualified type we just built. decl_base_sptr d = maybe_strip_qualification(is_qualified_type(q), - ctxt); + rdr); if (!d) d = get_type_declaration(q); ABG_ASSERT(d); @@ -16287,10 +15236,10 @@ build_ir_node_from_die(read_context& ctxt, // Associate the die to type ty again because 'ty'might be // different from 'q', because 'ty' is 'q' possibly // stripped from some redundant type qualifier. - ctxt.associate_die_to_type(die, ty, where_offset); + rdr.associate_die_to_type(die, ty, where_offset); result = - add_decl_to_scope(d, ctxt.cur_transl_unit()->get_global_scope()); - maybe_canonicalize_type(is_type(result), ctxt); + add_decl_to_scope(d, rdr.cur_transl_unit()->get_global_scope()); + maybe_canonicalize_type(is_type(result), rdr); } } break; @@ -16299,7 +15248,7 @@ build_ir_node_from_die(read_context& ctxt, { bool type_is_private = false; bool type_suppressed = - type_is_suppressed(ctxt, scope, die, type_is_private); + type_is_suppressed(rdr, scope, die, type_is_private); if (type_suppressed && type_is_private) { // The type is suppressed because it's private. If other @@ -16308,19 +15257,19 @@ build_ir_node_from_die(read_context& ctxt, // non-suppressed instances are opaque versions of the // suppressed private type. Lets return one of these opaque // types then. - result = get_opaque_version_of_type(ctxt, scope, die, where_offset); - maybe_canonicalize_type(is_type(result), ctxt); + result = get_opaque_version_of_type(rdr, scope, die, where_offset); + maybe_canonicalize_type(is_type(result), rdr); } else if (!type_suppressed) { - enum_type_decl_sptr e = build_enum_type(ctxt, die, scope, + enum_type_decl_sptr e = build_enum_type(rdr, die, scope, where_offset, is_declaration_only); result = add_decl_to_scope(e, scope); if (result) { maybe_set_member_type_access_specifier(is_decl(result), die); - maybe_canonicalize_type(is_type(result), ctxt); + maybe_canonicalize_type(is_type(result), rdr); } } } @@ -16331,7 +15280,7 @@ build_ir_node_from_die(read_context& ctxt, { bool type_is_private = false; bool type_suppressed= - type_is_suppressed(ctxt, scope, die, type_is_private); + type_is_suppressed(rdr, scope, die, type_is_private); if (type_suppressed && type_is_private) { @@ -16341,8 +15290,8 @@ build_ir_node_from_die(read_context& ctxt, // non-suppressed instances are opaque versions of the // suppressed private type. Lets return one of these opaque // types then. - result = get_opaque_version_of_type(ctxt, scope, die, where_offset); - maybe_canonicalize_type(is_type(result), ctxt); + result = get_opaque_version_of_type(rdr, scope, die, where_offset); + maybe_canonicalize_type(is_type(result), rdr); } else if (!type_suppressed) { @@ -16352,12 +15301,12 @@ build_ir_node_from_die(read_context& ctxt, if (die_die_attribute(die, DW_AT_specification, spec_die)) { scope_decl_sptr skope = - get_scope_for_die(ctxt, &spec_die, + get_scope_for_die(rdr, &spec_die, called_from_public_decl, where_offset); ABG_ASSERT(skope); decl_base_sptr cl = - is_decl(build_ir_node_from_die(ctxt, &spec_die, + is_decl(build_ir_node_from_die(rdr, &spec_die, skope.get(), called_from_public_decl, where_offset, @@ -16368,7 +15317,7 @@ build_ir_node_from_die(read_context& ctxt, ABG_ASSERT(klass); klass = - add_or_update_class_type(ctxt, die, + add_or_update_class_type(rdr, die, skope.get(), tag == DW_TAG_structure_type, klass, @@ -16378,7 +15327,7 @@ build_ir_node_from_die(read_context& ctxt, } else klass = - add_or_update_class_type(ctxt, die, scope, + add_or_update_class_type(rdr, die, scope, tag == DW_TAG_structure_type, class_decl_sptr(), called_from_public_decl, @@ -16388,16 +15337,16 @@ build_ir_node_from_die(read_context& ctxt, if (klass) { maybe_set_member_type_access_specifier(klass, die); - maybe_canonicalize_type(klass, ctxt); + maybe_canonicalize_type(klass, rdr); } } } break; case DW_TAG_union_type: - if (!type_is_suppressed(ctxt, scope, die)) + if (!type_is_suppressed(rdr, scope, die)) { union_decl_sptr union_type = - add_or_update_union_type(ctxt, die, scope, + add_or_update_union_type(rdr, die, scope, union_decl_sptr(), called_from_public_decl, where_offset, @@ -16405,7 +15354,7 @@ build_ir_node_from_die(read_context& ctxt, if (union_type) { maybe_set_member_type_access_specifier(union_type, die); - maybe_canonicalize_type(union_type, ctxt); + maybe_canonicalize_type(union_type, rdr); } result = union_type; } @@ -16414,29 +15363,29 @@ build_ir_node_from_die(read_context& ctxt, break; case DW_TAG_subroutine_type: { - function_type_sptr f = build_function_type(ctxt, die, + function_type_sptr f = build_function_type(rdr, die, class_decl_sptr(), where_offset); if (f) { result = f; result->set_is_artificial(false); - maybe_canonicalize_type(f, ctxt); + maybe_canonicalize_type(f, rdr); } } break; case DW_TAG_array_type: { - array_type_def_sptr a = build_array_type(ctxt, + array_type_def_sptr a = build_array_type(rdr, die, called_from_public_decl, where_offset); if (a) { result = - add_decl_to_scope(a, ctxt.cur_transl_unit()->get_global_scope()); - ctxt.associate_die_to_type(die, a, where_offset); - maybe_canonicalize_type(a, ctxt); + add_decl_to_scope(a, rdr.cur_transl_unit()->get_global_scope()); + rdr.associate_die_to_type(die, a, where_offset); + maybe_canonicalize_type(a, rdr); } break; } @@ -16446,13 +15395,13 @@ build_ir_node_from_die(read_context& ctxt, // form" defined in the global namespace of the current // translation unit, like what is found in Ada. array_type_def::subrange_sptr s = - build_subrange_type(ctxt, die, where_offset); + build_subrange_type(rdr, die, where_offset); if (s) { result = - add_decl_to_scope(s, ctxt.cur_transl_unit()->get_global_scope()); - ctxt.associate_die_to_type(die, s, where_offset); - maybe_canonicalize_type(s, ctxt); + add_decl_to_scope(s, rdr.cur_transl_unit()->get_global_scope()); + rdr.associate_die_to_type(die, s, where_offset); + maybe_canonicalize_type(s, rdr); } } break; @@ -16480,7 +15429,7 @@ build_ir_node_from_die(read_context& ctxt, case DW_TAG_namespace: case DW_TAG_module: - result = build_namespace_decl_and_add_to_ir(ctxt, die, where_offset); + result = build_namespace_decl_and_add_to_ir(rdr, die, where_offset); break; case DW_TAG_variable: @@ -16490,21 +15439,21 @@ build_ir_node_from_die(read_context& ctxt, bool var_is_cloned = false; if (tag == DW_TAG_member) - ABG_ASSERT(!is_c_language(ctxt.cur_transl_unit()->get_language())); + ABG_ASSERT(!is_c_language(rdr.cur_transl_unit()->get_language())); if (die_die_attribute(die, DW_AT_specification, spec_die, false) || (var_is_cloned = die_die_attribute(die, DW_AT_abstract_origin, spec_die, false))) { scope_decl_sptr spec_scope = - get_scope_for_die(ctxt, &spec_die, + get_scope_for_die(rdr, &spec_die, /*called_from_public_decl=*/ - die_is_effectively_public_decl(ctxt, die), + die_is_effectively_public_decl(rdr, die), where_offset); if (spec_scope) { decl_base_sptr d = - is_decl(build_ir_node_from_die(ctxt, &spec_die, + is_decl(build_ir_node_from_die(rdr, &spec_die, spec_scope.get(), called_from_public_decl, where_offset, @@ -16516,26 +15465,26 @@ build_ir_node_from_die(read_context& ctxt, dynamic_pointer_cast(d); if (var_is_cloned) m = m->clone(); - m = build_var_decl(ctxt, die, where_offset, m); + m = build_var_decl(rdr, die, where_offset, m); if (is_data_member(m)) { set_member_is_static(m, true); - ctxt.associate_die_to_decl(die, m, where_offset, + rdr.associate_die_to_decl(die, m, where_offset, /*associate_by_repr=*/false); } else { ABG_ASSERT(has_scope(m)); - ctxt.var_decls_to_re_add_to_tree().push_back(m); + rdr.var_decls_to_re_add_to_tree().push_back(m); } ABG_ASSERT(m->get_scope()); - ctxt.maybe_add_var_to_exported_decls(m.get()); + rdr.maybe_add_var_to_exported_decls(m.get()); result = m; } } } else if (var_decl_sptr v = - build_or_get_var_decl_if_not_suppressed(ctxt, scope, die, + build_or_get_var_decl_if_not_suppressed(rdr, scope, die, where_offset, /*result=*/var_decl_sptr(), is_required_decl_spec)) @@ -16545,8 +15494,8 @@ build_ir_node_from_die(read_context& ctxt, v = dynamic_pointer_cast(result); ABG_ASSERT(v); ABG_ASSERT(v->get_scope()); - ctxt.var_decls_to_re_add_to_tree().push_back(v); - ctxt.maybe_add_var_to_exported_decls(v.get()); + rdr.var_decls_to_re_add_to_tree().push_back(v); + rdr.maybe_add_var_to_exported_decls(v.get()); } } break; @@ -16580,7 +15529,7 @@ build_ir_node_from_die(read_context& ctxt, string linkage_name = die_linkage_name(die); string spec_linkage_name = die_linkage_name(interface_die); - interface_scope = get_scope_for_die(ctxt, interface_die, + interface_scope = get_scope_for_die(rdr, interface_die, called_from_public_decl, where_offset); if (interface_scope) @@ -16591,7 +15540,7 @@ build_ir_node_from_die(read_context& ctxt, d = c->find_member_function_sptr(linkage_name); if (!d) - d = is_decl(build_ir_node_from_die(ctxt, + d = is_decl(build_ir_node_from_die(rdr, origin_die, interface_scope.get(), called_from_public_decl, @@ -16612,14 +15561,14 @@ build_ir_node_from_die(read_context& ctxt, } } } - ctxt.scope_stack().push(scope); + rdr.scope_stack().push(scope); scope_decl* logical_scope = interface_scope ? interface_scope.get() : scope; - result = build_or_get_fn_decl_if_not_suppressed(ctxt, logical_scope, + result = build_or_get_fn_decl_if_not_suppressed(rdr, logical_scope, die, where_offset, is_declaration_only, fn); @@ -16642,18 +15591,18 @@ build_ir_node_from_die(read_context& ctxt, class_decl_sptr klass(static_cast(logical_scope), sptr_utils::noop_deleter()); ABG_ASSERT(klass); - finish_member_function_reading(die, fn, klass, ctxt); + finish_member_function_reading(die, fn, klass, rdr); } if (fn) { - ctxt.maybe_add_fn_to_exported_decls(fn.get()); - ctxt.associate_die_to_decl(die, fn, where_offset, + rdr.maybe_add_fn_to_exported_decls(fn.get()); + rdr.associate_die_to_decl(die, fn, where_offset, /*associate_by_repr=*/false); - maybe_canonicalize_type(fn->get_type(), ctxt); + maybe_canonicalize_type(fn->get_type(), rdr); } - ctxt.scope_stack().pop(); + rdr.scope_stack().pop(); } break; @@ -16718,11 +15667,11 @@ build_ir_node_from_die(read_context& ctxt, } if (result && tag != DW_TAG_subroutine_type) - ctxt.associate_die_to_decl(die, is_decl(result), where_offset, + rdr.associate_die_to_decl(die, is_decl(result), where_offset, /*associate_by_repr=*/false); if (result) - if (ctxt.load_all_types()) + if (rdr.load_all_types()) if (called_from_public_decl) if (type_base_sptr t = is_type(result)) if (corpus *abi_corpus = scope->get_corpus()) @@ -16733,48 +15682,48 @@ build_ir_node_from_die(read_context& ctxt, /// Build the IR node for a void type. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @return the void type node. static decl_base_sptr -build_ir_node_for_void_type(read_context& ctxt) +build_ir_node_for_void_type(reader& rdr) { - ir::environment* env = ctxt.env(); - ABG_ASSERT(env); - type_base_sptr t = env->get_void_type(); + const environment& env = rdr.env(); + + type_base_sptr t = env.get_void_type(); decl_base_sptr type_declaration = get_type_declaration(t); if (!has_scope(type_declaration)) add_decl_to_scope(type_declaration, - ctxt.cur_transl_unit()->get_global_scope()); + rdr.cur_transl_unit()->get_global_scope()); canonicalize(t); return type_declaration; } /// Build the IR node for a variadic parameter type. /// -/// @param ctxt the read context to use. +/// @param rdr the DWARF reader to use. /// /// @return the variadic parameter type. static decl_base_sptr -build_ir_node_for_variadic_parameter_type(read_context &ctxt) +build_ir_node_for_variadic_parameter_type(reader &rdr) { - ir::environment* env = ctxt.env(); - ABG_ASSERT(env); - type_base_sptr t = env->get_variadic_parameter_type(); + const environment& env = rdr.env(); + + type_base_sptr t = env.get_variadic_parameter_type(); decl_base_sptr type_declaration = get_type_declaration(t); if (!has_scope(type_declaration)) add_decl_to_scope(type_declaration, - ctxt.cur_transl_unit()->get_global_scope()); + rdr.cur_transl_unit()->get_global_scope()); canonicalize(t); return type_declaration; } /// Build an IR node from a given DIE and add the node to the current -/// IR being build and held in the read_context. Doing that is called +/// IR being build and held in the DWARF reader. Doing that is called /// "emitting an IR node for the DIE". /// -/// @param ctxt the read context. +/// @param rdr the DWARF reader. /// /// @param die the DIE to consider. /// @@ -16793,7 +15742,7 @@ build_ir_node_for_variadic_parameter_type(read_context &ctxt) /// /// @return the resulting IR node. static type_or_decl_base_sptr -build_ir_node_from_die(read_context& ctxt, +build_ir_node_from_die(reader& rdr, Dwarf_Die* die, bool called_from_public_decl, size_t where_offset) @@ -16801,10 +15750,10 @@ build_ir_node_from_die(read_context& ctxt, if (!die) return decl_base_sptr(); - if (is_c_language(ctxt.cur_transl_unit()->get_language())) + if (is_c_language(rdr.cur_transl_unit()->get_language())) { - const scope_decl_sptr& scop = ctxt.global_scope(); - return build_ir_node_from_die(ctxt, die, scop.get(), + const scope_decl_sptr& scop = rdr.global_scope(); + return build_ir_node_from_die(rdr, die, scop.get(), called_from_public_decl, where_offset, true); @@ -16819,17 +15768,17 @@ build_ir_node_from_die(read_context& ctxt, // to it, it'll be dropped on the floor anyway. Those variable // decls are considered as being "effectively public". bool consider_as_called_from_public_decl = - called_from_public_decl || die_is_effectively_public_decl(ctxt, die); - scope_decl_sptr scope = get_scope_for_die(ctxt, die, + called_from_public_decl || die_is_effectively_public_decl(rdr, die); + scope_decl_sptr scope = get_scope_for_die(rdr, die, consider_as_called_from_public_decl, where_offset); - return build_ir_node_from_die(ctxt, die, scope.get(), + return build_ir_node_from_die(rdr, die, scope.get(), called_from_public_decl, where_offset, true); } -/// Create a dwarf_reader::read_context. +/// Create a dwarf_reader::reader. /// /// @param elf_path the path to the elf file the context is to be used for. /// @@ -16839,14 +15788,14 @@ build_ir_node_from_die(read_context& ctxt, /// file. /// /// @param environment the environment used by the current context. -/// This environment contains resources needed by the reader and by +/// This environment contains resources needed by the DWARF 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 +/// reader the context uses resources that are allocated in the /// environment. /// /// @param load_all_types if set to false only the types that are @@ -16858,33 +15807,27 @@ build_ir_node_from_die(read_context& ctxt, /// linux kernel symbol tables when determining if a symbol is /// exported or not. /// -/// @return a smart pointer to the resulting dwarf_reader::read_context. -read_context_sptr -create_read_context(const std::string& elf_path, +/// @return a smart pointer to the resulting dwarf_reader::reader. +elf_based_reader_sptr +create_dwarf_reader(const std::string& elf_path, const vector& debug_info_root_paths, - ir::environment* environment, + environment& environment, bool load_all_types, bool linux_kernel_mode) { - // Create a DWARF Front End Library handle to be used by functions - // of that library. - read_context_sptr result(new read_context(elf_path, debug_info_root_paths, - environment, load_all_types, - linux_kernel_mode)); - return result; -} -/// Getter for the path to the binary this @ref read_context is for. -/// -/// @return the path to the binary the @ref read_context is for. -const string& -read_context_get_path(const read_context& ctxt) -{return ctxt.elf_path();} + reader_sptr r = reader::create(elf_path, + debug_info_root_paths, + environment, + load_all_types, + linux_kernel_mode); + return static_pointer_cast(r); +} -/// Re-initialize a read_context so that it can re-used to read +/// Re-initialize a reader so that it can re-used to read /// another binary. /// -/// @param ctxt the context to re-initialize. +/// @param rdr the context to re-initialize. /// /// @param elf_path the path to the elf file the context is to be used /// for. @@ -16895,14 +15838,14 @@ read_context_get_path(const read_context& ctxt) /// file. /// /// @param environment the environment used by the current context. -/// This environment contains resources needed by the reader and by +/// This environment contains resources needed by the DWARF 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 +/// reader the context uses resources that are allocated in the /// environment. /// /// @param load_all_types if set to false only the types that are @@ -16914,137 +15857,17 @@ read_context_get_path(const read_context& ctxt) /// linux kernel symbol tables when determining if a symbol is /// exported or not. /// -/// @return a smart pointer to the resulting dwarf_reader::read_context. -void -reset_read_context(read_context_sptr &ctxt, - const std::string& elf_path, - const vector& debug_info_root_path, - ir::environment* environment, - bool read_all_types, - bool linux_kernel_mode) -{ - if (ctxt) - ctxt->initialize(elf_path, debug_info_root_path, environment, - read_all_types, linux_kernel_mode); -} - -/// Add suppressions specifications to the set of suppressions to be -/// used during the construction of the ABI internal representation -/// (the ABI corpus) from ELF and DWARF. -/// -/// During the construction of the ABI corpus, ABI artifacts that -/// match the a given suppression specification are dropped on the -/// floor; that is, they are discarded and won't be part of the final -/// ABI corpus. This is a way to reduce the amount of data held by -/// the final ABI corpus. -/// -/// Note that the suppression specifications provided to this function -/// are only considered during the construction of the ABI corpus. -/// For instance, they are not taken into account during e.g -/// comparisons of two ABI corpora that might happen later. If you -/// want to apply suppression specificatins to the comparison (or -/// reporting) of ABI corpora please refer to the documentation of the -/// @ref diff_context type to learn how to set suppressions that are -/// to be used in that context. -/// -/// @param ctxt the context that is going to be used by functions that -/// read ELF and DWARF information to construct and ABI corpus. -/// -/// @param supprs the suppression specifications to be applied during -/// the construction of the ABI corpus. -void -add_read_context_suppressions(read_context& ctxt, - const suppr::suppressions_type& supprs) -{ - for (suppr::suppressions_type::const_iterator i = supprs.begin(); - i != supprs.end(); - ++i) - if ((*i)->get_drops_artifact_from_ir()) - ctxt.get_suppressions().push_back(*i); -} - -/// Set the @ref corpus_group being created to the current read context. -/// -/// @param ctxt the read_context to consider. -/// -/// @param group the @ref corpus_group to set. +/// @return a smart pointer to the resulting dwarf_reader::reader. void -set_read_context_corpus_group(read_context& ctxt, - corpus_group_sptr& group) -{ - ctxt.cur_corpus_group_ = group; -} - -/// Read all @ref abigail::translation_unit possible from the debug info -/// accessible from an elf file, stuff them into a libabigail ABI -/// Corpus and return it. -/// -/// @param ctxt the context to use for reading the elf file. -/// -/// @param resulting_corp a pointer to the resulting abigail::corpus. -/// -/// @return the resulting status. -corpus_sptr -read_corpus_from_elf(read_context& ctxt, status& status) -{ - status = STATUS_UNKNOWN; - - // Load debug info from the elf path. - if (!ctxt.load_debug_info()) - status |= STATUS_DEBUG_INFO_NOT_FOUND; - - { - string alt_di_path; - if (refers_to_alt_debug_info(ctxt, alt_di_path) && !ctxt.alt_dwarf()) - status |= STATUS_ALT_DEBUG_INFO_NOT_FOUND; - } - - ctxt.load_elf_properties(); // DT_SONAME, DT_NEEDED, architecture - - if (!ctxt.symtab() || !ctxt.symtab()->has_symbols()) - status |= STATUS_NO_SYMBOLS_FOUND; - - if (// If no elf symbol was found ... - status & STATUS_NO_SYMBOLS_FOUND - // ... or if debug info was found but not the required alternate - // debug info ... - || ((status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) - && !(status & STATUS_DEBUG_INFO_NOT_FOUND))) - // ... then we cannot handle the binary. - return corpus_sptr(); - - // Read the variable and function descriptions from the debug info - // we have, through the dwfl handle. - corpus_sptr corp = read_debug_info_into_corpus(ctxt); - - status |= STATUS_OK; - - return corp; -} - -/// Read a corpus and add it to a given @ref corpus_group. -/// -/// @param ctxt the reading context to consider. -/// -/// @param group the @ref corpus_group to add the new corpus to. -/// -/// @param status output parameter. The status of the read. It is set -/// by this function upon its completion. -corpus_sptr -read_and_add_corpus_to_group_from_elf(read_context& ctxt, - corpus_group& group, - status& status) +reset_dwarf_reader(elf_based_reader& rdr, + const std::string& elf_path, + const vector&debug_info_root_path, + bool read_all_types, + bool linux_kernel_mode) { - corpus_sptr result; - corpus_sptr corp = read_corpus_from_elf(ctxt, status); - if (status & STATUS_OK) - { - if (!corp->get_group()) - group.add_corpus(corp); - result = corp; - } - - return result; + reader& r = dynamic_cast(rdr); + r.initialize(elf_path, debug_info_root_path, + read_all_types, linux_kernel_mode); } /// Read all @ref abigail::translation_unit possible from the debug info @@ -17063,7 +15886,7 @@ read_and_add_corpus_to_group_from_elf(read_context& ctxt, /// containing the debug info file. /// /// @param environment the environment used by the current context. -/// This environment contains resources needed by the reader and by +/// This environment contains resources needed by the DWARF 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 @@ -17082,16 +15905,16 @@ read_and_add_corpus_to_group_from_elf(read_context& ctxt, corpus_sptr read_corpus_from_elf(const std::string& elf_path, const vector& debug_info_root_paths, - ir::environment* environment, + environment& environment, bool load_all_types, - status& status) + fe_iface::status& status) { - read_context_sptr c = create_read_context(elf_path, - debug_info_root_paths, - environment, - load_all_types); - read_context& ctxt = *c; - return read_corpus_from_elf(ctxt, status); + elf_based_reader_sptr rdr = + dwarf_reader::reader::create(elf_path, debug_info_root_paths, + environment, load_all_types, + /*linux_kernel_mode=*/false); + + return rdr->read_corpus(status); } /// Look into the symbol tables of a given elf file and see if we find @@ -17111,7 +15934,7 @@ read_corpus_from_elf(const std::string& elf_path, /// @return true iff the symbol was found among the publicly exported /// symbols of the ELF file. bool -lookup_symbol_from_elf(const environment* env, +lookup_symbol_from_elf(environment& env, const string& elf_path, const string& symbol_name, bool demangle, @@ -17156,7 +15979,7 @@ lookup_symbol_from_elf(const environment* env, /// @return true iff a function with symbol name @p symbol_name is /// found. bool -lookup_public_function_symbol_from_elf(const environment* env, +lookup_public_function_symbol_from_elf(environment& env, const string& path, const string& symname, vector& syms) @@ -17183,218 +16006,6 @@ lookup_public_function_symbol_from_elf(const environment* env, return value; } -/// Check if the underlying elf file refers to an alternate debug info -/// file associated to it. -/// -/// Note that "alternate debug info sections" is a GNU extension as -/// of DWARF4 and is described at -/// http://www.dwarfstd.org/ShowIssue.php?issue=120604.1. -/// -/// @param ctxt the context used to read the elf file. -/// -/// @param alt_di the path to the alternate debug info file. This is -/// set iff the function returns true. -/// -/// @return true if the ELF file refers to an alternate debug info -/// file. -bool -refers_to_alt_debug_info(const read_context& ctxt, - string& alt_di_path) -{ - if (!ctxt.alt_debug_info_path().empty()) - { - alt_di_path = ctxt.alt_debug_info_path(); - return true; - } - return false; -} - -/// Check if the underlying elf file has an alternate debug info file -/// associated to it. -/// -/// Note that "alternate debug info sections" is a GNU extension as -/// of DWARF4 and is described at -/// http://www.dwarfstd.org/ShowIssue.php?issue=120604.1. -/// -/// @param ctxt the read_context to use to handle the underlying elf file. -/// -/// @param has_alt_di out parameter. This is set to true upon -/// succesful completion of the function iff an alternate debug info -/// file was found, false otherwise. Note thas this parameter is set -/// only if the function returns STATUS_OK. -/// -/// @param alt_debug_info_path if the function returned STATUS_OK and -/// if @p has been set to true, then this parameter contains the path -/// to the alternate debug info file found. -/// -/// return STATUS_OK upon successful completion, false otherwise. -status -has_alt_debug_info(read_context& ctxt, - bool& has_alt_di, - string& alt_debug_info_path) -{ - // Load debug info from the elf path. - if (!ctxt.load_debug_info()) - return STATUS_DEBUG_INFO_NOT_FOUND; - - if (ctxt.alt_dwarf()) - { - has_alt_di = true; - alt_debug_info_path = ctxt.alt_debug_info_path(); - } - else - has_alt_di = false; - - return STATUS_OK; -} - -/// Check if a given elf file has an alternate debug info file -/// associated to it. -/// -/// Note that "alternate debug info sections" is a GNU extension as -/// of DWARF4 and is described at -/// http://www.dwarfstd.org/ShowIssue.php?issue=120604.1. -/// -/// @param elf_path the path to the elf file to consider. -/// -/// @param a pointer to the root directory under which the split debug info -/// file associated to elf_path is to be found. This has to be NULL -/// if the debug info file is not in a split file. -/// -/// @param has_alt_di out parameter. This is set to true upon -/// succesful completion of the function iff an alternate debug info -/// file was found, false otherwise. Note thas this parameter is set -/// only if the function returns STATUS_OK. -/// -/// @param alt_debug_info_path if the function returned STATUS_OK and -/// if @p has been set to true, then this parameter contains the path -/// to the alternate debug info file found. -/// -/// return STATUS_OK upon successful completion, false otherwise. -status -has_alt_debug_info(const string& elf_path, - char** debug_info_root_path, - bool& has_alt_di, - string& alt_debug_info_path) -{ - vector di_roots; - di_roots.push_back(debug_info_root_path); - read_context_sptr c = create_read_context(elf_path, di_roots, 0); - read_context& ctxt = *c; - - // Load debug info from the elf path. - if (!ctxt.load_debug_info()) - return STATUS_DEBUG_INFO_NOT_FOUND; - - if (ctxt.alt_dwarf()) - { - has_alt_di = true; - alt_debug_info_path = ctxt.alt_debug_info_path(); - } - else - has_alt_di = false; - - return STATUS_OK; -} - -/// Fetch the SONAME ELF property from an ELF binary file. -/// -/// @param path The path to the elf file to consider. -/// -/// @param soname out parameter. Set to the SONAME property of the -/// binary file, if it present in the ELF file. -/// -/// return false if an error occured while looking for the SONAME -/// property in the binary, true otherwise. -bool -get_soname_of_elf_file(const string& path, string &soname) -{ - - int fd = open(path.c_str(), O_RDONLY); - if (fd == -1) - return false; - - elf_version (EV_CURRENT); - Elf* elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); - - GElf_Ehdr ehdr_mem; - GElf_Ehdr* ehdr = gelf_getehdr (elf, &ehdr_mem); - if (ehdr == NULL) - return false; - - for (int i = 0; i < ehdr->e_phnum; ++i) - { - GElf_Phdr phdr_mem; - GElf_Phdr* phdr = gelf_getphdr (elf, i, &phdr_mem); - - if (phdr != NULL && phdr->p_type == PT_DYNAMIC) - { - Elf_Scn* scn = gelf_offscn (elf, phdr->p_offset); - GElf_Shdr shdr_mem; - GElf_Shdr* shdr = gelf_getshdr (scn, &shdr_mem); - size_t entsize = (shdr != NULL && shdr->sh_entsize != 0 - ? shdr->sh_entsize - : gelf_fsize (elf, ELF_T_DYN, 1, EV_CURRENT)); - int maxcnt = (shdr != NULL - ? shdr->sh_size / entsize : INT_MAX); - ABG_ASSERT (shdr == NULL || (shdr->sh_type == SHT_DYNAMIC - || shdr->sh_type == SHT_PROGBITS)); - Elf_Data* data = elf_getdata (scn, NULL); - if (data == NULL) - break; - - for (int cnt = 0; cnt < maxcnt; ++cnt) - { - GElf_Dyn dynmem; - GElf_Dyn* dyn = gelf_getdyn (data, cnt, &dynmem); - if (dyn == NULL) - continue; - - if (dyn->d_tag == DT_NULL) - break; - - if (dyn->d_tag != DT_SONAME) - continue; - - soname = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val); - break; - } - break; - } - } - - elf_end(elf); - close(fd); - - return true; -} - -/// Get the type of a given elf type. -/// -/// @param path the absolute path to the ELF file to analyzed. -/// -/// @param type the kind of the ELF file designated by @p path. -/// -/// @param out parameter. Is set to the type of ELF file of @p path. -/// This parameter is set iff the function returns true. -/// -/// @return true iff the file could be opened and analyzed. -bool -get_type_of_elf_file(const string& path, elf_type& type) -{ - int fd = open(path.c_str(), O_RDONLY); - if (fd == -1) - return false; - - elf_version (EV_CURRENT); - Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); - type = elf_file_type(elf); - elf_end(elf); - close(fd); - - return true; -} - }// end namespace dwarf_reader }// end namespace abigail diff --git a/src/abg-elf-based-reader.cc b/src/abg-elf-based-reader.cc new file mode 100644 index 00000000..b8e5eb09 --- /dev/null +++ b/src/abg-elf-based-reader.cc @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// -*- Mode: C++ -*- +// +// Copyright (C) 2022 Red Hat, Inc. +// +// Author: Dodji Seketeli + +/// @file +/// +/// This file contains the definitions of the entry points of the +/// generic interface for ELF-based front-ends. The generic interface +/// for ELF-based front-ends is named @ref elf_based_reader. Examples +/// of front-ends that implement that interface are @ref +/// abigail::dwarf_reader::reader and abigail::ctf_raeder::reader. + +#include "abg-internal.h" + +// +ABG_BEGIN_EXPORT_DECLARATIONS + +#include "abg-elf-based-reader.h" + +ABG_END_EXPORT_DECLARATIONS +// +namespace abigail +{ + +/// The private data of the @ref elf_based_reader type. +struct elf_based_reader::priv +{ + + void + initialize() + { + } + + priv() + { + initialize(); + } +}; // end struct elf_based_reader::priv + +/// Constructor of the @erf elf_based_reader type. +/// +/// @param elf_path the path the ELF file to read. +/// +/// @param debug_info_root_paths a vector of paths to look into for +/// split debug info files. +/// +/// @param env the environment used by the reader. +elf_based_reader::elf_based_reader(const std::string& elf_path, + const vector& debug_info_root_paths, + environment& env) + : elf_reader::reader(elf_path, debug_info_root_paths, env), + priv_(new priv) +{ + priv_->initialize(); +} + +/// Destructor of the reader. +elf_based_reader::~elf_based_reader() +{delete priv_;} + +/// Reset (re-initialize) the resources used by the current reader. +/// +/// This frees the resources of the current reader and gets it ready +/// to read data from another ELF file. +/// +/// @param elf_path the path to the new ELF file to consider. +/// +/// @param debug_info_root_paths a vector of paths to look into for +/// split debug info files. +void +elf_based_reader::reset(const std::string& elf_path, + const vector& debug_info_root_paths) +{ + elf_reader::reader::reset(elf_path, debug_info_root_paths); + priv_->initialize(); +} + +/// Read an ABI corpus and add it to a given corpus group. +/// +/// @param group the corpus group to consider. The new corpus is +/// added to this group. +/// +/// @param status output parameter. This is the status of the +/// creation of the current ABI corpus. It's set by this function iff +/// a non-nil @ref corpus_sptr is returned. +/// +/// @return the resulting ABI corpus. +ir::corpus_sptr +elf_based_reader::read_and_add_corpus_to_group(ir::corpus_group& group, + fe_iface::status& status) +{ + ir::corpus_sptr corp = read_corpus(status); + + if (status & fe_iface::STATUS_OK) + group.add_corpus(corp); + return corp; +} + +} // end namespace abigail diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc index cbcf5428..8221ff84 100644 --- a/src/abg-elf-helpers.cc +++ b/src/abg-elf-helpers.cc @@ -6,11 +6,13 @@ /// @file /// /// This contains the definitions of the ELF utilities for the dwarf reader. - +#include +#include +#include +#include +#include +#include #include "abg-elf-helpers.h" - -#include - #include "abg-tools-utils.h" namespace abigail @@ -1333,6 +1335,179 @@ address_is_in_opd_section(Elf* elf_handle, Dwarf_Addr addr) return false; } +/// Get data tag information of an ELF file by looking up into its +/// dynamic segment +/// +/// @param elf the elf handle to use for the query. +/// +/// @param dt_tag data tag to look for in dynamic segment +/// @param dt_tag_data vector of found information for a given @p data_tag +/// +/// @return true iff data tag @p data_tag was found +bool +lookup_data_tag_from_dynamic_segment(Elf* elf, + Elf64_Sxword data_tag, + vector& dt_tag_data) +{ + size_t num_prog_headers = 0; + bool found = false; + if (elf_getphdrnum(elf, &num_prog_headers) < 0) + return found; + + // Cycle through each program header. + for (size_t i = 0; i < num_prog_headers; ++i) + { + GElf_Phdr phdr_mem; + GElf_Phdr *phdr = gelf_getphdr(elf, i, &phdr_mem); + if (phdr == NULL || phdr->p_type != PT_DYNAMIC) + continue; + + // Poke at the dynamic segment like a section, so that we can + // get its section header information; also we'd like to read + // the data of the segment by using elf_getdata() but that + // function needs a Elf_Scn data structure to act on. + // Elfutils doesn't really have any particular function to + // access segment data, other than the functions used to + // access section data. + Elf_Scn *dynamic_section = gelf_offscn(elf, phdr->p_offset); + GElf_Shdr shdr_mem; + GElf_Shdr *dynamic_section_header = gelf_getshdr(dynamic_section, + &shdr_mem); + if (dynamic_section_header == NULL + || dynamic_section_header->sh_type != SHT_DYNAMIC) + continue; + + // Get data of the dynamic segment (seen as a section). + Elf_Data *data = elf_getdata(dynamic_section, NULL); + if (data == NULL) + continue; + + // Get the index of the section headers string table. + size_t string_table_index = 0; + ABG_ASSERT (elf_getshdrstrndx(elf, &string_table_index) >= 0); + + size_t dynamic_section_header_entry_size = gelf_fsize(elf, + ELF_T_DYN, 1, + EV_CURRENT); + + GElf_Shdr link_mem; + GElf_Shdr *link = + gelf_getshdr(elf_getscn(elf, + dynamic_section_header->sh_link), + &link_mem); + ABG_ASSERT(link != NULL); + + size_t num_dynamic_section_entries = + dynamic_section_header->sh_size / dynamic_section_header_entry_size; + + // Now walk through all the DT_* data tags that are in the + // segment/section + for (size_t j = 0; j < num_dynamic_section_entries; ++j) + { + GElf_Dyn dynamic_section_mem; + GElf_Dyn *dynamic_section = gelf_getdyn(data, + j, + &dynamic_section_mem); + if (dynamic_section->d_tag == data_tag) + { + dt_tag_data.push_back(elf_strptr(elf, + dynamic_section_header->sh_link, + dynamic_section->d_un.d_val)); + found = true; + } + } + } + return found; +} + +const Dwfl_Callbacks& +initialize_dwfl_callbacks(Dwfl_Callbacks& cb, + char** debug_info_root_path) +{ + cb.find_debuginfo = dwfl_standard_find_debuginfo; + cb.section_address = dwfl_offline_section_address; + cb.debuginfo_path = debug_info_root_path; + return cb; +} + +dwfl_sptr +create_new_dwfl_handle(Dwfl_Callbacks& cb) +{ + dwfl_sptr handle(dwfl_begin(&cb), dwfl_deleter()); + return handle; +} + +/// Fetch the SONAME ELF property from an ELF binary file. +/// +/// @param path The path to the elf file to consider. +/// +/// @param soname out parameter. Set to the SONAME property of the +/// binary file, if it present in the ELF file. +/// +/// return false if an error occured while looking for the SONAME +/// property in the binary, true otherwise. +bool +get_soname_of_elf_file(const string& path, string &soname) +{ + + int fd = open(path.c_str(), O_RDONLY); + if (fd == -1) + return false; + + elf_version (EV_CURRENT); + Elf* elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); + + GElf_Ehdr ehdr_mem; + GElf_Ehdr* ehdr = gelf_getehdr (elf, &ehdr_mem); + if (ehdr == NULL) + return false; + + for (int i = 0; i < ehdr->e_phnum; ++i) + { + GElf_Phdr phdr_mem; + GElf_Phdr* phdr = gelf_getphdr (elf, i, &phdr_mem); + + if (phdr != NULL && phdr->p_type == PT_DYNAMIC) + { + Elf_Scn* scn = gelf_offscn (elf, phdr->p_offset); + GElf_Shdr shdr_mem; + GElf_Shdr* shdr = gelf_getshdr (scn, &shdr_mem); + size_t entsize = (shdr != NULL && shdr->sh_entsize != 0 + ? shdr->sh_entsize + : gelf_fsize (elf, ELF_T_DYN, 1, EV_CURRENT)); + int maxcnt = (shdr != NULL + ? shdr->sh_size / entsize : INT_MAX); + ABG_ASSERT (shdr == NULL || (shdr->sh_type == SHT_DYNAMIC + || shdr->sh_type == SHT_PROGBITS)); + Elf_Data* data = elf_getdata (scn, NULL); + if (data == NULL) + break; + + for (int cnt = 0; cnt < maxcnt; ++cnt) + { + GElf_Dyn dynmem; + GElf_Dyn* dyn = gelf_getdyn (data, cnt, &dynmem); + if (dyn == NULL) + continue; + + if (dyn->d_tag == DT_NULL) + break; + + if (dyn->d_tag != DT_SONAME) + continue; + + soname = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val); + break; + } + break; + } + } + + elf_end(elf); + close(fd); + + return true; +} } // end namespace elf_helpers } // end namespace abigail diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h index e884c6a3..b0b105de 100644 --- a/src/abg-elf-helpers.h +++ b/src/abg-elf-helpers.h @@ -24,6 +24,27 @@ namespace abigail namespace elf_helpers { +/// A functor used by @ref dwfl_sptr. +struct dwfl_deleter +{ + void + operator()(Dwfl* dwfl) + {dwfl_end(dwfl);} +};//end struct dwfl_deleter + +/// A convenience typedef for a shared pointer to a Dwfl. +typedef shared_ptr dwfl_sptr; + +/// Convenience typedef for a map which key is an elf address and +/// which value is an elf_symbol_sptr. +typedef unordered_map addr_elf_symbol_sptr_map_type; + +/// Convenience typedef for a set of ELF addresses. +typedef unordered_set address_set_type; + +/// Convenience typedef for a shared pointer to an @ref address_set_type. +typedef shared_ptr address_set_sptr; + // // ELF Value Converters // @@ -173,6 +194,16 @@ is_linux_kernel_module(Elf *elf_handle); bool is_linux_kernel(Elf *elf_handle); +// +// elfutils helpers +// + +const Dwfl_Callbacks& +initialize_dwfl_callbacks(Dwfl_Callbacks&, char**); + +dwfl_sptr +create_new_dwfl_handle(Dwfl_Callbacks&); + // // Misc Helpers // @@ -195,6 +226,13 @@ maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf* elf_handle, GElf_Sym* sym); bool address_is_in_opd_section(Elf* elf_handle, Dwarf_Addr addr); +bool +lookup_data_tag_from_dynamic_segment(Elf* elf, + Elf64_Sxword data_tag, + vector& dt_tag_data); + +bool +get_soname_of_elf_file(const string& path, string &soname); } // end namespace elf_helpers } // end namespace abigail diff --git a/src/abg-elf-reader-common.cc b/src/abg-elf-reader-common.cc deleted file mode 100644 index 1d0aff15..00000000 --- a/src/abg-elf-reader-common.cc +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -*- Mode: C++ -*- -// -// Copyright (C) 2013-2022 Oracle, Inc. -// -// Author: Jose E. Marchesi - -/// @file -/// -/// This file contains the implementation of facilities to deal with -/// status codes related to ELF based readers. -/// -/// More generally, this file contains definitions related to -/// facilities shared by the various readers that handle the ELF -/// format, e.g, the DWARF and CTF realder. -#include "config.h" - -#include "abg-internal.h" - -// -ABG_BEGIN_EXPORT_DECLARATIONS - -#include "abg-elf-reader-common.h" - -ABG_END_EXPORT_DECLARATIONS -// - -namespace abigail -{ - -namespace elf_reader -{ - -status -operator|(status l, status r) -{ - return static_cast(static_cast(l) - | static_cast(r)); -} - -status -operator&(status l, status r) -{ - return static_cast(static_cast(l) - & static_cast(r)); -} - -status& -operator|=(status& l, status r) -{ - l = l | r; - return l; -} - -status& -operator&=(status& l, status r) -{ - l = l & r; - return l; -} - -/// Return a diagnostic status with english sentences to describe the -/// problems encoded in a given abigail::elf_reader::status, if -/// there is an error. -/// -/// @param status the status to diagnose -/// -/// @return a string containing sentences that describe the possible -/// errors encoded in @p s. If there is no error to encode, then the -/// empty string is returned. -std::string -status_to_diagnostic_string(status s) -{ - std::string str; - - if (s & STATUS_DEBUG_INFO_NOT_FOUND) - str += "could not find debug info\n"; - - if (s & STATUS_ALT_DEBUG_INFO_NOT_FOUND) - str += "could not find alternate debug info\n"; - - if (s & STATUS_NO_SYMBOLS_FOUND) - str += "could not load ELF symbols\n"; - - return str; -} - -}// end namespace elf_reader - -}// end namespace abigail diff --git a/src/abg-elf-reader.cc b/src/abg-elf-reader.cc new file mode 100644 index 00000000..346d17a2 --- /dev/null +++ b/src/abg-elf-reader.cc @@ -0,0 +1,890 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// -*- Mode: C++ -*- +// +// Copyright (C) 2022 Red Hat, Inc. +// +// Author: Dodji Seketeli + +/// @file +/// +/// Elf reader stuff + +#include "abg-internal.h" + +#include /* For open(3) */ +#include +#include +#include +#include +#include +#include + + +#include "abg-symtab-reader.h" +#include "abg-suppression-priv.h" +#include "abg-elf-helpers.h" + +// +ABG_BEGIN_EXPORT_DECLARATIONS +#include "abg-elf-reader.h" +#include "abg-tools-utils.h" +ABG_END_EXPORT_DECLARATIONS +// +namespace abigail +{ + +using namespace elf_helpers; + +namespace elf_reader +{ + +/// Find the file name of the alternate debug info file. +/// +/// @param elf_module the elf module to consider. +/// +/// @param out parameter. Is set to the file name of the alternate +/// debug info file, iff this function returns true. +/// +/// @return true iff the location of the alternate debug info file was +/// found. +static bool +find_alt_dwarf_debug_info_link(Dwfl_Module *elf_module, + string &alt_file_name) +{ + GElf_Addr bias = 0; + Dwarf *dwarf = dwfl_module_getdwarf(elf_module, &bias); + Elf *elf = dwarf_getelf(dwarf); + GElf_Ehdr ehmem, *elf_header; + elf_header = gelf_getehdr(elf, &ehmem); + + Elf_Scn* section = 0; + while ((section = elf_nextscn(elf, section)) != 0) + { + GElf_Shdr header_mem, *header; + header = gelf_getshdr(section, &header_mem); + if (header->sh_type != SHT_PROGBITS) + continue; + + const char *section_name = elf_strptr(elf, + elf_header->e_shstrndx, + header->sh_name); + + char *alt_name = 0; + char *buildid = 0; + size_t buildid_len = 0; + if (section_name != 0 + && strcmp(section_name, ".gnu_debugaltlink") == 0) + { + Elf_Data *data = elf_getdata(section, 0); + if (data != 0 && data->d_size != 0) + { + alt_name = (char*) data->d_buf; + char *end_of_alt_name = + (char *) memchr(alt_name, '\0', data->d_size); + buildid_len = data->d_size - (end_of_alt_name - alt_name + 1); + if (buildid_len == 0) + return false; + buildid = end_of_alt_name + 1; + } + } + else + continue; + + if (buildid == 0 || alt_name == 0) + return false; + + alt_file_name = alt_name; + return true; + } + + return false; +} + +/// Find alternate debuginfo file of a given "link" under a set of +/// root directories. +/// +/// The link is a string that is read by the function +/// find_alt_dwarf_debug_info_link(). That link is a path that is relative +/// to a given debug info file, e.g, "../../../.dwz/something.debug". +/// It designates the alternate debug info file associated to a given +/// debug info file. +/// +/// This function will thus try to find the .dwz/something.debug file +/// under some given root directories. +/// +/// @param root_dirs the set of root directories to look from. +/// +/// @param alt_file_name a relative path to the alternate debug info +/// file to look for. +/// +/// @param alt_file_path the resulting absolute path to the alternate +/// debuginfo path denoted by @p alt_file_name and found under one of +/// the directories in @p root_dirs. This is set iff the function +/// returns true. +/// +/// @return true iff the function found the alternate debuginfo file. +static bool +find_alt_dwarf_debug_info_path(const vector root_dirs, + const string &alt_file_name, + string &alt_file_path) +{ + if (alt_file_name.empty()) + return false; + + string altfile_name = tools_utils::trim_leading_string(alt_file_name, "../"); + + for (vector::const_iterator i = root_dirs.begin(); + i != root_dirs.end(); + ++i) + if (tools_utils::find_file_under_dir(**i, altfile_name, alt_file_path)) + return true; + + return false; +} + +/// Return the alternate debug info associated to a given main debug +/// info file. +/// +/// @param elf_module the elf module to consider. +/// +/// @param debug_root_dirs a set of root debuginfo directories under +/// which too look for the alternate debuginfo file. +/// +/// @param alt_file_name output parameter. This is set to the file +/// path of the alternate debug info file associated to @p elf_module. +/// This is set iff the function returns a non-null result. +/// +/// @param alt_fd the file descriptor used to access the alternate +/// debug info. If this parameter is set by the function, then the +/// caller needs to fclose it, otherwise the file descriptor is going +/// to be leaked. Note however that on recent versions of elfutils +/// where libdw.h contains the function dwarf_getalt(), this parameter +/// is set to 0, so it doesn't need to be fclosed. +/// +/// Note that the alternate debug info file is a DWARF extension as of +/// DWARF 4 ans is decribed at +/// http://www.dwarfstd.org/ShowIssue.php?issue=120604.1. +/// +/// @return the alternate debuginfo, or null. If @p alt_fd is +/// non-zero, then the caller of this function needs to call +/// dwarf_end() on the returned alternate debuginfo pointer, +/// otherwise, it's going to be leaked. +static Dwarf* +find_alt_dwarf_debug_info(Dwfl_Module *elf_module, + const vector debug_root_dirs, + string& alt_file_name, + int& alt_fd) +{ + if (elf_module == 0) + return 0; + + Dwarf* result = 0; + find_alt_dwarf_debug_info_link(elf_module, alt_file_name); + +#ifdef LIBDW_HAS_DWARF_GETALT + // We are on recent versions of elfutils where the function + // dwarf_getalt exists, so let's use it. + Dwarf_Addr bias = 0; + Dwarf* dwarf = dwfl_module_getdwarf(elf_module, &bias); + result = dwarf_getalt(dwarf); + alt_fd = 0; +#else + // We are on an old version of elfutils where the function + // dwarf_getalt doesn't exist yet, so let's open code its + // functionality + char *alt_name = 0; + const char *file_name = 0; + void **user_data = 0; + Dwarf_Addr low_addr = 0; + char *alt_file = 0; + + file_name = dwfl_module_info(elf_module, &user_data, + &low_addr, 0, 0, 0, 0, 0); + + alt_fd = dwfl_standard_find_debuginfo(elf_module, user_data, + file_name, low_addr, + alt_name, file_name, + 0, &alt_file); + + result = dwarf_begin(alt_fd, DWARF_C_READ); +#endif + + if (result == 0) + { + // So we didn't find the alternate debuginfo file from the + // information that is in the debuginfo file associated to + // elf_module. Maybe the alternate debuginfo file is located + // under one of the directories in debug_root_dirs. So let's + // look in there. + string alt_file_path; + if (!find_alt_dwarf_debug_info_path(debug_root_dirs, + alt_file_name, + alt_file_path)) + return result; + + // If we reach this point it means we have found the path to the + // alternate debuginfo file and it's in alt_file_path. So let's + // open it and read it. + int fd = open(alt_file_path.c_str(), O_RDONLY); + if (fd == -1) + return result; + result = dwarf_begin(fd, DWARF_C_READ); + +#ifdef LIBDW_HAS_DWARF_GETALT + Dwarf_Addr bias = 0; + Dwarf* dwarf = dwfl_module_getdwarf(elf_module, &bias); + dwarf_setalt(dwarf, result); +#endif + } + + return result; +} + +/// Private data of the @ref elf_reader::reader type. +struct reader::priv +{ + reader& rdr; + Elf* elf_handle = nullptr; + Elf_Scn* symtab_section = nullptr; + string elf_architecture; + vector dt_needed; + // An abstraction of the symbol table. This is loaded lazily, on + // demand. + mutable symtab_reader::symtab_sptr symt; + // Where split debug info is to be searched for on disk. + vector debug_info_root_paths; + // Some very useful callback functions that elfutils needs to + // perform various tasks. + Dwfl_Callbacks offline_callbacks; + // A pointer to the DWARF Front End Library handle of elfutils. + // This is useful to perform all kind of things at a higher level. + dwfl_sptr dwfl_handle; + // The address range of the offline elf file we are looking at. + Dwfl_Module* elf_module = nullptr; + // A pointer to the DWARF debug info, if found by locate_dwarf_debug_info. + Dwarf* dwarf_handle = nullptr; + // A pointer to the ALT DWARF debug info, which is the debug info + // that is constructed by the DWZ tool. It's made of all the type + // information that was redundant in the DWARF. DWZ put it there + // and make the DWARF reference it in here. + Dwarf* alt_dwarf_handle = nullptr; + string alt_dwarf_path; + int alt_dwarf_fd = 0; + Elf_Scn* ctf_section = nullptr; + Elf_Scn* alt_ctf_section = nullptr; + + priv(reader& reeder, const std::string& elf_path, + const vector& debug_info_roots) + : rdr(reeder) + { + rdr.corpus_path(elf_path); + initialize(debug_info_roots); + } + + /// Reset the private data of @elf elf_reader::reader. + /// + /// @param debug_info_roots the vector of new directories where to + /// look for split debug info file. + void + initialize(const vector& debug_info_roots) + { + debug_info_root_paths = debug_info_roots; + symt.reset(); + dwfl_handle.reset(); + elf_module = nullptr; + elf_handle = nullptr; + } + + /// Setup the necessary plumbing to open the ELF file and find all + /// the associated split debug info files. + /// + /// This function also setup the various handles on the opened ELF + /// file and whatnot. + void + crack_open_elf_file() + { + // Initialize the callback functions used by elfutils. + elf_helpers::initialize_dwfl_callbacks(offline_callbacks, + debug_info_root_paths.empty() + ? nullptr + : debug_info_root_paths.front()); + + // Create a handle to the DWARF Front End Library that we'll need. + dwfl_handle = elf_helpers::create_new_dwfl_handle(offline_callbacks); + + const string& elf_path = rdr.corpus_path(); + // Get the set of addresses that make up the ELF file we are + // looking at. + elf_module = + dwfl_report_offline(dwfl_handle.get(), + basename(const_cast(elf_path.c_str())), + elf_path.c_str(), -1); + dwfl_report_end(dwfl_handle.get(), 0, 0); + ABG_ASSERT(elf_module); + + // Finally, get and handle at the representation of the ELF file + // we've just cracked open. + GElf_Addr bias = 0; + elf_handle = dwfl_module_getelf(elf_module, &bias); + ABG_ASSERT(elf_handle); + } + + /// Find the alternate debuginfo file associated to a given elf file. + /// + /// @param elf_module represents the elf file to consider. + /// + /// @param alt_file_name the resulting path to the alternate + /// debuginfo file found. This is set iff the function returns a + /// non-nil value. + Dwarf* + find_alt_dwarf_debug_info(Dwfl_Module* elf_module, + string& alt_file_name, + int& alt_fd) + { + Dwarf *result = 0; + result = elf_reader::find_alt_dwarf_debug_info(elf_module, + debug_info_root_paths, + alt_file_name, alt_fd); + return result; + } + + /// Locate the DWARF debug info in the ELF file. + /// + /// This also knows how to locate split debug info. + void + locate_dwarf_debug_info() + { + ABG_ASSERT(dwfl_handle); + + if (dwarf_handle) + return; + + // First let's see if the ELF file that was cracked open does have + // some DWARF debug info embedded. + Dwarf_Addr bias = 0; + dwarf_handle = dwfl_module_getdwarf(elf_module, &bias); + + // If no debug info was found in the binary itself, then look for + // split debuginfo files under multiple possible debuginfo roots. + for (vector::const_iterator i = debug_info_root_paths.begin(); + dwarf_handle == 0 && i != debug_info_root_paths.end(); + ++i) + { + offline_callbacks.debuginfo_path = *i; + dwarf_handle = dwfl_module_getdwarf(elf_module, &bias); + } + + alt_dwarf_handle = find_alt_dwarf_debug_info(elf_module, + alt_dwarf_path, + alt_dwarf_fd); + } + + /// Locate the CTF "alternate" debug information associated with the + /// current ELF file ( and split out somewhere else). + /// + /// This is a sub-routine of @ref locate_ctf_debug_info(). + void + locate_alt_ctf_debug_info() + { + Elf_Scn *section = + elf_helpers::find_section(elf_handle, + ".gnu_debuglink", + SHT_PROGBITS); + + std::string name; + Elf_Data *data; + if (section + && (data = elf_getdata(section, nullptr)) + && data->d_size != 0) + name = (char *) data->d_buf; + + if (!name.empty()) + for (const auto& path : rdr.debug_info_root_paths()) + { + std::string file_path; + if (!tools_utils::find_file_under_dir(*path, name, file_path)) + continue; + + int fd; + if ((fd = open(file_path.c_str(), O_RDONLY)) == -1) + continue; + + Elf *hdl; + if ((hdl = elf_begin(fd, ELF_C_READ, nullptr)) == nullptr) + { + close(fd); + continue; + } + + // unlikely .ctf was designed to be present in stripped file + alt_ctf_section = + elf_helpers::find_section(hdl, ".ctf", SHT_PROGBITS); + break; + + elf_end(hdl); + close(fd); + } + } + + /// Locate the CTF debug information associated with the current ELF + /// file. It also locates the CTF debug information that is split + /// out in a separate file. + void + locate_ctf_debug_info() + { + ABG_ASSERT(elf_handle); + + ctf_section = elf_helpers::find_section_by_name(elf_handle, ".ctf"); + if (ctf_section == nullptr) + { + locate_alt_ctf_debug_info(); + ctf_section = alt_ctf_section; + } + } +}; //end reader::priv + +/// The constructor of the @ref elf_reader::reader type. +/// +/// @param elf_path the path to the ELF file to read from. +/// +/// @param debug_info_root a vector of directory paths to look into +/// for split debug information files. +/// +/// @param env the environment which the reader operates in. +reader::reader(const string& elf_path, + const vector& debug_info_roots, + ir::environment& env) + : fe_iface(elf_path, env), + priv_(new priv(*this, elf_path, debug_info_roots)) +{ + priv_->crack_open_elf_file(); + priv_->locate_dwarf_debug_info(); +} + +/// The destructor of the @ref elf_reader::reader type. +reader::~reader() +{delete priv_;} + +/// Resets (erase) the resources used by the current @ref +/// elf_reader::reader type. +/// +/// This lets the reader in a state where it's ready to read from +/// another ELF file. +/// +/// @param elf_path the new ELF path to read from. +/// +/// @param debug_info_roots a vector of directory paths to look into +/// for split debug information files. +void +reader::reset(const std::string& elf_path, + const vector& debug_info_roots) +{ + corpus_path(elf_path); + priv_->initialize(debug_info_roots); + priv_->crack_open_elf_file(); + priv_->locate_dwarf_debug_info(); +} + +/// Getter of the vector of directory paths to look into for split +/// debug information files. +/// +/// @return the vector of directory paths to look into for split +/// debug information files. +const vector& +reader::debug_info_root_paths() const +{return priv_->debug_info_root_paths;} + +/// Getter of the functions used by the DWARF Front End library of +/// elfutils to locate DWARF debug information. +/// +/// @return the functions used by the DWARF Front End library of +const Dwfl_Callbacks& +reader::dwfl_offline_callbacks() const +{return priv_->offline_callbacks;} + +/// Getter of the functions used by the DWARF Front End library of +/// elfutils to locate DWARF debug information. +/// +/// @return the functions used by the DWARF Front End library of +Dwfl_Callbacks& +reader::dwfl_offline_callbacks() +{return priv_->offline_callbacks;} + +/// Getter of the handle used to access ELF information from the +/// current ELF file. +/// +/// @return the handle used to access ELF information from the current +/// ELF file. +Elf* +reader::elf_handle() const +{return priv_->elf_handle;} + +/// Getter of the handle used to access DWARF information from the +/// current ELF file. +/// +/// @return the handle used to access DWARF information from the +/// current ELF file. +const Dwarf* +reader::dwarf_debug_info() const +{return priv_->dwarf_handle;} + +/// Getter of the handle use to access DWARF information from the +/// alternate split DWARF information. +/// +/// In other words, this accesses the factorized DWARF information +/// that has been constructed by the DWZ tool to de-duplicate DWARF +/// information on disk. +/// +/// @return the handle use to access DWARF information from the +/// alternate split DWARF information. +const Dwarf* +reader::alternate_dwarf_debug_info() const +{return priv_->alt_dwarf_handle;} + + +/// Getter of the path to the alternate split DWARF information file, +/// on disk. In othe words, this returns the path to the factorized +/// DWARF information used by the current ELF file, created by the +/// 'DWZ' tool. +/// +/// @return the path to the alternate split DWARF information file, +/// on disk. +const string& +reader::alternate_dwarf_debug_info_path() const +{return priv_->alt_dwarf_path;} + +/// Check if the underlying elf file refers to an alternate debug info +/// file associated to it. +/// +/// Note that "alternate debug info sections" is a GNU extension as +/// of DWARF4 and is described at +/// http://www.dwarfstd.org/ShowIssue.php?issue=120604.1. +/// +/// @param alt_di the path to the alternate debug info file. This is +/// set iff the function returns true. +/// +/// @return true if the ELF file refers to an alternate debug info +/// file. +bool +reader::refers_to_alt_debug_info(string& alt_di_path) const +{ + if (!alternate_dwarf_debug_info_path().empty()) + { + alt_di_path = alternate_dwarf_debug_info_path(); + return true; + } + return false; +} + +/// Find and return a pointer to the ELF symbol table +/// section. +/// +/// @return a pointer to the ELF symbol table section. +const Elf_Scn* +reader::find_symbol_table_section() const +{ + if (!priv_->symtab_section) + priv_->symtab_section = + elf_helpers::find_symbol_table_section(elf_handle()); + return priv_->symtab_section; +} + +/// Clear the pointer to the ELF symbol table section. +void +reader::reset_symbol_table_section() +{priv_->symtab_section = nullptr;} + +/// Find and return a pointer to the the CTF section. +/// +/// @return a pointer to the the CTF section. +const Elf_Scn* +reader::find_ctf_section() const +{ + if (priv_->ctf_section == nullptr) + priv_->locate_ctf_debug_info(); + + if (priv_->ctf_section) + return priv_->ctf_section; + + return priv_->alt_ctf_section; +} + +/// Find and return a pointer to the alternate CTF section of the +/// current ELF file. +/// +/// @return a pointer to the alternate CTF section of the current ELF +/// file. +const Elf_Scn* +reader::find_alternate_ctf_section() const +{ + if (priv_->alt_ctf_section == nullptr) + priv_->locate_alt_ctf_debug_info(); + + return priv_->alt_ctf_section; +} + +/// Get the value of the DT_NEEDED property of the current ELF file. +/// +/// @return the value of the DT_NEEDED property. +const vector& +reader::dt_needed()const +{return priv_->dt_needed;} + + +/// Get the value of the 'ARCHITECTURE' property of the current ELF file. +/// +/// @return the value of the 'ARCHITECTURE' property of the current +/// ELF file. +const string& +reader::elf_architecture() const +{return priv_->elf_architecture;} + +/// Getter of an abstract representation of the symbol table of the +/// underlying ELF file. +/// +/// Note that the symbol table is loaded lazily, upon the first +/// invocation of this member function. +/// +/// @returnt the symbol table. +symtab_reader::symtab_sptr& +reader::symtab() const +{ + ABG_ASSERT(elf_handle()); + + if (!priv_->symt) + priv_->symt = symtab_reader::symtab::load + (elf_handle(), options().env, + [&](const elf_symbol_sptr& symbol) + {return suppr::is_elf_symbol_suppressed(*this, symbol);}); + + if (!priv_->symt) + std::cerr << "Symbol table of '" << corpus_path() + << "' could not be loaded\n"; + return priv_->symt; +} + +/// Test if a given function symbol has been exported. +/// +/// @param symbol_address the address of the symbol we are looking +/// for. Note that this address must be a relative offset from the +/// beginning of the .text section, just like the kind of addresses +/// that are present in the .symtab section. +/// +/// @returnthe elf symbol if found, or nil otherwise. +elf_symbol_sptr +reader::function_symbol_is_exported(GElf_Addr symbol_address) const +{ + elf_symbol_sptr symbol = symtab()->lookup_symbol(symbol_address); + if (!symbol) + return symbol; + + if (!symbol->is_function() || !symbol->is_public()) + return elf_symbol_sptr(); + + address_set_sptr set; + bool looking_at_linux_kernel_binary = + load_in_linux_kernel_mode() && elf_helpers::is_linux_kernel(elf_handle()); + + if (looking_at_linux_kernel_binary) + { + if (symbol->is_in_ksymtab()) + return symbol; + return elf_symbol_sptr(); + } + + return symbol; +} + +/// Test if a given variable symbol has been exported. +/// +/// @param symbol_address the address of the symbol we are looking +/// for. Note that this address must be a relative offset from the +/// beginning of the .text section, just like the kind of addresses +/// that are present in the .symtab section. +/// +/// @returnthe elf symbol if found, or nil otherwise. +elf_symbol_sptr +reader::variable_symbol_is_exported(GElf_Addr symbol_address) const +{ + elf_symbol_sptr symbol = symtab()->lookup_symbol(symbol_address); + if (!symbol) + return symbol; + + if (!symbol->is_variable() || !symbol->is_public()) + return elf_symbol_sptr(); + + address_set_sptr set; + bool looking_at_linux_kernel_binary = + load_in_linux_kernel_mode() && elf_helpers::is_linux_kernel(elf_handle()); + + if (looking_at_linux_kernel_binary) + { + if (symbol->is_in_ksymtab()) + return symbol; + return elf_symbol_sptr(); + } + + return symbol; +} + +/// Load the DT_NEEDED and DT_SONAME elf TAGS. +void +reader::load_dt_soname_and_needed() +{ + elf_helpers::lookup_data_tag_from_dynamic_segment(elf_handle(), + DT_NEEDED, + priv_->dt_needed); + + vector dt_tag_data; + elf_helpers::lookup_data_tag_from_dynamic_segment(elf_handle(), + DT_SONAME, + dt_tag_data); + if (!dt_tag_data.empty()) + dt_soname(dt_tag_data[0]); +} + +/// Read the string representing the architecture of the current ELF +/// file. +void +reader::load_elf_architecture() +{ + if (!elf_handle()) + return; + + GElf_Ehdr eh_mem; + GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem); + + priv_->elf_architecture = + elf_helpers::e_machine_to_string(elf_header->e_machine); +} + +/// Load various ELF data. +/// +/// This function loads ELF data that are not symbol maps or debug +/// info. That is, things like various tags, elf architecture and +/// so on. +void +reader::load_elf_properties() +{ + // Note that we don't load the symbol table as it's loaded lazily, + // on demand. + + load_dt_soname_and_needed(); + load_elf_architecture(); +} + +/// Read the ELF information associated to the current ELF file and +/// construct an ABI representation from it. +/// +/// Note that this reader doesn't know how to interpret any debug +/// information so the resulting ABI corpus won't have any type +/// information. Rather, it will only have ELF symbol representation. +/// +/// To have type information, consider using readers that know how to +/// interpret the symbolic type information comprised in DWARF, CTF or +/// other symbolic debug information format, like the @ref or +/// abigail::dwarf_reader::reader, @ref abigail::ctf_reader::reader +/// readers. +/// +/// @return the resulting ABI corpus. +ir::corpus_sptr +reader::read_corpus(status& status) +{ + status = STATUS_UNKNOWN; + + load_elf_properties(); // DT_SONAME, DT_NEEDED, architecture + corpus()->set_soname(dt_soname()); + corpus()->set_needed(dt_needed()); + corpus()->set_architecture_name(elf_architecture()); + + // See if we could find symbol tables. + if (!symtab() || !symtab()->has_symbols()) + { + status |= STATUS_NO_SYMBOLS_FOUND; + // We found no ELF symbol, so we can't handle the binary. + return corpus_sptr(); + } + + // Set symbols information to the corpus. + corpus()->set_symtab(symtab()); + + // If we couldn't load debug info from the elf path, then say it. + if (dwarf_debug_info() == nullptr + && find_ctf_section() == nullptr) + status |= STATUS_DEBUG_INFO_NOT_FOUND; + + status |= STATUS_OK; + + return corpus(); +} + +/// Get the SONAME property of a designated ELF file. +/// +/// @param path the path to the ELF file to consider. +/// +/// @param soname output parameter. This is set to the SONAME of the +/// file located at @p path, iff this function return true. +/// +/// @return true iff the SONAME property was found in the ELF file +/// located at @p path and set into the argument of the parameter @p +/// soname. +bool +get_soname_of_elf_file(const string& path, string &soname) +{return elf_helpers::get_soname_of_elf_file(path, soname);} + +/// Convert the type of ELF file into @ref elf_type. +/// +/// @param elf the elf handle to use for the query. +/// +/// @return the @ref elf_type for a given elf type. +static elf_reader::elf_type +elf_file_type(Elf* elf) +{ + GElf_Ehdr ehdr_mem; + GElf_Ehdr *header = gelf_getehdr (elf, &ehdr_mem); + vector dt_debug_data; + + switch (header->e_type) + { + case ET_DYN: + if (lookup_data_tag_from_dynamic_segment(elf, DT_DEBUG, dt_debug_data)) + return elf_reader::ELF_TYPE_PI_EXEC; + else + return elf_reader::ELF_TYPE_DSO; + case ET_EXEC: + return elf_reader::ELF_TYPE_EXEC; + case ET_REL: + return elf_reader::ELF_TYPE_RELOCATABLE; + default: + return elf_reader::ELF_TYPE_UNKNOWN; + } +} + +/// Get the type of a given elf type. +/// +/// @param path the absolute path to the ELF file to analyzed. +/// +/// @param type the kind of the ELF file designated by @p path. +/// +/// @param out parameter. Is set to the type of ELF file of @p path. +/// This parameter is set iff the function returns true. +/// +/// @return true iff the file could be opened and analyzed. +bool +get_type_of_elf_file(const string& path, elf_reader::elf_type& type) +{ + int fd = open(path.c_str(), O_RDONLY); + if (fd == -1) + return false; + + elf_version (EV_CURRENT); + Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); + type = elf_file_type(elf); + elf_end(elf); + close(fd); + + return true; +} + +}// end namespace elf_reader +} // end namespace abigail diff --git a/src/abg-fe-iface.cc b/src/abg-fe-iface.cc new file mode 100644 index 00000000..88993248 --- /dev/null +++ b/src/abg-fe-iface.cc @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// -*- Mode: C++ -*- +// +// Copyright (C) 2022 Red Hat, Inc. +// +// Author: Dodji Seketeli + +/// @file +/// +/// This file contains the definitions of the the fe_iface base type. + +#include "abg-internal.h" +// +ABG_BEGIN_EXPORT_DECLARATIONS + +#include "abg-corpus.h" +#include "abg-fe-iface.h" + +ABG_END_EXPORT_DECLARATIONS +// + +namespace abigail +{ + +/// The private data structure for the @ref fe_iface type. +struct fe_iface::priv +{ + std::string corpus_path; + std::string dt_soname; + fe_iface::options_type options; + suppr::suppressions_type suppressions; + ir::corpus_sptr corpus; + ir::corpus_group_sptr corpus_group; + + priv(const std::string& path, environment& e) + : corpus_path(path), options(e) + { + initialize(); + } + + /// This function resets the data of @ref fe_iface::priv data so + /// that it can be re-used again. + void + initialize() + { + //TODO: initialize the options. + corpus_path.clear(); + dt_soname.clear(); + suppressions.clear(); + corpus_group.reset(); + } +}; //end struct fe_iface::priv + +/// Constructor of the type @ref fe_iface::options_type. +/// +/// @param e the environment used by the Front End Interface. +fe_iface::options_type::options_type(environment& e) + : env(e) +{ +} + +/// Constructor of the type @ref fe_iface. +/// +/// @param corpus_path the path to the file represented by the ABI +/// corpus that is going to be built by this Front End. +/// +/// @param e the environment in which the Front End operates. +fe_iface::fe_iface(const std::string& corpus_path, environment& e) + : priv_(new priv(corpus_path, e)) +{ +} + +/// Desctructor of the Front End Interface. +fe_iface::~fe_iface() +{delete priv_;} + +/// Re-initialize the current Front End. +/// +/// @param corpus_path the path to the file for which a new corpus is +/// to be created. +/// +/// @param e the environment in which the Front End operates. +void +fe_iface::reset(const std::string& corpus_path, + environment& e) +{ + delete priv_; + priv_ = new fe_iface::priv(corpus_path, e); +} + +/// Getter of the the options of the current Front End Interface. +/// +/// @return the options of the current Front End Interface. +const fe_iface::options_type& +fe_iface::options() const +{return priv_->options;} + +/// Getter of the the options of the current Front End Interface. +/// +/// @return the options of the current Front End Interface. +fe_iface::options_type& +fe_iface::options() +{return priv_->options;} + +/// Getter of the path to the file which an ABI corpus is to be +/// created for. +/// +/// @return the path to the file which an ABI corpus is to be created +/// for. +const std::string& +fe_iface::corpus_path() const +{return priv_->corpus_path;} + +/// Setter of the path to the file which an ABI corpus is to be +/// created for. +/// +/// @param p the new path to the file which an ABI corpus is to be +/// created for. +void +fe_iface::corpus_path(const std::string& p) +{priv_->corpus_path = p;} + +/// Getter for the SONAME of the analyzed binary. +/// +/// @return the SONAME of the analyzed binary. +const string& +fe_iface::dt_soname() const +{return priv_->dt_soname;} + +/// Getter for the SONAME of the analyzed binary. +/// +/// @return the SONAME of the analyzed binary. +void +fe_iface::dt_soname(const string& soname) +{priv_->dt_soname = soname;} + +/// Test if the input binary is to be considered as a Linux Kernel +/// binary. +/// +/// @return true iff the input binary is to be considered as a Linux +/// Kernel binary. +bool +fe_iface::load_in_linux_kernel_mode() const +{return priv_->options.load_in_linux_kernel_mode;} + +/// Getter of the vector of suppression specifications associated with +/// the current front-end. +/// +/// @return the vector of suppression specifications associated with +/// the current front-end. +suppr::suppressions_type& +fe_iface::suppressions() +{return priv_->suppressions;} + +/// Getter of the vector of suppression specifications associated with +/// the current front-end. +/// +/// @return the vector of suppression specifications associated with +/// the current front-end. +const suppr::suppressions_type& +fe_iface::suppressions() const +{return priv_->suppressions;} + +/// Setter of the vector of suppression specifications associated with +/// the current front-end. +/// +/// @param supprs the new vector of suppression specifications +/// associated with the current front-end. +void +fe_iface::suppressions(suppr::suppressions_type& supprs) +{priv_->suppressions = supprs;} + +/// Add suppressions specifications to the set of suppressions to be +/// used during the construction of the ABI internal representation +/// (the ABI corpus) from the input file. +/// +/// During the construction of the ABI corpus, ABI artifacts that +/// match a given suppression specification are dropped on the floor; +/// that is, they are discarded and won't be part of the final ABI +/// corpus. This is a way to reduce the amount of data held by the +/// final ABI corpus. +/// +/// Note that the suppression specifications provided to this function +/// are only considered during the construction of the ABI corpus. +/// For instance, they are not taken into account during e.g +/// comparisons of two ABI corpora that might happen later. If you +/// want to apply suppression specificatins to the comparison (or +/// reporting) of ABI corpora please refer to the documentation of the +/// @ref diff_context type to learn how to set suppressions that are +/// to be used in that context. +/// +/// @param supprs the suppression specifications to be applied during +/// the construction of the ABI corpus. +void +fe_iface::add_suppressions(const suppr::suppressions_type& supprs) +{ + for (const auto& s : supprs) + if (s->get_drops_artifact_from_ir()) + suppressions().push_back(s); +} + +/// Getter for the ABI corpus being built by the current front-end. +/// +/// @return the ABI corpus being built by the current front-end. +corpus_sptr +fe_iface::corpus() +{ + if (!priv_->corpus) + { + priv_->corpus = std::make_shared(options().env, + corpus_path()); + } + return priv_->corpus; +} + +/// Getter for the ABI corpus being built by the current front-end. +/// +/// @return the ABI corpus being built by the current front-end. +const corpus_sptr +fe_iface::corpus() const +{return const_cast(this)->corpus();} + +/// Getter for the ABI corpus group being built by the current front-end. +/// +/// @return the ABI corpus group being built by the current front-end. +corpus_group_sptr& +fe_iface::corpus_group() +{return priv_->corpus_group;} + +/// Getter for the ABI corpus group being built by the current front-end. +/// +/// @return the ABI corpus group being built by the current front-end. +const corpus_group_sptr& +fe_iface::corpus_group() const +{return const_cast(this)->corpus_group();} + +/// Setter for the ABI corpus group being built by the current +/// front-end. +/// +/// @param cg the new ABI corpus group being built by the current +/// front-end. +void +fe_iface::corpus_group(const ir::corpus_group_sptr& cg) +{priv_->corpus_group = cg;} + +/// Test if there is a corpus group being built. +/// +/// @return if there is a corpus group being built, false otherwise. +bool +fe_iface::has_corpus_group() const +{return bool(corpus_group());} + +/// Return the main corpus from the current corpus group, if any. +/// +/// @return the main corpus of the current corpus group, if any, nil +/// if no corpus group is being constructed. +corpus_sptr +fe_iface::main_corpus_from_current_group() +{ + if (corpus_group()) + return corpus_group()->get_main_corpus(); + return corpus_sptr(); +} + +/// Test if the current corpus being built is the main corpus of the +/// current corpus group. +/// +/// @return return true iff the current corpus being built is the +/// main corpus of the current corpus group. +bool +fe_iface::current_corpus_is_main_corpus_from_current_group() +{ + corpus_sptr main_corpus = main_corpus_from_current_group(); + + if (main_corpus.get() == corpus().get()) + return true; + + return false; +} + +/// Return true if the current corpus is part of a corpus group +/// being built and if it's not the main corpus of the group. +/// +/// For instance, this would return true if we are loading a linux +/// kernel *module* that is part of the current corpus group that is +/// being built. In this case, it means we should re-use types +/// coming from the "vmlinux" binary that is the main corpus of the +/// group. +/// +/// @return the corpus group the current corpus belongs to, if the +/// current corpus is part of a corpus group being built. Nil otherwise. +corpus_sptr +fe_iface::should_reuse_type_from_corpus_group() +{ + if (has_corpus_group()) + if (corpus_sptr main_corpus = main_corpus_from_current_group()) + if (!current_corpus_is_main_corpus_from_current_group()) + return corpus_group(); + + return corpus_sptr(); +} + +/// Try and add the representation of the ABI of a function to the set +/// of exported declarations of the current corpus. +/// +/// @param fn the internal representation of the ABI of a function. +void +fe_iface::maybe_add_fn_to_exported_decls(const function_decl* fn) +{ + if (fn) + if (corpus::exported_decls_builder* b = + corpus()->get_exported_decls_builder().get()) + b->maybe_add_fn_to_exported_fns(fn); +} + +/// Try and add the representation of the ABI of a variable to the set +/// of exported declarations of the current corpus. +/// +/// @param var the internal representation of the ABI of a variable. +void +fe_iface::maybe_add_var_to_exported_decls(const var_decl* var) +{ + if (var) + if (corpus::exported_decls_builder* b = + corpus()->get_exported_decls_builder().get()) + b->maybe_add_var_to_exported_vars(var); +} + +/// The bitwise OR operator for the @ref fe_iface::status type. +/// +/// @param l the left-hand side operand. +/// +/// @param r the right-hand side operand. +/// +/// @return the result of the operation. +fe_iface::status +operator|(fe_iface::status l, fe_iface::status r) +{ + return static_cast(static_cast(l) + | static_cast(r)); +} + +/// The bitwise AND operator for the @ref fe_iface::status type. +/// +/// @param l the left-hand side operand. +/// +/// @param r the right-hand side operand. +/// +/// @return the result of the operation. +fe_iface::status +operator&(fe_iface::status l, fe_iface::status r) +{ + return static_cast(static_cast(l) + & static_cast(r)); +} + +/// The bitwise |= operator for the @ref fe_iface::status type. +/// +/// @param l the left-hand side operand. +/// +/// @param r the right-hand side operand. +/// +/// @return the result of the operation. +fe_iface::status& +operator|=(fe_iface::status& l, fe_iface::status r) +{ + l = l | r; + return l; +} + +/// The bitwise &= operator for the @ref fe_iface::status type. +/// +/// @param l the left-hand side operand. +/// +/// @param r the right-hand side operand. +/// +/// @return the result of the operation. +fe_iface::status& +operator&=(fe_iface::status& l, fe_iface::status r) +{ + l = l & r; + return l; +} + +/// Return a diagnostic status with english sentences to describe the +/// problems encoded in a given abigail::elf_reader::status, if +/// there is an error. +/// +/// @param status the status to diagnose +/// +/// @return a string containing sentences that describe the possible +/// errors encoded in @p s. If there is no error to encode, then the +/// empty string is returned. +std::string +status_to_diagnostic_string(fe_iface::status s) +{ + std::string str; + + if (s & fe_iface::STATUS_DEBUG_INFO_NOT_FOUND) + str += "could not find debug info\n"; + + if (s & fe_iface::STATUS_ALT_DEBUG_INFO_NOT_FOUND) + str += "could not find alternate debug info\n"; + + if (s & fe_iface::STATUS_NO_SYMBOLS_FOUND) + str += "could not load ELF symbols\n"; + + return str; +} + +}// namespace abigail diff --git a/src/abg-ir-priv.h b/src/abg-ir-priv.h index dd3c6276..32041d31 100644 --- a/src/abg-ir-priv.h +++ b/src/abg-ir-priv.h @@ -141,7 +141,7 @@ parse_integral_type(const string& type_name, /// Private type to hold private members of @ref translation_unit struct translation_unit::priv { - const environment* env_; + const environment& env_; corpus* corp; bool is_constructed_; char address_size_; @@ -156,7 +156,7 @@ struct translation_unit::priv type_maps types_; - priv(const environment* env) + priv(const environment& env) : env_(env), corp(), is_constructed_(), @@ -845,7 +845,7 @@ struct environment::priv for (auto i : types_with_non_confirmed_propagated_ct_) { type_base *t = reinterpret_cast(i); - ABG_ASSERT(t->get_environment()->priv_->is_recursive_type(t) + ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t) || t->priv_->depends_on_recursive_type()); t->priv_->set_does_not_depend_on_recursive_type(dependant_type); if (!t->priv_->depends_on_recursive_type()) @@ -876,13 +876,12 @@ struct environment::priv if (!t || t->priv_->propagated_canonical_type_confirmed()) return; - const environment* env = t->get_environment(); - ABG_ASSERT(env); + const environment& env = t->get_environment(); - env->priv_->confirm_ct_propagation_for_types_dependant_on(t); + env.priv_->confirm_ct_propagation_for_types_dependant_on(t); t->priv_->set_does_not_depend_on_recursive_type(); - env->priv_->remove_from_types_with_non_confirmed_propagated_ct(t); - env->priv_->set_is_not_recursive(t); + env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t); + env.priv_->set_is_not_recursive(t); t->priv_->set_propagated_canonical_type_confirmed(true); } @@ -900,7 +899,7 @@ struct environment::priv for (auto i : types_with_non_confirmed_propagated_ct_) { type_base *t = reinterpret_cast(i); - ABG_ASSERT(t->get_environment()->priv_->is_recursive_type(t) + ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t) || t->priv_->depends_on_recursive_type()); t->priv_->set_does_not_depend_on_recursive_type(); t->priv_->set_propagated_canonical_type_confirmed(true); @@ -970,7 +969,7 @@ struct environment::priv for (auto i : to_remove) { type_base *t = reinterpret_cast(i); - ABG_ASSERT(t->get_environment()->priv_->is_recursive_type(t) + ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t) || t->priv_->depends_on_recursive_type()); type_base_sptr canonical = t->priv_->canonical_type.lock(); if (canonical) @@ -1007,10 +1006,10 @@ struct environment::priv if (!t) return; - const environment *env = t->get_environment(); - env->priv_->cancel_ct_propagation_for_types_dependant_on(t); + const environment& env = t->get_environment(); + env.priv_->cancel_ct_propagation_for_types_dependant_on(t); if (t->priv_->depends_on_recursive_type() - || env->priv_->is_recursive_type(t)) + || env.priv_->is_recursive_type(t)) { // This cannot carry any tentative canonical type at this // point. @@ -1020,7 +1019,7 @@ struct environment::priv // Reset the marking of the type as it no longer carries a // tentative canonical type that might be later cancelled. t->priv_->set_does_not_depend_on_recursive_type(); - env->priv_->remove_from_types_with_non_confirmed_propagated_ct(t); + env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t); } } @@ -1174,9 +1173,8 @@ struct class_or_union::priv mark_as_being_compared(const class_or_union& first, const class_or_union& second) const { - const environment* env = first.get_environment(); - ABG_ASSERT(env); - env->priv_->classes_being_compared_.insert + const environment& env = first.get_environment(); + env.priv_->classes_being_compared_.insert (std::make_pair(reinterpret_cast(&first), reinterpret_cast(&second))); } @@ -1237,9 +1235,8 @@ struct class_or_union::priv unmark_as_being_compared(const class_or_union& first, const class_or_union& second) const { - const environment* env = first.get_environment(); - ABG_ASSERT(env); - env->priv_->classes_being_compared_.erase + const environment& env = first.get_environment(); + env.priv_->classes_being_compared_.erase (std::make_pair(reinterpret_cast(&first), reinterpret_cast(&second))); } @@ -1279,9 +1276,8 @@ struct class_or_union::priv comparison_started(const class_or_union& first, const class_or_union& second) const { - const environment* env = first.get_environment(); - ABG_ASSERT(env); - return env->priv_-> + const environment& env = first.get_environment(); + return env.priv_-> classes_being_compared_.count (std::make_pair(reinterpret_cast(&first), reinterpret_cast((&second)))); @@ -1340,9 +1336,8 @@ struct function_type::priv mark_as_being_compared(const function_type& first, const function_type& second) const { - const environment* env = first.get_environment(); - ABG_ASSERT(env); - env->priv_->fn_types_being_compared_.insert + const environment& env = first.get_environment(); + env.priv_->fn_types_being_compared_.insert (std::make_pair(reinterpret_cast(&first), reinterpret_cast(&second))); } @@ -1358,9 +1353,8 @@ struct function_type::priv unmark_as_being_compared(const function_type& first, const function_type& second) const { - const environment* env = first.get_environment(); - ABG_ASSERT(env); - env->priv_->fn_types_being_compared_.erase + const environment& env = first.get_environment(); + env.priv_->fn_types_being_compared_.erase (std::make_pair(reinterpret_cast(&first), reinterpret_cast(&second))); } @@ -1374,9 +1368,8 @@ struct function_type::priv comparison_started(const function_type& first, const function_type& second) const { - const environment* env = first.get_environment(); - ABG_ASSERT(env); - return env->priv_->fn_types_being_compared_.count + const environment& env = first.get_environment(); + return env.priv_->fn_types_being_compared_.count (std::make_pair(reinterpret_cast(&first), reinterpret_cast(&second))); } diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 5193934a..7735447b 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -28,70 +28,17 @@ ABG_BEGIN_EXPORT_DECLARATIONS #include "abg-interned-str.h" #include "abg-ir.h" #include "abg-corpus.h" -#include "abg-corpus-priv.h" ABG_END_EXPORT_DECLARATIONS // +#include "abg-corpus-priv.h" #include "abg-tools-utils.h" #include "abg-comp-filter.h" #include "abg-ir-priv.h" namespace { -/// 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 -{ - const abigail::ir::environment* env_; - -public: - environment_setter(const abigail::ir::environment* env) - : env_(env) - {} - - /// 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 (const abigail::ir::environment* env = d->get_environment()) - { - ABG_ASSERT(env == env_); - return false; - } - else - d->set_environment(env_); - - return true; - - } - - /// 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()) - { - ABG_ASSERT(env == env_); - return false; - } - else - { - ABG_ASSERT(!t->get_environment()); - t->set_environment(env_); - } - return true; - } -}; - /// This internal type is a tree walking that is used to set the /// qualified name of a tree of decls and types. It used by the /// function update_qualified_name(). @@ -297,8 +244,8 @@ void push_composite_type_comparison_operands(const type_base& left, const type_base& right) { - const environment * env = left.get_environment(); - env->priv_->push_composite_type_comparison_operands(&left, &right); + const environment& env = left.get_environment(); + env.priv_->push_composite_type_comparison_operands(&left, &right); } /// Pop a pair of operands from the stack of operands to the current @@ -318,8 +265,8 @@ void pop_composite_type_comparison_operands(const type_base& left, const type_base& right) { - const environment * env = left.get_environment(); - env->priv_->pop_composite_type_comparison_operands(&left, &right); + const environment& env = left.get_environment(); + env.priv_->pop_composite_type_comparison_operands(&left, &right); } /// In the stack of the current types being compared (as part of type @@ -381,9 +328,9 @@ pop_composite_type_comparison_operands(const type_base& left, bool mark_dependant_types_compared_until(const type_base &r) { - const environment * env = r.get_environment(); - if (env->do_on_the_fly_canonicalization()) - return env->priv_->mark_dependant_types_compared_until(&r); + const environment& env = r.get_environment(); + if (env.do_on_the_fly_canonicalization()) + return env.priv_->mark_dependant_types_compared_until(&r); return false; } @@ -888,8 +835,8 @@ try_canonical_compare(const T *l, const T *r) // instructing us to compare them canonically, and the second time // with that boolean set to false, instructing us to compare them // structurally. - const environment *env = l->get_environment(); - if (env->priv_->use_canonical_type_comparison_) + const environment&env = l->get_environment(); + if (env.priv_->use_canonical_type_comparison_) { if (const type_base *lc = l->get_naked_canonical_type()) if (const type_base *rc = r->get_naked_canonical_type()) @@ -1073,8 +1020,8 @@ return_comparison_result(T& l, T& r, bool value, unmark_types_as_being_compared(l, r); - const environment* env = l.get_environment(); - if (env->do_on_the_fly_canonicalization()) + const environment& env = l.get_environment(); + if (env.do_on_the_fly_canonicalization()) // We are instructed to perform the "canonical type propagation" // optimization, making 'r' to possibly get the canonical type of // 'l' if it has one. This mostly means that we are currently @@ -1083,17 +1030,17 @@ return_comparison_result(T& l, T& r, bool value, { if (value == true && (is_type(&r)->priv_->depends_on_recursive_type() - || env->priv_->is_recursive_type(&r)) + || env.priv_->is_recursive_type(&r)) && is_type(&r)->priv_->canonical_type_propagated() && !is_type(&r)->priv_->propagated_canonical_type_confirmed() - && !env->priv_->right_type_comp_operands_.empty()) + && !env.priv_->right_type_comp_operands_.empty()) { // Track the object 'r' for which the propagated canonical // type might be re-initialized if the current comparison // eventually fails. - env->priv_->add_to_types_with_non_confirmed_propagated_ct(is_type(&r)); + env.priv_->add_to_types_with_non_confirmed_propagated_ct(is_type(&r)); } - else if (value == true && env->priv_->right_type_comp_operands_.empty()) + else if (value == true && env.priv_->right_type_comp_operands_.empty()) { // The type provided in the 'r' argument is the type that is // being canonicalized; 'r' is not a mere subtype being @@ -1102,16 +1049,16 @@ return_comparison_result(T& l, T& r, bool value, // confirm the "canonical type propagation" of all the // sub-types that were compared during the comparison of // 'r'. - env->priv_->confirm_ct_propagation(&r); + env.priv_->confirm_ct_propagation(&r); } else if (value == false) { // The comparison of the current sub-type failed. So all // the types in - // env->prix_->types_with_non_confirmed_propagated_ct_ + // env.prix_->types_with_non_confirmed_propagated_ct_ // should see their tentatively propagated canonical type // cancelled. - env->priv_->cancel_ct_propagation(&r); + env.priv_->cancel_ct_propagation(&r); } } @@ -1123,13 +1070,13 @@ return_comparison_result(T& l, T& r, bool value, // propagation can now see their tentative canonical type be // confirmed for real. if (value == true - && env->priv_->right_type_comp_operands_.empty() - && !env->priv_->types_with_non_confirmed_propagated_ct_.empty()) + && env.priv_->right_type_comp_operands_.empty() + && !env.priv_->types_with_non_confirmed_propagated_ct_.empty()) // So the comparison is completely done and there are some // types for which their propagated canonical type is sitll // considered not confirmed. As the comparison did yield true, we // shall now confirm the propagation for all those types. - env->priv_->confirm_ct_propagation(); + env.priv_->confirm_ct_propagation(); ABG_RETURN(value); } @@ -1188,7 +1135,7 @@ type_maps::get_types_sorted_by_name() const /// /// @param address_size the size of addresses in the translation unit, /// in bits. -translation_unit::translation_unit(const environment* env, +translation_unit::translation_unit(const environment& env, const std::string& path, char address_size) : priv_(new priv(env)) @@ -1220,10 +1167,6 @@ translation_unit::get_global_scope() { 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())); priv_->global_scope_->set_translation_unit (const_cast(this)); } @@ -1256,24 +1199,10 @@ translation_unit::get_live_fn_types() const /// Getter of the environment of the current @ref translation_unit. /// /// @return the translation unit of the current translation unit. -const environment* +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 const_cast(priv_->env_);} - -/// Setter of the environment of the current @ref translation_unit. -/// -/// @param env the environment. -void -translation_unit::set_environment(const environment* env) -{priv_->env_ = env;} - /// Getter of the language of the source code of the translation unit. /// /// @return the language of the source code. @@ -1496,8 +1425,7 @@ translation_unit::operator!=(const translation_unit& o) const void translation_unit::bind_function_type_life_time(function_type_sptr ftype) const { - const environment* env = get_environment(); - ABG_ASSERT(env); + const environment& env = get_environment(); const_cast(this)->priv_->live_fn_types_.push_back(ftype); @@ -1507,10 +1435,10 @@ translation_unit::bind_function_type_life_time(function_type_sptr ftype) const // The function type must be out of the same environment as its // translation unit. - if (const environment* e = ftype->get_environment()) - ABG_ASSERT(env == e); - else - ftype->set_environment(const_cast(env)); + { + const environment& e = ftype->get_environment(); + ABG_ASSERT(&env == &e); + } if (const translation_unit* existing_tu = ftype->get_translation_unit()) ABG_ASSERT(existing_tu == this); @@ -1749,7 +1677,7 @@ operator!=(const translation_unit_sptr& l, const translation_unit_sptr& r) // struct elf_symbol::priv { - const environment* env_; + const environment& env_; size_t index_; size_t size_; string name_; @@ -1796,8 +1724,8 @@ struct elf_symbol::priv elf_symbol_wptr next_common_instance_; string id_string_; - priv() - : env_(), + priv(const environment& e) + : env_(e), index_(), size_(), type_(elf_symbol::NOTYPE_TYPE), @@ -1811,7 +1739,7 @@ struct elf_symbol::priv is_suppressed_(false) {} - priv(const environment* e, + priv(const environment& e, size_t i, size_t s, const string& n, @@ -1845,16 +1773,6 @@ struct elf_symbol::priv } }; // end struct elf_symbol::priv -/// Default constructor of the @ref elf_symbol type. -/// -/// Note that this constructor is private, so client code cannot use -/// it to create instances of @ref elf_symbol. Rather, client code -/// should use the @ref elf_symbol::create() function to create -/// instances of @ref elf_symbol instead. -elf_symbol::elf_symbol() - : priv_(new priv) -{} - /// Constructor of the @ref elf_symbol type. /// /// Note that this constructor is private, so client code cannot use @@ -1885,7 +1803,7 @@ elf_symbol::elf_symbol() /// @param crc the CRC (modversions) value of Linux Kernel symbols /// /// @param ns the namespace of Linux Kernel symbols, if any -elf_symbol::elf_symbol(const environment* e, +elf_symbol::elf_symbol(const environment& e, size_t i, size_t s, const string& n, @@ -1915,20 +1833,6 @@ elf_symbol::elf_symbol(const environment* e, is_suppressed)) {} -/// Factory of instances of @ref elf_symbol. -/// -/// This is the function to use to create instances of @ref elf_symbol. -/// -/// @return a (smart) pointer to a newly created instance of @ref -/// elf_symbol. -elf_symbol_sptr -elf_symbol::create() -{ - elf_symbol_sptr e(new elf_symbol()); - e->priv_->main_symbol_ = e; - return e; -} - /// Factory of instances of @ref elf_symbol. /// /// This is the function to use to create instances of @ref elf_symbol. @@ -1960,7 +1864,7 @@ elf_symbol::create() /// @return a (smart) pointer to a newly created instance of @ref /// elf_symbol. elf_symbol_sptr -elf_symbol::create(const environment* e, +elf_symbol::create(const environment& e, size_t i, size_t s, const string& n, @@ -2015,19 +1919,10 @@ textually_equals(const elf_symbol&l, /// elf_symbol. /// /// @return the enviroment used by the current instance of @ref elf_symbol. -const environment* +const environment& elf_symbol::get_environment() const {return priv_->env_;} -/// Setter of the environment used by the current instance of @ref -/// elf_symbol. -/// -/// @param The new enviroment used by the current instance of @ref -/// elf_symbol. -void -elf_symbol::set_environment(const environment* e) const -{priv_->env_ = e;} - /// Getter for the index /// /// @return the index of the symbol. @@ -3593,7 +3488,7 @@ const type_base_sptr& environment::get_void_type() const { if (!priv_->void_type_) - priv_->void_type_.reset(new type_decl(const_cast(this), + priv_->void_type_.reset(new type_decl(*this, intern("void"), 0, 0, location())); return priv_->void_type_; @@ -3609,7 +3504,7 @@ environment::get_variadic_parameter_type() const { if (!priv_->variadic_marker_type_) priv_->variadic_marker_type_. - reset(new type_decl(const_cast(this), + reset(new type_decl(*this, intern("variadic parameter type"), 0, 0, location())); return priv_->variadic_marker_type_; @@ -4064,7 +3959,7 @@ struct type_or_decl_base::priv // hotspots, due to their use of dynamic_cast. void* type_or_decl_ptr_; bool hashing_started_; - const environment* env_; + const environment& env_; translation_unit* translation_unit_; // The location of an artifact as seen from its input by the // artifact reader. This might be different from the source @@ -4082,7 +3977,7 @@ struct type_or_decl_base::priv /// /// @param k the identifier of the runtime type of the current /// instance of ABI artifact. - priv(const environment* e = 0, + priv(const environment& e, enum type_or_decl_kind k = ABSTRACT_TYPE_OR_DECL) : kind_(k), rtti_(), @@ -4142,26 +4037,17 @@ operator&=(type_or_decl_base::type_or_decl_kind& l, return l; } -/// Default constructor of @ref type_or_decl_base. -type_or_decl_base::type_or_decl_base() - :priv_(new priv) -{} - /// Constructor of @ref type_or_decl_base. /// /// @param the environment the current ABI artifact is constructed /// from. /// /// @param k the runtime identifier bitmap of the type being built. -type_or_decl_base::type_or_decl_base(const environment* e, +type_or_decl_base::type_or_decl_base(const environment& e, enum type_or_decl_kind k) :priv_(new priv(e, k)) {} -/// 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() {} @@ -4280,22 +4166,10 @@ void type_or_decl_base::hashing_started(bool b) const {priv_->hashing_started_ = b;} -/// 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(const environment* env) -{priv_->env_ = env;} - /// Getter of the environment of the current ABI artifact. /// /// @return the environment of the artifact. -const environment* +const environment& type_or_decl_base::get_environment() const {return priv_->env_;} @@ -4345,13 +4219,6 @@ type_or_decl_base::has_artificial_location() const && priv_->artificial_location_.get_is_artificial()); } -/// Getter of the environment of the current ABI artifact. -/// -/// @return the environment of the artifact. -environment* -type_or_decl_base::get_environment() -{return const_cast(priv_->env_);} - /// Get the @ref corpus this ABI artifact belongs to. /// /// @return the corpus this ABI artifact belongs to, or nil if it @@ -4399,19 +4266,6 @@ const translation_unit* type_or_decl_base::get_translation_unit() const {return const_cast(this)->get_translation_unit();} -/// Assignment operator for @ref type_or_decl_base. -/// -/// @param o the other instance to assign the current instance to. -/// -/// return a reference to the assigned instance of @ref -/// type_or_decl_base. -type_or_decl_base& -type_or_decl_base::operator=(const type_or_decl_base& o) -{ - *priv_ = *o.priv_; - return *this; -} - /// Traverse the the ABI artifact. /// /// @param v the visitor used to traverse the sub-tree nodes of the @@ -4420,33 +4274,6 @@ 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, - const environment* env) -{ - ABG_ASSERT(artifact && env); - - ::environment_setter s(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, - const 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. @@ -4590,13 +4417,13 @@ struct decl_base::priv /// @param linkage_name the linkage name of the declaration. /// /// @param vis the visibility of the declaration. -decl_base::decl_base(const environment* e, +decl_base::decl_base(const environment& e, const string& name, const location& locus, const string& linkage_name, visibility vis) : type_or_decl_base(e, ABSTRACT_DECL_BASE), - priv_(new priv(e->intern(name), e->intern(linkage_name), vis)) + priv_(new priv(e.intern(name), e.intern(linkage_name), vis)) { set_location(locus); } @@ -4614,7 +4441,7 @@ decl_base::decl_base(const environment* e, /// constructed. /// /// @param vis the visibility of the declaration being constructed. -decl_base::decl_base(const environment* e, +decl_base::decl_base(const environment& e, const interned_string& name, const location& locus, const interned_string& linkage_name, @@ -4632,26 +4459,13 @@ decl_base::decl_base(const environment* e, /// /// @param l the location where to find the declaration in the source /// code. -decl_base::decl_base(const environment* e, const location& l) +decl_base::decl_base(const environment& e, const location& l) : type_or_decl_base(e, ABSTRACT_DECL_BASE), priv_(new priv()) { set_location(l); } -decl_base::decl_base(const decl_base& d) - : type_or_decl_base(d) -{ - priv_->in_pub_sym_tab_ = d.priv_->in_pub_sym_tab_; - priv_->location_ = d.priv_->location_; - priv_->name_ = d.priv_->name_; - priv_->qualified_parent_name_ = d.priv_->qualified_parent_name_; - priv_->qualified_name_ = d.priv_->qualified_name_; - priv_->linkage_name_ = d.priv_->linkage_name_; - priv_->context_ = d.priv_->context_; - priv_->visibility_ = d.priv_->visibility_; -} - /// Getter for the qualified name. /// /// Unlike decl_base::get_qualified_name() this doesn't try to update @@ -4831,7 +4645,7 @@ decl_base::set_location(const location& l) void decl_base::set_name(const string& n) { - priv_->name_ = get_environment()->intern(n); + priv_->name_ = get_environment().intern(n); priv_->is_anonymous_ = n.empty(); } @@ -4923,7 +4737,7 @@ decl_base::set_naming_typedef(const typedef_decl_sptr& t) priv_->naming_typedef_ = t; set_name(t->get_name()); string qualified_name = build_qualified_name(get_scope(), t->get_name()); - set_qualified_name(get_environment()->intern(qualified_name)); + set_qualified_name(get_environment().intern(qualified_name)); set_is_anonymous(false); // Now that the qualified type of the decl has changed, let's update // the qualified names of the member types of this decls. @@ -4943,9 +4757,8 @@ decl_base::get_linkage_name() const void decl_base::set_linkage_name(const string& m) { - const environment* env = get_environment(); - ABG_ASSERT(env); - priv_->linkage_name_ = env->intern(m); + const environment& env = get_environment(); + priv_->linkage_name_ = env.intern(m); } /// Getter for the visibility of the decl. @@ -5271,7 +5084,7 @@ get_decl_name_for_comparison(const decl_base &d) // other anymous types of the same kind. string r; r += get_generic_anonymous_internal_type_name(&d); - return d.get_environment()->intern(r); + return d.get_environment().intern(r); } interned_string n = (is_anonymous_or_typedef_named(d) @@ -6722,8 +6535,7 @@ strip_typedef(const type_base_sptr type) return type; } - environment* env = type->get_environment(); - ABG_ASSERT(env); + const environment& env = type->get_environment(); type_base_sptr t = type; if (const typedef_decl_sptr ty = is_typedef(t)) @@ -6818,9 +6630,6 @@ strip_typedef(const type_base_sptr type) ty->get_alignment_in_bits())); } - if (!t->get_environment()) - set_environment_for_artifact(t, env); - if (!t->get_translation_unit()) t->set_translation_unit(type->get_translation_unit()); @@ -6852,12 +6661,12 @@ strip_useless_const_qualification(const qualified_type_def_sptr t) decl_base_sptr result = t; type_base_sptr u = t->get_underlying_type(); - environment* env = t->get_environment(); + const environment& env = t->get_environment(); if ((t->get_cv_quals() & qualified_type_def::CV_CONST && (is_reference_type(u))) || (t->get_cv_quals() & qualified_type_def::CV_CONST - && env->is_void_type(u)) + && env.is_void_type(u)) || t->get_cv_quals() == qualified_type_def::CV_NONE) // Let's strip the const qualifier because a reference is always // 'const' and a const void doesn't make sense. They will just @@ -7696,7 +7505,7 @@ struct scope_decl::priv /// @param locus the source location where the scope_decl is defined. /// /// @param vis the visibility of the declaration. -scope_decl::scope_decl(const environment* env, +scope_decl::scope_decl(const environment& env, const string& name, const location& locus, visibility vis) @@ -7712,7 +7521,7 @@ scope_decl::scope_decl(const environment* env, /// @param l the source location where the scope_decl is defined. /// /// @param vis the visibility of the declaration. -scope_decl::scope_decl(const environment* env, location& l) +scope_decl::scope_decl(const environment& env, location& l) : type_or_decl_base(env, ABSTRACT_SCOPE_DECL|ABSTRACT_DECL_BASE), decl_base(env, "", l), priv_(new priv) @@ -7898,9 +7707,6 @@ scope_decl::add_member_decl(const decl_base_sptr& member) update_qualified_name(member); - if (const environment* env = get_environment()) - set_environment_for_artifact(member, env); - if (translation_unit* tu = get_translation_unit()) { if (translation_unit* existing_tu = member->get_translation_unit()) @@ -8043,9 +7849,6 @@ scope_decl::insert_member_decl(decl_base_sptr member, update_qualified_name(member); - if (const environment* env = get_environment()) - set_environment_for_artifact(member, env); - if (translation_unit* tu = get_translation_unit()) { if (translation_unit* existing_tu = member->get_translation_unit()) @@ -8714,18 +8517,18 @@ get_generic_anonymous_internal_type_name(const decl_base *d) { ABG_ASSERT(has_generic_anonymous_internal_type_name(d)); - const environment *env = d->get_environment(); + const environment&env = d->get_environment(); interned_string result; if (is_class_type(d)) result = - env->intern(tools_utils::get_anonymous_struct_internal_name_prefix()); + env.intern(tools_utils::get_anonymous_struct_internal_name_prefix()); else if (is_union_type(d)) result = - env->intern(tools_utils::get_anonymous_union_internal_name_prefix()); + env.intern(tools_utils::get_anonymous_union_internal_name_prefix()); else if (is_enum_type(d)) result = - env->intern(tools_utils::get_anonymous_enum_internal_name_prefix()); + env.intern(tools_utils::get_anonymous_enum_internal_name_prefix()); else ABG_ASSERT_NOT_REACHED; @@ -8795,15 +8598,14 @@ get_type_name(const type_base* t, bool qualified, bool internal) { string r; r += get_generic_anonymous_internal_type_name(d); - return t->get_environment()->intern(r); + return t->get_environment().intern(r); } if (qualified) return d->get_qualified_name(internal); - const environment *env = d->get_environment(); - ABG_ASSERT(env); - return env->intern(get_internal_integral_type_name(t)); + const environment&env = d->get_environment(); + return env.intern(get_internal_integral_type_name(t)); } if (qualified) @@ -8844,13 +8646,11 @@ interned_string get_name_of_pointer_to_type(const type_base& pointed_to_type, bool qualified, bool internal) { - const environment* env = pointed_to_type.get_environment(); - ABG_ASSERT(env); - + const environment& env = pointed_to_type.get_environment(); string tn = get_type_name(pointed_to_type, qualified, internal); tn = tn + "*"; - return env->intern(tn); + return env.intern(tn); } /// Get the name of the reference to a given type. @@ -8869,8 +8669,7 @@ get_name_of_reference_to_type(const type_base& pointed_to_type, bool lvalue_reference, bool qualified, bool internal) { - const environment* env = pointed_to_type.get_environment(); - ABG_ASSERT(env); + const environment& env = pointed_to_type.get_environment(); string name = get_type_name(pointed_to_type, qualified, internal); if (lvalue_reference) @@ -8878,7 +8677,7 @@ get_name_of_reference_to_type(const type_base& pointed_to_type, else name = name + "&&"; - return env->intern(name); + return env.intern(name); } /// Get the name of a qualified type, given the underlying type and @@ -8900,8 +8699,7 @@ get_name_of_qualified_type(const type_base_sptr& underlying_type, qualified_type_def::CV quals, bool qualified, bool internal) { - const environment* env = underlying_type->get_environment(); - ABG_ASSERT(env); + const environment& env = underlying_type->get_environment(); string quals_repr = get_string_representation_of_cv_quals(quals); string name = get_type_name(underlying_type, qualified, internal); @@ -8931,7 +8729,7 @@ get_name_of_qualified_type(const type_base_sptr& underlying_type, name = quals_repr + " " + name; } - return env->intern(name); + return env.intern(name); } /// Get the name of a given function type and return a copy of it. @@ -8994,8 +8792,7 @@ get_function_type_name(const function_type& fn_type, internal ? peel_typedef_type(fn_type.get_return_type()) : fn_type.get_return_type(); - const environment* env = fn_type.get_environment(); - ABG_ASSERT(env); + const environment& env = fn_type.get_environment(); o << get_pretty_representation(return_type, internal); @@ -9015,7 +8812,7 @@ get_function_type_name(const function_type& fn_type, } o <<")"; - return env->intern(o.str()); + return env.intern(o.str()); } /// Get the name of a given method type and return a copy of it. @@ -9076,8 +8873,7 @@ get_method_type_name(const method_type& fn_type, internal ? peel_typedef_type(fn_type.get_return_type()) : fn_type.get_return_type(); - const environment* env = fn_type.get_environment(); - ABG_ASSERT(env); + const environment& env = fn_type.get_environment(); if (return_type) o << return_type->get_cached_pretty_representation(internal); @@ -9112,7 +8908,7 @@ get_method_type_name(const method_type& fn_type, } o <<")"; - return env->intern(o.str()); + return env.intern(o.str()); } /// Build and return a copy of the pretty representation of an ABI @@ -10572,7 +10368,7 @@ is_void_pointer_type(const type_base* type) // Look through typedefs in the pointed-to type as well. type_base * ty = t->get_pointed_to_type().get(); ty = peel_qualified_or_typedef_type(ty); - if (ty->get_environment()->is_void_type(ty)) + if (ty->get_environment().is_void_type(ty)) return ty; return 0; @@ -11198,10 +10994,9 @@ lookup_basic_type(const interned_string& type_name, const translation_unit& tu) type_decl_sptr lookup_basic_type(const string& type_name, const translation_unit& tu) { - const environment* env = tu.get_environment(); - ABG_ASSERT(env); + const environment& env = tu.get_environment(); - interned_string s = env->intern(type_name); + interned_string s = env.intern(type_name); return lookup_basic_type(s, tu); } @@ -11221,10 +11016,8 @@ lookup_basic_type(const string& type_name, const translation_unit& tu) class_decl_sptr lookup_class_type(const string& fqn, const translation_unit& tu) { - const environment* env = tu.get_environment(); - ABG_ASSERT(env); - - interned_string s = env->intern(fqn); + const environment& env = tu.get_environment(); + interned_string s = env.intern(fqn); return lookup_class_type(s, tu); } @@ -11278,10 +11071,8 @@ lookup_union_type(const interned_string& type_name, const translation_unit& tu) union_decl_sptr lookup_union_type(const string& fqn, const translation_unit& tu) { - const environment* env = tu.get_environment(); - ABG_ASSERT(env); - - interned_string s = env->intern(fqn); + const environment& env = tu.get_environment(); + interned_string s = env.intern(fqn); return lookup_union_type(s, tu); } @@ -11312,10 +11103,8 @@ lookup_union_type_per_location(const interned_string &loc, const corpus& corp) union_decl_sptr lookup_union_type_per_location(const string& loc, const corpus& corp) { - const environment* env = corp.get_environment(); - ABG_ASSERT(env); - - return lookup_union_type_per_location(env->intern(loc), corp); + const environment& env = corp.get_environment(); + return lookup_union_type_per_location(env.intern(loc), corp); } /// Lookup an enum type from a translation unit. @@ -11350,10 +11139,8 @@ lookup_enum_type(const interned_string& type_name, const translation_unit& tu) enum_type_decl_sptr lookup_enum_type(const string& type_name, const translation_unit& tu) { - const environment* env = tu.get_environment(); - ABG_ASSERT(env); - - interned_string s = env->intern(type_name); + const environment& env = tu.get_environment(); + interned_string s = env.intern(type_name); return lookup_enum_type(s, tu); } @@ -11392,10 +11179,8 @@ lookup_typedef_type(const interned_string& type_name, typedef_decl_sptr lookup_typedef_type(const string& type_name, const translation_unit& tu) { - const environment* env = tu.get_environment(); - ABG_ASSERT(env); - - interned_string s = env->intern(type_name); + const environment& env = tu.get_environment(); + interned_string s = env.intern(type_name); return lookup_typedef_type(s, tu); } @@ -11481,10 +11266,8 @@ lookup_pointer_type(const interned_string& type_name, pointer_type_def_sptr lookup_pointer_type(const string& type_name, const translation_unit& tu) { - const environment* env = tu.get_environment(); - ABG_ASSERT(env); - - interned_string s = env->intern(type_name); + const environment& env = tu.get_environment(); + interned_string s = env.intern(type_name); return lookup_pointer_type(s, tu); } @@ -11666,9 +11449,8 @@ lookup_type(const interned_string& fqn, type_base_sptr lookup_type(const string& fqn, const translation_unit& tu) { - const environment *env = tu.get_environment(); - ABG_ASSERT(env); - interned_string ifqn = env->intern(fqn); + const environment&env = tu.get_environment(); + interned_string ifqn = env.intern(fqn); return lookup_type(ifqn, tu); } @@ -12450,10 +12232,8 @@ lookup_basic_type_per_location(const interned_string &loc, type_decl_sptr lookup_basic_type_per_location(const string &loc, const corpus &corp) { - const environment* env = corp.get_environment(); - ABG_ASSERT(env); - - return lookup_basic_type_per_location(env->intern(loc), corp); + const environment& env = corp.get_environment(); + return lookup_basic_type_per_location(env.intern(loc), corp); } /// Look into a given corpus to find a basic type which has a given @@ -12471,7 +12251,7 @@ lookup_basic_type_per_location(const string &loc, const corpus &corp) type_decl_sptr lookup_basic_type(const string& qualified_name, const corpus& corp) { - return lookup_basic_type(corp.get_environment()->intern(qualified_name), + return lookup_basic_type(corp.get_environment().intern(qualified_name), corp); } @@ -12508,7 +12288,7 @@ lookup_class_type(const class_decl& t, const corpus& corp) class_decl_sptr lookup_class_type(const string& qualified_name, const corpus& corp) { - interned_string s = corp.get_environment()->intern(qualified_name); + interned_string s = corp.get_environment().intern(qualified_name); return lookup_class_type(s, corp); } @@ -12595,7 +12375,7 @@ lookup_decl_only_class_types(const interned_string& qualified_name, const type_base_wptrs_type* lookup_class_types(const string& qualified_name, const corpus& corp) { - interned_string s = corp.get_environment()->intern(qualified_name); + interned_string s = corp.get_environment().intern(qualified_name); return lookup_class_types(s, corp); } @@ -12627,10 +12407,8 @@ lookup_class_type_per_location(const interned_string& loc, class_decl_sptr lookup_class_type_per_location(const string &loc, const corpus &corp) { - const environment* env = corp.get_environment(); - ABG_ASSERT(env); - - return lookup_class_type_per_location(env->intern(loc), corp); + const environment& env = corp.get_environment(); + return lookup_class_type_per_location(env.intern(loc), corp); } /// Look into a given corpus to find a union type which has a given @@ -12670,7 +12448,7 @@ lookup_union_type(const interned_string& type_name, const corpus& corp) union_decl_sptr lookup_union_type(const string& type_name, const corpus& corp) { - interned_string s = corp.get_environment()->intern(type_name); + interned_string s = corp.get_environment().intern(type_name); return lookup_union_type(s, corp); } @@ -12708,7 +12486,7 @@ lookup_enum_type(const enum_type_decl& t, const corpus& corp) enum_type_decl_sptr lookup_enum_type(const string& qualified_name, const corpus& corp) { - interned_string s = corp.get_environment()->intern(qualified_name); + interned_string s = corp.get_environment().intern(qualified_name); return lookup_enum_type(s, corp); } @@ -12764,7 +12542,7 @@ lookup_enum_types(const interned_string& qualified_name, const corpus& corp) const type_base_wptrs_type* lookup_enum_types(const string& qualified_name, const corpus& corp) { - interned_string s = corp.get_environment()->intern(qualified_name); + interned_string s = corp.get_environment().intern(qualified_name); return lookup_enum_types(s, corp); } @@ -12795,10 +12573,8 @@ lookup_enum_type_per_location(const interned_string &loc, const corpus& corp) enum_type_decl_sptr lookup_enum_type_per_location(const string &loc, const corpus &corp) { - const environment* env = corp.get_environment(); - ABG_ASSERT(env); - - return lookup_enum_type_per_location(env->intern(loc), corp); + const environment& env = corp.get_environment(); + return lookup_enum_type_per_location(env.intern(loc), corp); } /// Look into a given corpus to find a typedef type which has the @@ -12835,7 +12611,7 @@ lookup_typedef_type(const typedef_decl& t, const corpus& corp) typedef_decl_sptr lookup_typedef_type(const string& qualified_name, const corpus& corp) { - interned_string s = corp.get_environment()->intern(qualified_name); + interned_string s = corp.get_environment().intern(qualified_name); return lookup_typedef_type(s, corp); } @@ -12892,10 +12668,8 @@ lookup_typedef_type_per_location(const interned_string &loc, const corpus &corp) typedef_decl_sptr lookup_typedef_type_per_location(const string &loc, const corpus &corp) { - const environment* env = corp.get_environment(); - ABG_ASSERT(env); - - return lookup_typedef_type_per_location(env->intern(loc), corp); + const environment& env = corp.get_environment(); + return lookup_typedef_type_per_location(env.intern(loc), corp); } /// Look into a corpus to find a class, union or typedef type which @@ -13329,7 +13103,7 @@ maybe_update_types_lookup_map(const shared_ptr& type, else if (location l = type->get_location()) { string str = l.expand(); - s = type->get_environment()->intern(str); + s = type->get_environment().intern(str); } istring_type_base_wptrs_map_type::iterator i = types_map.find(s); @@ -13384,12 +13158,12 @@ maybe_update_types_lookup_map(const class_decl_sptr& class_type, if (use_type_name_as_key) { string qname = type->get_qualified_name(); - s = type->get_environment()->intern(qname); + s = type->get_environment().intern(qname); } else if (location l = type->get_location()) { string str = l.expand(); - s = type->get_environment()->intern(str); + s = type->get_environment().intern(str); } bool result = false; @@ -13988,7 +13762,6 @@ synthesize_type_from_translation_unit(const type_base_sptr& type, p->get_size_in_bits(), p->get_alignment_in_bits(), p->get_location())); - result->set_environment(pointed_to_type->get_environment()); } } else if (reference_type_def_sptr r = is_reference_type(type)) @@ -14002,7 +13775,6 @@ synthesize_type_from_translation_unit(const type_base_sptr& type, r->get_size_in_bits(), r->get_alignment_in_bits(), r->get_location())); - result->set_environment(pointed_to_type->get_environment()); } } else if (function_type_sptr f = is_function_type(type)) @@ -14046,13 +13818,12 @@ synthesize_function_type_from_translation_unit(const function_type& fn_type, { function_type_sptr nil = function_type_sptr(); - environment* env = tu.get_environment(); - ABG_ASSERT(env); + const environment& env = tu.get_environment(); type_base_sptr return_type = fn_type.get_return_type(); type_base_sptr result_return_type; - if (!return_type || env->is_void_type(return_type)) - result_return_type = env->get_void_type(); + if (!return_type || env.is_void_type(return_type)) + result_return_type = env.get_void_type(); else result_return_type = synthesize_type_from_translation_unit(return_type, tu); if (!result_return_type) @@ -14104,9 +13875,6 @@ 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()); tu.bind_function_type_life_time(result_fn_type); canonicalize(result_fn_type); @@ -14149,17 +13917,14 @@ demangle_cplus_mangled_name(const string& mangled_name) /// /// @return either @p t if it is non-null, or the void type. type_base_sptr -type_or_void(const type_base_sptr t, const environment* env) +type_or_void(const type_base_sptr t, const environment& env) { type_base_sptr r; if (t) r = t; else - { - ABG_ASSERT(env); - r = type_base_sptr(env->get_void_type()); - } + r = type_base_sptr(env.get_void_type()); return r; } @@ -14239,7 +14004,7 @@ types_defined_same_linux_kernel_corpus_public(const type_base& t1, { if (c1->get_is_declaration_only() != c2->get_is_declaration_only()) { - if (c1->get_environment()->decl_only_class_equals_definition()) + if (c1->get_environment().decl_only_class_equals_definition()) // At least one of classes/union is declaration-only. // Because we are in a context in which a declaration-only // class/union is equal to all definitions of that @@ -14316,13 +14081,13 @@ compare_types_during_canonicalization(const type_base_sptr& canonical_type, const type_base_sptr& candidate_type) { #ifdef WITH_DEBUG_TYPE_CANONICALIZATION - environment *env = canonical_type->get_environment(); - if (env->debug_type_canonicalization_is_on()) + const environment&env = canonical_type->get_environment(); + if (env.debug_type_canonicalization_is_on()) { bool canonical_equality = false, structural_equality = false; - env->priv_->use_canonical_type_comparison_ = false; + env.priv_->use_canonical_type_comparison_ = false; structural_equality = canonical_type == candidate_type; - env->priv_->use_canonical_type_comparison_ = true; + env.priv_->use_canonical_type_comparison_ = true; canonical_equality = canonical_type == candidate_type; if (canonical_equality != structural_equality) { @@ -14365,8 +14130,7 @@ type_base::get_canonical_type_for(type_base_sptr t) if (!t) return t; - environment* env = t->get_environment(); - ABG_ASSERT(env); + environment& env = const_cast(t->get_environment()); if (is_non_canonicalized_type(t)) // This type should not be canonicalized! @@ -14377,7 +14141,7 @@ type_base::get_canonical_type_for(type_base_sptr t) // Look through decl-only types (classes, unions and enums) bool decl_only_class_equals_definition = - (odr_is_relevant(*t) || env->decl_only_class_equals_definition()); + (odr_is_relevant(*t) || env.decl_only_class_equals_definition()); class_or_union_sptr class_or_union = is_class_or_union_type(t); @@ -14424,7 +14188,7 @@ type_base::get_canonical_type_for(type_base_sptr t) // type. type_base_sptr canonical_type_present_in_corpus; environment::canonical_types_map_type& types = - env->get_canonical_types_map(); + env.get_canonical_types_map(); type_base_sptr result; environment::canonical_types_map_type::iterator i = types.find(repr); @@ -14465,20 +14229,20 @@ type_base::get_canonical_type_for(type_base_sptr t) // declaration-only struct S should be left alone and not // resolved to any of the two definitions of struct S. bool saved_decl_only_class_equals_definition = - env->decl_only_class_equals_definition(); - env->do_on_the_fly_canonicalization(true); + env.decl_only_class_equals_definition(); + env.do_on_the_fly_canonicalization(true); // Compare types by considering that decl-only classes don't // equal their definition. - env->decl_only_class_equals_definition(false); - env->priv_->allow_type_comparison_results_caching(true); + env.decl_only_class_equals_definition(false); + env.priv_->allow_type_comparison_results_caching(true); bool equal = (types_defined_same_linux_kernel_corpus_public(**it, *t) || compare_types_during_canonicalization(*it, t)); // Restore the state of the on-the-fly-canonicalization and // the decl-only-class-being-equal-to-a-matching-definition // flags. - env->priv_->allow_type_comparison_results_caching(false); - env->do_on_the_fly_canonicalization(false); - env->decl_only_class_equals_definition + env.priv_->allow_type_comparison_results_caching(false); + env.do_on_the_fly_canonicalization(false); + env.decl_only_class_equals_definition (saved_decl_only_class_equals_definition); if (equal) { @@ -14487,12 +14251,12 @@ type_base::get_canonical_type_for(type_base_sptr t) } } #ifdef WITH_DEBUG_SELF_COMPARISON - if (env->self_comparison_debug_is_on()) + if (env.self_comparison_debug_is_on()) { // So we are debugging the canonicalization process, // possibly via the use of 'abidw --debug-abidiff '. corpus_sptr corp1, corp2; - env->get_self_comparison_debug_inputs(corp1, corp2); + env.get_self_comparison_debug_inputs(corp1, corp2); if (corp1 && corp2 && t->get_corpus() == corp2.get()) { // If 't' comes from the second corpus, then it *must* @@ -14503,7 +14267,7 @@ type_base::get_canonical_type_for(type_base_sptr t) // have canonical types coming from the first corpus. if (result) { - if (!env->priv_-> + if (!env.priv_-> check_canonical_type_from_abixml_during_self_comp(t, result)) // The canonical type of the type re-read from abixml @@ -14521,7 +14285,7 @@ type_base::get_canonical_type_for(type_base_sptr t) else //!result { uintptr_t ptr_val = reinterpret_cast(t.get()); - string type_id = env->get_type_id_from_pointer(ptr_val); + string type_id = env.get_type_id_from_pointer(ptr_val); if (type_id.empty()) type_id = "type-id-"; // We are in the case where 't' is different from all @@ -14743,7 +14507,7 @@ decl_base::set_definition_of_declaration(const decl_base_sptr& d) /// @param s the size of the type, in bits. /// /// @param a the alignment of the type, in bits. -type_base::type_base(const environment* e, size_t s, size_t a) +type_base::type_base(const environment& e, size_t s, size_t a) : type_or_decl_base(e, ABSTRACT_TYPE_BASE|ABSTRACT_TYPE_BASE), priv_(new priv(s, a)) {} @@ -14796,7 +14560,7 @@ type_base::get_cached_pretty_representation(bool internal) const if (!get_naked_canonical_type() || priv_->internal_cached_repr_.empty()) { string r = ir::get_pretty_representation(this, internal); - priv_->internal_cached_repr_ = get_environment()->intern(r); + priv_->internal_cached_repr_ = get_environment().intern(r); } return priv_->internal_cached_repr_; } @@ -14804,7 +14568,7 @@ type_base::get_cached_pretty_representation(bool internal) const if (!get_naked_canonical_type() || priv_->cached_repr_.empty()) { string r = ir::get_pretty_representation(this, internal); - priv_->cached_repr_ = get_environment()->intern(r); + priv_->cached_repr_ = get_environment().intern(r); } return priv_->cached_repr_; @@ -15291,7 +15055,7 @@ integral_type::operator string() const /// @param linkage_name the linkage_name of the current type declaration. /// /// @param vis the visibility of the type declaration. -type_decl::type_decl(const environment* env, +type_decl::type_decl(const environment& env, const string& name, size_t size_in_bits, size_t alignment_in_bits, @@ -15476,8 +15240,8 @@ type_decl::get_qualified_name(interned_string& qualified_name, const interned_string& type_decl::get_qualified_name(bool internal) const { - const environment* env = get_environment(); - ABG_ASSERT(env); + const environment& env = get_environment(); + if (internal) if (is_integral_type(this)) @@ -15486,13 +15250,13 @@ type_decl::get_qualified_name(bool internal) const { if (decl_base::priv_->internal_qualified_name_.empty()) decl_base::priv_->internal_qualified_name_ = - env->intern(get_internal_integral_type_name(this)); + env.intern(get_internal_integral_type_name(this)); return decl_base::priv_->internal_qualified_name_; } else { decl_base::priv_->temporary_internal_qualified_name_ = - env->intern(get_internal_integral_type_name(this)); + env.intern(get_internal_integral_type_name(this)); return decl_base::priv_->temporary_internal_qualified_name_; } } @@ -15569,7 +15333,7 @@ type_decl::~type_decl() /// @param locus the source location where the type is defined. /// /// @param vis the visibility of the type. -scope_type_decl::scope_type_decl(const environment* env, +scope_type_decl::scope_type_decl(const environment& env, const string& name, size_t size_in_bits, size_t alignment_in_bits, @@ -15706,7 +15470,7 @@ scope_type_decl::~scope_type_decl() /// @param locus the source location where the namespace is defined. /// /// @param vis the visibility of the namespace. -namespace_decl::namespace_decl(const environment* env, +namespace_decl::namespace_decl(const environment& env, const string& name, const location& locus, visibility vis) @@ -15883,7 +15647,7 @@ qualified_type_def::build_name(bool fully_qualified, bool internal) const // especially during the construction of the type, while the // underlying type is not yet constructed. In that case, let's do // like if the underlying type is the 'void' type. - t = get_environment()->get_void_type(); + t = get_environment().get_void_type(); return get_name_of_qualified_type(t, get_cv_quals(), fully_qualified, @@ -15922,7 +15686,7 @@ qualified_type_def::qualified_type_def(type_base_sptr type, priv_(new priv(quals, type)) { runtime_type_instance(this); - interned_string name = type->get_environment()->intern(build_name(false)); + interned_string name = type->get_environment().intern(build_name(false)); set_name(name); } @@ -15933,7 +15697,7 @@ qualified_type_def::qualified_type_def(type_base_sptr type, /// @param quals a bitfield representing the const/volatile qualifiers /// /// @param locus the location of the qualified type definition -qualified_type_def::qualified_type_def(environment* env, +qualified_type_def::qualified_type_def(const environment& env, CV quals, const location& locus) : type_or_decl_base(env, @@ -15948,7 +15712,7 @@ qualified_type_def::qualified_type_def(environment* env, runtime_type_instance(this); // We don't yet have an underlying type. So for naming purpose, // let's temporarily pretend the underlying type is 'void'. - interned_string name = env->intern("void"); + interned_string name = env.intern("void"); set_name(name); } @@ -16109,8 +15873,8 @@ qualified_type_def::get_qualified_name(interned_string& qualified_name, const interned_string& qualified_type_def::get_qualified_name(bool internal) const { - const environment* env = get_environment(); - ABG_ASSERT(env); + const environment& env = get_environment(); + if (!get_canonical_type()) { @@ -16124,14 +15888,14 @@ qualified_type_def::get_qualified_name(bool internal) const // Lets compute it and return a reference to where it's // stored. priv_->temporary_internal_name_ = - env->intern(build_name(true, /*internal=*/true)); + env.intern(build_name(true, /*internal=*/true)); return priv_->temporary_internal_name_; } else { // We are asked to return a temporary non-internal name. set_temporary_qualified_name - (env->intern(build_name(true, /*internal=*/false))); + (env.intern(build_name(true, /*internal=*/false))); return peek_temporary_qualified_name(); } } @@ -16143,7 +15907,7 @@ qualified_type_def::get_qualified_name(bool internal) const { if (priv_->internal_name_.empty()) priv_->internal_name_ = - env->intern(build_name(/*qualified=*/true, + env.intern(build_name(/*qualified=*/true, /*internal=*/true)); return priv_->internal_name_; } @@ -16151,7 +15915,7 @@ qualified_type_def::get_qualified_name(bool internal) const { if (peek_qualified_name().empty()) set_qualified_name - (env->intern(build_name(/*qualified=*/true, + (env.intern(build_name(/*qualified=*/true, /*internal=*/false))); return peek_qualified_name(); } @@ -16225,7 +15989,7 @@ qualified_type_def::set_underlying_type(const type_base_sptr& t) // Now we need to update other properties that depend on the new underlying type. set_size_in_bits(t->get_size_in_bits()); set_alignment_in_bits(t->get_alignment_in_bits()); - interned_string name = get_environment()->intern(build_name(false)); + interned_string name = get_environment().intern(build_name(false)); set_name(name); if (scope_decl* s = get_scope()) { @@ -16350,7 +16114,7 @@ struct pointer_type_def::priv interned_string temp_internal_qualified_name_; priv(const type_base_sptr& t) - : pointed_to_type_(type_or_void(t, 0)), + : pointed_to_type_(type_or_void(t, t->get_environment())), naked_pointed_to_type_(t.get()) {} @@ -16396,10 +16160,10 @@ pointer_type_def::pointer_type_def(const type_base_sptr& pointed_to, try { ABG_ASSERT(pointed_to); - const environment* env = pointed_to->get_environment(); + const environment& env = pointed_to->get_environment(); decl_base_sptr pto = dynamic_pointer_cast(pointed_to); string name = (pto ? pto->get_name() : string("void")) + "*"; - set_name(env->intern(name)); + set_name(env.intern(name)); if (pto) set_visibility(pto->get_visibility()); } @@ -16416,7 +16180,7 @@ pointer_type_def::pointer_type_def(const type_base_sptr& pointed_to, /// @param align_in_bits the alignment of the type, in bits. /// /// @param locus the source location where the type was defined. -pointer_type_def::pointer_type_def(environment* env, size_t size_in_bits, +pointer_type_def::pointer_type_def(const environment& env, size_t size_in_bits, size_t alignment_in_bits, const location& locus) : type_or_decl_base(env, @@ -16429,7 +16193,7 @@ pointer_type_def::pointer_type_def(environment* env, size_t size_in_bits, { runtime_type_instance(this); string name = string("void") + "*"; - set_name(env->intern(name)); + set_name(env.intern(name)); } /// Set the pointed-to type of the pointer. @@ -16444,11 +16208,10 @@ pointer_type_def::set_pointed_to_type(const type_base_sptr& t) try { - const environment* env = t->get_environment(); - ABG_ASSERT(get_environment() == env); + const environment& env = t->get_environment(); decl_base_sptr pto = dynamic_pointer_cast(t); string name = (pto ? pto->get_name() : string("void")) + "*"; - set_name(env->intern(name)); + set_name(env.intern(name)); if (pto) set_visibility(pto->get_visibility()); } @@ -16763,11 +16526,12 @@ reference_type_def::reference_type_def(const type_base_sptr pointed_to, if (!is_lvalue()) name += "&"; - environment* env = pointed_to->get_environment(); - ABG_ASSERT(env); - set_name(env->intern(name)); + const environment& env = pointed_to->get_environment(); + set_name(env.intern(name)); - pointed_to_type_ = type_base_wptr(type_or_void(pointed_to, 0)); + pointed_to_type_ = + type_base_wptr(type_or_void(pointed_to, + pointed_to->get_environment())); } catch (...) {} @@ -16790,7 +16554,7 @@ reference_type_def::reference_type_def(const type_base_sptr pointed_to, /// @param align_in_bits the alignment of the type, in bits. /// /// @param locus the source location of the type. -reference_type_def::reference_type_def(const environment* env, bool lvalue, +reference_type_def::reference_type_def(const environment& env, bool lvalue, size_t size_in_bits, size_t alignment_in_bits, const location& locus) @@ -16806,9 +16570,9 @@ reference_type_def::reference_type_def(const environment* env, bool lvalue, string name = "void&"; if (!is_lvalue()) name += "&"; - ABG_ASSERT(env); - set_name(env->intern(name)); - pointed_to_type_ = type_base_wptr(env->get_void_type()); + + set_name(env.intern(name)); + pointed_to_type_ = type_base_wptr(env.get_void_type()); } /// Setter of the pointed_to type of the current reference type. @@ -16832,9 +16596,8 @@ reference_type_def::set_pointed_to_type(type_base_sptr& pointed_to_type) string name = string(pto->get_name()) + "&"; if (!is_lvalue()) name += "&"; - environment* env = pto->get_environment(); - ABG_ASSERT(env && env == get_environment()); - set_name(env->intern(name)); + const environment& env = pto->get_environment(); + set_name(env.intern(name)); } } @@ -17210,7 +16973,7 @@ struct array_type_def::subrange_type::priv /// @param underlying_type the underlying type of the subrange type. /// /// @param loc the source location where the type is defined. -array_type_def::subrange_type::subrange_type(const environment* env, +array_type_def::subrange_type::subrange_type(const environment& env, const string& name, bound_value lower_bound, bound_value upper_bound, @@ -17242,7 +17005,7 @@ array_type_def::subrange_type::subrange_type(const environment* env, /// @param loc the source location where the type is defined. /// /// @param l the language that generated this subrange. -array_type_def::subrange_type::subrange_type(const environment* env, +array_type_def::subrange_type::subrange_type(const environment& env, const string& name, bound_value lower_bound, bound_value upper_bound, @@ -17270,7 +17033,7 @@ array_type_def::subrange_type::subrange_type(const environment* env, /// @param loc the source location of the type. /// /// @param the language that generated this type. -array_type_def::subrange_type::subrange_type(const environment* env, +array_type_def::subrange_type::subrange_type(const environment& env, const string& name, bound_value upper_bound, const location& loc, @@ -17625,7 +17388,7 @@ array_type_def::array_type_def(const type_base_sptr e_type, /// @param subs a vector of the array's subranges(dimensions) /// /// @param locus the source location of the array type definition. -array_type_def::array_type_def(environment* env, +array_type_def::array_type_def(const environment& env, const std::vector& subs, const location& locus) : type_or_decl_base(env, @@ -17655,9 +17418,6 @@ array_type_def::update_size() { for (const auto &sub : get_subranges()) s *= sub->get_length(); - - const environment* env = e->get_environment(); - ABG_ASSERT(env); set_size_in_bits(s); } set_alignment_in_bits(e->get_alignment_in_bits()); @@ -17900,7 +17660,7 @@ array_type_def::set_element_type(const type_base_sptr& element_type) { priv_->element_type_ = element_type; update_size(); - set_name(get_environment()->intern(get_pretty_representation())); + set_name(get_environment().intern(get_pretty_representation())); } /// Append subranges from the vector @param subs to the current @@ -17913,7 +17673,7 @@ array_type_def::append_subranges(const std::vector& subs) priv_->subranges_.push_back(sub); update_size(); - set_name(get_environment()->intern(get_pretty_representation())); + set_name(get_environment().intern(get_pretty_representation())); } /// @return true if one of the sub-ranges of the array is infinite, or @@ -17964,8 +17724,8 @@ array_type_def::get_qualified_name(interned_string& qn, bool internal) const const interned_string& array_type_def::get_qualified_name(bool internal) const { - const environment* env = get_environment(); - ABG_ASSERT(env); + const environment& env = get_environment(); + if (internal) { @@ -17973,13 +17733,13 @@ array_type_def::get_qualified_name(bool internal) const { if (priv_->internal_qualified_name_.empty()) priv_->internal_qualified_name_ = - env->intern(get_type_representation(*this, /*internal=*/true)); + env.intern(get_type_representation(*this, /*internal=*/true)); return priv_->internal_qualified_name_; } else { priv_->temp_internal_qualified_name_ = - env->intern(get_type_representation(*this, /*internal=*/true)); + env.intern(get_type_representation(*this, /*internal=*/true)); return priv_->temp_internal_qualified_name_; } } @@ -17988,13 +17748,13 @@ array_type_def::get_qualified_name(bool internal) const if (get_canonical_type()) { if (decl_base::peek_qualified_name().empty()) - set_qualified_name(env->intern(get_type_representation + set_qualified_name(env.intern(get_type_representation (*this, /*internal=*/false))); return decl_base::peek_qualified_name(); } else { - set_temporary_qualified_name(env->intern(get_type_representation + set_temporary_qualified_name(env.intern(get_type_representation (*this, /*internal=*/false))); return decl_base::peek_temporary_qualified_name(); @@ -18229,8 +17989,8 @@ enum_has_non_name_change(const enum_type_decl& l, } enum_type_decl &local_r = const_cast(r); - interned_string qn_r = l.get_environment()->intern(r.get_qualified_name()); - interned_string qn_l = l.get_environment()->intern(l.get_qualified_name()); + interned_string qn_r = l.get_environment().intern(r.get_qualified_name()); + interned_string qn_l = l.get_environment().intern(l.get_qualified_name()); string n_l = l.get_name(); string n_r = r.get_name(); local_r.set_qualified_name(qn_l); @@ -18576,10 +18336,9 @@ operator!=(const enum_type_decl_sptr& l, const enum_type_decl_sptr& r) /// enum_type_decl::enumerator. class enum_type_decl::enumerator::priv { - const environment* env_; - interned_string name_; + string name_; int64_t value_; - interned_string qualified_name_; + string qualified_name_; enum_type_decl* enum_type_; friend class enum_type_decl::enumerator; @@ -18587,16 +18346,13 @@ class enum_type_decl::enumerator::priv public: priv() - : env_(), - enum_type_() + : enum_type_() {} - priv(const environment* env, - const string& name, + priv(const string& name, int64_t value, enum_type_decl* e = 0) - : env_(env), - name_(env ? env->intern(name) : interned_string()), + : name_(name), value_(value), enum_type_(e) {} @@ -18609,7 +18365,6 @@ enum_type_decl::enumerator::enumerator() enum_type_decl::enumerator::~enumerator() = default; - /// Constructor of the @ref enum_type_decl::enumerator type. /// /// @param env the environment we are operating from. @@ -18617,18 +18372,16 @@ enum_type_decl::enumerator::~enumerator() = default; /// @param name the name of the enumerator. /// /// @param value the value of the enumerator. -enum_type_decl::enumerator::enumerator(const environment* env, - const string& name, +enum_type_decl::enumerator::enumerator(const string& name, int64_t value) - : priv_(new priv(env, name, value)) + : priv_(new priv(name, value)) {} /// Copy constructor of the @ref enum_type_decl::enumerator type. /// /// @param other enumerator to copy. enum_type_decl::enumerator::enumerator(const enumerator& other) - : priv_(new priv(other.get_environment(), - other.get_name(), + : priv_(new priv(other.get_name(), other.get_value(), other.get_enum_type())) {} @@ -18639,12 +18392,12 @@ enum_type_decl::enumerator::enumerator(const enumerator& other) enum_type_decl::enumerator& enum_type_decl::enumerator::operator=(const enumerator& o) { - priv_->env_ = o.get_environment(); priv_->name_ = o.get_name(); priv_->value_ = o.get_value(); priv_->enum_type_ = o.get_enum_type(); return *this; } + /// Equality operator /// /// @param other the enumerator to compare to the current @@ -18669,19 +18422,12 @@ bool enum_type_decl::enumerator::operator!=(const enumerator& other) const {return !operator==(other);} -/// Getter of the environment of this enumerator. -/// -/// @return the environment of this enumerator. -const environment* -enum_type_decl::enumerator::get_environment() const -{return priv_->env_;} - /// Getter for the name of the current instance of /// enum_type_decl::enumerator. /// /// @return a reference to the name of the current instance of /// enum_type_decl::enumerator. -const interned_string& +const string& enum_type_decl::enumerator::get_name() const {return priv_->name_;} @@ -18698,17 +18444,15 @@ enum_type_decl::enumerator::get_name() const /// /// @return the qualified name of the current instance of /// enum_type_decl::enumerator. -const interned_string& +const string& enum_type_decl::enumerator::get_qualified_name(bool internal) const { if (priv_->qualified_name_.empty()) { - const environment* env = priv_->enum_type_->get_environment(); - ABG_ASSERT(env); priv_->qualified_name_ = - env->intern(get_enum_type()->get_qualified_name(internal) - + "::" - + get_name()); + get_enum_type()->get_qualified_name(internal) + + "::" + + get_name(); } return priv_->qualified_name_; } @@ -18718,11 +18462,7 @@ enum_type_decl::enumerator::get_qualified_name(bool internal) const /// @param n the new name. void enum_type_decl::enumerator::set_name(const string& n) -{ - const environment* env = get_environment(); - ABG_ASSERT(env); - priv_->name_ = env->intern(n); -} +{priv_->name_ = n;} /// Getter for the value of @ref enum_type_decl::enumerator. /// @@ -18810,7 +18550,7 @@ typedef_decl::typedef_decl(const string& name, /// /// @param vis the visibility of the typedef type. typedef_decl::typedef_decl(const string& name, - environment* env, + const environment& env, const location& locus, const string& mangled_name, visibility vis) @@ -19117,7 +18857,7 @@ var_decl::set_symbol(const elf_symbol_sptr& sym) priv_->symbol_ = sym; // The variable id cache that depends on the symbol must be // invalidated because the symbol changed. - priv_->id_ = get_environment()->intern(""); + priv_->id_ = get_environment().intern(""); } /// Gets the the underlying ELF symbol for the current variable, @@ -19241,10 +18981,10 @@ equals(const var_decl& l, const var_decl& r, change_kind* k) // The variables have underlying elf symbols that are equal, so // now, let's compare the decl_base part of the variables w/o // considering their decl names. - const environment* env = l.get_environment(); + const environment& env = l.get_environment(); const interned_string n1 = l.get_qualified_name(), n2 = r.get_qualified_name(); - const_cast(l).set_qualified_name(env->intern("")); - const_cast(r).set_qualified_name(env->intern("")); + const_cast(l).set_qualified_name(env.intern("")); + const_cast(r).set_qualified_name(env.intern("")); bool decl_bases_different = !l.decl_base::operator==(r); const_cast(l).set_qualified_name(n1); const_cast(r).set_qualified_name(n2); @@ -19321,11 +19061,11 @@ var_decl::get_id() const sym_str = s->get_id_string(); else if (!get_linkage_name().empty()) sym_str = get_linkage_name(); - const environment* env = get_type()->get_environment(); - ABG_ASSERT(env); - priv_->id_ = env->intern(repr); + + const environment& env = get_type()->get_environment(); + priv_->id_ = env.intern(repr); if (!sym_str.empty()) - priv_->id_ = env->intern(priv_->id_ + "{" + sym_str + "}"); + priv_->id_ = env.intern(priv_->id_ + "{" + sym_str + "}"); } return priv_->id_; } @@ -19374,7 +19114,7 @@ var_decl::get_qualified_name(bool internal) const { // Display the anonymous data member in a way that makes sense. string r = get_pretty_representation(internal); - set_qualified_name(get_environment()->intern(r)); + set_qualified_name(get_environment().intern(r)); } return decl_base::get_qualified_name(internal); @@ -19614,7 +19354,7 @@ function_type::function_type(type_base_sptr return_type, /// @param size_in_bits the size of this type, in bits. /// /// @param alignment_in_bits the alignment of this type, in bits. -function_type::function_type(const environment* env, +function_type::function_type(const environment& env, size_t size_in_bits, size_t alignment_in_bits) : type_or_decl_base(env, FUNCTION_TYPE | ABSTRACT_TYPE_BASE), @@ -19772,7 +19512,7 @@ equals(const function_type& l, // comparison has been cached, let's just re-use it, rather than // comparing them all over again. bool cached_result = false; - if (l.get_environment()->priv_->is_type_comparison_cached(l, r, + if (l.get_environment().priv_->is_type_comparison_cached(l, r, cached_result)) return cached_result; } @@ -19914,7 +19654,7 @@ equals(const function_type& l, // perform this caching also on the earlier return points of this // function. That would basically mean to redefine the RETURN macro // to make it perform this caching for us. - l.get_environment()->priv_->cache_type_comparison_result(l, r, result); + l.get_environment().priv_->cache_type_comparison_result(l, r, result); RETURN(result); #undef RETURN @@ -20186,7 +19926,7 @@ method_type::method_type(type_base_sptr return_type, /// @param size_in_bits the size of the type, expressed in bits. /// /// @param alignment_in_bits the alignment of the type, expressed in bits -method_type::method_type(const environment* env, +method_type::method_type(const environment& env, size_t size_in_bits, size_t alignment_in_bits) : type_or_decl_base(env, METHOD_TYPE | ABSTRACT_TYPE_BASE | FUNCTION_TYPE), @@ -20493,7 +20233,7 @@ function_decl::get_pretty_representation_of_declarator (bool internal) const if (parm.get() != first_parm.get()) result += ", "; if (parm->get_variadic_marker() - || get_environment()->is_variadic_parameter_type(parm->get_type())) + || get_environment().is_variadic_parameter_type(parm->get_type())) result += "..."; else { @@ -20581,7 +20321,7 @@ function_decl::set_symbol(const elf_symbol_sptr& sym) priv_->symbol_ = sym; // The function id cache that depends on the symbol must be // invalidated because the symbol changed. - priv_->id_ = get_environment()->intern(""); + priv_->id_ = get_environment().intern(""); } /// Gets the the underlying ELF symbol for the current variable, @@ -20880,22 +20620,22 @@ function_decl::get_id() const { if (priv_->id_.empty()) { - const environment* env = get_type()->get_environment(); + const environment& env = get_type()->get_environment(); if (elf_symbol_sptr s = get_symbol()) { if (s->has_aliases()) // The symbol has several aliases, so let's use a scheme // that allows all aliased functions to have different // IDs. - priv_->id_ = env->intern(get_name() + "/" + s->get_id_string()); + priv_->id_ = env.intern(get_name() + "/" + s->get_id_string()); else // Let's use the full symbol name with its version as ID. - priv_->id_ = env->intern(s->get_id_string()); + priv_->id_ = env.intern(s->get_id_string()); } else if (!get_linkage_name().empty()) - priv_->id_= env->intern(get_linkage_name()); + priv_->id_= env.intern(get_linkage_name()); else - priv_->id_ = env->intern(get_pretty_representation()); + priv_->id_ = env.intern(get_pretty_representation()); } return priv_->id_; } @@ -21069,19 +20809,18 @@ function_decl::parameter::get_type()const interned_string function_decl::parameter::get_type_name() const { - const environment* env = get_environment(); - ABG_ASSERT(env); + const environment& env = get_environment(); type_base_sptr t = get_type(); string str; - if (get_variadic_marker() || env->is_variadic_parameter_type(t)) + if (get_variadic_marker() || env.is_variadic_parameter_type(t)) str = "..."; else { ABG_ASSERT(t); str = abigail::ir::get_type_name(t); } - return env->intern(str); + return env.intern(str); } /// @return a copy of the pretty representation of the type of the @@ -21092,7 +20831,7 @@ function_decl::parameter::get_type_pretty_representation() const type_base_sptr t = get_type(); string str; if (get_variadic_marker() - || get_environment()->is_variadic_parameter_type(t)) + || get_environment().is_variadic_parameter_type(t)) str = "..."; else { @@ -21108,13 +20847,13 @@ function_decl::parameter::get_type_pretty_representation() const interned_string function_decl::parameter::get_name_id() const { - const environment* env = get_environment(); - ABG_ASSERT(env); + const environment& env = get_environment(); + std::ostringstream o; o << "parameter-" << get_index(); - return env->intern(o.str()); + return env.intern(o.str()); } unsigned @@ -21302,14 +21041,13 @@ string function_decl::parameter::get_pretty_representation(bool internal, bool /*qualified_name*/) const { - const environment* env = get_environment(); - ABG_ASSERT(env); + const environment& env = get_environment(); string type_repr; type_base_sptr t = get_type(); if (!t) type_repr = "void"; - else if (env->is_variadic_parameter_type(t)) + else if (env.is_variadic_parameter_type(t)) type_repr = "..."; else type_repr = ir::get_pretty_representation(t, internal); @@ -21351,7 +21089,7 @@ function_decl::parameter::get_pretty_representation(bool internal, /// /// @param member_fns the vector of member functions of this instance /// of @ref class_or_union. -class_or_union::class_or_union(const environment* env, const string& name, +class_or_union::class_or_union(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, const location& locus, visibility vis, member_types& mem_types, @@ -21401,7 +21139,7 @@ class_or_union::class_or_union(const environment* env, const string& name, /// @param locus the source location of declaration point this class. /// /// @param vis the visibility of instances of @ref class_or_union. -class_or_union::class_or_union(const environment* env, const string& name, +class_or_union::class_or_union(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, const location& locus, visibility vis) : type_or_decl_base(env, @@ -21423,7 +21161,7 @@ class_or_union::class_or_union(const environment* env, const string& name, /// /// @param is_declaration_only a boolean saying whether the instance /// represents a declaration only, or not. -class_or_union::class_or_union(const environment* env, const string& name, +class_or_union::class_or_union(const environment& env, const string& name, bool is_declaration_only) : type_or_decl_base(env, ABSTRACT_TYPE_BASE @@ -22127,7 +21865,7 @@ class_or_union::operator==(const class_or_union& other) const /// classes of interest are being compared. void dump_classes_being_compared(const type_or_decl_base& c) -{c.get_environment()->priv_->dump_classes_being_compared();} +{c.get_environment().priv_->dump_classes_being_compared();} /// Dumps a textual representation (to the standard error output) of /// the content of the set of function types being currently compared @@ -22139,7 +21877,7 @@ dump_classes_being_compared(const type_or_decl_base& c) /// function types of interest are being compared. void dump_fn_types_being_compared(const type_or_decl_base& t) -{t.get_environment()->priv_->dump_fn_types_being_compared();} +{t.get_environment().priv_->dump_fn_types_being_compared();} /// Compares two instances of @ref class_or_union. /// @@ -22193,7 +21931,7 @@ equals(const class_or_union& l, const class_or_union& r, change_kind* k) // change. return true; - if ((l.get_environment()->decl_only_class_equals_definition() + if ((l.get_environment().decl_only_class_equals_definition() || ((odr_is_relevant(l) && !def1) || (odr_is_relevant(r) && !def2))) && !is_anonymous_or_typedef_named(l) @@ -22414,7 +22152,6 @@ copy_member_function(const class_or_union_sptr& t, const method_decl* method) old_type->get_is_const(), old_type->get_size_in_bits(), old_type->get_alignment_in_bits())); - new_type->set_environment(t->get_environment()); keep_type_alive(new_type); method_decl_sptr @@ -22553,18 +22290,17 @@ static bool maybe_propagate_canonical_type(const type_base& lhs_type, const type_base& rhs_type) { + const environment& env = lhs_type.get_environment(); #if WITH_DEBUG_TYPE_CANONICALIZATION - if (const environment *env = lhs_type.get_environment()) - if (!env->priv_->use_canonical_type_comparison_) - return false; + if (!env.priv_->use_canonical_type_comparison_) + return false; #endif - if (const environment *env = lhs_type.get_environment()) - if (env->do_on_the_fly_canonicalization()) - if (type_base_sptr canonical_type = lhs_type.get_canonical_type()) - if (!rhs_type.get_canonical_type()) - if (env->priv_->propagate_ct(lhs_type, rhs_type)) - return true; + if (env.do_on_the_fly_canonicalization()) + if (type_base_sptr canonical_type = lhs_type.get_canonical_type()) + if (!rhs_type.get_canonical_type()) + if (env.priv_->propagate_ct(lhs_type, rhs_type)) + return true; return false; } @@ -22623,7 +22359,7 @@ struct class_decl::priv /// /// @param mbr_fns the vector of member functions of this instance of /// class_decl. -class_decl::class_decl(const environment* env, const string& name, +class_decl::class_decl(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis, base_specs& bases, @@ -22674,7 +22410,7 @@ class_decl::class_decl(const environment* env, const string& name, /// /// @param is_anonymous whether the newly created instance is /// anonymous. -class_decl::class_decl(const environment* env, const string& name, +class_decl::class_decl(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis, base_specs& bases, @@ -22720,7 +22456,7 @@ class_decl::class_decl(const environment* env, const string& name, /// @param locus the source location of declaration point this class. /// /// @param vis the visibility of instances of class_decl. -class_decl::class_decl(const environment* env, const string& name, +class_decl::class_decl(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis) @@ -22757,7 +22493,7 @@ class_decl::class_decl(const environment* env, const string& name, /// /// @param is_anonymous whether the newly created instance is /// anonymous. -class_decl:: class_decl(const environment* env, const string& name, +class_decl:: class_decl(const environment& env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis, bool is_anonymous) @@ -22795,7 +22531,7 @@ class_decl:: class_decl(const environment* env, const string& name, /// /// @param is_declaration_only a boolean saying whether the instance /// represents a declaration only, or not. -class_decl::class_decl(const environment* env, const string& name, +class_decl::class_decl(const environment& env, const string& name, bool is_struct, bool is_declaration_only) : type_or_decl_base(env, CLASS_TYPE @@ -22848,12 +22584,8 @@ class_decl::is_struct() const void class_decl::add_base_specifier(base_spec_sptr b) { - ABG_ASSERT(get_environment()); - ABG_ASSERT(b->get_environment() == get_environment()); priv_->bases_.push_back(b); priv_->bases_map_[b->get_base_class()->get_qualified_name()] = b; - if (const environment* env = get_environment()) - b->set_environment(env); } /// Get the base specifiers for this class. @@ -23755,12 +23487,12 @@ method_matches_at_least_one_in_vector(const method_decl_sptr& method, static bool maybe_cancel_propagated_canonical_type(const class_or_union& t) { - const environment* env = t.get_environment(); - if (env && env->do_on_the_fly_canonicalization()) + const environment& env = t.get_environment(); + if (env.do_on_the_fly_canonicalization()) if (is_type(&t)->priv_->canonical_type_propagated()) { is_type(&t)->priv_->clear_propagated_canonical_type(); - env->priv_->remove_from_types_with_non_confirmed_propagated_ct(&t); + env.priv_->remove_from_types_with_non_confirmed_propagated_ct(&t); return true; } return false; @@ -23794,7 +23526,7 @@ equals(const class_decl& l, const class_decl& r, change_kind* k) // cached, let's just re-use it, rather than comparing them all // over again. bool result = false; - if (l.get_environment()->priv_->is_type_comparison_cached(l, r, result)) + if (l.get_environment().priv_->is_type_comparison_cached(l, r, result)) return result; } @@ -23950,7 +23682,7 @@ equals(const class_decl& l, const class_decl& r, change_kind* k) // perform this caching also on the earlier return points of this // function. That would basically mean to redefine the RETURN macro // to make it perform this caching for us. - l.get_environment()->priv_->cache_type_comparison_result(l, r, result); + l.get_environment().priv_->cache_type_comparison_result(l, r, result); RETURN(result); #undef RETURN @@ -24591,7 +24323,7 @@ set_member_is_static(const decl_base_sptr& d, bool s) /// @param data_mbrs the data members of the union. /// /// @param member_fns the member functions of the union. -union_decl::union_decl(const environment* env, const string& name, +union_decl::union_decl(const environment& env, const string& name, size_t size_in_bits, const location& locus, visibility vis, member_types& mbr_types, data_members& data_mbrs, member_functions& member_fns) @@ -24627,7 +24359,7 @@ union_decl::union_decl(const environment* env, const string& name, /// /// @param is_anonymous whether the newly created instance is /// anonymous. -union_decl::union_decl(const environment* env, const string& name, +union_decl::union_decl(const environment& env, const string& name, size_t size_in_bits, const location& locus, visibility vis, member_types& mbr_types, data_members& data_mbrs, member_functions& member_fns, @@ -24665,7 +24397,7 @@ union_decl::union_decl(const environment* env, const string& name, /// @param locus the location of the type. /// /// @param vis the visibility of instances of @ref union_decl. -union_decl::union_decl(const environment* env, const string& name, +union_decl::union_decl(const environment& env, const string& name, size_t size_in_bits, const location& locus, visibility vis) : type_or_decl_base(env, @@ -24696,7 +24428,7 @@ union_decl::union_decl(const environment* env, const string& name, /// /// @param is_anonymous whether the newly created instance is /// anonymous. -union_decl::union_decl(const environment* env, const string& name, +union_decl::union_decl(const environment& env, const string& name, size_t size_in_bits, const location& locus, visibility vis, bool is_anonymous) : type_or_decl_base(env, @@ -24731,7 +24463,7 @@ union_decl::union_decl(const environment* env, const string& name, /// /// @param is_declaration_only a boolean saying whether the instance /// represents a declaration only, or not. -union_decl::union_decl(const environment* env, +union_decl::union_decl(const environment& env, const string& name, bool is_declaration_only) : type_or_decl_base(env, @@ -24948,7 +24680,7 @@ equals(const union_decl& l, const union_decl& r, change_kind* k) // cached, let's just re-use it, rather than comparing them all // over again. bool result = false; - if (l.get_environment()->priv_->is_type_comparison_cached(l, r, result)) + if (l.get_environment().priv_->is_type_comparison_cached(l, r, result)) return result; } @@ -24970,7 +24702,7 @@ equals(const union_decl& l, const union_decl& r, change_kind* k) // perform this caching also on the earlier return points of this // function. That would basically mean to redefine the RETURN macro // to make it perform this caching for us. - l.get_environment()->priv_->cache_type_comparison_result(l, r, result); + l.get_environment().priv_->cache_type_comparison_result(l, r, result); RETURN(result); } @@ -25076,7 +24808,7 @@ template_decl::get_template_parameters() const /// defined. /// /// @param vis the visibility of the template declaration. -template_decl::template_decl(const environment* env, +template_decl::template_decl(const environment& env, const string& name, const location& locus, visibility vis) @@ -25556,7 +25288,7 @@ public: /// /// @param bind the binding of the declaration. This is the binding /// the functions instantiated from this template are going to have. -function_tdecl::function_tdecl(const environment* env, +function_tdecl::function_tdecl(const environment& env, const location& locus, visibility vis, binding bind) @@ -25730,7 +25462,7 @@ public: /// /// @param vis the visibility of the instance of class instantiated /// from this template. -class_tdecl::class_tdecl(const environment* env, +class_tdecl::class_tdecl(const environment& env, const location& locus, visibility vis) : type_or_decl_base(env, @@ -25976,9 +25708,8 @@ type_has_sub_type_changes(const type_base_sptr t_v1, void keep_type_alive(type_base_sptr t) { - environment* env = t->get_environment(); - ABG_ASSERT(env); - env->priv_->extra_live_types_.push_back(t); + const environment& env = t->get_environment(); + env.priv_->extra_live_types_.push_back(t); } /// Hash an ABI artifact that is either a type or a decl. @@ -26107,10 +25838,10 @@ is_non_canonicalized_type(const type_base *t) if (!t) return true; - const environment* env = t->get_environment(); + const environment& env = t->get_environment(); return (is_declaration_only_class_or_union_type(t) - || env->is_void_type(t) - || env->is_variadic_parameter_type(t)); + || env.is_void_type(t) + || env.is_variadic_parameter_type(t)); } /// For a given type, return its exemplar type. @@ -26984,15 +26715,15 @@ qualified_name_setter::do_update(abigail::ir::decl_base* d) else d->priv_->qualified_parent_name_ = abigail::interned_string(); - abigail::environment* env = d->get_environment(); - ABG_ASSERT(env); + const abigail::ir::environment& env = d->get_environment(); + if (!d->priv_->qualified_parent_name_.empty()) { if (d->get_name().empty()) d->priv_->qualified_name_ = abigail::interned_string(); else d->priv_->qualified_name_ = - env->intern(d->priv_->qualified_parent_name_ + "::" + d->get_name()); + env.intern(d->priv_->qualified_parent_name_ + "::" + d->get_name()); } if (d->priv_->scoped_name_.empty()) @@ -27001,10 +26732,10 @@ qualified_name_setter::do_update(abigail::ir::decl_base* d) && !parent->get_is_anonymous() && !parent->get_name().empty()) d->priv_->scoped_name_ = - env->intern(parent->get_name() + "::" + d->get_name()); + env.intern(parent->get_name() + "::" + d->get_name()); else d->priv_->scoped_name_ = - env->intern(d->get_name()); + env.intern(d->get_name()); } if (!is_scope_decl(d)) diff --git a/src/abg-reader.cc b/src/abg-reader.cc index 4afa427a..dbc2f921 100644 --- a/src/abg-reader.cc +++ b/src/abg-reader.cc @@ -8,7 +8,7 @@ /// This file contains the definitions of the entry points to /// de-serialize an instance of @ref abigail::translation_unit from an /// ABI Instrumentation file in libabigail native XML format. This -/// native XML format is named "abixml". +/// native XML format is named "ABIXML". #include "config.h" #include @@ -25,7 +25,7 @@ #include "abg-suppression-priv.h" #include "abg-internal.h" -#include "abg-tools-utils.h" +#include "abg-symtab-reader.h" // ABG_BEGIN_EXPORT_DECLARATIONS @@ -33,7 +33,8 @@ ABG_BEGIN_EXPORT_DECLARATIONS #include "abg-libxml-utils.h" #include "abg-reader.h" #include "abg-corpus.h" -#include "abg-symtab-reader.h" +#include "abg-fe-iface.h" +#include "abg-tools-utils.h" ABG_END_EXPORT_DECLARATIONS // @@ -44,7 +45,7 @@ namespace abigail using xml::xml_char_sptr; /// The namespace for the native XML file format reader. -namespace xml_reader +namespace abixml_reader { using std::string; using std::deque; @@ -54,6 +55,8 @@ using std::dynamic_pointer_cast; using std::vector; using std::istream; +class reader; + static bool read_is_declaration_only(xmlNodePtr, bool&); static bool read_is_artificial(xmlNodePtr, bool&); static bool read_tracking_non_reachable_types(xmlNodePtr, bool&); @@ -65,20 +68,44 @@ static bool maybe_map_type_with_type_id(const type_base_sptr&, xmlNodePtr); static bool maybe_map_type_with_type_id(const type_base_sptr&, const string&); + #define MAYBE_MAP_TYPE_WITH_TYPE_ID(type, xml_node) \ maybe_map_type_with_type_id(type, xml_node) #else #define MAYBE_MAP_TYPE_WITH_TYPE_ID(type, xml_node) #endif -static void maybe_set_naming_typedef(read_context& ctxt, xmlNodePtr, const decl_base_sptr &); -class read_context; +static void maybe_set_naming_typedef(reader& rdr, + xmlNodePtr, + const decl_base_sptr &); +class reader; + +static int advance_cursor(reader& rdr); + +static void +handle_version_attribute(xml::reader_sptr& reader, corpus& corp); +static void +walk_xml_node_to_map_type_ids(reader& rdr, xmlNodePtr node); + +static bool +read_elf_needed_from_input(reader& rdr, vector& needed); + +static bool +read_symbol_db_from_input(reader& rdr, + string_elf_symbols_map_sptr& fn_symdb, + string_elf_symbols_map_sptr& var_symdb); + +static translation_unit_sptr +read_translation_unit_from_input(fe_iface& rdr); + +/// The ABIXML reader object. +/// /// This abstracts the context in which the current ABI /// instrumentation dump is being de-serialized. It carries useful /// information needed during the de-serialization, but that does not /// make sense to be stored in the final resulting in-memory /// representation of ABI Corpus. -class read_context +class reader : public fe_iface { public: @@ -102,15 +129,13 @@ public: typedef unordered_map xml_node_decl_base_sptr_map; - friend vector* get_types_from_type_id(read_context&, + friend vector* get_types_from_type_id(reader&, const string&); friend unordered_map>* - get_artifact_used_by_relation_map(read_context& ctxt); + get_artifact_used_by_relation_map(reader& rdr); private: - string m_path; - environment* m_env; unordered_map > m_types_map; unordered_map > m_fn_tmpl_map; unordered_map > m_class_tmpl_map; @@ -120,10 +145,6 @@ private: xml::reader_sptr m_reader; xmlNodePtr m_corp_node; deque > m_decls_stack; - corpus_sptr m_corpus; - corpus_group_sptr m_corpus_group; - corpus::exported_decls_builder* m_exported_decls_builder; - suppr::suppressions_type m_supprs; bool m_tracking_non_reachable_types; bool m_drop_undefined_syms; #ifdef WITH_SHOW_TYPE_USE_IN_ABILINT @@ -131,18 +152,18 @@ private: vector> m_artifact_used_by_map; #endif - read_context(); + reader(); public: - read_context(xml::reader_sptr reader, - environment* env) - : m_env(env), + reader(xml::reader_sptr reader, + environment& env) + : fe_iface("", env), m_reader(reader), m_corp_node(), - m_exported_decls_builder(), m_tracking_non_reachable_types(), m_drop_undefined_syms() - {} + { + } /// Getter for the flag that tells us if we are tracking types that /// are not reachable from global functions and variables. @@ -184,38 +205,33 @@ public: /// @return the path to the native xml abi file. const string& get_path() const - {return m_path;} + {return corpus_path();} /// Setter of the path to the ABI file. /// /// @param the new path to the native ABI file. void set_path(const string& s) - {m_path = s;} + { + corpus_path(s); + } /// Getter for the environment of this reader. /// /// @return the environment of this reader. - const environment* - get_environment() const - {return m_env;} + environment& + get_environment() + {return options().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;} + const environment& + get_environment() const + {return const_cast(this)->get_environment();} xml::reader_sptr - get_reader() const + get_libxml_reader() const {return m_reader;} /// Getter of the current XML node in the corpus element sub-tree @@ -749,39 +765,6 @@ public: return true; } - const corpus_sptr - get_corpus() const - {return m_corpus;} - - corpus_sptr - get_corpus() - {return m_corpus;} - - void - set_corpus(corpus_sptr c) - {m_corpus = c;} - - /// Getter of the current corpus group. - /// - /// @return the current corpus group.n - const corpus_group_sptr& - get_corpus_group() const - {return m_corpus_group;} - - /// Getter of the current corpus group. - /// - /// @return the current corpus group. - corpus_group_sptr& - get_corpus_group() - {return m_corpus_group;} - - /// Setter of the corpus_group - /// - /// @param group the new corpus group. - void - set_corpus_group(const corpus_group_sptr& group) - {m_corpus_group = group;} - /// Getter for the object that determines if a given declaration /// ought to be put in the set of exported decls of the current /// corpus. @@ -789,34 +772,7 @@ public: /// @return the exported decls builder. corpus::exported_decls_builder* get_exported_decls_builder() - {return m_exported_decls_builder;} - - /// Setter for the object that determines if a given declaration - /// ought to be put in the set of exported decls of the current - /// corpus. - /// - /// @param d the new exported decls builder. - /// - /// @return the exported decls builder. - void - set_exported_decls_builder(corpus::exported_decls_builder* d) - {m_exported_decls_builder = d;} - - /// Getter of the vector of the suppression specifications - /// associated to the current read context. - /// - /// @return the vector of suppression specifications. - suppr::suppressions_type& - get_suppressions() - {return m_supprs;} - - /// Getter of the vector of the suppression specifications - /// associated to the current read context. - /// - /// @return the vector of suppression specifications. - const suppr::suppressions_type& - get_suppressions() const - {return const_cast(this)->get_suppressions();} + {return corpus()->get_exported_decls_builder().get();} /// Test if there are suppression specifications (associated to the /// current corpus) that match a given SONAME or file name. @@ -836,8 +792,8 @@ public: using suppr::file_suppression_sptr; using suppr::is_file_suppression; - for (suppressions_type::const_iterator s = get_suppressions().begin(); - s != get_suppressions().end(); + for (suppressions_type::const_iterator s = suppressions().begin(); + s != suppressions().end(); ++s) if (file_suppression_sptr suppr = is_file_suppression(*s)) if (suppr::suppression_matches_soname_or_filename(soname, filename, @@ -847,41 +803,6 @@ public: return false; } - /// Add a given function to the set of exported functions of the - /// current corpus, if the function satisfies the different - /// constraints requirements. - /// - /// @param fn the function to consider. - void - maybe_add_fn_to_exported_decls(function_decl* fn) - { - if (fn) - if (corpus::exported_decls_builder* b = get_exported_decls_builder()) - b->maybe_add_fn_to_exported_fns(fn); - } - - /// Add a given variable to the set of exported functions of the - /// current corpus, if the function satisfies the different - /// constraints requirements. - /// - /// @param var the variable to consider. - void - maybe_add_var_to_exported_decls(var_decl* var) - { - if (var && var->get_scope()) - if (corpus::exported_decls_builder* b = get_exported_decls_builder()) - b->maybe_add_var_to_exported_vars(var); - } - - /// Add a given variable to the set of exported functions of the - /// current corpus, if the function satisfies the different - /// constraints requirements. - /// - /// @param var the variable to consider. - void - maybe_add_var_to_exported_decls(const var_decl_sptr &var) - {return maybe_add_var_to_exported_decls(var.get());} - /// Clear all the data that must absolutely be cleared at the end of /// the parsing of a translation unit. void @@ -923,8 +844,8 @@ public: void maybe_check_abixml_canonical_type_stability(type_base_sptr& t) { - if (!m_env->self_comparison_debug_is_on() - || m_env->get_type_id_canonical_type_map().empty()) + if (!get_environment()->self_comparison_debug_is_on() + || get_environment()->get_type_id_canonical_type_map().empty()) return ; if (class_decl_sptr c = is_class_type(t)) @@ -936,15 +857,15 @@ public: // Let's get the type-id of this type as recorded in the // originating abixml file. string type_id = - m_env->get_type_id_from_pointer(reinterpret_cast(t.get())); + get_environment()->get_type_id_from_pointer(reinterpret_cast(t.get())); if (!type_id.empty()) { // Now let's get the canonical type that initially led to the // serialization of a type with this type-id, when the abixml // was being serialized. - auto j = m_env->get_type_id_canonical_type_map().find(type_id); - if (j == m_env->get_type_id_canonical_type_map().end()) + auto j = get_environment()->get_type_id_canonical_type_map().find(type_id); + if (j == get_environment()->get_type_id_canonical_type_map().end()) { if (t->get_naked_canonical_type()) std::cerr << "error: no type with type-id: '" @@ -1088,7 +1009,7 @@ public: bool suppression_can_match(const suppr::suppression_base& s) const { - corpus_sptr corp = get_corpus(); + corpus_sptr corp = corpus(); if (!s.priv_->matches_soname(corp->get_soname())) if (s.has_soname_related_property()) @@ -1129,88 +1050,6 @@ public: return suppr::suppression_matches_function_name(s, fn_name); } - /// Test whether if a given function suppression matches a function - /// designated by a regular expression that describes its linkage - /// name (symbol name). - /// - /// @param s the suppression specification to evaluate to see if it - /// matches a given function linkage name - /// - /// @param fn_linkage_name the linkage name of the function of interest. - /// - /// @return true iff the suppression specification @p s matches the - /// function whose linkage name is @p fn_linkage_name. - bool - suppression_matches_function_sym_name(const suppr::function_suppression_sptr& s, - const string& fn_linkage_name) const - { - if (!s) - return false; - return suppression_matches_function_sym_name(*s, fn_linkage_name); - } - - /// Test whether if a given function suppression matches a function - /// designated by a regular expression that describes its linkage - /// name (symbol name). - /// - /// @param s the suppression specification to evaluate to see if it - /// matches a given function linkage name - /// - /// @param fn_linkage_name the linkage name of the function of interest. - /// - /// @return true iff the suppression specification @p s matches the - /// function whose linkage name is @p fn_linkage_name. - bool - suppression_matches_function_sym_name(const suppr::function_suppression& s, - const string& fn_linkage_name) const - { - if (!s.get_drops_artifact_from_ir() - || !suppression_can_match(s)) - return false; - - return suppr::suppression_matches_function_sym_name(s, fn_linkage_name); - } - - /// Test whether if a given variable suppression specification - /// matches a variable denoted by its name. - /// - /// @param s the variable suppression specification to consider. - /// - /// @param var_name the name of the variable to consider. - /// - /// @return true iff the suppression specification @p s matches the - /// variable whose name is @p var_name. - bool - suppression_matches_variable_name(const suppr::variable_suppression& s, - const string& var_name) const - { - if (!s.get_drops_artifact_from_ir() - || !suppression_can_match(s)) - return false; - - return suppr::suppression_matches_variable_name(s, var_name); - } - - /// Test whether if a given variable suppression specification - /// matches a variable denoted by its linkage name. - /// - /// @param s the variable suppression specification to consider. - /// - /// @param var_linkage_name the linkage name of the variable to consider. - /// - /// @return true iff variable suppression specification @p s matches - /// the variable denoted by linkage name @p var_linkage_name. - bool - suppression_matches_variable_sym_name(const suppr::variable_suppression& s, - const string& var_linkage_name) const - { - if (!s.get_drops_artifact_from_ir() - || !suppression_can_match(s)) - return false; - - return suppr::suppression_matches_variable_sym_name(s, var_linkage_name); - } - /// Test if a given type suppression specification matches a type /// designated by its name and location. /// @@ -1233,19 +1072,212 @@ public: return suppr::suppression_matches_type_name_or_location(s, type_name, type_location); } -};// end class read_context -static int advance_cursor(read_context&); -static bool read_translation_unit(read_context&, translation_unit&, xmlNodePtr); -static translation_unit_sptr get_or_read_and_add_translation_unit(read_context&, xmlNodePtr); -static translation_unit_sptr read_translation_unit_from_input(read_context&); -static bool read_symbol_db_from_input(read_context&, + virtual ir::corpus_sptr + read_corpus(fe_iface::status& status) + { + corpus_sptr nil; + + xml::reader_sptr xml_reader = get_libxml_reader(); + if (!xml_reader) + return nil; + + // This is to remember to call xmlTextReaderNext if we ever call + // xmlTextReaderExpand. + bool call_reader_next = false; + + xmlNodePtr node = get_corpus_node(); + if (!node) + { + // The document must start with the abi-corpus node. + int status = 1; + while (status == 1 + && XML_READER_GET_NODE_TYPE(xml_reader) != XML_READER_TYPE_ELEMENT) + status = advance_cursor (*this); + + if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(xml_reader).get(), + BAD_CAST("abi-corpus"))) + return nil; + +#ifdef WITH_DEBUG_SELF_COMPARISON + if (get_environment()->self_comparison_debug_is_on()) + get_environment()-> + set_self_comparison_debug_input(corpus()); +#endif + + if (!corpus_group()) + clear_per_corpus_data(); + + ir::corpus& corp = *corpus(); + + corp.set_origin(corpus::NATIVE_XML_ORIGIN); + + handle_version_attribute(xml_reader, corp); + + xml::xml_char_sptr path_str = XML_READER_GET_ATTRIBUTE(xml_reader, "path"); + string path; + + if (path_str) + { + path = reinterpret_cast(path_str.get()); + corpus_path(path); + corp.set_path(path); + } + + xml::xml_char_sptr architecture_str = + XML_READER_GET_ATTRIBUTE(xml_reader, "architecture"); + if (architecture_str) + corp.set_architecture_name + (reinterpret_cast(architecture_str.get())); + + xml::xml_char_sptr soname_str = + XML_READER_GET_ATTRIBUTE(xml_reader, "soname"); + string soname; + + if (soname_str) + { + soname = reinterpret_cast(soname_str.get()); + dt_soname(soname); + corp.set_soname(soname); + } + + // Apply suppression specifications here to honour: + // + // [suppress_file] + // (soname_regexp + // |soname_not_regexp + // |file_name_regexp + // |file_name_not_regexp) = + if ((!soname.empty() || !path.empty()) + && corpus_is_suppressed_by_soname_or_filename(soname, path)) + return nil; + + node = xmlTextReaderExpand(xml_reader.get()); + if (!node) + return nil; + + call_reader_next = true; + } + else + { +#ifdef WITH_DEBUG_SELF_COMPARISON + if (get_environment()->self_comparison_debug_is_on()) + get_environment()-> + set_self_comparison_debug_input(corpus()); +#endif + + if (!corpus_group()) + clear_per_corpus_data(); + + ir::corpus& corp = *corpus(); + corp.set_origin(corpus::NATIVE_XML_ORIGIN); + + xml::xml_char_sptr path_str = XML_NODE_GET_ATTRIBUTE(node, "path"); + if (path_str) + corp.set_path(reinterpret_cast(path_str.get())); + + xml::xml_char_sptr architecture_str = + XML_NODE_GET_ATTRIBUTE(node, "architecture"); + if (architecture_str) + corp.set_architecture_name + (reinterpret_cast(architecture_str.get())); + + xml::xml_char_sptr soname_str = + XML_NODE_GET_ATTRIBUTE(node, "soname"); + if (soname_str) + corp.set_soname(reinterpret_cast(soname_str.get())); + } + + // If the corpus element node has children nodes, make + // get_corpus_node() returns the first child element node of + // the corpus element that *needs* to be processed. + if (node->children) + { + xmlNodePtr n = xmlFirstElementChild(node); + set_corpus_node(n); + } + + ir::corpus& corp = *corpus(); + + walk_xml_node_to_map_type_ids(*this, node); + + // Read the needed element + vector needed; + read_elf_needed_from_input(*this, needed); + if (!needed.empty()) + corp.set_needed(needed); + + string_elf_symbols_map_sptr fn_sym_db, var_sym_db; + + // Read the symbol databases. + read_symbol_db_from_input(*this, fn_sym_db, var_sym_db); + + // Note that it's possible that both fn_sym_db and var_sym_db are nil, + // due to potential suppression specifications. That's fine. + corp.set_symtab(symtab_reader::symtab::load(fn_sym_db, var_sym_db)); + + get_environment().canonicalization_is_done(false); + + // Read the translation units. + while (read_translation_unit_from_input(*this)) + ; + + if (tracking_non_reachable_types()) + { + bool is_tracking_non_reachable_types = false; + read_tracking_non_reachable_types(node, is_tracking_non_reachable_types); + + ABG_ASSERT + (corp.recording_types_reachable_from_public_interface_supported() + == is_tracking_non_reachable_types); + } + + + perform_late_type_canonicalizing(); + + get_environment().canonicalization_is_done(true); + + if (call_reader_next) + { + // This is the necessary counter-part of the xmlTextReaderExpand() + // call at the beginning of the function. + xmlTextReaderNext(xml_reader.get()); + // The call above invalidates the xml node returned by + // xmlTextReaderExpand, which is can still be accessed via + // set_corpus_node. + set_corpus_node(0); + } + else + { + node = get_corpus_node(); + node = xmlNextElementSibling(node); + if (!node) + { + node = get_corpus_node(); + if (node) + node = xmlNextElementSibling(node->parent); + } + set_corpus_node(node); + } + + status = STATUS_OK; + return corpus(); + } +};// end class reader + +typedef shared_ptr reader_sptr; + +static int advance_cursor(reader&); +static bool read_translation_unit(fe_iface&, translation_unit&, xmlNodePtr); +static translation_unit_sptr get_or_read_and_add_translation_unit(reader&, xmlNodePtr); +static translation_unit_sptr read_translation_unit_from_input(fe_iface&); +static bool read_symbol_db_from_input(reader&, string_elf_symbols_map_sptr&, string_elf_symbols_map_sptr&); -static bool read_location(const read_context&, xmlNodePtr, location&); -static bool read_artificial_location(const read_context&, +static bool read_location(const reader&, xmlNodePtr, location&); +static bool read_artificial_location(const reader&, xmlNodePtr, location&); -static bool maybe_set_artificial_location(const read_context&, +static bool maybe_set_artificial_location(const reader&, xmlNodePtr, type_or_decl_base_sptr); static bool read_visibility(xmlNodePtr, decl_base::visibility&); @@ -1264,7 +1296,7 @@ static bool read_elf_symbol_visibility(xmlNodePtr, elf_symbol::visibility&); static namespace_decl_sptr -build_namespace_decl(read_context&, const xmlNodePtr, bool); +build_namespace_decl(reader&, const xmlNodePtr, bool); // // @@ -1274,96 +1306,96 @@ build_namespace_decl(read_context&, const xmlNodePtr, bool); // below. static elf_symbol_sptr -build_elf_symbol(read_context&, const xmlNodePtr, bool); +build_elf_symbol(reader&, const xmlNodePtr, bool); static elf_symbol_sptr -build_elf_symbol_from_reference(read_context&, const xmlNodePtr); +build_elf_symbol_from_reference(reader&, const xmlNodePtr); static string_elf_symbols_map_sptr -build_elf_symbol_db(read_context&, const xmlNodePtr, bool); +build_elf_symbol_db(reader&, const xmlNodePtr, bool); static function_decl::parameter_sptr -build_function_parameter (read_context&, const xmlNodePtr); +build_function_parameter (reader&, const xmlNodePtr); static function_decl_sptr -build_function_decl(read_context&, const xmlNodePtr, +build_function_decl(reader&, const xmlNodePtr, class_or_union_sptr, bool); static function_decl_sptr -build_function_decl_if_not_suppressed(read_context&, const xmlNodePtr, +build_function_decl_if_not_suppressed(reader&, const xmlNodePtr, class_or_union_sptr, bool); static bool -function_is_suppressed(const read_context& ctxt, +function_is_suppressed(const reader& rdr, xmlNodePtr node); static var_decl_sptr -build_var_decl_if_not_suppressed(read_context&, const xmlNodePtr, bool); +build_var_decl_if_not_suppressed(reader&, const xmlNodePtr, bool); static var_decl_sptr -build_var_decl(read_context&, const xmlNodePtr, bool); +build_var_decl(reader&, const xmlNodePtr, bool); static bool -variable_is_suppressed(const read_context& ctxt, +variable_is_suppressed(const reader& rdr, xmlNodePtr node); static shared_ptr -build_type_decl(read_context&, const xmlNodePtr, bool); +build_type_decl(reader&, const xmlNodePtr, bool); static qualified_type_def_sptr -build_qualified_type_decl(read_context&, const xmlNodePtr, bool); +build_qualified_type_decl(reader&, const xmlNodePtr, bool); static shared_ptr -build_pointer_type_def(read_context&, const xmlNodePtr, bool); +build_pointer_type_def(reader&, const xmlNodePtr, bool); static shared_ptr -build_reference_type_def(read_context&, const xmlNodePtr, bool); +build_reference_type_def(reader&, const xmlNodePtr, bool); static shared_ptr -build_function_type(read_context&, const xmlNodePtr, bool); +build_function_type(reader&, const xmlNodePtr, bool); static array_type_def::subrange_sptr -build_subrange_type(read_context&, const xmlNodePtr); +build_subrange_type(reader&, const xmlNodePtr); static array_type_def_sptr -build_array_type_def(read_context&, const xmlNodePtr, bool); +build_array_type_def(reader&, const xmlNodePtr, bool); static enum_type_decl_sptr -build_enum_type_decl(read_context&, const xmlNodePtr, bool); +build_enum_type_decl(reader&, const xmlNodePtr, bool); static shared_ptr -build_typedef_decl(read_context&, const xmlNodePtr, bool); +build_typedef_decl(reader&, const xmlNodePtr, bool); static class_decl_sptr -build_class_decl(read_context&, const xmlNodePtr, bool); +build_class_decl(reader&, const xmlNodePtr, bool); static union_decl_sptr -build_union_decl(read_context&, const xmlNodePtr, bool); +build_union_decl(reader&, const xmlNodePtr, bool); static shared_ptr -build_function_tdecl(read_context&, const xmlNodePtr, bool); +build_function_tdecl(reader&, const xmlNodePtr, bool); static shared_ptr -build_class_tdecl(read_context&, const xmlNodePtr, bool); +build_class_tdecl(reader&, const xmlNodePtr, bool); static type_tparameter_sptr -build_type_tparameter(read_context&, const xmlNodePtr, +build_type_tparameter(reader&, const xmlNodePtr, unsigned, template_decl_sptr); static type_composition_sptr -build_type_composition(read_context&, const xmlNodePtr, +build_type_composition(reader&, const xmlNodePtr, unsigned, template_decl_sptr); static non_type_tparameter_sptr -build_non_type_tparameter(read_context&, const xmlNodePtr, +build_non_type_tparameter(reader&, const xmlNodePtr, unsigned, template_decl_sptr); static template_tparameter_sptr -build_template_tparameter(read_context&, const xmlNodePtr, +build_template_tparameter(reader&, const xmlNodePtr, unsigned, template_decl_sptr); static template_parameter_sptr -build_template_parameter(read_context&, const xmlNodePtr, +build_template_parameter(reader&, const xmlNodePtr, unsigned, template_decl_sptr); // Please make this build_type function be the last one of the list. @@ -1371,42 +1403,42 @@ build_template_parameter(read_context&, const xmlNodePtr, // please make sure to update it accordingly, whenever a new // type-building function is added here. static shared_ptr -build_type(read_context&, const xmlNodePtr, bool); +build_type(reader&, const xmlNodePtr, bool); // -static type_or_decl_base_sptr handle_element_node(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_type_decl(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_namespace_decl(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_qualified_type_decl(read_context&, +static type_or_decl_base_sptr handle_element_node(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_type_decl(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_namespace_decl(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_qualified_type_decl(reader&, xmlNodePtr, bool); -static decl_base_sptr handle_pointer_type_def(read_context&, +static decl_base_sptr handle_pointer_type_def(reader&, xmlNodePtr, bool); -static decl_base_sptr handle_reference_type_def(read_context&, +static decl_base_sptr handle_reference_type_def(reader&, xmlNodePtr, bool); -static type_base_sptr handle_function_type(read_context&, +static type_base_sptr handle_function_type(reader&, xmlNodePtr, bool); -static decl_base_sptr handle_array_type_def(read_context&, +static decl_base_sptr handle_array_type_def(reader&, xmlNodePtr, bool); -static decl_base_sptr handle_enum_type_decl(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_typedef_decl(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_var_decl(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_function_decl(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_class_decl(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_union_decl(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_function_tdecl(read_context&, xmlNodePtr, bool); -static decl_base_sptr handle_class_tdecl(read_context&, xmlNodePtr, bool); +static decl_base_sptr handle_enum_type_decl(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_typedef_decl(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_var_decl(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_function_decl(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_class_decl(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_union_decl(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_function_tdecl(reader&, xmlNodePtr, bool); +static decl_base_sptr handle_class_tdecl(reader&, xmlNodePtr, bool); #ifdef WITH_SHOW_TYPE_USE_IN_ABILINT -#define RECORD_ARTIFACT_AS_USED_BY(ctxt, used, user) \ - ctxt.record_artifact_as_used_by(used,user) -#define RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(ctxt, fn) \ - ctxt.record_artifacts_as_used_in_fn_decl(fn) -#define RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(ctxt, fn_type)\ - ctxt.record_artifacts_as_used_in_fn_type(fn_type) +#define RECORD_ARTIFACT_AS_USED_BY(rdr, used, user) \ + rdr.record_artifact_as_used_by(used,user) +#define RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(rdr, fn) \ + rdr.record_artifacts_as_used_in_fn_decl(fn) +#define RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(rdr, fn_type)\ + rdr.record_artifacts_as_used_in_fn_type(fn_type) #else -#define RECORD_ARTIFACT_AS_USED_BY(ctxt, used, user) -#define RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(ctxt, fn) -#define RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(ctxt, fn_type) +#define RECORD_ARTIFACT_AS_USED_BY(rdr, used, user) +#define RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(rdr, fn) +#define RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(rdr, fn_type) #endif /// Get the IR node representing the scope for a given XML node. @@ -1423,7 +1455,7 @@ static decl_base_sptr handle_class_tdecl(read_context&, xmlNodePtr, bool); /// @return the IR node representing the scope of the IR node for the /// XML node given in argument. scope_decl_sptr -read_context::get_scope_for_node(xmlNodePtr node, +reader::get_scope_for_node(xmlNodePtr node, access_specifier& access) { scope_decl_sptr nil, scope; @@ -1477,7 +1509,7 @@ read_context::get_scope_for_node(xmlNodePtr node, /// /// @return the type declaration for the ID given in parameter. type_base_sptr -read_context::build_or_get_type_decl(const string& id, +reader::build_or_get_type_decl(const string& id, bool add_decl_to_scope) { type_base_sptr t = get_type_decl(id); @@ -1528,12 +1560,12 @@ read_context::build_or_get_type_decl(const string& id, /// document. Return 1 of the parsing was successful, 0 if no input /// xml token is left, or -1 in case of error. /// -/// @param ctxt the read context +/// @param rdr the ABIXML reader /// static int -advance_cursor(read_context& ctxt) +advance_cursor(reader& rdr) { - xml::reader_sptr reader = ctxt.get_reader(); + xml::reader_sptr reader = rdr.get_libxml_reader(); return xmlTextReaderRead(reader.get()); } @@ -1541,12 +1573,12 @@ advance_cursor(read_context& ctxt) /// the value of the 'id' attribute (for type definitions) and the value /// is the xml node containing the 'id' attribute. /// -/// @param ctxt the context of the reader. +/// @param rdr the context of the reader. /// /// @param node the XML sub-tree node to walk. It must be an element /// node. static void -walk_xml_node_to_map_type_ids(read_context& ctxt, +walk_xml_node_to_map_type_ids(reader& rdr, xmlNodePtr node) { xmlNodePtr n = node; @@ -1557,17 +1589,20 @@ walk_xml_node_to_map_type_ids(read_context& ctxt, if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(n, "id")) { string id = CHAR_STR(s); - ctxt.map_id_and_node(id, n); + rdr.map_id_and_node(id, n); } for (n = xmlFirstElementChild(n); n; n = xmlNextElementSibling(n)) - walk_xml_node_to_map_type_ids(ctxt, n); + walk_xml_node_to_map_type_ids(rdr, n); } static bool -read_translation_unit(read_context& ctxt, translation_unit& tu, xmlNodePtr node) +read_translation_unit(fe_iface& iface, translation_unit& tu, xmlNodePtr node) { - tu.set_corpus(ctxt.get_corpus().get()); + abixml_reader::reader& rdr = dynamic_cast(iface); + + if (!rdr.corpus()->is_empty()) + tu.set_corpus(rdr.corpus().get()); xml::xml_char_sptr addrsize_str = XML_NODE_GET_ATTRIBUTE(node, "address-size"); @@ -1595,25 +1630,25 @@ read_translation_unit(read_context& ctxt, translation_unit& tu, xmlNodePtr node) // We are at global scope, as we've just seen the top-most // "abi-instr" element. - ctxt.push_decl(tu.get_global_scope()); - ctxt.map_xml_node_to_decl(node, tu.get_global_scope()); + rdr.push_decl(tu.get_global_scope()); + rdr.map_xml_node_to_decl(node, tu.get_global_scope()); - if (ctxt.get_id_xml_node_map().empty() - || !ctxt.get_corpus()) - walk_xml_node_to_map_type_ids(ctxt, node); + if (rdr.get_id_xml_node_map().empty() + || !rdr.corpus()) + walk_xml_node_to_map_type_ids(rdr, node); for (xmlNodePtr n = xmlFirstElementChild(node); n; n = xmlNextElementSibling(n)) - handle_element_node(ctxt, n, /*add_decl_to_scope=*/true); + handle_element_node(rdr, n, /*add_decl_to_scope=*/true); - ctxt.pop_scope_or_abort(tu.get_global_scope()); + rdr.pop_scope_or_abort(tu.get_global_scope()); - xml::reader_sptr reader = ctxt.get_reader(); + xml::reader_sptr reader = rdr.get_libxml_reader(); if (!reader) return false; - ctxt.clear_per_translation_unit_data(); + rdr.clear_per_translation_unit_data(); return true; } @@ -1626,15 +1661,15 @@ read_translation_unit(read_context& ctxt, translation_unit& tu, xmlNodePtr node) /// @ref translation_unit out of it, add it to the current corpus and /// return it. /// -/// @param ctxt the read context. +/// @param rdr the ABIXML reader. /// /// @param node the XML node to consider. /// /// @return the resulting translation unit. static translation_unit_sptr -get_or_read_and_add_translation_unit(read_context& ctxt, xmlNodePtr node) +get_or_read_and_add_translation_unit(reader& rdr, xmlNodePtr node) { - corpus_sptr corp = ctxt.get_corpus(); + corpus_sptr corp = rdr.corpus(); translation_unit_sptr tu; string tu_path; @@ -1645,18 +1680,18 @@ get_or_read_and_add_translation_unit(read_context& ctxt, xmlNodePtr node) tu_path = reinterpret_cast(path_str.get()); ABG_ASSERT(!tu_path.empty()); - if (corp) + if (corp && !corp->is_empty()) tu = corp->find_translation_unit(tu_path); if (tu) return tu; } - tu.reset(new translation_unit(ctxt.get_environment(), tu_path)); - if (corp) + tu.reset(new translation_unit(rdr.get_environment(), tu_path)); + if (corp && !corp->is_empty()) corp->add(tu); - if (read_translation_unit(ctxt, *tu, node)) + if (read_translation_unit(rdr, *tu, node)) return tu; return translation_unit_sptr(); @@ -1666,19 +1701,21 @@ get_or_read_and_add_translation_unit(read_context& ctxt, xmlNodePtr node) /// represented by an 'abi-instr' element node, associated to the current /// context. /// -/// @param ctxt the current input context +/// @param rdr the current input context /// /// @return the translation unit resulting from the parsing upon /// successful completion, or nil. static translation_unit_sptr -read_translation_unit_from_input(read_context& ctxt) +read_translation_unit_from_input(fe_iface& iface) { translation_unit_sptr tu, nil; - xmlNodePtr node = ctxt.get_corpus_node(); + abixml_reader::reader& rdr = dynamic_cast(iface); + + xmlNodePtr node = rdr.get_corpus_node(); if (!node) { - xml::reader_sptr reader = ctxt.get_reader(); + xml::reader_sptr reader = rdr.get_libxml_reader(); if (!reader) return nil; @@ -1686,7 +1723,7 @@ read_translation_unit_from_input(read_context& ctxt) int status = 1; while (status == 1 && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT) - status = advance_cursor (ctxt); + status = advance_cursor (rdr); if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(), BAD_CAST("abi-instr"))) @@ -1699,7 +1736,7 @@ read_translation_unit_from_input(read_context& ctxt) else { node = 0; - for (xmlNodePtr n = ctxt.get_corpus_node(); + for (xmlNodePtr n = rdr.get_corpus_node(); n; n = xmlNextElementSibling(n)) { @@ -1713,16 +1750,16 @@ read_translation_unit_from_input(read_context& ctxt) if (node == 0) return nil; - tu = get_or_read_and_add_translation_unit(ctxt, node); + tu = get_or_read_and_add_translation_unit(rdr, node); - if (ctxt.get_corpus_node()) + if (rdr.get_corpus_node()) { // We are not in the mode where the current corpus node came // from a local invocation of xmlTextReaderExpand. So let's set - // ctxt.get_corpus_node to the next child element node of the + // rdr.get_corpus_node to the next child element node of the // corpus that needs to be processed. node = xmlNextElementSibling(node); - ctxt.set_corpus_node(node); + rdr.set_corpus_node(node); } return tu; @@ -1736,7 +1773,7 @@ read_translation_unit_from_input(read_context& ctxt) /// element named "elf-variable-symbols." They contains "elf-symbol" /// XML elements. /// -/// @param ctxt the read_context to use for the parsing. +/// @param rdr the reader to use for the parsing. /// /// @param fn_symdb any resulting function symbol database object, if /// elf-function-symbols was present. @@ -1746,21 +1783,21 @@ read_translation_unit_from_input(read_context& ctxt) /// /// @return true upon successful parsing, false otherwise. static bool -read_symbol_db_from_input(read_context& ctxt, +read_symbol_db_from_input(reader& rdr, string_elf_symbols_map_sptr& fn_symdb, string_elf_symbols_map_sptr& var_symdb) { - xml::reader_sptr reader = ctxt.get_reader(); + xml::reader_sptr reader = rdr.get_libxml_reader(); if (!reader) return false; - if (!ctxt.get_corpus_node()) + if (!rdr.get_corpus_node()) for (;;) { int status = 1; while (status == 1 && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT) - status = advance_cursor (ctxt); + status = advance_cursor (rdr); if (status != 1) return false; @@ -1780,14 +1817,14 @@ read_symbol_db_from_input(read_context& ctxt, return false; if (has_fn_syms) - fn_symdb = build_elf_symbol_db(ctxt, node, true); + fn_symdb = build_elf_symbol_db(rdr, node, true); else if (has_var_syms) - var_symdb = build_elf_symbol_db(ctxt, node, false); + var_symdb = build_elf_symbol_db(rdr, node, false); xmlTextReaderNext(reader.get()); } else - for (xmlNodePtr n = ctxt.get_corpus_node(); n; n = xmlNextElementSibling(n)) + for (xmlNodePtr n = rdr.get_corpus_node(); n; n = xmlNextElementSibling(n)) { bool has_fn_syms = false, has_var_syms = false; if (xmlStrEqual(n->name, BAD_CAST("elf-function-symbols"))) @@ -1796,14 +1833,14 @@ read_symbol_db_from_input(read_context& ctxt, has_var_syms = true; else { - ctxt.set_corpus_node(n); + rdr.set_corpus_node(n); break; } if (has_fn_syms) - fn_symdb = build_elf_symbol_db(ctxt, n, true); + fn_symdb = build_elf_symbol_db(rdr, n, true); else if (has_var_syms) - var_symdb = build_elf_symbol_db(ctxt, n, false); + var_symdb = build_elf_symbol_db(rdr, n, false); else break; } @@ -1849,27 +1886,27 @@ build_needed(xmlNode* node, vector& needed) /// "elf-needed". Then read the sub-tree to made of that node and /// extracts a vector of needed dependencies name from it. /// -/// @param ctxt the read context used to the xml reading. +/// @param rdr the ABIXML reader used to the xml reading. /// /// @param needed the resulting vector of dependency names. /// /// @return true upon successful completion, false otherwise. static bool -read_elf_needed_from_input(read_context& ctxt, +read_elf_needed_from_input(reader& rdr, vector& needed) { - xml::reader_sptr reader = ctxt.get_reader(); + xml::reader_sptr reader = rdr.get_libxml_reader(); if (!reader) return false; xmlNodePtr node = 0; - if (ctxt.get_corpus_node() == 0) + if (rdr.get_corpus_node() == 0) { int status = 1; while (status == 1 && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT) - status = advance_cursor (ctxt); + status = advance_cursor (rdr); if (status != 1) return false; @@ -1884,7 +1921,7 @@ read_elf_needed_from_input(read_context& ctxt, } else { - for (xmlNodePtr n = ctxt.get_corpus_node(); + for (xmlNodePtr n = rdr.get_corpus_node(); n; n = xmlNextElementSibling(n)) { @@ -1900,7 +1937,7 @@ read_elf_needed_from_input(read_context& ctxt, { result = build_needed(node, needed); node = xmlNextElementSibling(node); - ctxt.set_corpus_node(node); + rdr.set_corpus_node(node); } return result; @@ -1925,35 +1962,38 @@ read_elf_needed_from_input(read_context& ctxt, /// @ref diff_context type to learn how to set suppressions that are /// to be used in that context. /// -/// @param ctxt the context that is going to be used by functions that +/// @param rdr the context that is going to be used by functions that /// read types and declarations information to construct and ABI /// corpus. /// /// @param supprs the suppression specifications to be applied during /// the construction of the ABI corpus. void -add_read_context_suppressions(read_context& ctxt, - const suppr::suppressions_type& supprs) +add_reader_suppressions(reader& rdr, + const suppr::suppressions_type& supprs) { for (suppr::suppressions_type::const_iterator i = supprs.begin(); i != supprs.end(); ++i) if ((*i)->get_drops_artifact_from_ir()) - ctxt.get_suppressions().push_back(*i); + rdr.suppressions().push_back(*i); } -/// Configure the @ref read_context so that types not reachable from +/// Configure the @ref reader so that types not reachable from /// public interface are taken into account when the abixml file is /// read. /// -/// @param ctxt the @read_context to consider. +/// @param rdr the @reader to consider. /// /// @param flag if yes, then types not reachable from public interface /// are taken into account when the abixml file is read. void -consider_types_not_reachable_from_public_interfaces(read_context& ctxt, +consider_types_not_reachable_from_public_interfaces(fe_iface& iface, bool flag) -{ctxt.tracking_non_reachable_types(flag);} +{ + abixml_reader::reader& rdr = dynamic_cast(iface); + rdr.tracking_non_reachable_types(flag); +} #ifdef WITH_SHOW_TYPE_USE_IN_ABILINT /// Get the vector of types that have a given type-id. @@ -1961,14 +2001,15 @@ consider_types_not_reachable_from_public_interfaces(read_context& ctxt, /// This function is available only if the project has been configured /// with --enable-show-type-use-in-abilint. /// -/// @param ctxt the abixml text reader context to use. +/// @param rdr the abixml text reader context to use. /// /// @param type_id the type-id to consider. vector* -get_types_from_type_id(read_context& ctxt, const string& type_id) +get_types_from_type_id(fe_iface& iface, const string& type_id) { - auto it = ctxt.m_types_map.find(type_id); - if (it == ctxt.m_types_map.end()) + xml_reader::reader& rdr = dynamic_cast(iface); + auto it = rdr.m_types_map.find(type_id); + if (it == rdr.m_types_map.end()) return nullptr; return &it->second; } @@ -1978,10 +2019,13 @@ get_types_from_type_id(read_context& ctxt, const string& type_id) /// This function is available only if the project has been configured /// with --enable-show-type-use-in-abilint. /// -/// @param ctxt the abixml text reader context to use. +/// @param rdr the abixml text reader context to use. unordered_map>* -get_artifact_used_by_relation_map(read_context& ctxt) -{return &ctxt.m_artifact_used_by_map;} +get_artifact_used_by_relation_map(fe_iface& iface) +{ + xml_reader::reader& rdr = dynamic_cast(iface); + return &rdr.m_artifact_used_by_map; +} #endif /// Read the "version" attribute from the current XML element which is @@ -2016,217 +2060,20 @@ handle_version_attribute(xml::reader_sptr& reader, corpus& corp) corp.set_format_minor_version_number(v[1]); } -/// Parse the input XML document containing an ABI corpus, represented -/// by an 'abi-corpus' element node, associated to the current -/// context. -/// -/// @param ctxt the current input context. -/// -/// @return the corpus resulting from the parsing -corpus_sptr -read_corpus_from_input(read_context& ctxt) -{ - corpus_sptr nil; - - xml::reader_sptr reader = ctxt.get_reader(); - if (!reader) - return nil; - - // This is to remember to call xmlTextReaderNext if we ever call - // xmlTextReaderExpand. - bool call_reader_next = false; - - xmlNodePtr node = ctxt.get_corpus_node(); - if (!node) - { - // The document must start with the abi-corpus node. - int status = 1; - while (status == 1 - && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT) - status = advance_cursor (ctxt); - - if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(), - BAD_CAST("abi-corpus"))) - return nil; - - ctxt.set_corpus(std::make_shared(ctxt.get_environment(), "")); -#ifdef WITH_DEBUG_SELF_COMPARISON - if (ctxt.get_environment()->self_comparison_debug_is_on()) - ctxt.get_environment()-> - set_self_comparison_debug_input(ctxt.get_corpus()); -#endif - - if (!ctxt.get_corpus_group()) - ctxt.clear_per_corpus_data(); - - corpus& corp = *ctxt.get_corpus(); - corp.set_origin(corpus::NATIVE_XML_ORIGIN); - ctxt.set_exported_decls_builder(corp.get_exported_decls_builder().get()); - - handle_version_attribute(reader, corp); - - xml::xml_char_sptr path_str = XML_READER_GET_ATTRIBUTE(reader, "path"); - string path; - - if (path_str) - { - path = reinterpret_cast(path_str.get()); - corp.set_path(path); - } - - xml::xml_char_sptr architecture_str = - XML_READER_GET_ATTRIBUTE(reader, "architecture"); - if (architecture_str) - corp.set_architecture_name - (reinterpret_cast(architecture_str.get())); - - xml::xml_char_sptr soname_str = - XML_READER_GET_ATTRIBUTE(reader, "soname"); - string soname; - - if (soname_str) - { - soname = reinterpret_cast(soname_str.get()); - corp.set_soname(soname); - } - - // Apply suppression specifications here to honour: - // - // [suppress_file] - // (soname_regexp - // |soname_not_regexp - // |file_name_regexp - // |file_name_not_regexp) = - if ((!soname.empty() || !path.empty()) - && ctxt.corpus_is_suppressed_by_soname_or_filename(soname, path)) - return nil; - - node = xmlTextReaderExpand(reader.get()); - if (!node) - return nil; - - call_reader_next = true; - } - else - { - ctxt.set_corpus(std::make_shared(ctxt.get_environment(), "")); -#ifdef WITH_DEBUG_SELF_COMPARISON - if (ctxt.get_environment()->self_comparison_debug_is_on()) - ctxt.get_environment()-> - set_self_comparison_debug_input(ctxt.get_corpus()); -#endif - - if (!ctxt.get_corpus_group()) - ctxt.clear_per_corpus_data(); - - corpus& corp = *ctxt.get_corpus(); - corp.set_origin(corpus::NATIVE_XML_ORIGIN); - - ctxt.set_exported_decls_builder(corp.get_exported_decls_builder().get()); - - xml::xml_char_sptr path_str = XML_NODE_GET_ATTRIBUTE(node, "path"); - if (path_str) - corp.set_path(reinterpret_cast(path_str.get())); - - xml::xml_char_sptr architecture_str = - XML_NODE_GET_ATTRIBUTE(node, "architecture"); - if (architecture_str) - corp.set_architecture_name - (reinterpret_cast(architecture_str.get())); - - xml::xml_char_sptr soname_str = - XML_NODE_GET_ATTRIBUTE(node, "soname"); - if (soname_str) - corp.set_soname(reinterpret_cast(soname_str.get())); - } - - // If the corpus element node has children nodes, make - // ctxt.get_corpus_node() returns the first child element node of - // the corpus element that *needs* to be processed. - if (node->children) - { - xmlNodePtr n = xmlFirstElementChild(node); - ctxt.set_corpus_node(n); - } - - corpus& corp = *ctxt.get_corpus(); - - walk_xml_node_to_map_type_ids(ctxt, node); - - // Read the needed element - vector needed; - read_elf_needed_from_input(ctxt, needed); - if (!needed.empty()) - corp.set_needed(needed); - - string_elf_symbols_map_sptr fn_sym_db, var_sym_db; - - // Read the symbol databases. - read_symbol_db_from_input(ctxt, fn_sym_db, var_sym_db); - // Note that it's possible that both fn_sym_db and var_sym_db are nil, - // due to potential suppression specifications. That's fine. - corp.set_symtab(symtab_reader::symtab::load(fn_sym_db, var_sym_db)); - - ctxt.get_environment()->canonicalization_is_done(false); - - // Read the translation units. - while (read_translation_unit_from_input(ctxt)) - ; - - if (ctxt.tracking_non_reachable_types()) - { - bool is_tracking_non_reachable_types = false; - read_tracking_non_reachable_types(node, is_tracking_non_reachable_types); - - ABG_ASSERT - (corp.recording_types_reachable_from_public_interface_supported() - == is_tracking_non_reachable_types); - } - - - ctxt.perform_late_type_canonicalizing(); - - ctxt.get_environment()->canonicalization_is_done(true); - - if (call_reader_next) - { - // This is the necessary counter-part of the xmlTextReaderExpand() - // call at the beginning of the function. - xmlTextReaderNext(reader.get()); - // The call above invalidates the xml node returned by - // xmlTextReaderExpand, which is can still be accessed via - // ctxt.set_corpus_node. - ctxt.set_corpus_node(0); - } - else - { - node = ctxt.get_corpus_node(); - node = xmlNextElementSibling(node); - if (!node) - { - node = ctxt.get_corpus_node(); - if (node) - node = xmlNextElementSibling(node->parent); - } - ctxt.set_corpus_node(node); - } - - return ctxt.get_corpus(); -} - /// Parse the input XML document containing an ABI corpus group, /// represented by an 'abi-corpus-group' element node, associated to /// the current context. /// -/// @param ctxt the current input context. +/// @param rdr the current input context. /// /// @return the corpus group resulting from the parsing corpus_group_sptr -read_corpus_group_from_input(read_context& ctxt) +read_corpus_group_from_input(fe_iface& iface) { corpus_group_sptr nil; - xml::reader_sptr reader = ctxt.get_reader(); + abixml_reader::reader& rdr = dynamic_cast(iface); + xml::reader_sptr reader = rdr.get_libxml_reader(); if (!reader) return nil; @@ -2234,21 +2081,21 @@ read_corpus_group_from_input(read_context& ctxt) int status = 1; while (status == 1 && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT) - status = advance_cursor (ctxt); + status = advance_cursor (rdr); if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(), BAD_CAST("abi-corpus-group"))) return nil; - if (!ctxt.get_corpus_group()) + if (!rdr.corpus_group()) { - corpus_group_sptr g(new corpus_group(ctxt.get_environment(), - ctxt.get_path())); + corpus_group_sptr g(new corpus_group(rdr.get_environment(), + rdr.get_path())); g->set_origin(corpus::NATIVE_XML_ORIGIN); - ctxt.set_corpus_group(g); + rdr.corpus_group(g); } - corpus_group_sptr group = ctxt.get_corpus_group(); + corpus_group_sptr group = rdr.corpus_group(); handle_version_attribute(reader, *group); @@ -2261,15 +2108,16 @@ read_corpus_group_from_input(read_context& ctxt) return nil; node = xmlFirstElementChild(node); - ctxt.set_corpus_node(node); + rdr.set_corpus_node(node); corpus_sptr corp; - while ((corp = read_corpus_from_input(ctxt))) - ctxt.get_corpus_group()->add_corpus(corp); + fe_iface::status sts; + while ((corp = rdr.read_corpus(sts))) + rdr.corpus_group()->add_corpus(corp); xmlTextReaderNext(reader.get()); - return ctxt.get_corpus_group(); + return rdr.corpus_group(); } /// De-serialize an ABI corpus group from an input XML document which @@ -2285,11 +2133,11 @@ read_corpus_group_from_input(read_context& ctxt) /// @return the resulting corpus group de-serialized from the parsing. /// This is non-null iff the parsing resulted in a valid corpus group. corpus_group_sptr -read_corpus_group_from_native_xml(std::istream* in, - environment* env) +read_corpus_group_from_abixml(std::istream* in, + environment& env) { - read_context_sptr read_ctxt = create_native_xml_read_context(in, env); - return read_corpus_group_from_input(*read_ctxt); + fe_iface_sptr rdr = create_abixml_reader(in, env); + return read_corpus_group_from_input(*rdr); } /// De-serialize an ABI corpus group from an XML document file which @@ -2307,11 +2155,11 @@ read_corpus_group_from_native_xml(std::istream* in, /// This is non-null if the parsing successfully resulted in a corpus /// group. corpus_group_sptr -read_corpus_group_from_native_xml_file(const string& path, - environment* env) +read_corpus_group_from_abixml_file(const string& path, + environment& env) { - read_context_sptr read_ctxt = create_native_xml_read_context(path, env); - corpus_group_sptr group = read_corpus_group_from_input(*read_ctxt); + fe_iface_sptr rdr = create_abixml_reader(path, env); + corpus_group_sptr group = read_corpus_group_from_input(*rdr); return group; } @@ -2326,13 +2174,13 @@ read_corpus_group_from_native_xml_file(const string& path, /// successful completion, or nil. translation_unit_sptr read_translation_unit_from_file(const string& input_file, - environment* env) + environment& env) { - read_context ctxt(xml::new_reader_from_file(input_file), env); - translation_unit_sptr tu = read_translation_unit_from_input(ctxt); - ctxt.get_environment()->canonicalization_is_done(false); - ctxt.perform_late_type_canonicalizing(); - ctxt.get_environment()->canonicalization_is_done(true); + reader rdr(xml::new_reader_from_file(input_file), env); + translation_unit_sptr tu = read_translation_unit_from_input(rdr); + env.canonicalization_is_done(false); + rdr.perform_late_type_canonicalizing(); + env.canonicalization_is_done(true); return tu; } @@ -2348,30 +2196,31 @@ read_translation_unit_from_file(const string& input_file, /// successful completion, or nil. translation_unit_sptr read_translation_unit_from_buffer(const string& buffer, - environment* env) + environment& env) { - read_context ctxt(xml::new_reader_from_buffer(buffer), env); - translation_unit_sptr tu = read_translation_unit_from_input(ctxt); - ctxt.get_environment()->canonicalization_is_done(false); - ctxt.perform_late_type_canonicalizing(); - ctxt.get_environment()->canonicalization_is_done(true); + reader rdr(xml::new_reader_from_buffer(buffer), env); + translation_unit_sptr tu = read_translation_unit_from_input(rdr); + env.canonicalization_is_done(false); + rdr.perform_late_type_canonicalizing(); + env.canonicalization_is_done(true); return tu; } /// Parse a translation unit from an abixml input from a given /// context. /// -/// @param ctxt the @ref read_context to consider. +/// @param rdr the @ref reader to consider. /// /// @return the constructed @ref translation_unit from the content of /// the input abixml. translation_unit_sptr -read_translation_unit(read_context& ctxt) +read_translation_unit(fe_iface& iface) { - translation_unit_sptr tu = read_translation_unit_from_input(ctxt); - ctxt.get_environment()->canonicalization_is_done(false); - ctxt.perform_late_type_canonicalizing(); - ctxt.get_environment()->canonicalization_is_done(true); + abixml_reader::reader& rdr = dynamic_cast(iface); + translation_unit_sptr tu = read_translation_unit_from_input(rdr); + rdr.options().env.canonicalization_is_done(false); + rdr.perform_late_type_canonicalizing(); + rdr.options().env.canonicalization_is_done(true); return tu; } @@ -2380,51 +2229,51 @@ read_translation_unit(read_context& ctxt) /// The result of the "handling" is to build the representation of the /// xml node and tied it to the current translation unit. /// -/// @param ctxt the current parsing context. +/// @param rdr the current parsing context. /// /// @return true upon successful completion, false otherwise. static type_or_decl_base_sptr -handle_element_node(read_context& ctxt, xmlNodePtr node, +handle_element_node(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { type_or_decl_base_sptr decl; if (!node) return decl; - ((decl = handle_namespace_decl(ctxt, node, add_to_current_scope)) - ||(decl = handle_type_decl(ctxt, node, add_to_current_scope)) - ||(decl = handle_qualified_type_decl(ctxt, node, + ((decl = handle_namespace_decl(rdr, node, add_to_current_scope)) + ||(decl = handle_type_decl(rdr, node, add_to_current_scope)) + ||(decl = handle_qualified_type_decl(rdr, node, add_to_current_scope)) - ||(decl = handle_pointer_type_def(ctxt, node, + ||(decl = handle_pointer_type_def(rdr, node, add_to_current_scope)) - || (decl = handle_reference_type_def(ctxt, node, add_to_current_scope)) - || (decl = handle_function_type(ctxt, node, add_to_current_scope)) - || (decl = handle_array_type_def(ctxt, node, add_to_current_scope)) - || (decl = handle_enum_type_decl(ctxt, node, + || (decl = handle_reference_type_def(rdr, node, add_to_current_scope)) + || (decl = handle_function_type(rdr, node, add_to_current_scope)) + || (decl = handle_array_type_def(rdr, node, add_to_current_scope)) + || (decl = handle_enum_type_decl(rdr, node, add_to_current_scope)) - || (decl = handle_typedef_decl(ctxt, node, + || (decl = handle_typedef_decl(rdr, node, add_to_current_scope)) - || (decl = handle_var_decl(ctxt, node, + || (decl = handle_var_decl(rdr, node, add_to_current_scope)) - || (decl = handle_function_decl(ctxt, node, + || (decl = handle_function_decl(rdr, node, add_to_current_scope)) - || (decl = handle_class_decl(ctxt, node, + || (decl = handle_class_decl(rdr, node, add_to_current_scope)) - || (decl = handle_union_decl(ctxt, node, + || (decl = handle_union_decl(rdr, node, add_to_current_scope)) - || (decl = handle_function_tdecl(ctxt, node, + || (decl = handle_function_tdecl(rdr, node, add_to_current_scope)) - || (decl = handle_class_tdecl(ctxt, node, + || (decl = handle_class_tdecl(rdr, node, add_to_current_scope))); // If the user wants us to track non-reachable types, then read the // 'is-non-reachable-type' attribute on type elements and record // reachable types accordingly. - if (ctxt.tracking_non_reachable_types()) + if (rdr.tracking_non_reachable_types()) { if (type_base_sptr t = is_type(decl)) { - corpus_sptr abi = ctxt.get_corpus(); + corpus_sptr abi = rdr.corpus(); ABG_ASSERT(abi); bool is_non_reachable_type = false; read_is_non_reachable_type(node, is_non_reachable_type); @@ -2438,13 +2287,13 @@ handle_element_node(read_context& ctxt, xmlNodePtr node, /// Parses location attributes on an xmlNodePtr. /// -///@param ctxt the current parsing context +///@param rdr the current parsing context /// ///@param loc the resulting location. /// /// @return true upon sucessful parsing, false otherwise. static bool -read_location(const read_context& ctxt, +read_location(const reader& rdr, xmlNodePtr node, location& loc) { @@ -2455,17 +2304,17 @@ read_location(const read_context& ctxt, file_path = CHAR_STR(f); if (file_path.empty()) - return read_artificial_location(ctxt, node, loc); + return read_artificial_location(rdr, node, loc); if (xml_char_sptr l = xml::build_sptr(xmlGetProp(node, BAD_CAST("line")))) line = atoi(CHAR_STR(l)); else - return read_artificial_location(ctxt, node, loc); + return read_artificial_location(rdr, node, loc); if (xml_char_sptr c = xml::build_sptr(xmlGetProp(node, BAD_CAST("column")))) column = atoi(CHAR_STR(c)); - read_context& c = const_cast(ctxt); + reader& c = const_cast(rdr); loc = c.get_translation_unit()->get_loc_mgr().create_new_location(file_path, line, column); @@ -2477,13 +2326,13 @@ read_location(const read_context& ctxt, /// The artificial location is the line number of the xmlNode as well /// as the URI of the node. /// -///@param ctxt the current parsing context +///@param rdr the current parsing context /// ///@param loc the resulting location. /// /// @return true upon sucessful parsing, false otherwise. static bool -read_artificial_location(const read_context& ctxt, +read_artificial_location(const reader& rdr, xmlNodePtr node, location& loc) { @@ -2498,7 +2347,7 @@ read_artificial_location(const read_context& ctxt, if (node->doc) file_path = reinterpret_cast(node->doc->URL); - read_context& c = const_cast(ctxt); + reader& c = const_cast(rdr); loc = c.get_translation_unit()->get_loc_mgr().create_new_location(file_path, line, column); @@ -2514,7 +2363,7 @@ read_artificial_location(const read_context& ctxt, /// The function sets the artificial location only if the artifact /// doesn"t already have one. /// -///@param ctxt the current parsing context +///@param rdr the current parsing context /// ///@param node the XML node to consider. /// @@ -2522,14 +2371,14 @@ read_artificial_location(const read_context& ctxt, /// /// @return true iff the location was set on the artifact. static bool -maybe_set_artificial_location(const read_context& ctxt, +maybe_set_artificial_location(const reader& rdr, xmlNodePtr node, type_or_decl_base_sptr artefact) { if (artefact && !artefact->has_artificial_location()) { location l; - if (read_artificial_location(ctxt, node, l)) + if (read_artificial_location(rdr, node, l)) { artefact->set_artificial_location(l); return true; @@ -3052,12 +2901,12 @@ maybe_map_type_with_type_id(const type_base_sptr& t, if (!t) return false; - environment *env = t->get_environment(); - if (!env->self_comparison_debug_is_on() + const environment& env = t->get_environment(); + if (!env.self_comparison_debug_is_on() || is_non_canonicalized_type(t.get())) return false; - env->get_pointer_type_id_map()[reinterpret_cast(t.get())] = + env.get_pointer_type_id_map()[reinterpret_cast(t.get())] = type_id; return true; @@ -3083,8 +2932,8 @@ maybe_map_type_with_type_id(const type_base_sptr& t, if (!t) return false; - environment *env = t->get_environment(); - if (!env->self_comparison_debug_is_on() + const environment&env = t->get_environment(); + if (!env.self_comparison_debug_is_on() || is_non_canonicalized_type(t.get())) return false; @@ -3100,13 +2949,13 @@ maybe_map_type_with_type_id(const type_base_sptr& t, /// Set the naming typedef to a given decl depending on the content of /// the "naming-typedef-id" property of its descriptive XML element. /// -/// @param ctxt the current read context. +/// @param rdr the current ABIXML reader. /// /// @param node the XML node to read from. /// /// @param decl the decl to set the naming typedef to. static void -maybe_set_naming_typedef(read_context& ctxt, +maybe_set_naming_typedef(reader& rdr, xmlNodePtr node, const decl_base_sptr& decl) { @@ -3115,7 +2964,7 @@ maybe_set_naming_typedef(read_context& ctxt, if (!naming_typedef_id.empty()) { typedef_decl_sptr naming_typedef = - is_typedef(ctxt.build_or_get_type_decl(naming_typedef_id, true)); + is_typedef(rdr.build_or_get_type_decl(naming_typedef_id, true)); ABG_ASSERT(naming_typedef); decl->set_naming_typedef(naming_typedef); } @@ -3126,7 +2975,7 @@ maybe_set_naming_typedef(read_context& ctxt, /// content of the namespace and builds the proper IR nodes /// accordingly. /// -/// @param ctxt the read context to use. +/// @param rdr the ABIXML reader to use. /// /// @param node the XML node to consider. It must constain the /// content of the namespace, that is, children XML nodes representing @@ -3137,7 +2986,7 @@ maybe_set_naming_typedef(read_context& ctxt, /// /// @return a pointer to the the resulting @ref namespace_decl. static namespace_decl_sptr -build_namespace_decl(read_context& ctxt, +build_namespace_decl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -3145,7 +2994,7 @@ build_namespace_decl(read_context& ctxt, if (!node || !xmlStrEqual(node->name, BAD_CAST("namespace-decl"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { namespace_decl_sptr result = dynamic_pointer_cast(d); ABG_ASSERT(result); @@ -3157,20 +3006,20 @@ build_namespace_decl(read_context& ctxt, name = xml::unescape_xml_string(CHAR_STR(s)); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); - const environment* env = ctxt.get_environment(); + const environment& env = rdr.get_environment(); namespace_decl_sptr decl(new namespace_decl(env, name, loc)); - maybe_set_artificial_location(ctxt, node, decl); - ctxt.push_decl_to_current_scope(decl, add_to_current_scope); - ctxt.map_xml_node_to_decl(node, decl); + maybe_set_artificial_location(rdr, node, decl); + rdr.push_decl_to_current_scope(decl, add_to_current_scope); + rdr.map_xml_node_to_decl(node, decl); for (xmlNodePtr n = xmlFirstElementChild(node); n; n = xmlNextElementSibling(n)) - handle_element_node(ctxt, n, /*add_to_current_scope=*/true); + handle_element_node(rdr, n, /*add_to_current_scope=*/true); - ctxt.pop_scope_or_abort(decl); + rdr.pop_scope_or_abort(decl); return decl; } @@ -3178,7 +3027,7 @@ build_namespace_decl(read_context& ctxt, /// Build an instance of @ref elf_symbol from an XML element node /// which name is 'elf-symbol'. /// -/// @param ctxt the context used for reading the XML input. +/// @param rdr the context used for reading the XML input. /// /// @param node the XML node to read. /// @@ -3187,7 +3036,7 @@ build_namespace_decl(read_context& ctxt, /// /// @return the @ref elf_symbol built, or nil if it couldn't be built. static elf_symbol_sptr -build_elf_symbol(read_context& ctxt, const xmlNodePtr node, +build_elf_symbol(reader& rdr, const xmlNodePtr node, bool drop_if_suppressed) { elf_symbol_sptr nil; @@ -3251,11 +3100,11 @@ build_elf_symbol(read_context& ctxt, const xmlNodePtr node, elf_symbol::version version(version_string, is_default_version); - const bool is_suppressed = suppr::is_elf_symbol_suppressed(ctxt, name, type); + const bool is_suppressed = suppr::is_elf_symbol_suppressed(rdr, name, type); if (drop_if_suppressed && is_suppressed) return elf_symbol_sptr(); - const environment* env = ctxt.get_environment(); + const environment& env = rdr.get_environment(); elf_symbol_sptr e = elf_symbol::create(env, /*index=*/0, size, name, type, binding, is_defined, is_common, @@ -3281,7 +3130,7 @@ build_elf_symbol(read_context& ctxt, const xmlNodePtr node, /// present in the symbol db of the corpus associated to the current /// context. /// -/// @param ctxt the current context to consider. +/// @param rdr the current context to consider. /// /// @param node the xml element node to consider. /// @@ -3290,7 +3139,7 @@ build_elf_symbol(read_context& ctxt, const xmlNodePtr node, /// /// @return a shared pointer the resutling elf_symbol. static elf_symbol_sptr -build_elf_symbol_from_reference(read_context& ctxt, const xmlNodePtr node) +build_elf_symbol_from_reference(reader& rdr, const xmlNodePtr node) { elf_symbol_sptr nil; @@ -3310,7 +3159,7 @@ build_elf_symbol_from_reference(read_context& ctxt, const xmlNodePtr node) return nil; const elf_symbols& symbols = - ctxt.get_corpus()->get_symtab()->lookup_symbol(name); + rdr.corpus()->get_symtab()->lookup_symbol(name); for (const auto& symbol : symbols) if (symbol->get_id_string() == sym_id) @@ -3324,7 +3173,7 @@ build_elf_symbol_from_reference(read_context& ctxt, const xmlNodePtr node) /// element representing either a function symbols data base, or a /// variable symbols database. /// -/// @param ctxt the context to take in account. +/// @param rdr the context to take in account. /// /// @param node the XML node to consider. /// @@ -3332,7 +3181,7 @@ build_elf_symbol_from_reference(read_context& ctxt, const xmlNodePtr node) /// data base, false if we should look for a variable symbols data /// base. static string_elf_symbols_map_sptr -build_elf_symbol_db(read_context& ctxt, +build_elf_symbol_db(reader& rdr, const xmlNodePtr node, bool function_syms) { @@ -3350,7 +3199,7 @@ build_elf_symbol_db(read_context& ctxt, && !xmlStrEqual(node->name, BAD_CAST("elf-variable-symbols"))) return nil; - ctxt.set_corpus_node(node); + rdr.set_corpus_node(node); typedef std::unordered_map xml_node_ptr_elf_symbol_sptr_map_type; @@ -3360,7 +3209,7 @@ build_elf_symbol_db(read_context& ctxt, for (xmlNodePtr n = xmlFirstElementChild(node); n; n = xmlNextElementSibling(n)) - if ((sym = build_elf_symbol(ctxt, n, /*drop_if_suppress=*/false))) + if ((sym = build_elf_symbol(rdr, n, /*drop_if_suppress=*/false))) { id_sym_map[sym->get_id_string()] = sym; xml_node_ptr_elf_symbol_map[n] = sym; @@ -3410,19 +3259,17 @@ build_elf_symbol_db(read_context& ctxt, /// Build a function parameter from a 'parameter' xml element node. /// -/// @param ctxt the contexte of the xml parsing. +/// @param rdr the contexte of the xml parsing. /// /// @param node the xml 'parameter' element node to de-serialize from. static shared_ptr -build_function_parameter(read_context& ctxt, const xmlNodePtr node) +build_function_parameter(reader& rdr, const xmlNodePtr node) { shared_ptr nil; if (!node || !xmlStrEqual(node->name, BAD_CAST("parameter"))) return nil; - ABG_ASSERT(ctxt.get_environment()); - bool is_variadic = false; string is_variadic_str; if (xml_char_sptr s = @@ -3441,21 +3288,20 @@ build_function_parameter(read_context& ctxt, const xmlNodePtr node) type_base_sptr type; if (is_variadic) - type = ctxt.get_environment()->get_variadic_parameter_type(); + type = rdr.get_environment().get_variadic_parameter_type(); else { ABG_ASSERT(!type_id.empty()); - type = ctxt.build_or_get_type_decl(type_id, true); + type = rdr.build_or_get_type_decl(type_id, true); } ABG_ASSERT(type); - ABG_ASSERT(type->get_environment() == ctxt.get_environment()); string name; if (xml_char_sptr a = xml::build_sptr(xmlGetProp(node, BAD_CAST("name")))) name = CHAR_STR(a); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); function_decl::parameter_sptr p (new function_decl::parameter(type, name, loc, @@ -3466,7 +3312,7 @@ build_function_parameter(read_context& ctxt, const xmlNodePtr node) /// Build a function_decl from a 'function-decl' xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the function_decl from. /// @@ -3483,7 +3329,7 @@ build_function_parameter(read_context& ctxt, const xmlNodePtr node) /// @return a pointer to a newly created function_decl upon successful /// completion, a null pointer otherwise. static function_decl_sptr -build_function_decl(read_context& ctxt, +build_function_decl(reader& rdr, const xmlNodePtr node, class_or_union_sptr as_method_decl, bool add_to_current_scope) @@ -3512,16 +3358,16 @@ build_function_decl(read_context& ctxt, decl_base::binding bind = decl_base::BINDING_NONE; read_binding(node, bind); - size_t size = ctxt.get_translation_unit()->get_address_size(), align = 0; + size_t size = rdr.get_translation_unit()->get_address_size(), align = 0; read_size_and_alignment(node, size, align); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); + + const environment& env = rdr.get_environment(); - environment* env = ctxt.get_environment(); - ABG_ASSERT(env); std::vector parms; - type_base_sptr return_type = env->get_void_type(); + type_base_sptr return_type = env.get_void_type(); for (xmlNodePtr n = xmlFirstElementChild(node); n ; @@ -3530,7 +3376,7 @@ build_function_decl(read_context& ctxt, if (xmlStrEqual(n->name, BAD_CAST("parameter"))) { if (function_decl::parameter_sptr p = - build_function_parameter(ctxt, n)) + build_function_parameter(rdr, n)) parms.push_back(p); } else if (xmlStrEqual(n->name, BAD_CAST("return"))) @@ -3540,7 +3386,7 @@ build_function_decl(read_context& ctxt, xml::build_sptr(xmlGetProp(n, BAD_CAST("type-id")))) type_id = CHAR_STR(s); if (!type_id.empty()) - return_type = ctxt.build_or_get_type_decl(type_id, true); + return_type = rdr.build_or_get_type_decl(type_id, true); } } @@ -3564,22 +3410,22 @@ build_function_decl(read_context& ctxt, mangled_name, vis, bind)); - maybe_set_artificial_location(ctxt, node, fn_decl); - ctxt.push_decl_to_current_scope(fn_decl, add_to_current_scope); - RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(ctxt, fn_decl); + maybe_set_artificial_location(rdr, node, fn_decl); + rdr.push_decl_to_current_scope(fn_decl, add_to_current_scope); + RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(rdr, fn_decl); - elf_symbol_sptr sym = build_elf_symbol_from_reference(ctxt, node); + elf_symbol_sptr sym = build_elf_symbol_from_reference(rdr, node); if (sym) fn_decl->set_symbol(sym); if (fn_decl->get_symbol() && fn_decl->get_symbol()->is_public()) fn_decl->set_is_in_public_symbol_table(true); - ctxt.get_translation_unit()->bind_function_type_life_time(fn_type); + rdr.get_translation_unit()->bind_function_type_life_time(fn_type); - ctxt.maybe_canonicalize_type(fn_type, !add_to_current_scope); + rdr.maybe_canonicalize_type(fn_type, !add_to_current_scope); - ctxt.maybe_add_fn_to_exported_decls(fn_decl.get()); + rdr.maybe_add_fn_to_exported_decls(fn_decl.get()); return fn_decl; } @@ -3588,7 +3434,7 @@ build_function_decl(read_context& ctxt, /// been suppressed by a suppression specification that is in the /// context. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the function_decl from. /// @@ -3606,20 +3452,20 @@ build_function_decl(read_context& ctxt, /// completion. If the function was suppressed by a suppression /// specification then returns nil. static function_decl_sptr -build_function_decl_if_not_suppressed(read_context& ctxt, +build_function_decl_if_not_suppressed(reader& rdr, const xmlNodePtr node, class_or_union_sptr as_method_decl, bool add_to_current_scope) { function_decl_sptr fn; - if (function_is_suppressed(ctxt, node)) + if (function_is_suppressed(rdr, node)) // The function was suppressed by at least one suppression - // specification associated to the current read context. So + // specification associated to the current ABIXML reader. So // don't build any IR for it. ; else - fn = build_function_decl(ctxt, node, as_method_decl, + fn = build_function_decl(rdr, node, as_method_decl, add_to_current_scope); return fn; } @@ -3628,7 +3474,7 @@ build_function_decl_if_not_suppressed(read_context& ctxt, /// suppressed by any of the suppression specifications associated to /// a given context of native xml reading. /// -/// @param ctxt the native xml reading context of interest. +/// @param rdr the native xml reading context of interest. /// /// @param note the XML node that represents the fucntion. /// match. @@ -3636,7 +3482,7 @@ build_function_decl_if_not_suppressed(read_context& ctxt, /// @return true iff at least one function specification matches the /// function denoted by the node @p node. static bool -function_is_suppressed(const read_context& ctxt, xmlNodePtr node) +function_is_suppressed(const reader& rdr, xmlNodePtr node) { string fname; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name")) @@ -3646,49 +3492,49 @@ function_is_suppressed(const read_context& ctxt, xmlNodePtr node) if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name")) flinkage_name = xml::unescape_xml_string(CHAR_STR(s)); - scope_decl* scope = ctxt.get_cur_scope(); + scope_decl* scope = rdr.get_cur_scope(); string qualified_name = build_qualified_name(scope, fname); - return suppr::function_is_suppressed(ctxt, qualified_name, flinkage_name); + return suppr::is_function_suppressed(rdr, qualified_name, flinkage_name); } /// Test if a type denoted by its name, context and location is /// suppressed by the suppression specifications that are associated -/// to a given read context. +/// to a given ABIXML reader. /// -/// @param ctxt the read context to consider. +/// @param rdr the ABIXML reader to consider. /// /// @param note the XML node that represents the type. /// /// @return true iff the type designated by @p node is suppressed by /// at least of suppression specifications associated to the current -/// read context. +/// ABIXML reader. static bool -type_is_suppressed(const read_context& ctxt, xmlNodePtr node) +type_is_suppressed(const reader& rdr, xmlNodePtr node) { string type_name; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name")) type_name = xml::unescape_xml_string(CHAR_STR(s)); location type_location; - read_location(ctxt, node, type_location); + read_location(rdr, node, type_location); - scope_decl* scope = ctxt.get_cur_scope(); + scope_decl* scope = rdr.get_cur_scope(); string qualified_name = build_qualified_name(scope, type_name); bool type_is_private = false; - return suppr::type_is_suppressed(ctxt, qualified_name, type_location, + return suppr::is_type_suppressed(rdr, qualified_name, type_location, type_is_private, /*require_drop_property=*/true); } /// Build a @ref var_decl out of a an XML node that describes it iff /// the variable denoted by the XML node is not suppressed by a -/// suppression specification associated to the current read context. +/// suppression specification associated to the current ABIXML reader. /// -/// @param ctxt the read context to use. +/// @param rdr the ABIXML reader to use. /// /// @param node the XML node for the variable to consider. /// @@ -3697,26 +3543,26 @@ type_is_suppressed(const read_context& ctxt, xmlNodePtr node) /// /// @return true iff the @ref var_decl was built. static var_decl_sptr -build_var_decl_if_not_suppressed(read_context& ctxt, +build_var_decl_if_not_suppressed(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { var_decl_sptr var; - if (!variable_is_suppressed(ctxt, node)) - var = build_var_decl(ctxt, node, add_to_current_scope); + if (!variable_is_suppressed(rdr, node)) + var = build_var_decl(rdr, node, add_to_current_scope); return var; } /// Test if a variable denoted by its XML node is suppressed by a -/// suppression specification that is present in a given read context. +/// suppression specification that is present in a given ABIXML reader. /// -/// @param ctxt the read context to consider. +/// @param rdr the ABIXML reader to consider. /// /// @param node the XML node of the variable to consider. /// /// @return true iff the variable denoted by @p node is suppressed. static bool -variable_is_suppressed(const read_context& ctxt, xmlNodePtr node) +variable_is_suppressed(const reader& rdr, xmlNodePtr node) { string name; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name")) @@ -3726,17 +3572,17 @@ variable_is_suppressed(const read_context& ctxt, xmlNodePtr node) if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name")) linkage_name = xml::unescape_xml_string(CHAR_STR(s)); - scope_decl* scope = ctxt.get_cur_scope(); + scope_decl* scope = rdr.get_cur_scope(); string qualified_name = build_qualified_name(scope, name); - return suppr::variable_is_suppressed(ctxt, qualified_name, linkage_name); + return suppr::is_variable_suppressed(rdr, qualified_name, linkage_name); } /// Test if a variable in a particular scope is suppressed by a -/// suppression specification that is present in a given read context. +/// suppression specification that is present in a given ABIXML reader. /// -/// @parm ctxt the read context to consider. +/// @parm rdr the ABIXML reader to consider. /// /// @param scope the scope of the variable to consider. /// @@ -3744,25 +3590,25 @@ variable_is_suppressed(const read_context& ctxt, xmlNodePtr node) /// /// @return true iff the variable @p v is suppressed. static bool -variable_is_suppressed(const read_context& ctxt, +variable_is_suppressed(const reader& rdr, const scope_decl* scope, const var_decl& v) { string qualified_name = build_qualified_name(scope, v.get_name()); - return suppr::variable_is_suppressed(ctxt, qualified_name, + return suppr::is_variable_suppressed(rdr, qualified_name, v.get_linkage_name()); } /// Build pointer to var_decl from a 'var-decl' xml Node /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the var_decl from. /// /// @return a pointer to a newly built var_decl upon successful /// completion, a null pointer otherwise. static shared_ptr -build_var_decl(read_context& ctxt, +build_var_decl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -3778,7 +3624,7 @@ build_var_decl(read_context& ctxt, string type_id; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id")) type_id = CHAR_STR(s); - type_base_sptr underlying_type = ctxt.build_or_get_type_decl(type_id, + type_base_sptr underlying_type = rdr.build_or_get_type_decl(type_id, true); ABG_ASSERT(underlying_type); @@ -3793,23 +3639,23 @@ build_var_decl(read_context& ctxt, read_binding(node, bind); location locus; - read_location(ctxt, node, locus); + read_location(rdr, node, locus); var_decl_sptr decl(new var_decl(name, underlying_type, locus, mangled_name, vis, bind)); - maybe_set_artificial_location(ctxt, node, decl); + maybe_set_artificial_location(rdr, node, decl); - elf_symbol_sptr sym = build_elf_symbol_from_reference(ctxt, node); + elf_symbol_sptr sym = build_elf_symbol_from_reference(rdr, node); if (sym) decl->set_symbol(sym); - ctxt.push_decl_to_current_scope(decl, add_to_current_scope); + rdr.push_decl_to_current_scope(decl, add_to_current_scope); if (add_to_current_scope) { // This variable is really being kept in the IR, so let's record // that it's using its type. - RECORD_ARTIFACT_AS_USED_BY(ctxt, underlying_type, decl); + RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, decl); } if (decl->get_symbol() && decl->get_symbol()->is_public()) @@ -3820,7 +3666,7 @@ build_var_decl(read_context& ctxt, /// Build a type_decl from a "type-decl" XML Node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the XML node to build the type_decl from. /// @@ -3830,7 +3676,7 @@ build_var_decl(read_context& ctxt, /// @return a pointer to type_decl upon successful completion, a null /// pointer otherwise. static shared_ptr -build_type_decl(read_context& ctxt, +build_type_decl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -3839,7 +3685,7 @@ build_type_decl(read_context& ctxt, if (!xmlStrEqual(node->name, BAD_CAST("type-decl"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { type_decl_sptr result = dynamic_pointer_cast(d); ABG_ASSERT(result); @@ -3867,12 +3713,12 @@ build_type_decl(read_context& ctxt, read_is_declaration_only(node, is_decl_only); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); bool is_anonymous = false; read_is_anonymous(node, is_anonymous); - if (type_base_sptr d = ctxt.get_type_decl(id)) + if (type_base_sptr d = rdr.get_type_decl(id)) { // I've seen instances of DSOs where a type_decl would appear // several times. Hugh. @@ -3885,15 +3731,15 @@ build_type_decl(read_context& ctxt, return ty; } - const environment* env = ctxt.get_environment(); + const environment& env = rdr.get_environment(); type_decl_sptr decl(new type_decl(env, name, size_in_bits, alignment_in_bits, loc)); - maybe_set_artificial_location(ctxt, node, decl); + maybe_set_artificial_location(rdr, node, decl); decl->set_is_anonymous(is_anonymous); decl->set_is_declaration_only(is_decl_only); - if (ctxt.push_and_key_type_decl(decl, id, add_to_current_scope)) + if (rdr.push_and_key_type_decl(decl, id, add_to_current_scope)) { - ctxt.map_xml_node_to_decl(node, decl); + rdr.map_xml_node_to_decl(node, decl); return decl; } @@ -3902,7 +3748,7 @@ build_type_decl(read_context& ctxt, /// Build a qualified_type_def from a 'qualified-type-def' xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the qualified_type_def from. /// @@ -3912,7 +3758,7 @@ build_type_decl(read_context& ctxt, /// @return a pointer to a newly built qualified_type_def upon /// successful completion, a null pointer otherwise. static qualified_type_def_sptr -build_qualified_type_decl(read_context& ctxt, +build_qualified_type_decl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -3920,7 +3766,7 @@ build_qualified_type_decl(read_context& ctxt, if (!xmlStrEqual(node->name, BAD_CAST("qualified-type-def"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { qualified_type_def_sptr result = dynamic_pointer_cast(d); @@ -3935,7 +3781,7 @@ build_qualified_type_decl(read_context& ctxt, ABG_ASSERT(!id.empty()); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); qualified_type_def::CV cv = qualified_type_def::CV_NONE; string const_str; @@ -3966,11 +3812,11 @@ build_qualified_type_decl(read_context& ctxt, ABG_ASSERT(!type_id.empty()); shared_ptr underlying_type = - ctxt.build_or_get_type_decl(type_id, true); + rdr.build_or_get_type_decl(type_id, true); ABG_ASSERT(underlying_type); qualified_type_def_sptr decl; - if (type_base_sptr t = ctxt.get_type_decl(id)) + if (type_base_sptr t = rdr.get_type_decl(id)) { decl = is_qualified_type(t); ABG_ASSERT(decl); @@ -3978,19 +3824,19 @@ build_qualified_type_decl(read_context& ctxt, else { decl.reset(new qualified_type_def(underlying_type, cv, loc)); - maybe_set_artificial_location(ctxt, node, decl); - ctxt.push_and_key_type_decl(decl, id, add_to_current_scope); - RECORD_ARTIFACT_AS_USED_BY(ctxt, underlying_type, decl); + maybe_set_artificial_location(rdr, node, decl); + rdr.push_and_key_type_decl(decl, id, add_to_current_scope); + RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, decl); } - ctxt.map_xml_node_to_decl(node, decl); + rdr.map_xml_node_to_decl(node, decl); return decl; } /// Build a pointer_type_def from a 'pointer-type-def' xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the pointer_type_def from. /// @@ -4000,7 +3846,7 @@ build_qualified_type_decl(read_context& ctxt, /// @return a pointer to a newly built pointer_type_def upon /// successful completion, a null pointer otherwise. static pointer_type_def_sptr -build_pointer_type_def(read_context& ctxt, +build_pointer_type_def(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -4010,7 +3856,7 @@ build_pointer_type_def(read_context& ctxt, if (!xmlStrEqual(node->name, BAD_CAST("pointer-type-def"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { pointer_type_def_sptr result = dynamic_pointer_cast(d); @@ -4023,7 +3869,7 @@ build_pointer_type_def(read_context& ctxt, id = CHAR_STR(s); ABG_ASSERT(!id.empty()); - if (type_base_sptr t = ctxt.get_type_decl(id)) + if (type_base_sptr t = rdr.get_type_decl(id)) { pointer_type_def_sptr result = is_pointer_type(t); ABG_ASSERT(result); @@ -4034,39 +3880,39 @@ build_pointer_type_def(read_context& ctxt, if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id")) type_id = CHAR_STR(s); - size_t size_in_bits = ctxt.get_translation_unit()->get_address_size(); + size_t size_in_bits = rdr.get_translation_unit()->get_address_size(); size_t alignment_in_bits = 0; read_size_and_alignment(node, size_in_bits, alignment_in_bits); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); // Create the pointer type /before/ the pointed-to type. After the - // creation, the type is 'keyed' using ctxt.push_and_key_type_decl. + // creation, the type is 'keyed' using rdr.push_and_key_type_decl. // This means that the type can be retrieved from its type ID. This // is so that if the pointed-to type indirectly uses this pointer // type (via recursion) then that is made possible. - pointer_type_def_sptr t(new pointer_type_def(ctxt.get_environment(), + pointer_type_def_sptr t(new pointer_type_def(rdr.get_environment(), size_in_bits, alignment_in_bits, loc)); - maybe_set_artificial_location(ctxt, node, t); + maybe_set_artificial_location(rdr, node, t); - if (ctxt.push_and_key_type_decl(t, id, add_to_current_scope)) - ctxt.map_xml_node_to_decl(node, t); + if (rdr.push_and_key_type_decl(t, id, add_to_current_scope)) + rdr.map_xml_node_to_decl(node, t); type_base_sptr pointed_to_type = - ctxt.build_or_get_type_decl(type_id, true); + rdr.build_or_get_type_decl(type_id, true); ABG_ASSERT(pointed_to_type); t->set_pointed_to_type(pointed_to_type); - RECORD_ARTIFACT_AS_USED_BY(ctxt, pointed_to_type, t); + RECORD_ARTIFACT_AS_USED_BY(rdr, pointed_to_type, t); return t; } /// Build a reference_type_def from a pointer to 'reference-type-def' /// xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the reference_type_def from. /// @@ -4076,7 +3922,7 @@ build_pointer_type_def(read_context& ctxt, /// @return a pointer to a newly built reference_type_def upon /// successful completio, a null pointer otherwise. static shared_ptr -build_reference_type_def(read_context& ctxt, +build_reference_type_def(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -4085,7 +3931,7 @@ build_reference_type_def(read_context& ctxt, if (!xmlStrEqual(node->name, BAD_CAST("reference-type-def"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { reference_type_def_sptr result = dynamic_pointer_cast(d); @@ -4098,7 +3944,7 @@ build_reference_type_def(read_context& ctxt, id = CHAR_STR(s); ABG_ASSERT(!id.empty()); - if (type_base_sptr d = ctxt.get_type_decl(id)) + if (type_base_sptr d = rdr.get_type_decl(id)) { reference_type_def_sptr ty = is_reference_type(d); ABG_ASSERT(ty); @@ -4106,13 +3952,13 @@ build_reference_type_def(read_context& ctxt, } location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); string kind; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "kind")) kind = CHAR_STR(s); // this should be either "lvalue" or "rvalue". bool is_lvalue = kind == "lvalue"; - size_t size_in_bits = ctxt.get_translation_unit()->get_address_size(); + size_t size_in_bits = rdr.get_translation_unit()->get_address_size(); size_t alignment_in_bits = 0; read_size_and_alignment(node, size_in_bits, alignment_in_bits); @@ -4123,22 +3969,22 @@ build_reference_type_def(read_context& ctxt, // Create the reference type /before/ the pointed-to type. After // the creation, the type is 'keyed' using - // ctxt.push_and_key_type_decl. This means that the type can be + // rdr.push_and_key_type_decl. This means that the type can be // retrieved from its type ID. This is so that if the pointed-to // type indirectly uses this reference type (via recursion) then // that is made possible. - reference_type_def_sptr t(new reference_type_def(ctxt.get_environment(), + reference_type_def_sptr t(new reference_type_def(rdr.get_environment(), is_lvalue, size_in_bits, alignment_in_bits, loc)); - maybe_set_artificial_location(ctxt, node, t); - if (ctxt.push_and_key_type_decl(t, id, add_to_current_scope)) - ctxt.map_xml_node_to_decl(node, t); + maybe_set_artificial_location(rdr, node, t); + if (rdr.push_and_key_type_decl(t, id, add_to_current_scope)) + rdr.map_xml_node_to_decl(node, t); type_base_sptr pointed_to_type = - ctxt.build_or_get_type_decl(type_id,/*add_to_current_scope=*/ true); + rdr.build_or_get_type_decl(type_id,/*add_to_current_scope=*/ true); ABG_ASSERT(pointed_to_type); t->set_pointed_to_type(pointed_to_type); - RECORD_ARTIFACT_AS_USED_BY(ctxt, pointed_to_type, t); + RECORD_ARTIFACT_AS_USED_BY(rdr, pointed_to_type, t); return t; } @@ -4146,7 +3992,7 @@ build_reference_type_def(read_context& ctxt, /// Build a function_type from a pointer to 'function-type' /// xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the function_type from. /// @@ -4156,7 +4002,7 @@ build_reference_type_def(read_context& ctxt, /// @return a pointer to a newly built function_type upon /// successful completion, a null pointer otherwise. static function_type_sptr -build_function_type(read_context& ctxt, +build_function_type(reader& rdr, const xmlNodePtr node, bool /*add_to_current_scope*/) { @@ -4176,34 +4022,32 @@ build_function_type(read_context& ctxt, bool is_method_t = !method_class_id.empty(); - size_t size = ctxt.get_translation_unit()->get_address_size(), align = 0; + size_t size = rdr.get_translation_unit()->get_address_size(), align = 0; read_size_and_alignment(node, size, align); - environment* env = ctxt.get_environment(); - ABG_ASSERT(env); + const environment& env = rdr.get_environment(); std::vector > parms; - type_base_sptr return_type = env->get_void_type(); + type_base_sptr return_type = env.get_void_type(); class_or_union_sptr method_class_type; if (is_method_t) { method_class_type = - is_class_or_union_type(ctxt.build_or_get_type_decl(method_class_id, + is_class_or_union_type(rdr.build_or_get_type_decl(method_class_id, /*add_decl_to_scope=*/true)); ABG_ASSERT(method_class_type); } - function_type_sptr fn_type(is_method_t ? new method_type(method_class_type, - ctxt.get_environment(), + /*is_const=*/false, size, align) : new function_type(return_type, parms, size, align)); - ctxt.get_translation_unit()->bind_function_type_life_time(fn_type); - ctxt.key_type_decl(fn_type, id); - RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(ctxt, fn_type); + rdr.get_translation_unit()->bind_function_type_life_time(fn_type); + rdr.key_type_decl(fn_type, id); + RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(rdr, fn_type); for (xmlNodePtr n = xmlFirstElementChild(node); n; @@ -4212,7 +4056,7 @@ build_function_type(read_context& ctxt, if (xmlStrEqual(n->name, BAD_CAST("parameter"))) { if (function_decl::parameter_sptr p = - build_function_parameter(ctxt, n)) + build_function_parameter(rdr, n)) parms.push_back(p); } else if (xmlStrEqual(n->name, BAD_CAST("return"))) @@ -4222,7 +4066,7 @@ build_function_type(read_context& ctxt, xml::build_sptr(xmlGetProp(n, BAD_CAST("type-id")))) type_id = CHAR_STR(s); if (!type_id.empty()) - fn_type->set_return_type(ctxt.build_or_get_type_decl + fn_type->set_return_type(rdr.build_or_get_type_decl (type_id, true)); } } @@ -4234,7 +4078,7 @@ build_function_type(read_context& ctxt, /// Build a array_type_def::subrange_type from a 'subrange' xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the /// array_type_def::subrange_type from. @@ -4243,7 +4087,7 @@ build_function_type(read_context& ctxt, /// @return a pointer to a newly built array_type_def::subrange_type /// upon successful completion, a null pointer otherwise. static array_type_def::subrange_sptr -build_subrange_type(read_context& ctxt, +build_subrange_type(reader& rdr, const xmlNodePtr node) { array_type_def::subrange_sptr nil; @@ -4251,7 +4095,7 @@ build_subrange_type(read_context& ctxt, if (!node || !xmlStrEqual(node->name, BAD_CAST("subrange"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { array_type_def::subrange_sptr result = dynamic_pointer_cast(d); @@ -4268,7 +4112,7 @@ build_subrange_type(read_context& ctxt, id = CHAR_STR(s); if (!id.empty()) - if (type_base_sptr d = ctxt.get_type_decl(id)) + if (type_base_sptr d = rdr.get_type_decl(id)) { array_type_def::subrange_sptr ty = is_subrange_type(d); ABG_ASSERT(ty); @@ -4310,12 +4154,12 @@ build_subrange_type(read_context& ctxt, type_base_sptr underlying_type; if (!underlying_type_id.empty()) { - underlying_type = ctxt.build_or_get_type_decl(underlying_type_id, true); + underlying_type = rdr.build_or_get_type_decl(underlying_type_id, true); ABG_ASSERT(underlying_type); } location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); // Note that DWARF would actually have a lower_bound of -1 for an // array of length 0. @@ -4337,10 +4181,10 @@ build_subrange_type(read_context& ctxt, } array_type_def::subrange_sptr p - (new array_type_def::subrange_type(ctxt.get_environment(), + (new array_type_def::subrange_type(rdr.get_environment(), name, min_bound, max_bound, underlying_type, loc)); - maybe_set_artificial_location(ctxt, node, p); + maybe_set_artificial_location(rdr, node, p); p->is_infinite(is_infinite); return p; @@ -4348,7 +4192,7 @@ build_subrange_type(read_context& ctxt, /// Build a array_type_def from a 'array-type-def' xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the array_type_def from. /// @@ -4358,7 +4202,7 @@ build_subrange_type(read_context& ctxt, /// @return a pointer to a newly built array_type_def upon /// successful completion, a null pointer otherwise. static array_type_def_sptr -build_array_type_def(read_context& ctxt, +build_array_type_def(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -4368,7 +4212,7 @@ build_array_type_def(read_context& ctxt, if (!xmlStrEqual(node->name, BAD_CAST("array-type-def"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { array_type_def_sptr result = dynamic_pointer_cast(d); @@ -4381,7 +4225,7 @@ build_array_type_def(read_context& ctxt, id = CHAR_STR(s); ABG_ASSERT(!id.empty()); - if (type_base_sptr d = ctxt.get_type_decl(id)) + if (type_base_sptr d = rdr.get_type_decl(id)) { array_type_def_sptr ty = is_array_type(d); ABG_ASSERT(ty); @@ -4398,7 +4242,7 @@ build_array_type_def(read_context& ctxt, // maybe building the type of array elements triggered building this // one in the mean time ... - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { array_type_def_sptr result = dynamic_pointer_cast(d); @@ -4431,7 +4275,7 @@ build_array_type_def(read_context& ctxt, } location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); array_type_def::subranges_type subranges; for (xmlNodePtr n = xmlFirstElementChild(node); @@ -4440,13 +4284,13 @@ build_array_type_def(read_context& ctxt, if (xmlStrEqual(n->name, BAD_CAST("subrange"))) { if (array_type_def::subrange_sptr s = - build_subrange_type(ctxt, n)) + build_subrange_type(rdr, n)) { MAYBE_MAP_TYPE_WITH_TYPE_ID(s, n); if (add_to_current_scope) { - add_decl_to_scope(s, ctxt.get_cur_scope()); - ctxt.maybe_canonicalize_type(s); + add_decl_to_scope(s, rdr.get_cur_scope()); + rdr.maybe_canonicalize_type(s); } subranges.push_back(s); } @@ -4454,14 +4298,14 @@ build_array_type_def(read_context& ctxt, // The type of array elements. type_base_sptr type = - ctxt.build_or_get_type_decl(type_id, true); + rdr.build_or_get_type_decl(type_id, true); ABG_ASSERT(type); array_type_def_sptr ar_type(new array_type_def(type, subranges, loc)); - maybe_set_artificial_location(ctxt, node, ar_type); - if (ctxt.push_and_key_type_decl(ar_type, id, add_to_current_scope)) - ctxt.map_xml_node_to_decl(node, ar_type); - RECORD_ARTIFACT_AS_USED_BY(ctxt, type, ar_type); + maybe_set_artificial_location(rdr, node, ar_type); + if (rdr.push_and_key_type_decl(ar_type, id, add_to_current_scope)) + rdr.map_xml_node_to_decl(node, ar_type); + RECORD_ARTIFACT_AS_USED_BY(rdr, type, ar_type); if (dimensions != ar_type->get_dimension_count() || (alignment_in_bits @@ -4508,9 +4352,9 @@ build_array_type_def(read_context& ctxt, /// Build an @ref enum_type_decl from the XML node that represents it, /// if it was not suppressed by a supression specification present in -/// the current read_context. +/// the current reader. /// -/// @param ctxt the read_context to take into account. +/// @param rdr the reader to take into account. /// /// @param node the XML node representing the @ref enum_type_decl to /// build. @@ -4521,19 +4365,19 @@ build_array_type_def(read_context& ctxt, /// @return the newly built @ref enum_type_decl iff it was effectively /// built. static enum_type_decl_sptr -build_enum_type_decl_if_not_suppressed(read_context& ctxt, +build_enum_type_decl_if_not_suppressed(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { enum_type_decl_sptr enum_type; - if (!type_is_suppressed(ctxt, node)) - enum_type = build_enum_type_decl(ctxt, node, add_to_current_scope); + if (!type_is_suppressed(rdr, node)) + enum_type = build_enum_type_decl(rdr, node, add_to_current_scope); return enum_type; } /// Build an enum_type_decl from an 'enum-type-decl' xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the enum_type_decl from. /// @@ -4543,7 +4387,7 @@ build_enum_type_decl_if_not_suppressed(read_context& ctxt, /// @return a pointer to a newly built enum_type_decl upon successful /// completion, a null pointer otherwise. static enum_type_decl_sptr -build_enum_type_decl(read_context& ctxt, +build_enum_type_decl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -4552,7 +4396,7 @@ build_enum_type_decl(read_context& ctxt, if (!xmlStrEqual(node->name, BAD_CAST("enum-decl"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { enum_type_decl_sptr result = dynamic_pointer_cast(d); @@ -4569,7 +4413,7 @@ build_enum_type_decl(read_context& ctxt, linkage_name = xml::unescape_xml_string(CHAR_STR(s)); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); bool is_decl_only = false; read_is_declaration_only(node, is_decl_only); @@ -4586,9 +4430,6 @@ build_enum_type_decl(read_context& ctxt, ABG_ASSERT(!id.empty()); - const environment* env = ctxt.get_environment(); - ABG_ASSERT(env); - string base_type_id; enum_type_decl::enumerators enums; for (xmlNodePtr n = xmlFirstElementChild(node); @@ -4623,26 +4464,26 @@ build_enum_type_decl(read_context& ctxt, return nil; } - enums.push_back(enum_type_decl::enumerator(env, name, value)); + enums.push_back(enum_type_decl::enumerator(name, value)); } } type_base_sptr underlying_type = - ctxt.build_or_get_type_decl(base_type_id, true); + rdr.build_or_get_type_decl(base_type_id, true); ABG_ASSERT(underlying_type); enum_type_decl_sptr t(new enum_type_decl(name, loc, underlying_type, enums, linkage_name)); - maybe_set_artificial_location(ctxt, node, t); + maybe_set_artificial_location(rdr, node, t); t->set_is_anonymous(is_anonymous); t->set_is_artificial(is_artificial); t->set_is_declaration_only(is_decl_only); - if (ctxt.push_and_key_type_decl(t, id, add_to_current_scope)) + if (rdr.push_and_key_type_decl(t, id, add_to_current_scope)) { - maybe_set_naming_typedef(ctxt, node, t); - ctxt.map_xml_node_to_decl(node, t); - RECORD_ARTIFACT_AS_USED_BY(ctxt, underlying_type, t); + maybe_set_naming_typedef(rdr, node, t); + rdr.map_xml_node_to_decl(node, t); + RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, t); return t; } @@ -4651,14 +4492,14 @@ build_enum_type_decl(read_context& ctxt, /// Build a typedef_decl from a 'typedef-decl' xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the typedef_decl from. /// /// @return a pointer to a newly built typedef_decl upon successful /// completion, a null pointer otherwise. static shared_ptr -build_typedef_decl(read_context& ctxt, +build_typedef_decl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -4667,7 +4508,7 @@ build_typedef_decl(read_context& ctxt, if (!xmlStrEqual(node->name, BAD_CAST("typedef-decl"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { typedef_decl_sptr result = is_typedef(d); ABG_ASSERT(result); @@ -4679,7 +4520,7 @@ build_typedef_decl(read_context& ctxt, id = CHAR_STR(s); ABG_ASSERT(!id.empty()); - if (type_base_sptr t = ctxt.get_type_decl(id)) + if (type_base_sptr t = rdr.get_type_decl(id)) { typedef_decl_sptr result = is_typedef(t); ABG_ASSERT(result); @@ -4691,29 +4532,29 @@ build_typedef_decl(read_context& ctxt, name = xml::unescape_xml_string(CHAR_STR(s)); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); string type_id; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id")) type_id = CHAR_STR(s); ABG_ASSERT(!type_id.empty()); - type_base_sptr underlying_type(ctxt.build_or_get_type_decl(type_id, true)); + type_base_sptr underlying_type(rdr.build_or_get_type_decl(type_id, true)); ABG_ASSERT(underlying_type); typedef_decl_sptr t(new typedef_decl(name, underlying_type, loc)); - maybe_set_artificial_location(ctxt, node, t); - ctxt.push_and_key_type_decl(t, id, add_to_current_scope); - ctxt.map_xml_node_to_decl(node, t); - RECORD_ARTIFACT_AS_USED_BY(ctxt, underlying_type, t); + maybe_set_artificial_location(rdr, node, t); + rdr.push_and_key_type_decl(t, id, add_to_current_scope); + rdr.map_xml_node_to_decl(node, t); + RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, t); return t; } /// Build a class from its XML node if it is not suppressed by a -/// suppression specification that is present in the read context. +/// suppression specification that is present in the ABIXML reader. /// -/// @param ctxt the read context to consider. +/// @param rdr the ABIXML reader to consider. /// /// @param node the XML node to consider. /// @@ -4722,13 +4563,13 @@ build_typedef_decl(read_context& ctxt, /// /// @return true iff the class was built. static class_decl_sptr -build_class_decl_if_not_suppressed(read_context& ctxt, +build_class_decl_if_not_suppressed(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { class_decl_sptr class_type; - if (!type_is_suppressed(ctxt, node)) - class_type = build_class_decl(ctxt, node, add_to_current_scope); + if (!type_is_suppressed(rdr, node)) + class_type = build_class_decl(rdr, node, add_to_current_scope); return class_type; } @@ -4736,7 +4577,7 @@ build_class_decl_if_not_suppressed(read_context& ctxt, /// by a suppression specification that is present in the read /// context. /// -/// @param ctxt the read context to consider. +/// @param rdr the ABIXML reader to consider. /// /// @param node the XML node to consider. /// @@ -4745,19 +4586,19 @@ build_class_decl_if_not_suppressed(read_context& ctxt, /// /// @return true iff the @ref union_decl was built. static union_decl_sptr -build_union_decl_if_not_suppressed(read_context& ctxt, +build_union_decl_if_not_suppressed(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { union_decl_sptr union_type; - if (!type_is_suppressed(ctxt, node)) - union_type = build_union_decl(ctxt, node, add_to_current_scope); + if (!type_is_suppressed(rdr, node)) + union_type = build_union_decl(rdr, node, add_to_current_scope); return union_type; } /// Build a class_decl from a 'class-decl' xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the class_decl from. /// @@ -4768,7 +4609,7 @@ build_union_decl_if_not_suppressed(read_context& ctxt, /// @return a pointer to class_decl upon successful completion, a null /// pointer otherwise. static class_decl_sptr -build_class_decl(read_context& ctxt, +build_class_decl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -4777,7 +4618,7 @@ build_class_decl(read_context& ctxt, if (!xmlStrEqual(node->name, BAD_CAST("class-decl"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { class_decl_sptr result = dynamic_pointer_cast(d); ABG_ASSERT(result); @@ -4802,7 +4643,7 @@ build_class_decl(read_context& ctxt, id = CHAR_STR(s); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); class_decl::member_types mbrs; class_decl::data_members data_mbrs; @@ -4824,7 +4665,7 @@ build_class_decl(read_context& ctxt, class_decl_sptr previous_definition, previous_declaration; if (!is_anonymous) - if (type_base_sptr t = ctxt.get_type_decl(id)) + if (type_base_sptr t = rdr.get_type_decl(id)) { previous_definition = is_class_type(t); ABG_ASSERT(previous_definition); @@ -4832,7 +4673,7 @@ build_class_decl(read_context& ctxt, const vector *types_ptr = 0; if (!is_anonymous && !previous_definition) - types_ptr = ctxt.get_all_type_decls(id); + types_ptr = rdr.get_all_type_decls(id); if (types_ptr) { // Lets look at the previous declarations and the first previous @@ -4864,8 +4705,7 @@ build_class_decl(read_context& ctxt, return previous_declaration; } - const environment* env = ctxt.get_environment(); - ABG_ASSERT(env); + const environment& env = rdr.get_environment(); if (!is_decl_only && previous_definition) // We are in the case where we've read this class definition @@ -4891,7 +4731,7 @@ build_class_decl(read_context& ctxt, data_mbrs, mbr_functions, is_anonymous)); } - maybe_set_artificial_location(ctxt, node, decl); + maybe_set_artificial_location(rdr, node, decl); decl->set_is_artificial(is_artificial); string def_id; @@ -4901,7 +4741,7 @@ build_class_decl(read_context& ctxt, if (!def_id.empty()) { - decl_base_sptr d = is_decl(ctxt.get_type_decl(def_id)); + decl_base_sptr d = is_decl(rdr.get_type_decl(def_id)); if (d && d->get_is_declaration_only()) { is_def_of_decl = true; @@ -4946,13 +4786,13 @@ build_class_decl(read_context& ctxt, ABG_ASSERT(!is_decl_only || !is_def_of_decl); - ctxt.push_decl_to_current_scope(decl, add_to_current_scope); + rdr.push_decl_to_current_scope(decl, add_to_current_scope); - ctxt.map_xml_node_to_decl(node, decl); - ctxt.key_type_decl(decl, id); + rdr.map_xml_node_to_decl(node, decl); + rdr.key_type_decl(decl, id); // If this class has a naming typedef, get it and refer to it. - maybe_set_naming_typedef(ctxt, node, decl); + maybe_set_naming_typedef(rdr, node, decl); for (xmlNodePtr n = xmlFirstElementChild(node); !is_decl_only && n; @@ -4971,7 +4811,7 @@ build_class_decl(read_context& ctxt, type_id = CHAR_STR(s); shared_ptr b = dynamic_pointer_cast - (ctxt.build_or_get_type_decl(type_id, true)); + (rdr.build_or_get_type_decl(type_id, true)); ABG_ASSERT(b); if (decl->find_base_class(b->get_qualified_name())) @@ -5002,30 +4842,30 @@ build_class_decl(read_context& ctxt, : private_access; read_access(n, access); - ctxt.map_xml_node_to_decl(n, decl); + rdr.map_xml_node_to_decl(n, decl); for (xmlNodePtr p = xmlFirstElementChild(n); p; p = xmlNextElementSibling(p)) { if (type_base_sptr t = - build_type(ctxt, p, /*add_to_current_scope=*/true)) + build_type(rdr, p, /*add_to_current_scope=*/true)) { decl_base_sptr td = get_type_declaration(t); ABG_ASSERT(td); set_member_access_specifier(td, access); - ctxt.maybe_canonicalize_type(t, !add_to_current_scope); + rdr.maybe_canonicalize_type(t, !add_to_current_scope); xml_char_sptr i= XML_NODE_GET_ATTRIBUTE(p, "id"); string id = CHAR_STR(i); ABG_ASSERT(!id.empty()); - ctxt.key_type_decl(t, id); - ctxt.map_xml_node_to_decl(p, td); + rdr.key_type_decl(t, id); + rdr.map_xml_node_to_decl(p, td); } } } else if (xmlStrEqual(n->name, BAD_CAST("data-member"))) { - ctxt.map_xml_node_to_decl(n, decl); + rdr.map_xml_node_to_decl(n, decl); access_specifier access = is_struct @@ -5046,7 +4886,7 @@ build_class_decl(read_context& ctxt, p = xmlNextElementSibling(p)) { if (var_decl_sptr v = - build_var_decl(ctxt, p, /*add_to_cur_scope=*/false)) + build_var_decl(rdr, p, /*add_to_cur_scope=*/false)) { if (decl->find_data_member(v)) { @@ -5056,19 +4896,19 @@ build_class_decl(read_context& ctxt, // So we need to discard the data member we have // built (and that was pushed to the current // stack of decls built) and move on. - decl_base_sptr d = ctxt.pop_decl(); + decl_base_sptr d = rdr.pop_decl(); ABG_ASSERT(is_var_decl(d)); continue; } - if (!variable_is_suppressed(ctxt, decl.get(), *v)) + if (!variable_is_suppressed(rdr, decl.get(), *v)) { decl->add_data_member(v, access, is_laid_out, is_static, offset_in_bits); if (is_static) - ctxt.maybe_add_var_to_exported_decls(v.get()); + rdr.maybe_add_var_to_exported_decls(v.get()); // Now let's record the fact that the data // member uses its type and that the class being // built uses the data member. @@ -5078,11 +4918,11 @@ build_class_decl(read_context& ctxt, // can't name it. Rather, let's record that // the class being built uses the type of the // (anonymous) data member. - RECORD_ARTIFACT_AS_USED_BY(ctxt, v->get_type(), decl); + RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), decl); else { - RECORD_ARTIFACT_AS_USED_BY(ctxt, v->get_type(), v); - RECORD_ARTIFACT_AS_USED_BY(ctxt, v, decl); + RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), v); + RECORD_ARTIFACT_AS_USED_BY(rdr, v, decl); } } } @@ -5090,7 +4930,7 @@ build_class_decl(read_context& ctxt, } else if (xmlStrEqual(n->name, BAD_CAST("member-function"))) { - ctxt.map_xml_node_to_decl(n, decl); + rdr.map_xml_node_to_decl(n, decl); access_specifier access = is_struct @@ -5118,7 +4958,7 @@ build_class_decl(read_context& ctxt, p = xmlNextElementSibling(p)) { if (function_decl_sptr f = - build_function_decl_if_not_suppressed(ctxt, p, decl, + build_function_decl_if_not_suppressed(rdr, p, decl, /*add_to_cur_sc=*/true)) { method_decl_sptr m = is_method_decl(f); @@ -5137,7 +4977,7 @@ build_class_decl(read_context& ctxt, } else if (xmlStrEqual(n->name, BAD_CAST("member-template"))) { - ctxt.map_xml_node_to_decl(n, decl); + rdr.map_xml_node_to_decl(n, decl); access_specifier access = is_struct @@ -5156,7 +4996,7 @@ build_class_decl(read_context& ctxt, p = xmlNextElementSibling(p)) { if (shared_ptr f = - build_function_tdecl(ctxt, p, + build_function_tdecl(rdr, p, /*add_to_current_scope=*/true)) { shared_ptr m @@ -5166,7 +5006,7 @@ build_class_decl(read_context& ctxt, decl->add_member_function_template(m); } else if (shared_ptr c = - build_class_tdecl(ctxt, p, + build_class_tdecl(rdr, p, /*add_to_current_scope=*/true)) { member_class_template_sptr m(new member_class_template(c, @@ -5179,14 +5019,14 @@ build_class_decl(read_context& ctxt, } } - ctxt.pop_scope_or_abort(decl); + rdr.pop_scope_or_abort(decl); return decl; } /// Build a union_decl from a 'union-decl' xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the union_decl from. /// @@ -5197,7 +5037,7 @@ build_class_decl(read_context& ctxt, /// @return a pointer to union_decl upon successful completion, a null /// pointer otherwise. static union_decl_sptr -build_union_decl(read_context& ctxt, +build_union_decl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -5206,7 +5046,7 @@ build_union_decl(read_context& ctxt, if (!xmlStrEqual(node->name, BAD_CAST("union-decl"))) return nil; - if (decl_base_sptr d = ctxt.get_decl_for_xml_node(node)) + if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) { union_decl_sptr result = dynamic_pointer_cast(d); ABG_ASSERT(result); @@ -5231,7 +5071,7 @@ build_union_decl(read_context& ctxt, id = CHAR_STR(s); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); union_decl::member_types mbrs; union_decl::data_members data_mbrs; @@ -5249,7 +5089,7 @@ build_union_decl(read_context& ctxt, union_decl_sptr previous_definition, previous_declaration; const vector *types_ptr = 0; if (!is_anonymous) - types_ptr = ctxt.get_all_type_decls(id); + types_ptr = rdr.get_all_type_decls(id); if (types_ptr) { // Lets look at the previous declarations and the first previous @@ -5281,8 +5121,7 @@ build_union_decl(read_context& ctxt, return previous_declaration; } - const environment* env = ctxt.get_environment(); - ABG_ASSERT(env); + const environment& env = rdr.get_environment(); if (!is_decl_only && previous_definition) // We are in the case where we've read this class definition @@ -5304,7 +5143,7 @@ build_union_decl(read_context& ctxt, is_anonymous)); } - maybe_set_artificial_location(ctxt, node, decl); + maybe_set_artificial_location(rdr, node, decl); decl->set_is_artificial(is_artificial); string def_id; @@ -5315,7 +5154,7 @@ build_union_decl(read_context& ctxt, if (!def_id.empty()) { class_decl_sptr d = - dynamic_pointer_cast(ctxt.get_type_decl(def_id)); + dynamic_pointer_cast(rdr.get_type_decl(def_id)); if (d && d->get_is_declaration_only()) { is_def_of_decl = true; @@ -5360,12 +5199,12 @@ build_union_decl(read_context& ctxt, ABG_ASSERT(!is_decl_only || !is_def_of_decl); - ctxt.push_decl_to_current_scope(decl, add_to_current_scope); + rdr.push_decl_to_current_scope(decl, add_to_current_scope); - ctxt.map_xml_node_to_decl(node, decl); - ctxt.key_type_decl(decl, id); + rdr.map_xml_node_to_decl(node, decl); + rdr.key_type_decl(decl, id); - maybe_set_naming_typedef(ctxt, node, decl); + maybe_set_naming_typedef(rdr, node, decl); for (xmlNodePtr n = xmlFirstElementChild(node); !is_decl_only && n; @@ -5376,30 +5215,30 @@ build_union_decl(read_context& ctxt, access_specifier access = private_access; read_access(n, access); - ctxt.map_xml_node_to_decl(n, decl); + rdr.map_xml_node_to_decl(n, decl); for (xmlNodePtr p = xmlFirstElementChild(n); p; p = xmlNextElementSibling(p)) { if (type_base_sptr t = - build_type(ctxt, p, /*add_to_current_scope=*/true)) + build_type(rdr, p, /*add_to_current_scope=*/true)) { decl_base_sptr td = get_type_declaration(t); ABG_ASSERT(td); set_member_access_specifier(td, access); - ctxt.maybe_canonicalize_type(t, !add_to_current_scope); + rdr.maybe_canonicalize_type(t, !add_to_current_scope); xml_char_sptr i= XML_NODE_GET_ATTRIBUTE(p, "id"); string id = CHAR_STR(i); ABG_ASSERT(!id.empty()); - ctxt.key_type_decl(t, id); - ctxt.map_xml_node_to_decl(p, td); + rdr.key_type_decl(t, id); + rdr.map_xml_node_to_decl(p, td); } } } else if (xmlStrEqual(n->name, BAD_CAST("data-member"))) { - ctxt.map_xml_node_to_decl(n, decl); + rdr.map_xml_node_to_decl(n, decl); access_specifier access = private_access; read_access(n, access); @@ -5414,7 +5253,7 @@ build_union_decl(read_context& ctxt, p = xmlNextElementSibling(p)) { if (var_decl_sptr v = - build_var_decl(ctxt, p, /*add_to_cur_scope=*/false)) + build_var_decl(rdr, p, /*add_to_cur_scope=*/false)) { if (decl->find_data_member(v)) { @@ -5424,12 +5263,12 @@ build_union_decl(read_context& ctxt, // So we need to discard the data member we have // built (and that was pushed to the current // stack of decls built) and move on. - decl_base_sptr d = ctxt.pop_decl(); + decl_base_sptr d = rdr.pop_decl(); ABG_ASSERT(is_var_decl(d)); continue; } if (!is_static - || !variable_is_suppressed(ctxt, decl.get(), *v)) + || !variable_is_suppressed(rdr, decl.get(), *v)) { decl->add_data_member(v, access, is_laid_out, @@ -5444,11 +5283,11 @@ build_union_decl(read_context& ctxt, // can't name it. Rather, let's record that // the class being built uses the type of the // (anonymous) data member. - RECORD_ARTIFACT_AS_USED_BY(ctxt, v->get_type(), decl); + RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), decl); else { - RECORD_ARTIFACT_AS_USED_BY(ctxt, v->get_type(), v); - RECORD_ARTIFACT_AS_USED_BY(ctxt, v, decl); + RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), v); + RECORD_ARTIFACT_AS_USED_BY(rdr, v, decl); } } } @@ -5456,7 +5295,7 @@ build_union_decl(read_context& ctxt, } else if (xmlStrEqual(n->name, BAD_CAST("member-function"))) { - ctxt.map_xml_node_to_decl(n, decl); + rdr.map_xml_node_to_decl(n, decl); access_specifier access = private_access; read_access(n, access); @@ -5472,7 +5311,7 @@ build_union_decl(read_context& ctxt, p = xmlNextElementSibling(p)) { if (function_decl_sptr f = - build_function_decl_if_not_suppressed(ctxt, p, decl, + build_function_decl_if_not_suppressed(rdr, p, decl, /*add_to_cur_sc=*/true)) { method_decl_sptr m = is_method_decl(f); @@ -5488,7 +5327,7 @@ build_union_decl(read_context& ctxt, } else if (xmlStrEqual(n->name, BAD_CAST("member-template"))) { - ctxt.map_xml_node_to_decl(n, decl); + rdr.map_xml_node_to_decl(n, decl); access_specifier access = private_access; read_access(n, access); @@ -5504,7 +5343,7 @@ build_union_decl(read_context& ctxt, p = xmlNextElementSibling(p)) { if (function_tdecl_sptr f = - build_function_tdecl(ctxt, p, + build_function_tdecl(rdr, p, /*add_to_current_scope=*/true)) { member_function_template_sptr m @@ -5514,7 +5353,7 @@ build_union_decl(read_context& ctxt, decl->add_member_function_template(m); } else if (class_tdecl_sptr c = - build_class_tdecl(ctxt, p, + build_class_tdecl(rdr, p, /*add_to_current_scope=*/true)) { member_class_template_sptr m(new member_class_template(c, @@ -5527,7 +5366,7 @@ build_union_decl(read_context& ctxt, } } - ctxt.pop_scope_or_abort(decl); + rdr.pop_scope_or_abort(decl); return decl; } @@ -5535,7 +5374,7 @@ build_union_decl(read_context& ctxt, /// Build an intance of function_tdecl, from an /// 'function-template-decl' xml element node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to parse from. /// @@ -5545,7 +5384,7 @@ build_union_decl(read_context& ctxt, /// @return the newly built function_tdecl upon successful /// completion, a null pointer otherwise. static shared_ptr -build_function_tdecl(read_context& ctxt, +build_function_tdecl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -5557,11 +5396,11 @@ build_function_tdecl(read_context& ctxt, string id; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id")) id = CHAR_STR(s); - if (id.empty() || ctxt.get_fn_tmpl_decl(id)) + if (id.empty() || rdr.get_fn_tmpl_decl(id)) return nil; location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); decl_base::visibility vis = decl_base::VISIBILITY_NONE; read_visibility(node, vis); @@ -5569,13 +5408,12 @@ build_function_tdecl(read_context& ctxt, decl_base::binding bind = decl_base::BINDING_NONE; read_binding(node, bind); - const environment* env = ctxt.get_environment(); - ABG_ASSERT(env); + const environment& env = rdr.get_environment(); function_tdecl_sptr fn_tmpl_decl(new function_tdecl(env, loc, vis, bind)); - maybe_set_artificial_location(ctxt, node, fn_tmpl_decl); + maybe_set_artificial_location(rdr, node, fn_tmpl_decl); - ctxt.push_decl_to_current_scope(fn_tmpl_decl, add_to_current_scope); + rdr.push_decl_to_current_scope(fn_tmpl_decl, add_to_current_scope); unsigned parm_index = 0; for (xmlNodePtr n = xmlFirstElementChild(node); @@ -5583,18 +5421,18 @@ build_function_tdecl(read_context& ctxt, n = xmlNextElementSibling(n)) { if (template_parameter_sptr parm = - build_template_parameter(ctxt, n, parm_index, fn_tmpl_decl)) + build_template_parameter(rdr, n, parm_index, fn_tmpl_decl)) { fn_tmpl_decl->add_template_parameter(parm); ++parm_index; } else if (function_decl_sptr f = - build_function_decl_if_not_suppressed(ctxt, n, class_decl_sptr(), + build_function_decl_if_not_suppressed(rdr, n, class_decl_sptr(), /*add_to_current_scope=*/true)) fn_tmpl_decl->set_pattern(f); } - ctxt.key_fn_tmpl_decl(fn_tmpl_decl, id); + rdr.key_fn_tmpl_decl(fn_tmpl_decl, id); return fn_tmpl_decl; } @@ -5602,7 +5440,7 @@ build_function_tdecl(read_context& ctxt, /// Build an intance of class_tdecl, from a /// 'class-template-decl' xml element node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to parse from. /// @@ -5612,7 +5450,7 @@ build_function_tdecl(read_context& ctxt, /// @return the newly built function_tdecl upon successful /// completion, a null pointer otherwise. static shared_ptr -build_class_tdecl(read_context& ctxt, +build_class_tdecl(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { @@ -5624,22 +5462,21 @@ build_class_tdecl(read_context& ctxt, string id; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id")) id = CHAR_STR(s); - if (id.empty() || ctxt.get_class_tmpl_decl(id)) + if (id.empty() || rdr.get_class_tmpl_decl(id)) return nil; location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); decl_base::visibility vis = decl_base::VISIBILITY_NONE; read_visibility(node, vis); - const environment* env = ctxt.get_environment(); - ABG_ASSERT(env); + const environment& env = rdr.get_environment(); class_tdecl_sptr class_tmpl (new class_tdecl(env, loc, vis)); - maybe_set_artificial_location(ctxt, node, class_tmpl); + maybe_set_artificial_location(rdr, node, class_tmpl); - ctxt.push_decl_to_current_scope(class_tmpl, add_to_current_scope); + rdr.push_decl_to_current_scope(class_tmpl, add_to_current_scope); unsigned parm_index = 0; for (xmlNodePtr n = xmlFirstElementChild(node); @@ -5647,22 +5484,22 @@ build_class_tdecl(read_context& ctxt, n = xmlNextElementSibling(n)) { if (template_parameter_sptr parm= - build_template_parameter(ctxt, n, parm_index, class_tmpl)) + build_template_parameter(rdr, n, parm_index, class_tmpl)) { class_tmpl->add_template_parameter(parm); ++parm_index; } else if (class_decl_sptr c = - build_class_decl_if_not_suppressed(ctxt, n, + build_class_decl_if_not_suppressed(rdr, n, add_to_current_scope)) { if (c->get_scope()) - ctxt.maybe_canonicalize_type(c, /*force_delay=*/false); + rdr.maybe_canonicalize_type(c, /*force_delay=*/false); class_tmpl->set_pattern(c); } } - ctxt.key_class_tmpl_decl(class_tmpl, id); + rdr.key_class_tmpl_decl(class_tmpl, id); return class_tmpl; } @@ -5670,7 +5507,7 @@ build_class_tdecl(read_context& ctxt, /// Build a type_tparameter from a 'template-type-parameter' /// xml element node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to parse from. /// @@ -5683,7 +5520,7 @@ build_class_tdecl(read_context& ctxt, /// @return a pointer to a newly created instance of /// type_tparameter, a null pointer otherwise. static type_tparameter_sptr -build_type_tparameter(read_context& ctxt, +build_type_tparameter(reader& rdr, const xmlNodePtr node, unsigned index, template_decl_sptr tdecl) @@ -5697,14 +5534,14 @@ build_type_tparameter(read_context& ctxt, if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id")) id = CHAR_STR(s); if (!id.empty()) - ABG_ASSERT(!ctxt.get_type_decl(id)); + ABG_ASSERT(!rdr.get_type_decl(id)); string type_id; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id")) type_id = CHAR_STR(s); if (!type_id.empty() && !(result = dynamic_pointer_cast - (ctxt.build_or_get_type_decl(type_id, true)))) + (rdr.build_or_get_type_decl(type_id, true)))) abort(); string name; @@ -5712,20 +5549,18 @@ build_type_tparameter(read_context& ctxt, name = xml::unescape_xml_string(CHAR_STR(s)); location loc; - read_location(ctxt, node,loc); + read_location(rdr, node,loc); result.reset(new type_tparameter(index, tdecl, name, loc)); - maybe_set_artificial_location(ctxt, node, result); + maybe_set_artificial_location(rdr, node, result); if (id.empty()) - ctxt.push_decl_to_current_scope(dynamic_pointer_cast(result), + rdr.push_decl_to_current_scope(dynamic_pointer_cast(result), /*add_to_current_scope=*/true); else - ctxt.push_and_key_type_decl(result, id, /*add_to_current_scope=*/true); + rdr.push_and_key_type_decl(result, id, /*add_to_current_scope=*/true); - ABG_ASSERT(result->get_environment()); - - ctxt.maybe_canonicalize_type(result, /*force_delay=*/false); + rdr.maybe_canonicalize_type(result, /*force_delay=*/false); return result; } @@ -5733,7 +5568,7 @@ build_type_tparameter(read_context& ctxt, /// Build a tmpl_parm_type_composition from a /// "template-parameter-type-composition" xml element node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to parse from. /// @@ -5745,7 +5580,7 @@ build_type_tparameter(read_context& ctxt, /// @return a pointer to a new instance of tmpl_parm_type_composition /// upon successful completion, a null pointer otherwise. static type_composition_sptr -build_type_composition(read_context& ctxt, +build_type_composition(reader& rdr, const xmlNodePtr node, unsigned index, template_decl_sptr tdecl) @@ -5757,7 +5592,7 @@ build_type_composition(read_context& ctxt, type_base_sptr composed_type; result.reset(new type_composition(index, tdecl, composed_type)); - ctxt.push_decl_to_current_scope(dynamic_pointer_cast(result), + rdr.push_decl_to_current_scope(dynamic_pointer_cast(result), /*add_to_current_scope=*/true); for (xmlNodePtr n = xmlFirstElementChild(node); @@ -5765,19 +5600,19 @@ build_type_composition(read_context& ctxt, n = xmlNextElementSibling(n)) { if ((composed_type = - build_pointer_type_def(ctxt, n, + build_pointer_type_def(rdr, n, /*add_to_current_scope=*/true)) ||(composed_type = - build_reference_type_def(ctxt, n, + build_reference_type_def(rdr, n, /*add_to_current_scope=*/true)) ||(composed_type = - build_array_type_def(ctxt, n, + build_array_type_def(rdr, n, /*add_to_current_scope=*/true)) || (composed_type = - build_qualified_type_decl(ctxt, n, + build_qualified_type_decl(rdr, n, /*add_to_current_scope=*/true))) { - ctxt.maybe_canonicalize_type(composed_type, + rdr.maybe_canonicalize_type(composed_type, /*force_delay=*/true); result->set_composed_type(composed_type); break; @@ -5790,7 +5625,7 @@ build_type_composition(read_context& ctxt, /// Build an instance of non_type_tparameter from a /// 'template-non-type-parameter' xml element node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to parse from. /// @@ -5803,7 +5638,7 @@ build_type_composition(read_context& ctxt, /// non_type_tparameter upon successful completion, a null /// pointer code otherwise. static non_type_tparameter_sptr -build_non_type_tparameter(read_context& ctxt, +build_non_type_tparameter(reader& rdr, const xmlNodePtr node, unsigned index, template_decl_sptr tdecl) @@ -5818,7 +5653,7 @@ build_non_type_tparameter(read_context& ctxt, type_id = CHAR_STR(s); type_base_sptr type; if (type_id.empty() - || !(type = ctxt.build_or_get_type_decl(type_id, true))) + || !(type = rdr.build_or_get_type_decl(type_id, true))) abort(); string name; @@ -5826,11 +5661,11 @@ build_non_type_tparameter(read_context& ctxt, name = xml::unescape_xml_string(CHAR_STR(s)); location loc; - read_location(ctxt, node,loc); + read_location(rdr, node,loc); r.reset(new non_type_tparameter(index, tdecl, name, type, loc)); - maybe_set_artificial_location(ctxt, node, r); - ctxt.push_decl_to_current_scope(dynamic_pointer_cast(r), + maybe_set_artificial_location(rdr, node, r); + rdr.push_decl_to_current_scope(dynamic_pointer_cast(r), /*add_to_current_scope=*/true); return r; @@ -5839,7 +5674,7 @@ build_non_type_tparameter(read_context& ctxt, /// Build an intance of template_tparameter from a /// 'template-template-parameter' xml element node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to parse from. /// @@ -5851,7 +5686,7 @@ build_non_type_tparameter(read_context& ctxt, /// @return a pointer to a new instance of template_tparameter /// upon successful completion, a null pointer otherwise. static template_tparameter_sptr -build_template_tparameter(read_context& ctxt, +build_template_tparameter(reader& rdr, const xmlNodePtr node, unsigned index, template_decl_sptr tdecl) @@ -5873,7 +5708,7 @@ build_template_tparameter(read_context& ctxt, // Bail out if no type with this ID exists. if (!type_id.empty() && !(dynamic_pointer_cast - (ctxt.build_or_get_type_decl(type_id, true)))) + (rdr.build_or_get_type_decl(type_id, true)))) abort(); string name; @@ -5881,12 +5716,12 @@ build_template_tparameter(read_context& ctxt, name = xml::unescape_xml_string(CHAR_STR(s)); location loc; - read_location(ctxt, node, loc); + read_location(rdr, node, loc); template_tparameter_sptr result(new template_tparameter(index, tdecl, name, loc)); - maybe_set_artificial_location(ctxt, node, result); - ctxt.push_decl_to_current_scope(result, /*add_to_current_scope=*/true); + maybe_set_artificial_location(rdr, node, result); + rdr.push_decl_to_current_scope(result, /*add_to_current_scope=*/true); // Go parse template parameters that are children nodes int parm_index = 0; @@ -5894,7 +5729,7 @@ build_template_tparameter(read_context& ctxt, n; n = xmlNextElementSibling(n)) if (shared_ptr p = - build_template_parameter(ctxt, n, parm_index, result)) + build_template_parameter(rdr, n, parm_index, result)) { result->add_template_parameter(p); ++parm_index; @@ -5902,8 +5737,8 @@ build_template_tparameter(read_context& ctxt, if (result) { - ctxt.key_type_decl(result, id); - ctxt.maybe_canonicalize_type(result, /*force_delay=*/false); + rdr.key_type_decl(result, id); + rdr.maybe_canonicalize_type(result, /*force_delay=*/false); } return result; @@ -5912,7 +5747,7 @@ build_template_tparameter(read_context& ctxt, /// Build a template parameter type from several possible xml elment /// nodes representing a serialized form a template parameter. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml element node to parse from. /// @@ -5925,52 +5760,52 @@ build_template_tparameter(read_context& ctxt, /// template_parameter upon successful completion, a null pointer /// otherwise. static template_parameter_sptr -build_template_parameter(read_context& ctxt, +build_template_parameter(reader& rdr, const xmlNodePtr node, unsigned index, template_decl_sptr tdecl) { shared_ptr r; - ((r = build_type_tparameter(ctxt, node, index, tdecl)) - || (r = build_non_type_tparameter(ctxt, node, index, tdecl)) - || (r = build_template_tparameter(ctxt, node, index, tdecl)) - || (r = build_type_composition(ctxt, node, index, tdecl))); + ((r = build_type_tparameter(rdr, node, index, tdecl)) + || (r = build_non_type_tparameter(rdr, node, index, tdecl)) + || (r = build_template_tparameter(rdr, node, index, tdecl)) + || (r = build_type_composition(rdr, node, index, tdecl))); return r; } /// Build a type from an xml node. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the xml node to build the type_base from. /// /// @return a pointer to the newly built type_base upon successful /// completion, a null pointer otherwise. static type_base_sptr -build_type(read_context& ctxt, +build_type(reader& rdr, const xmlNodePtr node, bool add_to_current_scope) { type_base_sptr t; - ((t = build_type_decl(ctxt, node, add_to_current_scope)) - || (t = build_qualified_type_decl(ctxt, node, add_to_current_scope)) - || (t = build_pointer_type_def(ctxt, node, add_to_current_scope)) - || (t = build_reference_type_def(ctxt, node , add_to_current_scope)) - || (t = build_function_type(ctxt, node, add_to_current_scope)) - || (t = build_array_type_def(ctxt, node, add_to_current_scope)) - || (t = build_enum_type_decl_if_not_suppressed(ctxt, node, + ((t = build_type_decl(rdr, node, add_to_current_scope)) + || (t = build_qualified_type_decl(rdr, node, add_to_current_scope)) + || (t = build_pointer_type_def(rdr, node, add_to_current_scope)) + || (t = build_reference_type_def(rdr, node , add_to_current_scope)) + || (t = build_function_type(rdr, node, add_to_current_scope)) + || (t = build_array_type_def(rdr, node, add_to_current_scope)) + || (t = build_enum_type_decl_if_not_suppressed(rdr, node, add_to_current_scope)) - || (t = build_typedef_decl(ctxt, node, add_to_current_scope)) - || (t = build_class_decl_if_not_suppressed(ctxt, node, + || (t = build_typedef_decl(rdr, node, add_to_current_scope)) + || (t = build_class_decl_if_not_suppressed(rdr, node, add_to_current_scope)) - || (t = build_union_decl_if_not_suppressed(ctxt, node, + || (t = build_union_decl_if_not_suppressed(rdr, node, add_to_current_scope))); - if (ctxt.tracking_non_reachable_types() && t) + if (rdr.tracking_non_reachable_types() && t) { - corpus_sptr abi = ctxt.get_corpus(); + corpus_sptr abi = rdr.corpus(); ABG_ASSERT(abi); bool is_non_reachable_type = false; read_is_non_reachable_type(node, is_non_reachable_type); @@ -5981,263 +5816,263 @@ build_type(read_context& ctxt, MAYBE_MAP_TYPE_WITH_TYPE_ID(t, node); if (t) - ctxt.maybe_canonicalize_type(t,/*force_delay=*/false ); + rdr.maybe_canonicalize_type(t,/*force_delay=*/false ); return t; } /// Parses 'type-decl' xml element. /// -/// @param ctxt the parsing context. +/// @param rdr the parsing context. /// /// @return true upon successful parsing, false otherwise. static decl_base_sptr -handle_type_decl(read_context& ctxt, +handle_type_decl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - type_decl_sptr decl = build_type_decl(ctxt, node, add_to_current_scope); + type_decl_sptr decl = build_type_decl(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node); if (decl && decl->get_scope()) - ctxt.maybe_canonicalize_type(decl, /*force_delay=*/false); + rdr.maybe_canonicalize_type(decl, /*force_delay=*/false); return decl; } /// Parses 'namespace-decl' xml element. /// -/// @param ctxt the parsing context. +/// @param rdr the parsing context. /// /// @return true upon successful parsing, false otherwise. static decl_base_sptr -handle_namespace_decl(read_context& ctxt, +handle_namespace_decl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - namespace_decl_sptr d = build_namespace_decl(ctxt, node, + namespace_decl_sptr d = build_namespace_decl(rdr, node, add_to_current_scope); return d; } /// Parse a qualified-type-def xml element. /// -/// @param ctxt the parsing context. +/// @param rdr the parsing context. /// /// @return true upon successful parsing, false otherwise. static decl_base_sptr -handle_qualified_type_decl(read_context& ctxt, +handle_qualified_type_decl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { qualified_type_def_sptr decl = - build_qualified_type_decl(ctxt, node, + build_qualified_type_decl(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node); if (decl && decl->get_scope()) - ctxt.maybe_canonicalize_type(decl, /*force_delay=*/false); + rdr.maybe_canonicalize_type(decl, /*force_delay=*/false); return decl; } /// Parse a pointer-type-decl element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @return true upon successful completion, false otherwise. static decl_base_sptr -handle_pointer_type_def(read_context& ctxt, +handle_pointer_type_def(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - pointer_type_def_sptr decl = build_pointer_type_def(ctxt, node, + pointer_type_def_sptr decl = build_pointer_type_def(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node); if (decl && decl->get_scope()) - ctxt.maybe_canonicalize_type(decl, /*force_delay=*/false); + rdr.maybe_canonicalize_type(decl, /*force_delay=*/false); return decl; } /// Parse a reference-type-def element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// reference_type_def is added to. static decl_base_sptr -handle_reference_type_def(read_context& ctxt, +handle_reference_type_def(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - reference_type_def_sptr decl = build_reference_type_def(ctxt, node, + reference_type_def_sptr decl = build_reference_type_def(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node); if (decl && decl->get_scope()) - ctxt.maybe_canonicalize_type(decl, /*force_delay=*/false); + rdr.maybe_canonicalize_type(decl, /*force_delay=*/false); return decl; } /// Parse a function-type element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// function_type is added to. static type_base_sptr -handle_function_type(read_context& ctxt, +handle_function_type(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - function_type_sptr type = build_function_type(ctxt, node, + function_type_sptr type = build_function_type(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(type, node); - ctxt.maybe_canonicalize_type(type, /*force_delay=*/true); + rdr.maybe_canonicalize_type(type, /*force_delay=*/true); return type; } /// Parse a array-type-def element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// array_type_def is added to. static decl_base_sptr -handle_array_type_def(read_context& ctxt, +handle_array_type_def(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - array_type_def_sptr decl = build_array_type_def(ctxt, node, + array_type_def_sptr decl = build_array_type_def(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node); - ctxt.maybe_canonicalize_type(decl, /*force_delay=*/false); + rdr.maybe_canonicalize_type(decl, /*force_delay=*/false); return decl; } /// Parse an enum-decl element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. static decl_base_sptr -handle_enum_type_decl(read_context& ctxt, +handle_enum_type_decl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { enum_type_decl_sptr decl = - build_enum_type_decl_if_not_suppressed(ctxt, node, + build_enum_type_decl_if_not_suppressed(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node); if (decl && decl->get_scope()) - ctxt.maybe_canonicalize_type(decl, /*force_delay=*/false); + rdr.maybe_canonicalize_type(decl, /*force_delay=*/false); return decl; } /// Parse a typedef-decl element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. static decl_base_sptr -handle_typedef_decl(read_context& ctxt, +handle_typedef_decl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - typedef_decl_sptr decl = build_typedef_decl(ctxt, node, + typedef_decl_sptr decl = build_typedef_decl(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node); if (decl && decl->get_scope()) - ctxt.maybe_canonicalize_type(decl, /*force_delay=*/false); + rdr.maybe_canonicalize_type(decl, /*force_delay=*/false); return decl; } /// Parse a var-decl element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @param node the node to read & parse from. /// /// @param add_to_current_scope if set to yes, the resulting of this /// function is added to its current scope. static decl_base_sptr -handle_var_decl(read_context& ctxt, +handle_var_decl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - decl_base_sptr decl = build_var_decl_if_not_suppressed(ctxt, node, + decl_base_sptr decl = build_var_decl_if_not_suppressed(rdr, node, add_to_current_scope); - ctxt.maybe_add_var_to_exported_decls(is_var_decl(decl)); + rdr.maybe_add_var_to_exported_decls(is_var_decl(decl).get()); return decl; } /// Parse a function-decl element. /// -/// @param ctxt the context of the parsing +/// @param rdr the context of the parsing /// /// @return true upon successful completion of the parsing, false /// otherwise. static decl_base_sptr -handle_function_decl(read_context& ctxt, +handle_function_decl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - return build_function_decl_if_not_suppressed(ctxt, node, class_decl_sptr(), + return build_function_decl_if_not_suppressed(rdr, node, class_decl_sptr(), add_to_current_scope); } /// Parse a 'class-decl' xml element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @return the resulting @ref class_decl built from the XML element /// upon successful completion of the parsing, nil otherwise. static decl_base_sptr -handle_class_decl(read_context& ctxt, +handle_class_decl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { class_decl_sptr decl = - build_class_decl_if_not_suppressed(ctxt, node, add_to_current_scope); + build_class_decl_if_not_suppressed(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(is_type(decl), node); if (decl && decl->get_scope()) - ctxt.maybe_canonicalize_type(decl, /*force_delay=*/false); + rdr.maybe_canonicalize_type(decl, /*force_delay=*/false); return decl; } /// Parse a 'union-decl' xml element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @return the resulting @ref union_decl built from the XML element /// upon successful completion of the parsing, nil otherwise. static decl_base_sptr -handle_union_decl(read_context& ctxt, +handle_union_decl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { union_decl_sptr decl = - build_union_decl_if_not_suppressed(ctxt, node, add_to_current_scope); + build_union_decl_if_not_suppressed(rdr, node, add_to_current_scope); MAYBE_MAP_TYPE_WITH_TYPE_ID(is_type(decl), node); if (decl && decl->get_scope()) - ctxt.maybe_canonicalize_type(decl, /*force_delay=*/false); + rdr.maybe_canonicalize_type(decl, /*force_delay=*/false); return decl; } /// Parse a 'function-template-decl' xml element. /// -/// @param ctxt the parsing context. +/// @param rdr the parsing context. /// /// @return true upon successful completion of the parsing, false /// otherwise. static decl_base_sptr -handle_function_tdecl(read_context& ctxt, +handle_function_tdecl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - function_tdecl_sptr d = build_function_tdecl(ctxt, node, + function_tdecl_sptr d = build_function_tdecl(rdr, node, add_to_current_scope); return d; } /// Parse a 'class-template-decl' xml element. /// -/// @param ctxt the context of the parsing. +/// @param rdr the context of the parsing. /// /// @return true upon successful completion, false otherwise. static decl_base_sptr -handle_class_tdecl(read_context& ctxt, +handle_class_tdecl(reader& rdr, xmlNodePtr node, bool add_to_current_scope) { - class_tdecl_sptr decl = build_class_tdecl(ctxt, node, + class_tdecl_sptr decl = build_class_tdecl(rdr, node, add_to_current_scope); return decl; } @@ -6252,10 +6087,10 @@ handle_class_tdecl(read_context& ctxt, /// @return the translation unit resulting from the parsing upon /// successful completion, or nil. translation_unit_sptr -read_translation_unit_from_istream(istream* in, environment* env) +read_translation_unit_from_istream(istream* in, environment& env) { - read_context read_ctxt(xml::new_reader_from_istream(in), env); - return read_translation_unit_from_input(read_ctxt); + reader read_rdr(xml::new_reader_from_istream(in), env); + return read_translation_unit_from_input(read_rdr); } template struct array_deleter @@ -6268,30 +6103,29 @@ struct array_deleter };//end array_deleter -/// Create an xml_reader::read_context to read a native XML ABI file. +/// Create an xml_reader::reader to read a native XML ABI file. /// /// @param path the path to the native XML file to read. /// /// @param env the environment to use. /// /// @return the created context. -read_context_sptr -create_native_xml_read_context(const string& path, environment *env) +fe_iface_sptr +create_abixml_reader(const string& path, environment& env) { - read_context_sptr result(new read_context(xml::new_reader_from_file(path), - env)); - corpus_sptr corp(new corpus(env)); + reader_sptr result(new reader(xml::new_reader_from_file(path), + env)); + corpus_sptr corp = result->corpus(); corp->set_origin(corpus::NATIVE_XML_ORIGIN); - result->set_corpus(corp); #ifdef WITH_DEBUG_SELF_COMPARISON - if (env->self_comparison_debug_is_on()) - env->set_self_comparison_debug_input(result->get_corpus()); + if (env.self_comparison_debug_is_on()) + env.set_self_comparison_debug_input(result->corpus()); #endif result->set_path(path); return result; } -/// Create an xml_reader::read_context to read a native XML ABI from +/// Create an xml_reader::reader to read a native XML ABI from /// an input stream.. /// /// @param in the input stream that contains the native XML file to read. @@ -6299,28 +6133,20 @@ create_native_xml_read_context(const string& path, environment *env) /// @param env the environment to use. /// /// @return the created context. -read_context_sptr -create_native_xml_read_context(std::istream* in, environment* env) +fe_iface_sptr +create_abixml_reader(std::istream* in, environment& env) { - read_context_sptr result(new read_context(xml::new_reader_from_istream(in), - env)); - corpus_sptr corp(new corpus(env, "")); + reader_sptr result(new reader(xml::new_reader_from_istream(in), + env)); + corpus_sptr corp = result->corpus(); corp->set_origin(corpus::NATIVE_XML_ORIGIN); - result->set_corpus(corp); #ifdef WITH_DEBUG_SELF_COMPARISON - if (env->self_comparison_debug_is_on()) - env->set_self_comparison_debug_input(result->get_corpus()); + if (env.self_comparison_debug_is_on()) + env.set_self_comparison_debug_input(result->corpus()); #endif return result; } -/// Getter for the path to the binary this @ref read_context is for. -/// -/// @return the path to the binary the @ref read_context is for. -const string& -read_context_get_path(const read_context& ctxt) -{return ctxt.get_path();} - /// De-serialize an ABI corpus from an input XML document which root /// node is 'abi-corpus'. /// @@ -6334,11 +6160,12 @@ read_context_get_path(const read_context& ctxt) /// @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, - environment* env) +read_corpus_from_abixml(std::istream* in, + environment& env) { - read_context_sptr read_ctxt = create_native_xml_read_context(in, env); - return read_corpus_from_input(*read_ctxt); + fe_iface_sptr rdr = create_abixml_reader(in, env); + fe_iface::status sts; + return rdr->read_corpus(sts); } /// De-serialize an ABI corpus from an XML document file which root @@ -6355,11 +6182,12 @@ read_corpus_from_native_xml(std::istream* in, /// @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, - environment* env) +read_corpus_from_abixml_file(const string& path, + environment& env) { - read_context_sptr read_ctxt = create_native_xml_read_context(path, env); - corpus_sptr corp = read_corpus_from_input(*read_ctxt); + fe_iface_sptr rdr = create_abixml_reader(path, env); + fe_iface::status sts; + corpus_sptr corp = rdr->read_corpus(sts); return corp; } @@ -6377,15 +6205,17 @@ read_corpus_from_native_xml_file(const string& path, /// The function that stored the map in that file is /// write_canonical_type_ids. /// -/// @param ctxt the read context to use. +/// @param rdr the ABIXML reader to use. /// /// @param file_path the path to the file containing the type-ids <-> /// canonical type mapping. /// /// @return true iff the loading was successful. bool -load_canonical_type_ids(xml_reader::read_context& ctxt, const string &file_path) +load_canonical_type_ids(fe_iface& iface, const string &file_path) { + xml_reader::reader& rdr = dynamic_cast(iface) + xmlDocPtr doc = xmlReadFile(file_path.c_str(), NULL, XML_PARSE_NOERROR); if (!doc) return false; @@ -6443,7 +6273,7 @@ load_canonical_type_ids(xml_reader::read_context& ctxt, const string &file_path) // that are not canonicalized. Look into function // hash_as_canonical_type_or_constant for the details. && v != 0xdeadbabe) - ctxt.get_environment()->get_type_id_canonical_type_map()[id] = v; + rdr.get_environment()->get_type_id_canonical_type_map()[id] = v; } } return true; diff --git a/src/abg-suppression-priv.h b/src/abg-suppression-priv.h index 47e39e76..13d17059 100644 --- a/src/abg-suppression-priv.h +++ b/src/abg-suppression-priv.h @@ -404,59 +404,10 @@ bool suppression_matches_variable_name(const suppr::variable_suppression& s, const string& var_name); - bool suppression_matches_variable_sym_name(const suppr::variable_suppression& s, const string& var_linkage_name); -/// Test if a given function denoted by its name and linkage name is -/// suppressed by any of the suppression specifications associated to -/// a given read context used to build the current internal -/// representation of ABI corpus. -/// -/// @param ctxt the reading context of interest. -/// -/// @param fn_name the name of the function that a specification can -/// match. -/// -/// @param fn_linkage_name the linkage name of the function that a -/// specification can match. -/// -/// @param require_drop_property if set to "true", tests if the -/// function is suppressed and if its representation is dropped from -/// the ABI corpus being built. Otherwise, if set to "false", only -/// test if the function is suppressed. -/// -/// @return true iff at least one function specification matches a -/// function with name @p fn_name or with linkage name @p -/// fn_linkage_name. -template -bool -function_is_suppressed(const ReadContextType& ctxt, - const string& fn_name, - const string& fn_linkage_name, - bool require_drop_property = false) -{ - for (suppr::suppressions_type::const_iterator i = - ctxt.get_suppressions().begin(); - i != ctxt.get_suppressions().end(); - ++i) - if (suppr::function_suppression_sptr suppr = is_function_suppression(*i)) - { - if (require_drop_property && !(*i)->get_drops_artifact_from_ir()) - continue; - if (!fn_name.empty() - && ctxt.suppression_matches_function_name(*suppr, fn_name)) - return true; - if (!fn_linkage_name.empty() - && ctxt.suppression_matches_function_sym_name(*suppr, - fn_linkage_name)) - return true; - } - return false; -} -// - // /// The type of the private data of the @ref variable_suppression /// type. @@ -604,32 +555,6 @@ struct variable_suppression::priv } };// end class variable_supppression::priv -template -bool -variable_is_suppressed(const ReadContextType& ctxt, - const string& var_name, - const string& var_linkage_name, - bool require_drop_property = false) -{ - for (suppr::suppressions_type::const_iterator i = - ctxt.get_suppressions().begin(); - i != ctxt.get_suppressions().end(); - ++i) - if (suppr::variable_suppression_sptr suppr = is_variable_suppression(*i)) - { - if (require_drop_property && !(*i)->get_drops_artifact_from_ir()) - continue; - if (!var_name.empty() - && ctxt.suppression_matches_variable_name(*suppr, var_name)) - return true; - if (!var_linkage_name.empty() - && ctxt.suppression_matches_variable_sym_name(*suppr, - var_linkage_name)) - return true; - } - return false; -} - // // @@ -777,110 +702,6 @@ suppression_matches_type_name_or_location(const type_suppression& s, const string& type_name, const location& type_location); -/// Test if a type (designated by its name and location) is suppressed -/// by at least one suppression specification associated with a given -/// read context. -/// -/// @param ctxt the read context to consider. -/// -/// @param type_name the name of the type to consider. -/// -/// @param type_location the location of the type to consider. -/// -/// @param require_drop_property if set to "true", tests if the type -/// is suppressed and if its representation is dropped from the ABI -/// corpus being built. Otherwise, if set to "false", only test if -/// the type is suppressed. -/// -/// @return true iff at least one type specification matches a type -/// with name @p type_name and with location @p type_location. -template -bool -type_is_suppressed(const ReadContextType& ctxt, - const string& type_name, - const location& type_location) -{ - bool type_is_private = false; - return type_is_suppressed(ctxt, type_name, type_location, type_is_private); -} - -/// Test if a type (designated by its name and location) is suppressed -/// by at least one suppression specification associated with a given -/// read context. -/// -/// @param ctxt the read context to consider. -/// -/// @param type_name the name of the type to consider. -/// -/// @param type_location the location of the type to consider. -/// -/// @param type_is_private out parameter. If the type is suppressed -/// because it's private then this out parameter is set to true. -/// -/// @param require_drop_property if set to "true", tests if the type -/// is suppressed and if its representation is dropped from the ABI -/// corpus being built. Otherwise, if set to "false", only test if -/// the type is suppressed. -/// -/// @return true iff at least one type specification matches a type -/// with name @p type_name and with location @p type_location. -template -bool -type_is_suppressed(const ReadContextType& ctxt, - const string& type_name, - const location& type_location, - bool& type_is_private, - bool require_drop_property = false) -{ - for (suppr::suppressions_type::const_iterator i = - ctxt.get_suppressions().begin(); - i != ctxt.get_suppressions().end(); - ++i) - if (suppr::type_suppression_sptr suppr = is_type_suppression(*i)) - { - if (require_drop_property && !(*i)->get_drops_artifact_from_ir()) - continue; - if (ctxt.suppression_matches_type_name_or_location(*suppr, type_name, - type_location)) - { - if (is_private_type_suppr_spec(*suppr)) - type_is_private = true; - - return true; - } - } - - type_is_private = false; - return false; -} - -/// Test if a given ELF symbol is suppressed by a suppression -/// specification. -/// -/// @param ctxt the read context to use. -/// -/// @param sym_name the name of the symbol to consider. -/// -/// @param sym_type the type of the symbol to consider. -/// -/// @return true iff the elf symbol denoted by @p sym_name and @p -/// sym_type is suppressed. -template -bool -is_elf_symbol_suppressed(const ReadContextType& ctxt, - const string& sym_name, - elf_symbol::type sym_type) -{ - if (elf_symbol_is_function(sym_type)) - return suppr::function_is_suppressed(ctxt, /*fn_name=*/"", - /*symbol_name=*/sym_name); - else if (elf_symbol_is_variable(sym_type)) - return suppr::variable_is_suppressed(ctxt, /*var_name=*/"", - /*symbol_name=*/sym_name); - - return false; -} - // }// end namespace suppr diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc index 21b8ec6a..07fe47f4 100644 --- a/src/abg-suppression.cc +++ b/src/abg-suppression.cc @@ -23,6 +23,7 @@ ABG_BEGIN_EXPORT_DECLARATIONS #include "abg-comp-filter.h" #include "abg-suppression.h" #include "abg-tools-utils.h" +#include "abg-fe-iface.h" ABG_END_EXPORT_DECLARATIONS // @@ -2932,78 +2933,6 @@ operator|(function_suppression::change_kind l, (static_cast(l) | static_cast(r)); } - /// Test whether if a given function suppression matches a function - /// designated by a regular expression that describes its name. - /// - /// @param s the suppression specification to evaluate to see if it - /// matches a given function name. - /// - /// @param fn_name the name of the function of interest. Note that - /// this name must be *non* qualified. - /// - /// @return true iff the suppression specification @p s matches the - /// function whose name is @p fn_name. -bool -suppression_matches_function_name(const suppr::function_suppression& s, - const string& fn_name) -{ - if (regex_t_sptr regexp = s.priv_->get_name_regex()) - { - if (!regex::match(regexp, fn_name)) - return false; - } - else if (regex_t_sptr regexp = s.priv_->get_name_not_regex()) - { - if (regex::match(regexp, fn_name)) - return false; - } - else if (s.priv_->name_.empty()) - return false; - else // if (!s.priv_->name_.empty()) - { - if (s.priv_->name_ != fn_name) - return false; - } - - return true; -} - -/// Test whether if a given function suppression matches a function -/// designated by a regular expression that describes its linkage -/// name (symbol name). -/// -/// @param s the suppression specification to evaluate to see if it -/// matches a given function linkage name -/// -/// @param fn_linkage_name the linkage name of the function of interest. -/// -/// @return true iff the suppression specification @p s matches the -/// function whose linkage name is @p fn_linkage_name. -bool -suppression_matches_function_sym_name(const suppr::function_suppression& s, - const string& fn_linkage_name) -{ - if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex()) - { - if (!regex::match(regexp, fn_linkage_name)) - return false; - } - else if (regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex()) - { - if (regex::match(regexp, fn_linkage_name)) - return false; - } - else if (s.priv_->symbol_name_.empty()) - return false; - else // if (!s.priv_->symbol_name_.empty()) - { - if (s.priv_->symbol_name_ != fn_linkage_name) - return false; - } - - return true; -} - /// Test if a variable suppression matches a variable denoted by its name. /// /// @param s the variable suppression to consider. @@ -4239,6 +4168,43 @@ read_variable_suppression(const ini::config::section& section) return result; } +/// Test if a given variable is suppressed by at least one suppression +/// specification among a vector of suppression specifications. +/// +/// @param supprs the vector of suppression specifications to consider. +/// +/// @param var_name the name of the variable to consider. +/// +/// @param var_linkage_name the linkage name of the variable to consider. +/// +/// @param require_drop_property if yes, then only suppression +/// specifications that require that the variable be dropped from the +/// internal representation are taking into account. +/// +/// @return true if there is at least one suppression specification in +/// @p supprs which matches a variable named @p var_name, OR a +/// variable which linkage name is @p var_linkage_name. +bool +variable_is_suppressed(const suppr::suppressions_type& supprs, + const string& var_name, + const string& var_linkage_name, + bool require_drop_property) +{ + for (auto i : supprs) + if (suppr::variable_suppression_sptr suppr = is_variable_suppression(i)) + { + if (require_drop_property && !i->get_drops_artifact_from_ir()) + continue; + if (!var_name.empty() + && suppression_matches_variable_name(*suppr, var_name)) + return true; + if (!var_linkage_name.empty() + && suppression_matches_variable_sym_name(*suppr, + var_linkage_name)) + return true; + } + return false; +} // // @@ -4501,7 +4467,374 @@ is_private_type_suppr_spec(const suppression_sptr& s) return (type_suppr && type_suppr->get_label() == get_private_types_suppr_spec_label()); } - // + +/// Test if a given suppression specification can match an ABI +/// artifact coming from the corpus being analyzed by a given +/// front-end interface. +/// +/// @param fe the front-end to consider. +/// +/// @param s the suppression speficication to consider. +/// +/// @return true if the suppression specification @p s CAN patch ABI +/// artifacts coming from the ABI corpus being analyzed by the +/// front-end @p fe. +bool +suppression_can_match(const fe_iface& fe, + const suppression_base& s) +{ + if (!s.priv_->matches_soname(fe.dt_soname())) + if (s.has_soname_related_property()) + // The suppression has some SONAME related properties, but + // none of them match the SONAME of the current binary. So + // the suppression cannot match the current binary. + return false; + + if (!s.priv_->matches_binary_name(fe.corpus_path())) + if (s.has_file_name_related_property()) + // The suppression has some file_name related properties, but + // none of them match the file name of the current binary. So + // the suppression cannot match the current binary. + return false; + + return true; +} + +/// Test if a given function is suppressed by a suppression +/// specification. +/// +/// @param fe the front-end to consider. +/// +/// @param s the suppression specification to consider. +/// +/// @param fn_name the name of the function to consider. +/// +/// @return true iff the suppression specification @p s matches the +/// function which name is @p fn_name. +bool +suppression_matches_function_name(const fe_iface& fe, + const suppr::function_suppression& s, + const string& fn_name) +{ + if (!suppression_can_match(fe, s)) + return false; + + if (regex::regex_t_sptr regexp = s.priv_->get_name_regex()) + { + if (!regex::match(regexp, fn_name)) + return false; + } + else if (regex::regex_t_sptr regexp = s.priv_->get_name_not_regex()) + { + if (regex::match(regexp, fn_name)) + return false; + } + else if (s.priv_->name_.empty()) + return false; + else // if (!s.priv_->name_.empty()) + { + if (s.priv_->name_ != fn_name) + return false; + } + + return true; +} + +/// Test if a given function is suppressed by a suppression +/// specification. +/// +/// @param fe the front-end to consider. +/// +/// @param s the suppression specification to consider. +/// +/// @param fn_linkage_name the linkage name of the function to +/// consider. +/// +/// @return true iff the suppression specification @p s matches the +/// function which linkage name is @p fn_linkage_name. +bool +suppression_matches_function_sym_name(const fe_iface& fe, + const suppr::function_suppression& s, + const string& fn_linkage_name) +{ + if (!suppression_can_match(fe, s)) + return false; + + if (regex::regex_t_sptr regexp = s.priv_->get_symbol_name_regex()) + { + if (!regex::match(regexp, fn_linkage_name)) + return false; + } + else if (regex::regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex()) + { + if (regex::match(regexp, fn_linkage_name)) + return false; + } + else if (s.priv_->symbol_name_.empty()) + return false; + else // if (!s.priv_->symbol_name_.empty()) + { + if (s.priv_->symbol_name_ != fn_linkage_name) + return false; + } + + return true; +} + +/// Test if a suppression specification matches a variable of a given +/// name, in the context of a given front-end. +/// +/// @param fe the front-end to consider. +/// +/// @param s the variable suppression specification to consider. +/// +/// @param var_name the name of the variable to consider. +/// +/// @return true iff the suppression specification @p s matches the +/// variable which name is @p var_name. +bool +suppression_matches_variable_name(const fe_iface& fe, + const suppr::variable_suppression& s, + const string& var_name) +{ + if (!suppression_can_match(fe, s)) + return false; + + return suppression_matches_variable_name(s, var_name); +} + +/// Test if a suppression specification matches a variable which ELF +/// symbol has a given name, in the context of a given front-end. +/// +/// @param fe the front-end to consider. +/// +/// @param s the variable suppression specification to consider. +/// +/// @param var_linkage_name the name of the ELF symbol of the variable +/// to consider. +/// +/// @return true iff the suppression specification @p s matches the +/// variable which ELF symbol name is @p var_linkage_name. +bool +suppression_matches_variable_sym_name(const fe_iface& fe, + const suppr::variable_suppression& s, + const string& var_linkage_name) +{ + if (!suppression_can_match(fe, s)) + return false; + + return suppression_matches_variable_sym_name(s, var_linkage_name); +} + +/// Test if a suppression specification matches a type designated by +/// its name and source location, in the context of a given front-end. +/// +/// @param fe the front-end to consider. +/// +/// @param s the suppression specification to consider. +/// +/// @param type_name the name of the type to consider. +/// +/// @param type_location the source location of the type designated by +/// @p type_name. +/// +/// @return true iff the suppression @p s matches the type designated +/// by @p type_name at source location @type_location. +bool +suppression_matches_type_name_or_location(const fe_iface& fe, + const suppr::type_suppression& s, + const string& type_name, + const location& type_location) +{ + if (!suppression_can_match(fe, s)) + return false; + + return suppression_matches_type_name_or_location(s, type_name, + type_location); +} + +/// Test if an ELF symbol is suppressed by at least one of the +/// suppression specifications associated with a given front-end. +/// +/// The function looks for each suppression specification provided to +/// a given libabigail front-end and analyzes them to see if they +/// match a given ELF symbol. +/// +/// @param fe the front-end to consider. +/// +/// @param symbol the ELF symbol to consider. +/// +/// @return true iff the symbol @p symbol is matched by at least a +/// suppression specification associated with the front-end @p fe. +bool +is_elf_symbol_suppressed(const fe_iface& fe, + const elf_symbol_sptr& symbol) +{ + if (elf_symbol_is_function(symbol->get_type())) + return is_function_suppressed(fe, /*fn_name=*/"", + /*symbol_name=*/symbol->get_name()); + else if (elf_symbol_is_variable(symbol->get_type())) + return is_variable_suppressed(fe, /*var_name=*/"", + /*symbol_name=*/symbol->get_name()); + return false; +} + +/// Test if an ELF symbol is suppressed by at least one of the +/// suppression specifications associated with a given front-end. +/// +/// The function looks for each suppression specification provided to +/// a given libabigail front-end and analyzes them to see if they +/// match a given ELF symbol, designated by its name and kind. +/// +/// @param fe the front-end to consider. +/// +/// @param sym_name the name of the symbol to consider. +/// +/// @return true iff the symbol denoted by @p sym_name, of kind @p +/// sym_type, is matched by at least a suppression specification +/// associated with the front-end @p fe. +bool +is_elf_symbol_suppressed(const fe_iface& fe, + const string& sym_name, + elf_symbol::type sym_type) +{ + if (elf_symbol_is_function(sym_type)) + return is_function_suppressed(fe, /*fn_name=*/"", + /*symbol_name=*/sym_name); + else if (elf_symbol_is_variable(sym_type)) + return is_variable_suppressed(fe, /*var_name=*/"", + /*symbol_name=*/sym_name); + return false; +} + +/// Test if a function is matched by at least one suppression +/// specification associated with a given front-end. +/// +/// The function is designated by its name and its linkage_name. +/// +/// @param fe the front-end to consider. +/// +/// @param fn_name the name of the function to consider. +/// +/// @param fn_linkage_name the linkage name of the function to +/// consider. +/// +/// @param require_drop_property if true, this function requires the +/// suppression specification to contain the "drop" property to match +/// the function. +/// +/// @return true iff the function is matched by at least one +/// suppression specification coming from the front-end. +bool +is_function_suppressed(const fe_iface& fe, + const string& fn_name, + const string& fn_linkage_name, + bool require_drop_property) +{ + for (auto i : fe.suppressions()) + if (suppr::function_suppression_sptr suppr = is_function_suppression(i)) + { + if (require_drop_property && !i->get_drops_artifact_from_ir()) + continue; + if (!fn_name.empty() + && suppression_matches_function_name(fe, *suppr, fn_name)) + return true; + if (!fn_linkage_name.empty() + && suppression_matches_function_sym_name(fe, *suppr, + fn_linkage_name)) + return true; + } + return false; +} + +/// Test if a variable is matched by at least one suppression +/// specification associated with a given front-end. +/// +/// The variable is designated by its name and its linkage_name. +/// +/// @param fe the front-end to consider. +/// +/// @param var_name the name of the variable to consider. +/// +/// @param var_linkage_name the linkage name of the variable to +/// consider. +/// +/// @param require_drop_property if true, this variable requires the +/// suppression specification to contain the "drop" property to match +/// the function. +/// +/// @return true iff the variable is matched by at least one +/// suppression specification coming from the front-end. +bool +is_variable_suppressed(const fe_iface& fe, + const string& var_name, + const string& var_linkage_name, + bool require_drop_property) +{ + for (auto i : fe.suppressions()) + if (suppr::variable_suppression_sptr suppr = is_variable_suppression(i)) + { + if (require_drop_property && !i->get_drops_artifact_from_ir()) + continue; + if (!var_name.empty() + && suppression_matches_variable_name(fe, *suppr, var_name)) + return true; + if (!var_linkage_name.empty() + && suppression_matches_variable_sym_name(fe, *suppr, + var_linkage_name)) + return true; + } + return false; +} + +/// Test if a type is matched by at least one suppression +/// specification associated with a given front-end. +/// +/// The type is designated by its name and its source location. +/// +/// @param fe the front-end to consider. +/// +/// @param type_name the name of the type to consider. +/// +/// @param type_location the source location of the type. +/// +/// @param type_is_private output parameter. This is set to true if +/// the type was matched by one suppression specification, and if the +/// suppression was for private types. +/// +/// @param require_drop_property if true, this type requires the +/// suppression specification to contain the "drop" property to match +/// the type. +/// +/// @return true iff the type is matched by at least one suppression +/// specification coming from the front-end. +bool +is_type_suppressed(const fe_iface& fe, + const string& type_name, + const location& type_location, + bool& type_is_private, + bool require_drop_property) +{ + for (auto i : fe.suppressions()) + if (suppr::type_suppression_sptr suppr = is_type_suppression(i)) + { + if (require_drop_property && !i->get_drops_artifact_from_ir()) + continue; + if (suppression_matches_type_name_or_location(fe, *suppr, + type_name, + type_location)) + { + if (is_private_type_suppr_spec(*suppr)) + type_is_private = true; + + return true; + } + } + + type_is_private = false; + return false; +} + }// end namespace suppr } // end namespace abigail diff --git a/src/abg-symtab-reader.cc b/src/abg-symtab-reader.cc index 606c96a2..219ab6c6 100644 --- a/src/abg-symtab-reader.cc +++ b/src/abg-symtab-reader.cc @@ -139,11 +139,10 @@ static struct /// not completed symtab_ptr symtab::load(Elf* elf_handle, - ir::environment* env, + const ir::environment& env, symbol_predicate is_suppressed) { ABG_ASSERT(elf_handle); - ABG_ASSERT(env); symtab_ptr result(new symtab); if (!result->load_(elf_handle, env, is_suppressed)) @@ -201,7 +200,7 @@ symtab::symtab() /// @return true if the load succeeded bool symtab::load_(Elf* elf_handle, - ir::environment* env, + const ir::environment& env, symbol_predicate is_suppressed) { GElf_Ehdr ehdr_mem; diff --git a/src/abg-symtab-reader.h b/src/abg-symtab-reader.h index 384d757f..4d90c302 100644 --- a/src/abg-symtab-reader.h +++ b/src/abg-symtab-reader.h @@ -243,7 +243,7 @@ public: static symtab_ptr load(Elf* elf_handle, - ir::environment* env, + const ir::environment& env, symbol_predicate is_suppressed = NULL); static symtab_ptr @@ -283,7 +283,9 @@ private: addr_symbol_map_type entry_addr_symbol_map_; bool - load_(Elf* elf_handle, ir::environment* env, symbol_predicate is_suppressed); + load_(Elf* elf_handle, + const ir::environment& env, + symbol_predicate is_suppressed); bool load_(string_elf_symbols_map_sptr function_symbol_map, diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc index fe9ebc72..08b581be 100644 --- a/src/abg-tools-utils.cc +++ b/src/abg-tools-utils.cc @@ -405,6 +405,56 @@ is_regular_file(const string& path) return false; } +/// Test if an ELF file has DWARF debug info. +/// +/// This function supports split debug info files as well. +/// +/// @param elf_file_path the path to the ELF file to consider. +/// +/// @param debug_info_root a vector of pointer to directory to look +/// for debug info, in case the file is associated to split debug +/// info. If there is no split debug info then this vector can be +/// empty. Note that convert_char_stars_to_char_star_stars() can be +/// used to ease the construction of this vector. +/// +/// @return true iff the ELF file at @elf_file_path is an ELF file +/// that contains debug info. +bool +file_has_dwarf_debug_info(const string& elf_file_path, + const vector& debug_info_root_paths) +{ + if (guess_file_type(elf_file_path) != FILE_TYPE_ELF) + return false; + + environment env; + elf_reader::reader r(elf_file_path, + debug_info_root_paths, + env); + + if (r.dwarf_debug_info()) + return true; + + return false; +} + +bool +file_has_ctf_debug_info(const string& elf_file_path, + const vector& debug_info_root_paths) +{ + if (guess_file_type(elf_file_path) != FILE_TYPE_ELF) + return false; + + environment env; + elf_reader::reader r(elf_file_path, + debug_info_root_paths, + env); + + if (r.find_ctf_section()) + return true; + + return false; +} + /// Tests if a given path is a directory or a symbolic link to a /// directory. /// @@ -2211,7 +2261,7 @@ find_file_under_dir(const string& root_dir, /// /// @param opts the options to consider. static void -load_generate_apply_suppressions(dwarf_reader::read_context &read_ctxt, +load_generate_apply_suppressions(elf_based_reader &rdr, vector& suppr_paths, vector& kabi_whitelist_paths, suppressions_type& supprs) @@ -2229,7 +2279,7 @@ load_generate_apply_suppressions(dwarf_reader::read_context &read_ctxt, supprs.insert(supprs.end(), wl_suppr.begin(), wl_suppr.end()); } - abigail::dwarf_reader::add_read_context_suppressions(read_ctxt, supprs); + rdr.add_suppressions(supprs); } /// Test if an FTSENT pointer (resulting from fts_read) represents the @@ -2537,21 +2587,21 @@ maybe_load_vmlinux_dwarf_corpus(corpus::origin origin, suppressions_type& supprs, bool verbose, timer& t, - environment_sptr& env) + environment& env) { if (!(origin & corpus::DWARF_ORIGIN)) return; - abigail::elf_reader::status status = abigail::elf_reader::STATUS_OK; - dwarf_reader::read_context_sptr ctxt; - ctxt = - dwarf_reader::create_read_context(vmlinux, di_roots, env.get(), - /*read_all_types=*/false, - /*linux_kernel_mode=*/true); - dwarf_reader::set_do_log(*ctxt, verbose); + abigail::fe_iface::status status = abigail::fe_iface::STATUS_OK; + elf_based_reader_sptr rdr = + dwarf_reader::create_dwarf_reader(vmlinux, di_roots, env, + /*read_all_types=*/false, + /*linux_kernel_mode=*/true); + ABG_ASSERT(rdr); + rdr->options().do_log = verbose; t.start(); - load_generate_apply_suppressions(*ctxt, suppr_paths, + load_generate_apply_suppressions(*rdr, suppr_paths, kabi_wl_paths, supprs); t.stop(); @@ -2560,9 +2610,9 @@ maybe_load_vmlinux_dwarf_corpus(corpus::origin origin, << t << "\n"; - group.reset(new corpus_group(env.get(), root)); + group.reset(new corpus_group(env, root)); - set_read_context_corpus_group(*ctxt, group); + rdr->corpus_group(group); if (verbose) std::cerr << "reading kernel binary '" @@ -2570,7 +2620,7 @@ maybe_load_vmlinux_dwarf_corpus(corpus::origin origin, // Read the vmlinux corpus and add it to the group. t.start(); - read_and_add_corpus_to_group_from_elf(*ctxt, *group, status); + rdr->read_and_add_corpus_to_group(*group, status); t.stop(); if (verbose) @@ -2595,18 +2645,17 @@ maybe_load_vmlinux_dwarf_corpus(corpus::origin origin, << "/" << total_nb_modules << ") ... " << std::flush; - reset_read_context(ctxt, *m, di_roots, env.get(), - /*read_all_types=*/false, - /*linux_kernel_mode=*/true); + dwarf_reader::reset_dwarf_reader(*rdr, *m, di_roots, + /*read_all_types=*/false, + /*linux_kernel_mode=*/true); - load_generate_apply_suppressions(*ctxt, suppr_paths, + load_generate_apply_suppressions(*rdr, suppr_paths, kabi_wl_paths, supprs); - set_read_context_corpus_group(*ctxt, group); + rdr->corpus_group(group); t.start(); - read_and_add_corpus_to_group_from_elf(*ctxt, - *group, status); + rdr->read_and_add_corpus_to_group(*group, status); t.stop(); if (verbose) std::cerr << "module '" @@ -2652,16 +2701,18 @@ maybe_load_vmlinux_ctf_corpus(corpus::origin origin, vector& di_roots, bool verbose, timer& t, - environment_sptr& env) + environment& env) { if (!(origin & corpus::CTF_ORIGIN)) return; - abigail::elf_reader::status status = abigail::elf_reader::STATUS_OK; - ctf_reader::read_context_sptr ctxt; - ctxt = ctf_reader::create_read_context(vmlinux, di_roots, env.get()); - group.reset(new corpus_group(env.get(), root)); - set_read_context_corpus_group(*ctxt, group); + abigail::fe_iface::status status = abigail::fe_iface::STATUS_OK; + elf_based_reader_sptr rdr = + ctf_reader::create_ctf_reader(vmlinux, di_roots, env); + ABG_ASSERT(rdr); + + group.reset(new corpus_group(env, root)); + rdr->corpus_group(group); if (verbose) std::cerr << "reading kernel binary '" @@ -2669,7 +2720,7 @@ maybe_load_vmlinux_ctf_corpus(corpus::origin origin, // Read the vmlinux corpus and add it to the group. t.start(); - read_and_add_corpus_to_group_from_elf(ctxt.get(), *group, status); + rdr->read_and_add_corpus_to_group(*group, status); t.stop(); if (verbose) @@ -2694,12 +2745,11 @@ maybe_load_vmlinux_ctf_corpus(corpus::origin origin, << "/" << total_nb_modules << ") ... " << std::flush; - reset_read_context(ctxt, *m, di_roots, env.get()); - set_read_context_corpus_group(*ctxt, group); + ctf_reader::reset_reader(*rdr, *m, di_roots); + rdr->corpus_group(group); t.start(); - read_and_add_corpus_to_group_from_elf(ctxt.get(), - *group, status); + rdr->read_and_add_corpus_to_group(*group, status); t.stop(); if (verbose) std::cerr << "module '" @@ -2757,7 +2807,7 @@ build_corpus_group_from_kernel_dist_under(const string& root, vector& kabi_wl_paths, suppressions_type& supprs, bool verbose, - environment_sptr& env, + environment& env, corpus::origin origin) { string vmlinux = vmlinux_path; @@ -2800,6 +2850,53 @@ build_corpus_group_from_kernel_dist_under(const string& root, return group; } +/// Create the best elf based reader (or front-end), given an ELF file. +/// +/// This function looks into the ELF file. If it contains DWARF debug +/// info, then a DWARF Reader front-end is created and returned. +/// Otherwise, if it contains CTF debug info, then a CTF Reader +/// front-end is created and returned. +/// +/// Otherwise, if the file contains no debug info or if the king of +/// debug info is not yet recognized, a DWARF Reader front-end is +/// created and returned. +/// +/// @param elf_file_path a path to the ELF file to consider +/// +/// @param debug_info_root_paths a vector of the paths where to look +/// for debug info, if applicable. +/// +/// @param env the environment to use for the front-end. +/// +/// @return the ELF based Reader that is better adapted for the binary +/// designated by @p elf_file_path. +elf_based_reader_sptr +create_best_elf_based_reader(const string& elf_file_path, + const vector& debug_info_root_paths, + environment& env) +{ + elf_based_reader_sptr result; + if (guess_file_type(elf_file_path) != FILE_TYPE_ELF) + return result; + + if (file_has_dwarf_debug_info(elf_file_path, debug_info_root_paths)) + result = dwarf_reader::create_dwarf_reader(elf_file_path, + debug_info_root_paths, + env); +#ifdef WITH_CTF + else if (file_has_ctf_debug_info(elf_file_path, debug_info_root_paths)) + result = ctf_reader::create_ctf_reader(elf_file_path, + debug_info_root_paths, + env); +#endif + else + result = dwarf_reader::create_dwarf_reader(elf_file_path, + debug_info_root_paths, + env); + + return result; +} + }//end namespace tools_utils using abigail::ir::function_decl; diff --git a/src/abg-writer.cc b/src/abg-writer.cc index dff8813a..1cffd77b 100644 --- a/src/abg-writer.cc +++ b/src/abg-writer.cc @@ -65,7 +65,7 @@ namespace xml_writer class id_manager { - const environment* m_env; + const environment& m_env; mutable unsigned long long m_cur_id; unsigned long long @@ -73,11 +73,11 @@ class id_manager { return ++m_cur_id; } public: - id_manager(const environment* env) + id_manager(const environment& env) : m_env(env), m_cur_id(0) {} - const environment* + const environment& get_environment() const {return m_env;} @@ -87,9 +87,8 @@ public: { ostringstream o; o << get_new_id(); - const environment* env = get_environment(); - ABG_ASSERT(env); - return env->intern(o.str()); + const environment& env = get_environment(); + return env.intern(o.str()); } /// Return a unique string representing a numerical ID, prefixed by @@ -101,9 +100,8 @@ public: { ostringstream o; o << prefix << get_new_id(); - const environment* env = get_environment(); - ABG_ASSERT(env); - return env->intern(o.str()); + const environment& env = get_environment(); + return env.intern(o.str()); } }; @@ -207,7 +205,7 @@ typedef unordered_map, class write_context { - const environment* m_env; + const environment& m_env; id_manager m_id_manager; ostream* m_ostream; bool m_annotate; @@ -243,7 +241,7 @@ public: /// @param env the enviroment we are operating from. /// /// @param os the output stream to write to. - write_context(const environment* env, ostream& os) + write_context(const environment& env, ostream& os) : m_env(env), m_id_manager(env), m_ostream(&os), @@ -262,16 +260,13 @@ public: /// Getter of the environment we are operating from. /// /// @return the environment we are operating from. - const environment* + const environment& get_environment() const {return m_env;} const config& get_config() const - { - ABG_ASSERT(get_environment()); - return get_environment()->get_config(); - } + {return get_environment().get_config();} /// Getter for the current ostream /// @@ -498,7 +493,7 @@ public: ++hash; std::ostringstream os; os << std::hex << std::setfill('0') << std::setw(8) << hash; - return m_type_id_map[c] = c->get_environment()->intern(os.str()); + return m_type_id_map[c] = c->get_environment().intern(os.str()); } } ABG_ASSERT_NOT_REACHED; @@ -808,7 +803,7 @@ public: { ABG_ASSERT(!is_type(decl)); string repr = get_pretty_representation(decl, true); - interned_string irepr = decl->get_environment()->intern(repr); + interned_string irepr = decl->get_environment().intern(repr); return m_emitted_decls_set.find(irepr) != m_emitted_decls_set.end(); } @@ -819,7 +814,7 @@ public: record_decl_as_emitted(const decl_base_sptr& decl) { string repr = get_pretty_representation(decl, true); - interned_string irepr = decl->get_environment()->intern(repr); + interned_string irepr = decl->get_environment().intern(repr); m_emitted_decls_set.insert(irepr); } @@ -2064,7 +2059,7 @@ write_decl_in_scope(const decl_base_sptr& decl, /// /// @return the new @ref write_context object. write_context_sptr -create_write_context(const environment *env, +create_write_context(const environment& env, ostream& default_output_stream) { write_context_sptr ctxt(new write_context(env, default_output_stream)); @@ -3691,7 +3686,7 @@ write_class_decl(const class_decl_sptr& d, { type_base_wptrs_type result; canonical_type_sptr_set_type member_types; - const environment* env = ctxt.get_environment(); + const environment& env = ctxt.get_environment(); // We are looking at a decl-only class. All decl-only classes // of a given name are equal. But then the problem is that a @@ -3708,7 +3703,7 @@ write_class_decl(const class_decl_sptr& d, // // So let's gather all the member-types of all the decl-only // classes of the fully-qualified name and emit them here. - if (lookup_decl_only_class_types(env->intern(decl->get_qualified_name()), + if (lookup_decl_only_class_types(env.intern(decl->get_qualified_name()), *decl->get_corpus(), result)) { diff --git a/tests/data/test-read-ctf/test0.abi b/tests/data/test-read-ctf/test0.abi index 7a250218..2129de41 100644 --- a/tests/data/test-read-ctf/test0.abi +++ b/tests/data/test-read-ctf/test0.abi @@ -1,4 +1,7 @@ + + + diff --git a/tests/data/test-read-ctf/test0.hash.abi b/tests/data/test-read-ctf/test0.hash.abi index 09e76da1..e98c97db 100644 --- a/tests/data/test-read-ctf/test0.hash.abi +++ b/tests/data/test-read-ctf/test0.hash.abi @@ -1,4 +1,7 @@ + + + diff --git a/tests/data/test-read-ctf/test1.so.abi b/tests/data/test-read-ctf/test1.so.abi index 40a434ba..4d0895a3 100644 --- a/tests/data/test-read-ctf/test1.so.abi +++ b/tests/data/test-read-ctf/test1.so.abi @@ -1,4 +1,7 @@ + + + diff --git a/tests/data/test-read-ctf/test1.so.hash.abi b/tests/data/test-read-ctf/test1.so.hash.abi index cbdd0dc9..89bbb528 100644 --- a/tests/data/test-read-ctf/test1.so.hash.abi +++ b/tests/data/test-read-ctf/test1.so.hash.abi @@ -1,4 +1,7 @@ + + + diff --git a/tests/data/test-read-ctf/test2.so.abi b/tests/data/test-read-ctf/test2.so.abi index 67f802f9..53001972 100644 --- a/tests/data/test-read-ctf/test2.so.abi +++ b/tests/data/test-read-ctf/test2.so.abi @@ -1,4 +1,7 @@ + + + diff --git a/tests/data/test-read-ctf/test2.so.hash.abi b/tests/data/test-read-ctf/test2.so.hash.abi index 6bbf347e..84fcaa96 100644 --- a/tests/data/test-read-ctf/test2.so.hash.abi +++ b/tests/data/test-read-ctf/test2.so.hash.abi @@ -1,4 +1,7 @@ + + + diff --git a/tests/data/test-read-ctf/test3.so.abi b/tests/data/test-read-ctf/test3.so.abi index 3d2f6326..25fe7685 100644 --- a/tests/data/test-read-ctf/test3.so.abi +++ b/tests/data/test-read-ctf/test3.so.abi @@ -1,4 +1,7 @@ - + + + + diff --git a/tests/data/test-read-ctf/test3.so.hash.abi b/tests/data/test-read-ctf/test3.so.hash.abi index 1c69e2e1..07dd9601 100644 --- a/tests/data/test-read-ctf/test3.so.hash.abi +++ b/tests/data/test-read-ctf/test3.so.hash.abi @@ -1,4 +1,7 @@ - + + + + diff --git a/tests/data/test-read-ctf/test4.so.abi b/tests/data/test-read-ctf/test4.so.abi index dc18e191..21241d30 100644 --- a/tests/data/test-read-ctf/test4.so.abi +++ b/tests/data/test-read-ctf/test4.so.abi @@ -1,4 +1,7 @@ + + + diff --git a/tests/data/test-read-ctf/test4.so.hash.abi b/tests/data/test-read-ctf/test4.so.hash.abi index dc428592..40ab7069 100644 --- a/tests/data/test-read-ctf/test4.so.hash.abi +++ b/tests/data/test-read-ctf/test4.so.hash.abi @@ -1,4 +1,7 @@ + + + diff --git a/tests/print-diff-tree.cc b/tests/print-diff-tree.cc index c0c7195a..a06b1d51 100644 --- a/tests/print-diff-tree.cc +++ b/tests/print-diff-tree.cc @@ -101,24 +101,24 @@ main(int argc, char* argv[]) if (!opts.elf1.empty() && !opts.elf2.empty()) { - elf_reader::status c1_status, c2_status; + fe_iface::status c1_status, c2_status; corpus_sptr c1, c2; - environment_sptr env(new environment); + environment env; vector di_roots; - c1 = dwarf_reader::read_corpus_from_elf(opts.elf1, di_roots, env.get(), + c1 = dwarf_reader::read_corpus_from_elf(opts.elf1, di_roots, env, /*load_all_types=*/false, c1_status); - if (c1_status != elf_reader::STATUS_OK) + if (c1_status != fe_iface::STATUS_OK) { cerr << "Failed to read elf file " << opts.elf1 << "\n"; return 1; } - c2 = dwarf_reader::read_corpus_from_elf(opts.elf2, di_roots, env.get(), + c2 = dwarf_reader::read_corpus_from_elf(opts.elf2, di_roots, env, /*load_all_types=*/false, c2_status); - if (c2_status != elf_reader::STATUS_OK) + if (c2_status != fe_iface::STATUS_OK) { cerr << "Failed to read elf file " << opts.elf2 << "\n"; return 1; diff --git a/tests/test-abidiff.cc b/tests/test-abidiff.cc index 951b6d25..c703284a 100644 --- a/tests/test-abidiff.cc +++ b/tests/test-abidiff.cc @@ -171,9 +171,9 @@ using abigail::corpus_sptr; using abigail::corpus_group_sptr; using abigail::translation_unit; using abigail::translation_unit_sptr; -using abigail::xml_reader::read_translation_unit_from_file; -using abigail::xml_reader::read_corpus_from_native_xml_file; -using abigail::xml_reader::read_corpus_group_from_native_xml_file; +using abigail::abixml_reader::read_translation_unit_from_file; +using abigail::abixml_reader::read_corpus_from_abixml_file; +using abigail::abixml_reader::read_corpus_group_from_abixml_file; using abigail::comparison::corpus_diff_sptr; using abigail::comparison::translation_unit_diff_sptr; using abigail::comparison::compute_diff; @@ -211,18 +211,18 @@ main(int, char*[]) continue; } - environment_sptr env(new environment); + environment env; translation_unit_sptr tu1, tu2; corpus_sptr corpus1, corpus2; corpus_group_sptr corpus_group1, corpus_group2; 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, env.get()); + tu1 = read_translation_unit_from_file(first_in_path, env); else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS) - corpus1 = read_corpus_from_native_xml_file(first_in_path, env.get()); + corpus1 = read_corpus_from_abixml_file(first_in_path, env); else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS_GROUP) - corpus_group1 = read_corpus_group_from_native_xml_file(first_in_path, - env.get()); + corpus_group1 = read_corpus_group_from_abixml_file(first_in_path, + env); else abort(); if (!tu1 && !corpus1 && !corpus_group1) @@ -234,12 +234,12 @@ 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, env.get()); + tu2 = read_translation_unit_from_file(second_in_path, env); else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS) - corpus2 = read_corpus_from_native_xml_file(second_in_path, env.get()); + corpus2 = read_corpus_from_abixml_file(second_in_path, env); else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS_GROUP) - corpus_group2 = read_corpus_group_from_native_xml_file(first_in_path, - env.get()); + corpus_group2 = read_corpus_group_from_abixml_file(first_in_path, + env); else abort(); if (!tu2 && !corpus2 && !corpus_group2) diff --git a/tests/test-diff-dwarf.cc b/tests/test-diff-dwarf.cc index 42e25dfa..0e00a3ce 100644 --- a/tests/test-diff-dwarf.cc +++ b/tests/test-diff-dwarf.cc @@ -380,24 +380,18 @@ main() continue; } - abigail::elf_reader::status status = - abigail::elf_reader::STATUS_UNKNOWN; + abigail::fe_iface::status status = + abigail::fe_iface::STATUS_UNKNOWN; - environment_sptr env(new environment); + environment env; std::vector di_roots; abigail::corpus_sptr corp0 = - read_corpus_from_elf(in_elfv0_path, - /*debug_info_root_path=*/di_roots, - env.get(), - /*load_all_types=*/false, - status); + read_corpus_from_elf(in_elfv0_path, /*debug_info_root_path=*/di_roots, + env, /*load_all_types=*/false, status); abigail::corpus_sptr corp1 = - read_corpus_from_elf(in_elfv1_path, - /*debug_info_root_path=*/di_roots, - env.get(), - /*load_all_types=*/false, - status); + read_corpus_from_elf(in_elfv1_path, /*debug_info_root_path=*/di_roots, + env, /*load_all_types=*/false, status); if (!corp0) { diff --git a/tests/test-ir-walker.cc b/tests/test-ir-walker.cc index b6042d20..c76d04a6 100644 --- a/tests/test-ir-walker.cc +++ b/tests/test-ir-walker.cc @@ -155,12 +155,11 @@ main(int argc, char **argv) string file_name = argv[1]; - abigail::ir::environment_sptr env(new abigail::ir::environment); + abigail::ir::environment env; abigail::corpus_sptr c; - abigail::elf_reader::status status = abigail::elf_reader::STATUS_OK; + abigail::fe_iface::status status = abigail::fe_iface::STATUS_OK; std::vector di_roots; - if (!(c = abigail::dwarf_reader::read_corpus_from_elf(file_name, di_roots, - env.get(), + if (!(c = abigail::dwarf_reader::read_corpus_from_elf(file_name, di_roots, env, /*load_all_type=*/false, status))) { diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc index b0ef7de6..3a7db586 100644 --- a/tests/test-read-ctf.cc +++ b/tests/test-read-ctf.cc @@ -29,8 +29,7 @@ using abigail::tests::read_common::test_task; using abigail::tests::read_common::display_usage; using abigail::tests::read_common::options; -using abigail::ctf_reader::read_context_sptr; -using abigail::ctf_reader::create_read_context; +using abigail::ctf_reader::create_ctf_reader; using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE; using abigail::xml_writer::HASH_TYPE_ID_STYLE; using abigail::tools_utils::emit_prefix; @@ -348,23 +347,22 @@ test_task_ctf::test_task_ctf(const InOutSpec &s, void test_task_ctf::perform() { - abigail::ir::environment_sptr env; + abigail::ir::environment env; set_in_elf_path(); set_in_suppr_spec_path(); - env.reset(new abigail::ir::environment); - abigail::elf_reader::status status = - abigail::elf_reader::STATUS_UNKNOWN; + abigail::fe_iface::status status = + abigail::fe_iface::STATUS_UNKNOWN; vector di_roots; ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path)); - read_context_sptr ctxt = create_read_context(in_elf_path, - di_roots, - env.get()); - ABG_ASSERT(ctxt); + abigail::elf_based_reader_sptr rdr = create_ctf_reader(in_elf_path, + di_roots, env); + ABG_ASSERT(rdr); + + corpus_sptr corp = rdr->read_corpus(status); - corpus_sptr corp = read_corpus(ctxt.get(), status); // if there is no output and no input, assume that we do not care about the // actual read result, just that it succeeded. if (!spec.in_abi_path && !spec.out_abi_path) diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc index 0227c89b..22292029 100644 --- a/tests/test-read-dwarf.cc +++ b/tests/test-read-dwarf.cc @@ -29,9 +29,6 @@ using abigail::tests::read_common::options; using abigail::tests::get_build_dir; using abigail::dwarf_reader::read_corpus_from_elf; -using abigail::dwarf_reader::read_context; -using abigail::dwarf_reader::read_context_sptr; -using abigail::dwarf_reader::create_read_context; using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE; using abigail::xml_writer::HASH_TYPE_ID_STYLE; using abigail::xml_writer::type_id_style_kind; diff --git a/tests/test-read-write.cc b/tests/test-read-write.cc index 7e8e3ecc..52ebc294 100644 --- a/tests/test-read-write.cc +++ b/tests/test-read-write.cc @@ -36,9 +36,6 @@ 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; -using abigail::xml_reader::read_corpus_from_native_xml_file; -using abigail::xml_writer::write_translation_unit; using abigail::workers::queue; using abigail::workers::task; diff --git a/tests/test-symtab.cc b/tests/test-symtab.cc index efef9a99..68c30692 100644 --- a/tests/test-symtab.cc +++ b/tests/test-symtab.cc @@ -24,9 +24,7 @@ using namespace abigail; -using dwarf_reader::create_read_context; -using dwarf_reader::read_context_sptr; -using dwarf_reader::read_corpus_from_elf; +using dwarf_reader::create_dwarf_reader; using ir::environment; using ir::environment_sptr; using suppr::suppressions_type; @@ -34,7 +32,7 @@ using suppr::suppressions_type; static const std::string test_data_dir = std::string(abigail::tests::get_src_dir()) + "/tests/data/test-symtab/"; -elf_reader::status +fe_iface::status read_corpus(const std::string& path, corpus_sptr& result, const std::vector& whitelist_paths = @@ -42,12 +40,12 @@ read_corpus(const std::string& path, { const std::string& absolute_path = test_data_dir + path; - environment_sptr env(new environment); + environment env; const std::vector debug_info_root_paths; - read_context_sptr ctxt = - create_read_context(absolute_path, debug_info_root_paths, env.get(), - /* load_all_type = */ true, - /* linux_kernel_mode = */ true); + abigail::elf_based_reader_sptr rdr = + create_dwarf_reader(absolute_path, debug_info_root_paths, + env, /* load_all_type = */ true, + /* linux_kernel_mode = */ true); if (!whitelist_paths.empty()) { @@ -55,13 +53,13 @@ read_corpus(const std::string& path, tools_utils::gen_suppr_spec_from_kernel_abi_whitelists( whitelist_paths); REQUIRE_FALSE(wl_suppr.empty()); - dwarf_reader::add_read_context_suppressions(*ctxt, wl_suppr); + rdr->add_suppressions(wl_suppr); } - elf_reader::status status = elf_reader::STATUS_UNKNOWN; - result = read_corpus_from_elf(*ctxt, status); + fe_iface::status status = fe_iface::STATUS_UNKNOWN; + result = rdr->read_corpus(status); - REQUIRE(status != elf_reader::STATUS_UNKNOWN); + REQUIRE(status != fe_iface::STATUS_UNKNOWN); return status; } @@ -69,22 +67,22 @@ TEST_CASE("Symtab::Empty", "[symtab, basic]") { const std::string binary = "basic/empty.so"; corpus_sptr corpus_ptr; - const elf_reader::status status = read_corpus(binary, corpus_ptr); + const fe_iface::status status = read_corpus(binary, corpus_ptr); REQUIRE(!corpus_ptr); - REQUIRE((status & elf_reader::STATUS_NO_SYMBOLS_FOUND)); + REQUIRE((status & fe_iface::STATUS_NO_SYMBOLS_FOUND)); } TEST_CASE("Symtab::NoDebugInfo", "[symtab, basic]") { const std::string binary = "basic/no_debug_info.so"; corpus_sptr corpus_ptr; - const elf_reader::status status = read_corpus(binary, corpus_ptr); + const fe_iface::status status = read_corpus(binary, corpus_ptr); REQUIRE(corpus_ptr); REQUIRE(status - == (elf_reader::STATUS_OK - | elf_reader::STATUS_DEBUG_INFO_NOT_FOUND)); + == (fe_iface::STATUS_OK + | fe_iface::STATUS_DEBUG_INFO_NOT_FOUND)); } // this value indicates in the following helper method, that we do not want to @@ -102,11 +100,11 @@ assert_symbol_count(const std::string& path, std::vector()) { corpus_sptr corpus_ptr; - const elf_reader::status status = + const fe_iface::status status = read_corpus(path, corpus_ptr, whitelist_paths); REQUIRE(corpus_ptr); - REQUIRE((status & elf_reader::STATUS_OK)); + REQUIRE((status & fe_iface::STATUS_OK)); const corpus& corpus = *corpus_ptr; size_t total_symbols = 0; @@ -244,10 +242,10 @@ TEST_CASE("Symtab::SymtabWithWhitelist", "[symtab, whitelist]") + "basic/one_function_one_variable_irrelevant.whitelist"); corpus_sptr corpus_ptr; - const elf_reader::status status = + const fe_iface::status status = read_corpus(binary, corpus_ptr, whitelists); REQUIRE(!corpus_ptr); - REQUIRE((status & elf_reader::STATUS_NO_SYMBOLS_FOUND)); + REQUIRE((status & fe_iface::STATUS_NO_SYMBOLS_FOUND)); } GIVEN("we read the binary with only the function whitelisted") diff --git a/tools/Makefile.am b/tools/Makefile.am index f7592b60..abd09022 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -10,41 +10,36 @@ else endif noinst_PROGRAMS = abisym abinilint +LDADD = $(abs_top_builddir)/src/libabigail.la abidiff_SOURCES = abidiff.cc abidiffdir = $(bindir) -abidiff_LDADD = ../src/libabigail.la abilint_SOURCES = abilint.cc abilintdir = $(bindir) -abilint_LDADD = ../src/libabigail.la abidw_SOURCES = abidw.cc abidwdir = $(bindir) -abidw_LDADD = ../src/libabigail.la abisym_SOURCES = abisym.cc abisymdir = $(bindir) -abisym_LDADD = ../src/libabigail.la abinilint_SOURCES = binilint.cc abinilintdir = $(bindir) -abinilint_LDADD = $(abs_top_builddir)/src/libabigail.la abicompat_SOURCES = abicompat.cc abicompatdir = $(bindir) -abicompat_LDADD = $(abs_top_builddir)/src/libabigail.la abipkgdiff_SOURCES = abipkgdiff.cc abipkgdiffdir = $(bindir) abipkgdiff_CPPFLAGS = $(FTS_CFLAGS) -abipkgdiff_LDADD = $(abs_top_builddir)/src/libabigail.la $(FTS_LIBS) -abipkgdiff_LDFLAGS = -pthread +abipkgdiff_LDADD = $(FTS_LIBS) +abipkgdiff_LDFLAGS = $(abs_top_builddir)/src/libabigail.la -pthread kmidiff_SOURCES = kmidiff.cc kmidiffdir = $(bindir) kmidiff_LDADD = $(abs_top_builddir)/src/libabigail.la -kmidiff_LDFLAGS = -pthread +kmidiff_LDFLAGS = $(abs_top_builddir)/src/libabigail.la -pthread AM_CXXFLAGS = \ $(VISIBILITY_FLAGS) -I$(abs_top_srcdir)/include \ diff --git a/tools/abicompat.cc b/tools/abicompat.cc index 0be49a86..b015a7f7 100644 --- a/tools/abicompat.cc +++ b/tools/abicompat.cc @@ -274,9 +274,6 @@ using abigail::ir::type_base_sptr; using abigail::ir::function_type_sptr; using abigail::ir::function_decl; using abigail::ir::var_decl; -using abigail::elf_reader::status; -using abigail::elf_reader::STATUS_ALT_DEBUG_INFO_NOT_FOUND; -using abigail::elf_reader::STATUS_DEBUG_INFO_NOT_FOUND; using abigail::dwarf_reader::read_corpus_from_elf; using abigail::comparison::diff_context_sptr; using abigail::comparison::diff_context; @@ -646,7 +643,7 @@ perform_compat_check_in_weak_mode(options& opts, /// /// @param opts the options passed from the user to the program. /// -/// @param status the resulting elf_reader::status to send back to the +/// @param status the resulting fe_iface::status to send back to the /// caller. /// /// @param di_roots the directories from where to look for debug info. @@ -655,14 +652,16 @@ perform_compat_check_in_weak_mode(options& opts, /// /// @param path the path to the ABI corpus to read from. static corpus_sptr -read_corpus(options opts, status &status, - const vector di_roots, - const environment_sptr &env, - const string &path) +read_corpus(options opts, + abigail::fe_iface::status& status, + const vector di_roots, + environment &env, + const string &path) { corpus_sptr retval = NULL; abigail::tools_utils::file_type type = abigail::tools_utils::guess_file_type(path); + abigail::fe_iface_sptr rdr; switch (type) { @@ -675,26 +674,23 @@ read_corpus(options opts, status &status, #ifdef WITH_CTF if (opts.use_ctf) { - abigail::ctf_reader::read_context_sptr r_ctxt - = abigail::ctf_reader::create_read_context(path, - env.get()); - ABG_ASSERT(r_ctxt); + rdr = abigail::ctf_reader::create_reader(path, env); + ABG_ASSERT(rdr); - retval = abigail::ctf_reader::read_corpus(r_ctxt.get(), status); + retval = abigail::ctf_reader::read_corpus(rdr.get(), status); } else #endif - retval = read_corpus_from_elf(path, di_roots, env.get(), + retval = read_corpus_from_elf(path, di_roots, env, /*load_all_types=*/opts.weak_mode, status); } break; case abigail::tools_utils::FILE_TYPE_XML_CORPUS: { - abigail::xml_reader::read_context_sptr r_ctxt = - abigail::xml_reader::create_native_xml_read_context(path, env.get()); - assert(r_ctxt); - retval = abigail::xml_reader::read_corpus_from_input(*r_ctxt); + rdr = abigail::abixml_reader::create_abixml_reader(path, env); + assert(rdr); + retval = rdr->read_corpus(status); } break; case abigail::tools_utils::FILE_TYPE_AR: @@ -788,8 +784,8 @@ main(int argc, char* argv[]) char * app_di_root = opts.app_di_root_path.get(); vector app_di_roots; app_di_roots.push_back(&app_di_root); - status status = abigail::elf_reader::STATUS_UNKNOWN; - environment_sptr env(new environment); + abigail::fe_iface::status status = abigail::fe_iface::STATUS_UNKNOWN; + environment env; corpus_sptr app_corpus = read_corpus(opts, status, app_di_roots, env, @@ -801,20 +797,21 @@ main(int argc, char* argv[]) return abigail::tools_utils::ABIDIFF_ERROR; } - if (opts.fail_no_debug_info && (status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) - && (status & STATUS_DEBUG_INFO_NOT_FOUND)) + if (opts.fail_no_debug_info + && (status & abigail::fe_iface::STATUS_ALT_DEBUG_INFO_NOT_FOUND) + && (status & abigail::fe_iface::STATUS_DEBUG_INFO_NOT_FOUND)) { emit_prefix(argv[0], cerr) << opts.app_path << " does not have debug symbols\n"; return abigail::tools_utils::ABIDIFF_ERROR; } - if (status & abigail::elf_reader::STATUS_NO_SYMBOLS_FOUND) + if (status & abigail::fe_iface::STATUS_NO_SYMBOLS_FOUND) { emit_prefix(argv[0], cerr) << "could not read symbols from " << opts.app_path << "\n"; return abigail::tools_utils::ABIDIFF_ERROR; } - if (!(status & abigail::elf_reader::STATUS_OK)) + if (!(status & abigail::fe_iface::STATUS_OK)) { emit_prefix(argv[0], cerr) << "could not read file " << opts.app_path << "\n"; @@ -856,17 +853,18 @@ main(int argc, char* argv[]) << " is not a supported file\n"; return abigail::tools_utils::ABIDIFF_ERROR; } - if (opts.fail_no_debug_info && (status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) - && (status & STATUS_DEBUG_INFO_NOT_FOUND)) + if (opts.fail_no_debug_info + && (status & abigail::fe_iface::STATUS_ALT_DEBUG_INFO_NOT_FOUND) + && (status & abigail::fe_iface::STATUS_DEBUG_INFO_NOT_FOUND)) emit_prefix(argv[0], cerr) << "could not read debug info for " << opts.lib1_path << "\n"; - if (status & abigail::elf_reader::STATUS_NO_SYMBOLS_FOUND) + if (status & abigail::fe_iface::STATUS_NO_SYMBOLS_FOUND) { emit_prefix(argv[0], cerr) << "could not read symbols from " << opts.lib1_path << "\n"; return abigail::tools_utils::ABIDIFF_ERROR; } - if (!(status & abigail::elf_reader::STATUS_OK)) + if (!(status & abigail::fe_iface::STATUS_OK)) { emit_prefix(argv[0], cerr) << "could not read file " << opts.lib1_path << "\n"; @@ -891,20 +889,21 @@ main(int argc, char* argv[]) return abigail::tools_utils::ABIDIFF_ERROR; } - if (opts.fail_no_debug_info && (status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) - && (status & STATUS_DEBUG_INFO_NOT_FOUND)) + if (opts.fail_no_debug_info + && (status & abigail::fe_iface::STATUS_ALT_DEBUG_INFO_NOT_FOUND) + && (status & abigail::fe_iface::STATUS_DEBUG_INFO_NOT_FOUND)) { emit_prefix(argv[0], cerr) << "could not read debug info for " << opts.lib2_path << "\n"; return abigail::tools_utils::ABIDIFF_ERROR; } - if (status & abigail::elf_reader::STATUS_NO_SYMBOLS_FOUND) + if (status & abigail::fe_iface::STATUS_NO_SYMBOLS_FOUND) { emit_prefix(argv[0], cerr) << "could not read symbols from " << opts.lib2_path << "\n"; return abigail::tools_utils::ABIDIFF_ERROR; } - if (!(status & abigail::elf_reader::STATUS_OK)) + if (!(status & abigail::fe_iface::STATUS_OK)) { emit_prefix(argv[0], cerr) << "could not read file " << opts.lib2_path << "\n"; diff --git a/tools/abidiff.cc b/tools/abidiff.cc index 9b2ab784..b35d4587 100644 --- a/tools/abidiff.cc +++ b/tools/abidiff.cc @@ -809,13 +809,12 @@ set_diff_context_from_opts(diff_context_sptr ctxt, /// specifications to. Note that the type of this parameter is /// generic (class template) because in practise, it can be either an /// abigail::dwarf_reader::read_context type or an -/// abigail::xml_reader::read_context type. +/// abigail::abiabixml_reader::reader type. /// /// @param opts the options where to get the suppression /// specifications from. -template static void -set_suppressions(ReadContextType& read_ctxt, const options& opts) +set_suppressions(abigail::fe_iface& reader, const options& opts) { suppressions_type supprs; for (vector::const_iterator i = opts.suppression_paths.begin(); @@ -823,7 +822,7 @@ set_suppressions(ReadContextType& read_ctxt, const options& opts) ++i) read_suppressions(*i, supprs); - if (read_context_get_path(read_ctxt) == opts.file1 + if (reader.corpus_path() == opts.file1 && (!opts.headers_dirs1.empty() || !opts.header_files1.empty())) { // Generate suppression specification to avoid showing ABI @@ -843,7 +842,7 @@ set_suppressions(ReadContextType& read_ctxt, const options& opts) } } - if (read_context_get_path(read_ctxt) == opts.file2 + if (reader.corpus_path() == opts.file2 && (!opts.headers_dirs2.empty() || !opts.header_files2.empty())) { // Generate suppression specification to avoid showing ABI @@ -869,7 +868,7 @@ set_suppressions(ReadContextType& read_ctxt, const options& opts) supprs.insert(supprs.end(), wl_suppr.begin(), wl_suppr.end()); - add_read_context_suppressions(read_ctxt, supprs); + reader.add_suppressions(supprs); } /// Configure the abigail::xml_reacher::read_context based on the @@ -879,11 +878,11 @@ set_suppressions(ReadContextType& read_ctxt, const options& opts) /// /// @param opts the command-line options to configure @p ctxt from. static void -set_native_xml_reader_options(abigail::xml_reader::read_context& ctxt, +set_native_xml_reader_options(abigail::fe_iface& rdr, const options& opts) { - consider_types_not_reachable_from_public_interfaces(ctxt, - opts.show_all_types); + abigail::abixml_reader::consider_types_not_reachable_from_public_interfaces(rdr, + opts.show_all_types); } /// Set the regex patterns describing the functions to drop from the @@ -979,17 +978,17 @@ prepare_di_root_paths(options& o) /// @return abigail::tools_utils::ABIDIFF_ERROR if an error was /// detected, abigail::tools_utils::ABIDIFF_OK otherwise. static abigail::tools_utils::abidiff_status -handle_error(abigail::elf_reader::status status_code, - const abigail::dwarf_reader::read_context* ctxt, +handle_error(abigail::fe_iface::status status_code, + const abigail::elf_based_reader* rdr, const string& prog_name, const options& opts) { - if (!(status_code & abigail::elf_reader::STATUS_OK)) + if (!(status_code & abigail::fe_iface::STATUS_OK)) { emit_prefix(prog_name, cerr) << "failed to read input file " << opts.file1 << "\n"; - if (status_code & abigail::elf_reader::STATUS_DEBUG_INFO_NOT_FOUND) + if (status_code & abigail::fe_iface::STATUS_DEBUG_INFO_NOT_FOUND) { emit_prefix(prog_name, cerr) << "could not find the debug info\n"; @@ -1042,22 +1041,18 @@ handle_error(abigail::elf_reader::status status_code, } } - if (status_code & abigail::elf_reader::STATUS_ALT_DEBUG_INFO_NOT_FOUND) + if (status_code & abigail::fe_iface::STATUS_ALT_DEBUG_INFO_NOT_FOUND) { emit_prefix(prog_name, cerr) << "could not find the alternate debug info file"; - if (ctxt) - { - string alt_di_path; - abigail::dwarf_reader::refers_to_alt_debug_info(*ctxt, - alt_di_path); - if (!alt_di_path.empty()) - cerr << " at: " << alt_di_path; - } - cerr << "\n"; + + if (rdr->alternate_dwarf_debug_info()) + cerr << " at: " + << rdr->alternate_dwarf_debug_info_path() + << "\n"; } - if (status_code & abigail::elf_reader::STATUS_NO_SYMBOLS_FOUND) + if (status_code & abigail::fe_iface::STATUS_NO_SYMBOLS_FOUND) emit_prefix(prog_name, cerr) << "could not find the ELF symbols in the file '" << opts.file1 @@ -1153,22 +1148,22 @@ main(int argc, char* argv[]) t1_type = guess_file_type(opts.file1); t2_type = guess_file_type(opts.file2); - environment_sptr env(new environment); + environment env; if (opts.exported_interfaces_only.has_value()) - env->analyze_exported_interfaces_only(*opts.exported_interfaces_only); + env.analyze_exported_interfaces_only(*opts.exported_interfaces_only); #ifdef WITH_DEBUG_SELF_COMPARISON if (opts.do_debug_self_comparison) - env->self_comparison_debug_is_on(true); + env.self_comparison_debug_is_on(true); #endif #ifdef WITH_DEBUG_TYPE_CANONICALIZATION if (opts.do_debug_type_canonicalization) - env->debug_type_canonicalization_is_on(true); + env.debug_type_canonicalization_is_on(true); #endif translation_unit_sptr t1, t2; - abigail::elf_reader::status c1_status = - abigail::elf_reader::STATUS_OK, - c2_status = abigail::elf_reader::STATUS_OK; + abigail::fe_iface::status c1_status = + abigail::fe_iface::STATUS_OK, + c2_status = abigail::fe_iface::STATUS_OK; corpus_sptr c1, c2; corpus_group_sptr g1, g2; bool files_suppressed = false; @@ -1193,69 +1188,62 @@ 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, - env.get()); + t1 = abigail::abixml_reader::read_translation_unit_from_file(opts.file1, + env); break; case abigail::tools_utils::FILE_TYPE_ELF: // fall through case abigail::tools_utils::FILE_TYPE_AR: { + abigail::elf_based_reader_sptr rdr; #ifdef WITH_CTF if (opts.use_ctf) - { - abigail::ctf_reader::read_context_sptr ctxt - = abigail::ctf_reader::create_read_context(opts.file1, - opts.prepared_di_root_paths1, - env.get()); - ABG_ASSERT(ctxt); - c1 = abigail::ctf_reader::read_corpus(ctxt.get(), - c1_status); - } + rdr = abigail::ctf_reader::create_ctf_reader(opts.file1, + opts.prepared_di_root_paths1, + env); else #endif - { - abigail::dwarf_reader::read_context_sptr ctxt = - abigail::dwarf_reader::create_read_context - (opts.file1, opts.prepared_di_root_paths1, - env.get(), /*read_all_types=*/opts.show_all_types, - opts.linux_kernel_mode); - assert(ctxt); - - abigail::dwarf_reader::set_show_stats(*ctxt, opts.show_stats); - set_suppressions(*ctxt, opts); - abigail::dwarf_reader::set_do_log(*ctxt, opts.do_log); - c1 = abigail::dwarf_reader::read_corpus_from_elf(*ctxt, c1_status); - if (!c1 - || (opts.fail_no_debug_info - && (c1_status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) - && (c1_status & STATUS_DEBUG_INFO_NOT_FOUND))) - return handle_error(c1_status, ctxt.get(), - argv[0], opts); - } + rdr = abigail::dwarf_reader::create_dwarf_reader + (opts.file1, opts.prepared_di_root_paths1, + env, /*read_all_types=*/opts.show_all_types, + opts.linux_kernel_mode); + + assert(rdr); + + rdr->options().show_stats = opts.show_stats; + rdr->options().do_log = opts.do_log; + set_suppressions(*rdr, opts); + c1 = rdr->read_corpus(c1_status); + + if (!c1 + || (opts.fail_no_debug_info + && (c1_status & abigail::fe_iface::STATUS_ALT_DEBUG_INFO_NOT_FOUND) + && (c1_status & abigail::fe_iface::STATUS_DEBUG_INFO_NOT_FOUND))) + return handle_error(c1_status, rdr.get(), + argv[0], opts); + } break; case abigail::tools_utils::FILE_TYPE_XML_CORPUS: { - abigail::xml_reader::read_context_sptr ctxt = - abigail::xml_reader::create_native_xml_read_context(opts.file1, - env.get()); - assert(ctxt); - set_suppressions(*ctxt, opts); - set_native_xml_reader_options(*ctxt, opts); - c1 = abigail::xml_reader::read_corpus_from_input(*ctxt); + abigail::fe_iface_sptr rdr = + abigail::abixml_reader::create_abixml_reader(opts.file1, env); + assert(rdr); + set_suppressions(*rdr, opts); + set_native_xml_reader_options(*rdr, opts); + c1 = rdr->read_corpus(c1_status); if (!c1) - return handle_error(c1_status, /*ctxt=*/0, - argv[0], opts); + return handle_error(c1_status, /*ctxt=*/0, argv[0], opts); } break; case abigail::tools_utils::FILE_TYPE_XML_CORPUS_GROUP: { - abigail::xml_reader::read_context_sptr ctxt = - abigail::xml_reader::create_native_xml_read_context(opts.file1, - env.get()); - assert(ctxt); - set_suppressions(*ctxt, opts); - set_native_xml_reader_options(*ctxt, opts); - g1 = abigail::xml_reader::read_corpus_group_from_input(*ctxt); + abigail::fe_iface_sptr rdr = + abigail::abixml_reader::create_abixml_reader(opts.file1, + env); + assert(rdr); + set_suppressions(*rdr, opts); + set_native_xml_reader_options(*rdr, opts); + g1 = abigail::abixml_reader::read_corpus_group_from_input(*rdr); if (!g1) return handle_error(c1_status, /*ctxt=*/0, argv[0], opts); @@ -1277,54 +1265,48 @@ 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, - env.get()); + t2 = abigail::abixml_reader::read_translation_unit_from_file(opts.file2, + env); break; case abigail::tools_utils::FILE_TYPE_ELF: // Fall through case abigail::tools_utils::FILE_TYPE_AR: { + abigail::elf_based_reader_sptr rdr; #ifdef WITH_CTF if (opts.use_ctf) - { - abigail::ctf_reader::read_context_sptr ctxt - = abigail::ctf_reader::create_read_context(opts.file2, - opts.prepared_di_root_paths2, - env.get()); - ABG_ASSERT(ctxt); - c2 = abigail::ctf_reader::read_corpus(ctxt.get(), - c2_status); - } + rdr = abigail::ctf_reader::create_ctf_reader(opts.file2, + opts.prepared_di_root_paths2, + env); else #endif - { - abigail::dwarf_reader::read_context_sptr ctxt = - abigail::dwarf_reader::create_read_context - (opts.file2, opts.prepared_di_root_paths2, - env.get(), /*read_all_types=*/opts.show_all_types, - opts.linux_kernel_mode); - assert(ctxt); - abigail::dwarf_reader::set_show_stats(*ctxt, opts.show_stats); - abigail::dwarf_reader::set_do_log(*ctxt, opts.do_log); - set_suppressions(*ctxt, opts); - - c2 = abigail::dwarf_reader::read_corpus_from_elf(*ctxt, c2_status); - if (!c2 - || (opts.fail_no_debug_info - && (c2_status & STATUS_ALT_DEBUG_INFO_NOT_FOUND) - && (c2_status & STATUS_DEBUG_INFO_NOT_FOUND))) - return handle_error(c2_status, ctxt.get(), argv[0], opts); - } + rdr = abigail::dwarf_reader::create_dwarf_reader + (opts.file2, opts.prepared_di_root_paths2, + env, /*read_all_types=*/opts.show_all_types, + opts.linux_kernel_mode); + + assert(rdr); + rdr->options().show_stats = opts.show_stats; + rdr->options().do_log = opts.do_log; + set_suppressions(*rdr, opts); + + c2 = rdr->read_corpus(c2_status); + + if (!c2 + || (opts.fail_no_debug_info + && (c2_status & abigail::fe_iface::STATUS_ALT_DEBUG_INFO_NOT_FOUND) + && (c2_status & abigail::fe_iface::STATUS_DEBUG_INFO_NOT_FOUND))) + return handle_error(c2_status, rdr.get(), argv[0], opts); } break; case abigail::tools_utils::FILE_TYPE_XML_CORPUS: { - abigail::xml_reader::read_context_sptr ctxt = - abigail::xml_reader::create_native_xml_read_context(opts.file2, - env.get()); - assert(ctxt); - set_suppressions(*ctxt, opts); - set_native_xml_reader_options(*ctxt, opts); - c2 = abigail::xml_reader::read_corpus_from_input(*ctxt); + abigail::fe_iface_sptr rdr = + abigail::abixml_reader::create_abixml_reader(opts.file2, + env); + assert(rdr); + set_suppressions(*rdr, opts); + set_native_xml_reader_options(*rdr, opts); + c2 = rdr->read_corpus(c2_status); if (!c2) return handle_error(c2_status, /*ctxt=*/0, argv[0], opts); @@ -1332,13 +1314,13 @@ main(int argc, char* argv[]) break; case abigail::tools_utils::FILE_TYPE_XML_CORPUS_GROUP: { - abigail::xml_reader::read_context_sptr ctxt = - abigail::xml_reader::create_native_xml_read_context(opts.file2, - env.get()); - assert(ctxt); - set_suppressions(*ctxt, opts); - set_native_xml_reader_options(*ctxt, opts); - g2 = abigail::xml_reader::read_corpus_group_from_input(*ctxt); + abigail::fe_iface_sptr rdr = + abigail::abixml_reader::create_abixml_reader(opts.file2, + env); + assert(rdr); + set_suppressions(*rdr, opts); + set_native_xml_reader_options(*rdr, opts); + g2 = abigail::abixml_reader::read_corpus_group_from_input(*rdr); if (!g2) return handle_error(c2_status, /*ctxt=*/0, argv[0], opts); } diff --git a/tools/abidw.cc b/tools/abidw.cc index f38d6048..d92ec198 100644 --- a/tools/abidw.cc +++ b/tools/abidw.cc @@ -32,6 +32,7 @@ #include "abg-writer.h" #include "abg-reader.h" #include "abg-comparison.h" +#include "abg-suppression.h" using std::string; using std::cerr; @@ -66,8 +67,9 @@ using abigail::xml_writer::create_write_context; using abigail::xml_writer::type_id_style_kind; using abigail::xml_writer::write_context_sptr; using abigail::xml_writer::write_corpus; -using abigail::xml_reader::read_corpus_from_native_xml_file; -using abigail::xml_reader::create_native_xml_read_context; +using abigail::abixml_reader::read_corpus_from_abixml_file; +using abigail::abixml_reader::create_abixml_reader; + using namespace abigail; struct options @@ -489,7 +491,7 @@ maybe_check_header_files(const options& opts) /// @param opts the options where to get the suppression /// specifications from. static void -set_suppressions(dwarf_reader::read_context& read_ctxt, options& opts) +set_suppressions(abigail::elf_based_reader& rdr, options& opts) { suppressions_type supprs; for (vector::const_iterator i = opts.suppression_paths.begin(); @@ -514,8 +516,8 @@ set_suppressions(dwarf_reader::read_context& read_ctxt, options& opts) opts.kabi_whitelist_supprs.insert(opts.kabi_whitelist_supprs.end(), wl_suppr.begin(), wl_suppr.end()); - add_read_context_suppressions(read_ctxt, supprs); - add_read_context_suppressions(read_ctxt, opts.kabi_whitelist_supprs); + rdr.add_suppressions(supprs); + rdr.add_suppressions(opts.kabi_whitelist_supprs); } /// Load an ABI @ref corpus (the internal representation of the ABI of @@ -531,7 +533,7 @@ set_suppressions(dwarf_reader::read_context& read_ctxt, options& opts) /// otherwise. static int load_corpus_and_write_abixml(char* argv[], - environment_sptr& env, + environment& env, options& opts) { int exit_code = 0; @@ -539,106 +541,92 @@ load_corpus_and_write_abixml(char* argv[], #ifdef WITH_DEBUG_SELF_COMPARISON if (opts.debug_abidiff) - env->self_comparison_debug_is_on(true); + env.self_comparison_debug_is_on(true); #endif #ifdef WITH_DEBUG_TYPE_CANONICALIZATION if (opts.debug_type_canonicalization) - env->debug_type_canonicalization_is_on(true); + env.debug_type_canonicalization_is_on(true); if (opts.debug_die_canonicalization) - env->debug_die_canonicalization_is_on(true); + env.debug_die_canonicalization_is_on(true); #endif - // First of all, read a libabigail IR corpus from the file specified - // in OPTS. corpus_sptr corp; - elf_reader::status s = elf_reader::STATUS_UNKNOWN; + fe_iface::status s = fe_iface::STATUS_UNKNOWN; + // First of all, create a reader to read the ABI from the file + // specfied in opts ... + abigail::elf_based_reader_sptr reader; #ifdef WITH_CTF if (opts.use_ctf) - { - abigail::ctf_reader::read_context_sptr ctxt - = abigail::ctf_reader::create_read_context(opts.in_file_path, - opts.prepared_di_root_paths, - env.get()); - assert (ctxt); - t.start(); - corp = abigail::ctf_reader::read_corpus (ctxt, s); - t.stop(); - if (opts.do_log) - emit_prefix(argv[0], cerr) - << "read corpus from elf file in: " << t << "\n"; - } + reader = abigail::ctf_reader::create_ctf_reader(opts.in_file_path, + opts.prepared_di_root_paths, + env); else #endif + reader = abigail::dwarf_reader::create_dwarf_reader(opts.in_file_path, + opts.prepared_di_root_paths, + env, + opts.load_all_types, + opts.linux_kernel_mode); + + // ... then tune a bunch of "buttons" on the newly created reader ... + reader->options().drop_undefined_syms = opts.drop_undefined_syms; + reader->options().show_stats = opts.show_stats; + reader->options().do_log = opts.do_log; + set_suppressions(*reader, opts); + + // If the user asked us to check if we found the "alternate debug + // info file" associated to the input binary, then proceed to do so + // ... + if (opts.check_alt_debug_info_path) { - dwarf_reader::read_context_sptr c - = abigail::dwarf_reader::create_read_context(opts.in_file_path, - opts.prepared_di_root_paths, - env.get(), - opts.load_all_types, - opts.linux_kernel_mode); - dwarf_reader::read_context& ctxt = *c; - set_drop_undefined_syms(ctxt, opts.drop_undefined_syms); - set_show_stats(ctxt, opts.show_stats); - set_suppressions(ctxt, opts); - abigail::dwarf_reader::set_do_log(ctxt, opts.do_log); - - if (opts.check_alt_debug_info_path) - { - bool has_alt_di = false; - string alt_di_path; - abigail::elf_reader::status status = - abigail::dwarf_reader::has_alt_debug_info(ctxt, - has_alt_di, - alt_di_path); - if (status & abigail::elf_reader::STATUS_OK) - { - if (alt_di_path.empty()) - ; - else - { - cout << "found the alternate debug info file"; - if (opts.show_base_name_alt_debug_info_path) - { - tools_utils::base_name(alt_di_path, alt_di_path); - cout << " '" << alt_di_path << "'"; - } - cout << "\n"; - } - return 0; - } - else - { - emit_prefix(argv[0], cerr) - << "could not find alternate debug info file\n"; - return 1; - } - } + string alt_di_path = reader->alternate_dwarf_debug_info_path(); + if (!alt_di_path.empty()) + { + cout << "found the alternate debug info file"; + if (opts.show_base_name_alt_debug_info_path) + { + tools_utils::base_name(alt_di_path, alt_di_path); + cout << " '" << alt_di_path << "'"; + } + cout << "\n"; + return 0; + } + else + { + emit_prefix(argv[0], cerr) + << "could not find alternate debug info file\n"; + return 1; + } + } - if (opts.exported_interfaces_only.has_value()) - env->analyze_exported_interfaces_only(*opts.exported_interfaces_only); + // ... ff we are asked to only analyze exported interfaces (to stay + // concise), then take that into account ... + if (opts.exported_interfaces_only.has_value()) + env.analyze_exported_interfaces_only(*opts.exported_interfaces_only); - t.start(); - corp = dwarf_reader::read_corpus_from_elf(ctxt, s); - t.stop(); - if (opts.do_log) - emit_prefix(argv[0], cerr) - << "read corpus from elf file in: " << t << "\n"; + // And now, really read/analyze the ABI of the input file. + t.start(); + corp = reader->read_corpus(s); + t.stop(); + if (opts.do_log) + emit_prefix(argv[0], cerr) + << "read corpus from elf file in: " << t << "\n"; - t.start(); - c.reset(); - t.stop(); + // Clear some resources to gain back some space. + t.start(); + reader.reset(); + t.stop(); - if (opts.do_log) - emit_prefix(argv[0], cerr) - << "reset read context in: " << t << "\n"; - } + if (opts.do_log) + emit_prefix(argv[0], cerr) + << "reset reader ELF in: " << t << "\n"; // If we couldn't create a corpus, emit some (hopefully) useful // diagnostics and return and error. if (!corp) { - if (s == elf_reader::STATUS_DEBUG_INFO_NOT_FOUND) + if (s == fe_iface::STATUS_DEBUG_INFO_NOT_FOUND) { if (opts.di_root_paths.empty()) { @@ -668,7 +656,7 @@ load_corpus_and_write_abixml(char* argv[], } } } - else if (s == elf_reader::STATUS_NO_SYMBOLS_FOUND) + else if (s == fe_iface::STATUS_NO_SYMBOLS_FOUND) emit_prefix(argv[0], cerr) << "Could not read ELF symbol information from " << opts.in_file_path << "\n"; @@ -679,8 +667,7 @@ load_corpus_and_write_abixml(char* argv[], // Now create a write context and write out an ABI XML description // of the read corpus. t.start(); - const write_context_sptr& write_ctxt - = create_write_context(corp->get_environment(), cout); + const write_context_sptr& write_ctxt = create_write_context(env, cout); set_common_options(*write_ctxt, opts); t.stop(); @@ -706,17 +693,16 @@ load_corpus_and_write_abixml(char* argv[], write_canonical_type_ids(*write_ctxt, opts.type_id_file_path); } #endif - xml_reader::read_context_sptr read_ctxt = - create_native_xml_read_context(tmp_file->get_path(), env.get()); + fe_iface_sptr rdr = create_abixml_reader(tmp_file->get_path(), env); #ifdef WITH_DEBUG_SELF_COMPARISON if (opts.debug_abidiff && !opts.type_id_file_path.empty()) - load_canonical_type_ids(*read_ctxt, opts.type_id_file_path); + load_canonical_type_ids(*rdr, opts.type_id_file_path); #endif t.start(); - corpus_sptr corp2 = - read_corpus_from_input(*read_ctxt); + fe_iface::status sts; + corpus_sptr corp2 = rdr->read_corpus(sts); t.stop(); if (opts.do_log) emit_prefix(argv[0], cerr) @@ -810,7 +796,7 @@ load_corpus_and_write_abixml(char* argv[], /// otherwise. static int load_kernel_corpus_group_and_write_abixml(char* argv[], - environment_sptr& env, + environment& env, options& opts) { if (!(tools_utils::is_dir(opts.in_file_path) && opts.corpus_group_for_linux)) @@ -826,7 +812,7 @@ load_kernel_corpus_group_and_write_abixml(char* argv[], suppressions_type supprs; if (opts.exported_interfaces_only.has_value()) - env->analyze_exported_interfaces_only(*opts.exported_interfaces_only); + env.analyze_exported_interfaces_only(*opts.exported_interfaces_only); if (opts.do_log) emit_prefix(argv[0], cerr) @@ -861,7 +847,7 @@ corpus::origin origin = if (!opts.noout) { const xml_writer::write_context_sptr& ctxt - = xml_writer::create_write_context(group->get_environment(), cout); + = xml_writer::create_write_context(env, cout); set_common_options(*ctxt, opts); if (!opts.out_file_path.empty()) @@ -983,7 +969,7 @@ main(int argc, char* argv[]) return 1; } - environment_sptr env(new environment); + environment env; int exit_code = 0; if (tools_utils::is_regular_file(opts.in_file_path)) diff --git a/tools/abilint.cc b/tools/abilint.cc index 087fc45f..d2664c09 100644 --- a/tools/abilint.cc +++ b/tools/abilint.cc @@ -56,14 +56,14 @@ using abigail::type_base_sptr; using abigail::type_or_decl_base_sptr; using abigail::corpus; using abigail::corpus_sptr; -using abigail::xml_reader::read_translation_unit_from_file; -using abigail::xml_reader::read_translation_unit_from_istream; -using abigail::xml_reader::read_corpus_from_native_xml; -using abigail::xml_reader::read_corpus_from_native_xml_file; -using abigail::xml_reader::read_corpus_group_from_input; +using abigail::abixml_reader::read_translation_unit_from_file; +using abigail::abixml_reader::read_translation_unit_from_istream; +using abigail::abixml_reader::read_corpus_from_abixml; +using abigail::abixml_reader::read_corpus_from_abixml_file; +using abigail::abixml_reader::read_corpus_group_from_input; #ifdef WITH_SHOW_TYPE_USE_IN_ABILINT -using abigail::xml_reader::get_types_from_type_id; -using abigail::xml_reader::get_artifact_used_by_relation_map; +using abigail::abixml_reader::get_types_from_type_id; +using abigail::abixml_reader::get_artifact_used_by_relation_map; #endif using abigail::dwarf_reader::read_corpus_from_elf; using abigail::xml_writer::write_translation_unit; @@ -302,7 +302,7 @@ fill_artifact_use_tree(const std::unordered_map -build_type_use_tree(abigail::xml_reader::read_context &ctxt, +build_type_use_tree(abigail::abixml_reader::reader &ctxt, const string& type_id) { unique_ptr result; @@ -452,7 +452,7 @@ emit_artifact_use_trace(const artifact_use_relation_tree& artifact_use_tree, /// /// @param the type_id of the type which usage to analyse. static bool -show_how_type_is_used(abigail::xml_reader::read_context &ctxt, +show_how_type_is_used(abigail::abixml_reader::reader &ctxt, const string& type_id) { if (type_id.empty()) @@ -641,7 +641,7 @@ maybe_check_suppression_files(const options& opts) return true; } -/// Set suppression specifications to the @p read_context used to load +/// Set suppression specifications to the @p reader used to load /// the ABI corpus from the ELF/DWARF file. /// /// These suppression specifications are going to be applied to drop @@ -652,14 +652,13 @@ maybe_check_suppression_files(const options& opts) /// @param read_ctxt the read context to apply the suppression /// specifications to. Note that the type of this parameter is /// generic (class template) because in practise, it can be either an -/// abigail::dwarf_reader::read_context type or an -/// abigail::xml_reader::read_context type. +/// abigail::dwarf_reader::reader type or an +/// abigail::abixml_reader::reader type. /// /// @param opts the options where to get the suppression /// specifications from. -template static void -set_suppressions(ReadContextType& read_ctxt, const options& opts) +set_suppressions(abigail::fe_iface& reader, const options& opts) { suppressions_type supprs; for (vector::const_iterator i = opts.suppression_paths.begin(); @@ -673,7 +672,7 @@ set_suppressions(ReadContextType& read_ctxt, const options& opts) if (suppr) supprs.push_back(suppr); - add_read_context_suppressions(read_ctxt, supprs); + reader.add_suppressions(supprs); } /// Reads a bi (binary instrumentation) file, saves it back to a @@ -702,7 +701,7 @@ main(int argc, char* argv[]) if (!maybe_check_suppression_files(opts)) return 1; - abigail::ir::environment_sptr env(new abigail::ir::environment); + abigail::ir::environment env; if (opts.read_from_stdin) { if (!cin.good()) @@ -711,7 +710,7 @@ main(int argc, char* argv[]) if (opts.read_tu) { abigail::translation_unit_sptr tu = - read_translation_unit_from_istream(&cin, env.get()); + read_translation_unit_from_istream(&cin, env); if (!tu) { @@ -723,23 +722,23 @@ main(int argc, char* argv[]) if (!opts.noout) { const write_context_sptr& ctxt - = create_write_context(tu->get_environment(), cout); + = create_write_context(env, cout); write_translation_unit(*ctxt, *tu, 0); } return 0; } else { - abigail::xml_reader::read_context_sptr ctxt = - abigail::xml_reader::create_native_xml_read_context(&cin, - env.get()); - assert(ctxt); - set_suppressions(*ctxt, opts); - corpus_sptr corp = abigail::xml_reader::read_corpus_from_input(*ctxt); + abigail::fe_iface_sptr rdr = + abigail::abixml_reader::create_abixml_reader(&cin, env); + assert(rdr); + set_suppressions(*rdr, opts); + abigail::fe_iface::status sts; + corpus_sptr corp = rdr->read_corpus(sts); if (!opts.noout) { const write_context_sptr& ctxt - = create_write_context(corp->get_environment(), cout); + = create_write_context(env, cout); write_corpus(*ctxt, corp, /*indent=*/0); } return 0; @@ -752,10 +751,9 @@ main(int argc, char* argv[]) abigail::translation_unit_sptr tu; abigail::corpus_sptr corp; abigail::corpus_group_sptr group; - abigail::elf_reader::status s = abigail::elf_reader::STATUS_OK; + abigail::fe_iface::status s = abigail::fe_iface::STATUS_OK; char* di_root_path = 0; file_type type = guess_file_type(opts.file_path); - abigail::xml_reader::read_context_sptr abixml_read_ctxt; switch (type) { @@ -766,10 +764,10 @@ main(int argc, char* argv[]) return 1; case abigail::tools_utils::FILE_TYPE_NATIVE_BI: { - abixml_read_ctxt = - abigail::xml_reader::create_native_xml_read_context(opts.file_path, - env.get()); - tu = read_translation_unit(*abixml_read_ctxt); + abigail::fe_iface_sptr rdr = + abigail::abixml_reader::create_abixml_reader(opts.file_path, + env); + tu = abigail::abixml_reader::read_translation_unit(*rdr); } break; case abigail::tools_utils::FILE_TYPE_ELF: @@ -778,48 +776,41 @@ main(int argc, char* argv[]) di_root_path = opts.di_root_path.get(); vector di_roots; di_roots.push_back(&di_root_path); - + abigail::elf_based_reader_sptr rdr; #ifdef WITH_CTF if (opts.use_ctf) - { - abigail::ctf_reader::read_context_sptr ctxt = - abigail::ctf_reader::create_read_context(opts.file_path, - di_roots, - env.get()); - ABG_ASSERT(ctxt); - corp = abigail::ctf_reader::read_corpus(ctxt.get(), s); - } + rdr = + abigail::ctf_reader::create_ctf_reader(opts.file_path, + di_roots, + env); else #endif - { - abigail::dwarf_reader::read_context_sptr ctxt = - abigail::dwarf_reader::create_read_context(opts.file_path, - di_roots, env.get(), - /*load_all_types=*/false); - assert(ctxt); - set_suppressions(*ctxt, opts); - corp = read_corpus_from_elf(*ctxt, s); - } + rdr = + abigail::dwarf_reader::create_dwarf_reader(opts.file_path, + di_roots, env, + /*load_all_types=*/false); + set_suppressions(*rdr, opts); + corp = rdr->read_corpus(s); } break; case abigail::tools_utils::FILE_TYPE_XML_CORPUS: { - abixml_read_ctxt = - abigail::xml_reader::create_native_xml_read_context(opts.file_path, - env.get()); - assert(abixml_read_ctxt); - set_suppressions(*abixml_read_ctxt, opts); - corp = read_corpus_from_input(*abixml_read_ctxt); + abigail::fe_iface_sptr rdr = + abigail::abixml_reader::create_abixml_reader(opts.file_path, + env); + assert(rdr); + set_suppressions(*rdr, opts); + corp = rdr->read_corpus(s); break; } case abigail::tools_utils::FILE_TYPE_XML_CORPUS_GROUP: { - abixml_read_ctxt = - abigail::xml_reader::create_native_xml_read_context(opts.file_path, - env.get()); - assert(abixml_read_ctxt); - set_suppressions(*abixml_read_ctxt, opts); - group = read_corpus_group_from_input(*abixml_read_ctxt); + abigail::fe_iface_sptr rdr = + abigail::abixml_reader::create_abixml_reader(opts.file_path, + env); + assert(rdr); + set_suppressions(*rdr, opts); + group = read_corpus_group_from_input(*rdr); } break; case abigail::tools_utils::FILE_TYPE_RPM: @@ -838,9 +829,9 @@ main(int argc, char* argv[]) { emit_prefix(argv[0], cerr) << "failed to read " << opts.file_path << "\n"; - if (!(s & abigail::elf_reader::STATUS_OK)) + if (!(s & abigail::fe_iface::STATUS_OK)) { - if (s & abigail::elf_reader::STATUS_DEBUG_INFO_NOT_FOUND) + if (s & abigail::fe_iface::STATUS_DEBUG_INFO_NOT_FOUND) { cerr << "could not find the debug info"; if(di_root_path == 0) @@ -854,7 +845,7 @@ main(int argc, char* argv[]) << "Maybe the root path to the debug " "information is wrong?\n"; } - if (s & abigail::elf_reader::STATUS_NO_SYMBOLS_FOUND) + if (s & abigail::fe_iface::STATUS_NO_SYMBOLS_FOUND) emit_prefix(argv[0], cerr) << "could not find the ELF symbols in the file " << opts.file_path @@ -874,15 +865,6 @@ main(int argc, char* argv[]) } std::ostream& of = opts.diff ? tmp_file->get_stream() : cout; - const abigail::ir::environment* env = 0; - if (tu) - env = tu->get_environment(); - else if (corp) - env = corp->get_environment(); - else if (group) - env = group->get_environment(); - - ABG_ASSERT(env); const write_context_sptr ctxt = create_write_context(env, of); bool is_ok = true; diff --git a/tools/abipkgdiff.cc b/tools/abipkgdiff.cc index 656d5882..0065e763 100644 --- a/tools/abipkgdiff.cc +++ b/tools/abipkgdiff.cc @@ -147,11 +147,9 @@ using abigail::comparison::get_default_harmful_categories_bitmap; using abigail::suppr::suppression_sptr; using abigail::suppr::suppressions_type; using abigail::suppr::read_suppressions; -using abigail::dwarf_reader::read_context_sptr; -using abigail::dwarf_reader::create_read_context; -using abigail::dwarf_reader::get_soname_of_elf_file; -using abigail::dwarf_reader::get_type_of_elf_file; -using abigail::dwarf_reader::read_corpus_from_elf; +using abigail::elf_reader::get_soname_of_elf_file; +using abigail::elf_reader::get_type_of_elf_file; +using abigail::dwarf_reader::create_dwarf_reader; using abigail::xml_writer::create_write_context; using abigail::xml_writer::write_context_sptr; using abigail::xml_writer::write_corpus; @@ -279,7 +277,7 @@ public: string name; string soname; off_t size; - abigail::dwarf_reader::elf_type type; + abigail::elf_reader::elf_type type; /// The path to the elf file. /// @@ -1248,22 +1246,22 @@ set_diff_context_from_opts(diff_context_sptr ctxt, /// /// @param detailed_error_status is this pointer is non-null and if /// the function returns ABIDIFF_ERROR, then the function sets the -/// pointed-to parameter to the abigail::elf_reader::status value +/// pointed-to parameter to the abigail::fe_iface::status value /// that gives details about the rror. /// /// @return the status of the comparison. static abidiff_status -compare(const elf_file& elf1, - const string& debug_dir1, - const suppressions_type& priv_types_supprs1, - const elf_file& elf2, - const string& debug_dir2, - const suppressions_type& priv_types_supprs2, - const options& opts, - abigail::ir::environment_sptr &env, - corpus_diff_sptr &diff, - diff_context_sptr &ctxt, - abigail::elf_reader::status *detailed_error_status = 0) +compare(const elf_file& elf1, + const string& debug_dir1, + const suppressions_type& priv_types_supprs1, + const elf_file& elf2, + const string& debug_dir2, + const suppressions_type& priv_types_supprs2, + const options& opts, + abigail::ir::environment& env, + corpus_diff_sptr& diff, + diff_context_sptr& ctxt, + abigail::fe_iface::status* detailed_error_status = 0) { char *di_dir1 = (char*) debug_dir1.c_str(), *di_dir2 = (char*) debug_dir2.c_str(); @@ -1280,8 +1278,8 @@ compare(const elf_file& elf1, << elf2.path << "...\n"; - abigail::elf_reader::status c1_status = abigail::elf_reader::STATUS_OK, - c2_status = abigail::elf_reader::STATUS_OK; + abigail::fe_iface::status c1_status = abigail::fe_iface::STATUS_OK, + c2_status = abigail::fe_iface::STATUS_OK; ctxt.reset(new diff_context); set_diff_context_from_opts(ctxt, opts); @@ -1320,36 +1318,28 @@ compare(const elf_file& elf1, << elf1.path << " ...\n"; + abigail::elf_based_reader_sptr reader; corpus_sptr corpus1; -#ifdef WITH_CTF - abigail::ctf_reader::read_context_sptr ctxt_ctf; -#endif - read_context_sptr ctxt_dwarf; { #ifdef WITH_CTF if (opts.use_ctf) - { - ctxt_ctf = abigail::ctf_reader::create_read_context(elf1.path, - di_dirs1, - env.get()); - ABG_ASSERT(ctxt_ctf); - corpus1 = abigail::ctf_reader::read_corpus(ctxt_ctf.get(), - c1_status); - } + reader = abigail::ctf_reader::create_ctf_reader(elf1.path, di_dirs1, env); else #endif - { - ctxt_dwarf = create_read_context(elf1.path, di_dirs1, env.get(), - /*load_all_types=*/opts.show_all_types); - add_read_context_suppressions(*ctxt_dwarf, priv_types_supprs1); - if (!opts.kabi_suppressions.empty()) - add_read_context_suppressions(*ctxt_dwarf, opts.kabi_suppressions); + reader = + create_dwarf_reader(elf1.path, di_dirs1, env, + /*load_all_types=*/opts.show_all_types); - corpus1 = read_corpus_from_elf(*ctxt_dwarf, c1_status); - } + ABG_ASSERT(reader); + + reader->add_suppressions(priv_types_supprs1); + if (!opts.kabi_suppressions.empty()) + reader->add_suppressions(opts.kabi_suppressions); + + corpus1 = reader->read_corpus(c1_status); bool bail_out = false; - if (!(c1_status & abigail::elf_reader::STATUS_OK)) + if (!(c1_status & abigail::fe_iface::STATUS_OK)) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1366,7 +1356,7 @@ compare(const elf_file& elf1, if (opts.fail_if_no_debug_info) { bool debug_info_error = false; - if (c1_status & abigail::elf_reader::STATUS_DEBUG_INFO_NOT_FOUND) + if (c1_status & abigail::fe_iface::STATUS_DEBUG_INFO_NOT_FOUND) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1383,7 +1373,7 @@ compare(const elf_file& elf1, debug_info_error = true; } - if (c1_status & abigail::elf_reader::STATUS_ALT_DEBUG_INFO_NOT_FOUND) + if (c1_status & abigail::fe_iface::STATUS_ALT_DEBUG_INFO_NOT_FOUND) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1397,8 +1387,7 @@ compare(const elf_file& elf1, ; else #endif - abigail::dwarf_reader::refers_to_alt_debug_info(*ctxt_dwarf, - alt_di_path); + reader->refers_to_alt_debug_info(alt_di_path); if (!alt_di_path.empty()) cerr << ": " << alt_di_path << "\n"; else @@ -1433,28 +1422,22 @@ compare(const elf_file& elf1, { #ifdef WITH_CTF if (opts.use_ctf) - { - ctxt_ctf = abigail::ctf_reader::create_read_context(elf2.path, - di_dirs2, - env.get()); - corpus2 = abigail::ctf_reader::read_corpus(ctxt_ctf.get(), - c2_status); - } + reader = + abigail::ctf_reader::create_ctf_reader(elf2.path, di_dirs2, env); else #endif - { - ctxt_dwarf = create_read_context(elf2.path, di_dirs2, env.get(), - /*load_all_types=*/opts.show_all_types); - add_read_context_suppressions(*ctxt_dwarf, priv_types_supprs2); + reader = + create_dwarf_reader(elf2.path, di_dirs2, env, + /*load_all_types=*/opts.show_all_types); - if (!opts.kabi_suppressions.empty()) - add_read_context_suppressions(*ctxt_dwarf, opts.kabi_suppressions); + reader->add_suppressions(priv_types_supprs2); + if (!opts.kabi_suppressions.empty()) + reader->add_suppressions(opts.kabi_suppressions); - corpus2 = read_corpus_from_elf(*ctxt_dwarf, c2_status); - } + corpus2 = reader->read_corpus(c2_status); bool bail_out = false; - if (!(c2_status & abigail::elf_reader::STATUS_OK)) + if (!(c2_status & abigail::fe_iface::STATUS_OK)) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1471,7 +1454,7 @@ compare(const elf_file& elf1, if (opts.fail_if_no_debug_info) { bool debug_info_error = false; - if (c2_status & abigail::elf_reader::STATUS_DEBUG_INFO_NOT_FOUND) + if (c2_status & abigail::fe_iface::STATUS_DEBUG_INFO_NOT_FOUND) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1488,7 +1471,7 @@ compare(const elf_file& elf1, debug_info_error = true; } - if (c2_status & abigail::elf_reader::STATUS_ALT_DEBUG_INFO_NOT_FOUND) + if (c2_status & abigail::fe_iface::STATUS_ALT_DEBUG_INFO_NOT_FOUND) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1502,8 +1485,7 @@ compare(const elf_file& elf1, ; else #endif - abigail::dwarf_reader::refers_to_alt_debug_info(*ctxt_dwarf, - alt_di_path); + reader->refers_to_alt_debug_info(alt_di_path); if (!alt_di_path.empty()) cerr << ": " << alt_di_path << "\n"; else @@ -1572,20 +1554,20 @@ compare(const elf_file& elf1, /// /// @return the status of the self comparison. static abidiff_status -compare_to_self(const elf_file& elf, - const string& debug_dir, - const options& opts, - abigail::ir::environment_sptr &env, - corpus_diff_sptr &diff, - diff_context_sptr &ctxt, - abigail::elf_reader::status *detailed_error_status = 0) +compare_to_self(const elf_file& elf, + const string& debug_dir, + const options& opts, + abigail::ir::environment& env, + corpus_diff_sptr& diff, + diff_context_sptr& ctxt, + abigail::fe_iface::status* detailed_error_status = 0) { char *di_dir = (char*) debug_dir.c_str(); vector di_dirs; di_dirs.push_back(&di_dir); - abigail::elf_reader::status c_status = abigail::elf_reader::STATUS_OK; + abigail::fe_iface::status c_status = abigail::fe_iface::STATUS_OK; if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1600,32 +1582,20 @@ compare_to_self(const elf_file& elf, << " ...\n"; corpus_sptr corp; -#ifdef WITH_CTF - abigail::ctf_reader::read_context_sptr ctxt_ctf; -#endif - read_context_sptr ctxt_dwarf; + abigail::elf_based_reader_sptr reader; { #ifdef WITH_CTF if (opts.use_ctf) - { - ctxt_ctf = abigail::ctf_reader::create_read_context(elf.path, - di_dirs, - env.get()); - ABG_ASSERT(ctxt_ctf); - corp = abigail::ctf_reader::read_corpus(ctxt_ctf.get(), - c_status); - } + reader = + abigail::ctf_reader::create_ctf_reader(elf.path, di_dirs, env); else #endif - { - ctxt_dwarf = - create_read_context(elf.path, di_dirs, env.get(), - /*read_all_types=*/opts.show_all_types); + reader = create_dwarf_reader(elf.path, di_dirs, env, + /*read_all_types=*/opts.show_all_types); - corp = read_corpus_from_elf(*ctxt_dwarf, c_status); - } + corp = reader->read_corpus(c_status); - if (!(c_status & abigail::elf_reader::STATUS_OK)) + if (!(c_status & abigail::fe_iface::STATUS_OK)) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1666,7 +1636,7 @@ compare_to_self(const elf_file& elf, { const abigail::xml_writer::write_context_sptr c = - abigail::xml_writer::create_write_context(env.get(), of); + abigail::xml_writer::create_write_context(env, of); if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1695,10 +1665,9 @@ compare_to_self(const elf_file& elf, } { - abigail::xml_reader::read_context_sptr c = - abigail::xml_reader::create_native_xml_read_context(abi_file_path, - env.get()); - if (!c) + abigail::fe_iface_sptr rdr = + abigail::abixml_reader::create_abixml_reader(abi_file_path, env); + if (!rdr) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -1714,7 +1683,8 @@ compare_to_self(const elf_file& elf, << abi_file_path << "' ...\n"; - reread_corp = read_corpus_from_input(*c); + abigail::fe_iface::status sts; + reread_corp = rdr->read_corpus(sts); if (!reread_corp) { if (opts.verbose) @@ -2074,15 +2044,15 @@ public: virtual void perform() { - abigail::ir::environment_sptr env(new abigail::ir::environment); + abigail::ir::environment env; diff_context_sptr ctxt; corpus_diff_sptr diff; - abigail::elf_reader::status detailed_status = - abigail::elf_reader::STATUS_UNKNOWN; + abigail::fe_iface::status detailed_status = + abigail::fe_iface::STATUS_UNKNOWN; if (args->opts.exported_interfaces_only.has_value()) - env->analyze_exported_interfaces_only + env.analyze_exported_interfaces_only (*args->opts.exported_interfaces_only); status |= compare(args->elf1, args->debug_dir1, args->private_types_suppr1, @@ -2113,7 +2083,7 @@ public: if (status & abigail::tools_utils::ABIDIFF_ERROR) { string diagnostic = - abigail::elf_reader::status_to_diagnostic_string(detailed_status); + abigail::status_to_diagnostic_string(detailed_status); if (diagnostic.empty()) diagnostic = "Unknown error. Please run the tool again with --verbose\n"; @@ -2147,16 +2117,16 @@ public: virtual void perform() { - abigail::ir::environment_sptr env(new abigail::ir::environment); + abigail::ir::environment env; diff_context_sptr ctxt; corpus_diff_sptr diff; if (args->opts.exported_interfaces_only.has_value()) - env->analyze_exported_interfaces_only + env.analyze_exported_interfaces_only (*args->opts.exported_interfaces_only); - abigail::elf_reader::status detailed_status = - abigail::elf_reader::STATUS_UNKNOWN; + abigail::fe_iface::status detailed_status = + abigail::fe_iface::STATUS_UNKNOWN; status |= compare_to_self(args->elf1, args->debug_dir1, args->opts, env, diff, ctxt, @@ -2183,7 +2153,7 @@ public: if (status & abigail::tools_utils::ABIDIFF_ERROR) { string diagnostic = - abigail::elf_reader::status_to_diagnostic_string(detailed_status); + abigail::status_to_diagnostic_string(detailed_status); if (diagnostic.empty()) diagnostic = @@ -2370,7 +2340,7 @@ create_maps_of_package_content(package& package, options& opts) elf_file_sptr e (new elf_file(*file)); if (opts.compare_dso_only) { - if (e->type != abigail::dwarf_reader::ELF_TYPE_DSO) + if (e->type != abigail::elf_reader::ELF_TYPE_DSO) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -2380,13 +2350,13 @@ create_maps_of_package_content(package& package, options& opts) } else { - if (e->type != abigail::dwarf_reader::ELF_TYPE_DSO - && e->type != abigail::dwarf_reader::ELF_TYPE_EXEC - && e->type != abigail::dwarf_reader::ELF_TYPE_PI_EXEC) + if (e->type != abigail::elf_reader::ELF_TYPE_DSO + && e->type != abigail::elf_reader::ELF_TYPE_EXEC + && e->type != abigail::elf_reader::ELF_TYPE_PI_EXEC) { if (is_linux_kernel_package) { - if (e->type == abigail::dwarf_reader::ELF_TYPE_RELOCATABLE) + if (e->type == abigail::elf_reader::ELF_TYPE_RELOCATABLE) { // This is a Linux Kernel module. ; @@ -2405,7 +2375,7 @@ create_maps_of_package_content(package& package, options& opts) if (e->soname.empty()) { - if (e->type == abigail::dwarf_reader::ELF_TYPE_DSO + if (e->type == abigail::elf_reader::ELF_TYPE_DSO && must_compare_public_dso_only(package, opts)) { // We are instructed to compare public DSOs only. Yet @@ -2751,12 +2721,12 @@ compare_prepared_userspace_packages(package& first_package, second_package.path_elf_file_sptr_map().find(it->first); if (iter != second_package.path_elf_file_sptr_map().end() - && (iter->second->type == abigail::dwarf_reader::ELF_TYPE_DSO - || iter->second->type == abigail::dwarf_reader::ELF_TYPE_EXEC - || iter->second->type == abigail::dwarf_reader::ELF_TYPE_PI_EXEC - || iter->second->type == abigail::dwarf_reader::ELF_TYPE_RELOCATABLE)) + && (iter->second->type == abigail::elf_reader::ELF_TYPE_DSO + || iter->second->type == abigail::elf_reader::ELF_TYPE_EXEC + || iter->second->type == abigail::elf_reader::ELF_TYPE_PI_EXEC + || iter->second->type == abigail::elf_reader::ELF_TYPE_RELOCATABLE)) { - if (iter->second->type != abigail::dwarf_reader::ELF_TYPE_RELOCATABLE) + if (iter->second->type != abigail::elf_reader::ELF_TYPE_RELOCATABLE) { if (opts.verbose) emit_prefix("abipkgdiff", cerr) @@ -2914,12 +2884,12 @@ self_compare_prepared_userspace_package(package& pkg, ++it) { if (it != pkg.path_elf_file_sptr_map().end() - && (it->second->type == abigail::dwarf_reader::ELF_TYPE_DSO - || it->second->type == abigail::dwarf_reader::ELF_TYPE_EXEC - || it->second->type == abigail::dwarf_reader::ELF_TYPE_PI_EXEC - || it->second->type == abigail::dwarf_reader::ELF_TYPE_RELOCATABLE)) + && (it->second->type == abigail::elf_reader::ELF_TYPE_DSO + || it->second->type == abigail::elf_reader::ELF_TYPE_EXEC + || it->second->type == abigail::elf_reader::ELF_TYPE_PI_EXEC + || it->second->type == abigail::elf_reader::ELF_TYPE_RELOCATABLE)) { - if (it->second->type != abigail::dwarf_reader::ELF_TYPE_RELOCATABLE) + if (it->second->type != abigail::elf_reader::ELF_TYPE_RELOCATABLE) { compare_args_sptr args (new compare_args(*it->second, @@ -3036,9 +3006,9 @@ compare_prepared_linux_kernel_packages(package& first_package, string dist_root1 = first_package.extracted_dir_path(); string dist_root2 = second_package.extracted_dir_path(); - abigail::ir::environment_sptr env(new abigail::ir::environment); + abigail::ir::environment env; if (opts.exported_interfaces_only.has_value()) - env->analyze_exported_interfaces_only + env.analyze_exported_interfaces_only (*opts.exported_interfaces_only); suppressions_type supprs; diff --git a/tools/abisym.cc b/tools/abisym.cc index 1e2215a6..902a3f83 100644 --- a/tools/abisym.cc +++ b/tools/abisym.cc @@ -28,7 +28,6 @@ using std::ostringstream; using std::vector; using abigail::ir::environment; -using abigail::ir::environment_sptr; using abigail::dwarf_reader::lookup_symbol_from_elf; using abigail::elf_symbol; using abigail::elf_symbol_sptr; @@ -131,9 +130,9 @@ main(int argc, char* argv[]) && opts.symbol_name != 0); string p = opts.elf_path, n = opts.symbol_name; - environment_sptr env(new environment); + environment env; vector syms; - if (!lookup_symbol_from_elf(env.get(), p, n, opts.demangle, syms)) + if (!lookup_symbol_from_elf(env, p, n, opts.demangle, syms)) { cout << "could not find symbol '" << opts.symbol_name diff --git a/tools/kmidiff.cc b/tools/kmidiff.cc index f3332765..699ab829 100644 --- a/tools/kmidiff.cc +++ b/tools/kmidiff.cc @@ -48,7 +48,7 @@ using abigail::suppr::suppressions_type; using abigail::suppr::read_suppressions; using abigail::tools_utils::guess_file_type; using abigail::tools_utils::file_type; -using abigail::xml_reader::read_corpus_group_from_native_xml_file; +using abigail::abixml_reader::read_corpus_group_from_abixml_file; /// The options of this program. struct options @@ -415,10 +415,10 @@ main(int argc, char* argv[]) return 0; } - environment_sptr env(new environment); + environment env; if (opts.exported_interfaces_only.has_value()) - env->analyze_exported_interfaces_only(*opts.exported_interfaces_only); + env.analyze_exported_interfaces_only(*opts.exported_interfaces_only); corpus_group_sptr group1, group2; string debug_info_root_dir; @@ -450,8 +450,8 @@ main(int argc, char* argv[]) } else if (ftype == FILE_TYPE_XML_CORPUS_GROUP) group1 = - read_corpus_group_from_native_xml_file(opts.kernel_dist_root1, - env.get()); + read_corpus_group_from_abixml_file(opts.kernel_dist_root1, + env); } @@ -476,8 +476,8 @@ main(int argc, char* argv[]) } else if (ftype == FILE_TYPE_XML_CORPUS_GROUP) group2 = - read_corpus_group_from_native_xml_file(opts.kernel_dist_root2, - env.get()); + read_corpus_group_from_abixml_file(opts.kernel_dist_root2, + env); } abidiff_status status = abigail::tools_utils::ABIDIFF_OK;