@@ -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 \
@@ -45,9 +45,10 @@ public:
{
ARTIFICIAL_ORIGIN = 0,
NATIVE_XML_ORIGIN = 1,
- DWARF_ORIGIN = 1 << 1,
- CTF_ORIGIN = 1 << 2,
- LINUX_KERNEL_BINARY_ORIGIN = 1 << 3
+ ELF_ORIGIN = 1 << 1,
+ DWARF_ORIGIN = 1 << 2,
+ CTF_ORIGIN = 1 << 3,
+ LINUX_KERNEL_BINARY_ORIGIN = 1 << 4
};
private:
@@ -68,7 +69,7 @@ public:
get_environment() const;
void
- add(const translation_unit_sptr);
+ add(const translation_unit_sptr&);
const translation_units&
get_translation_units() const;
@@ -326,10 +327,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.
@@ -17,40 +17,24 @@
#include <ostream>
#include "abg-corpus.h"
#include "abg-suppression.h"
-#include "abg-elf-reader-common.h"
+#include "abg-elf-based-reader.h"
#include "ctf-api.h"
namespace abigail
{
-namespace ctf_reader
+namespace ctf
{
-class read_context;
-typedef shared_ptr<read_context> read_context_sptr;
-
-read_context_sptr
-create_read_context(const std::string& elf_path,
- const vector<char**>& 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_reader(const std::string& elf_path,
+ const vector<char**>& debug_info_root_paths,
+ environment& env);
void
-reset_read_context(read_context_sptr &ctxt,
- const std::string& elf_path,
+reset_reader(elf_based_reader& ctxt,
+ const std::string& elf_path,
const vector<char**>& debug_info_root_path);
-std::string
-dic_type_key(ctf_dict_t *dic, ctf_id_t ctf_type);
} // end namespace ctf_reader
} // end namespace abigail
@@ -18,74 +18,37 @@
#include <elfutils/libdwfl.h>
#include "abg-corpus.h"
#include "abg-suppression.h"
-#include "abg-elf-reader-common.h"
+#include "abg-elf-based-reader.h"
namespace abigail
{
/// The namespace for the DWARF reader.
-namespace dwarf_reader
+namespace dwarf
{
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> read_context_sptr;
-
-read_context_sptr
-create_read_context(const std::string& elf_path,
- const vector<char**>& debug_info_root_paths,
- ir::environment& environment,
- bool read_all_types = false,
- bool linux_kernel_mode = false);
-
-const string&
-read_context_get_path(const read_context&);
+elf_based_reader_sptr
+create_reader(const std::string& elf_path,
+ const vector<char**>& debug_info_root_paths,
+ environment& environment,
+ bool read_all_types = false,
+ bool linux_kernel_mode = false);
void
-reset_read_context(read_context_sptr &ctxt,
- const std::string& elf_path,
- const vector<char**>& debug_info_root_paths,
- 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_reader(elf_based_reader& rdr,
+ const std::string& elf_path,
+ const vector<char**>& 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<char**>& 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<char**>& debug_info_root_paths,
+ environment& environment,
+ bool load_all_types,
+ fe_iface::status& status);
bool
lookup_symbol_from_elf(environment& env,
@@ -99,61 +62,7 @@ lookup_public_function_symbol_from_elf(environment& env,
const string& path,
const string& symname,
vector<elf_symbol_sptr>& 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 dwarf
}// end namespace abigail
new file mode 100644
@@ -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 <memory>
+#include <string>
+
+#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
+{
+ 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<char**>& debug_info_root_paths,
+ environment& env);
+public:
+
+ ~elf_based_reader();
+
+ virtual void
+ reset(const std::string& elf_path,
+ const vector<char**>& 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> elf_based_reader_sptr;
+}// namespace
+#endif
deleted file mode 100644
@@ -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 <string>
-
-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__
new file mode 100644
@@ -0,0 +1,161 @@
+// 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 <memory>
+#include <string>
+
+#include <elfutils/libdwfl.h>
+
+#include "abg-fe-iface.h"
+#include "abg-ir.h"
+#include "abg-suppression.h"
+
+namespace abigail
+{
+
+/// The namespace for the ELF Reader.
+namespace elf
+{
+
+/// 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::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<char**>& debug_info_roots,
+ environment& env);
+
+ ~reader();
+
+ void
+ reset(const std::string& elf_path,
+ const vector<char**>& debug_info_roots);
+
+ const vector<char**>&
+ 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<string>&
+ 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;
+
+ elf_symbol_sptr
+ function_symbol_is_exported(const string& name) const;
+
+ elf_symbol_sptr
+ variable_symbol_is_exported(const string& name) 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.
+typedef shared_ptr<elf::reader> 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.
+} // end namespace abigail
+
+#endif // __ABG_ELF_READER_H__
new file mode 100644
@@ -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> 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__
@@ -1440,6 +1440,11 @@ types_have_similar_structure(const type_base* first,
const type_base* second,
bool indirect_type = false);
+string
+build_internal_underlying_enum_type_name(const string &base_name,
+ bool is_anonymous,
+ uint64_t size);
+
} // end namespace ir
using namespace abigail::ir;
@@ -17,17 +17,16 @@
#include <istream>
#include "abg-corpus.h"
#include "abg-suppression.h"
+#include "abg-fe-iface.h"
namespace abigail
{
-namespace xml_reader
+namespace abixml
{
using namespace abigail::ir;
-class read_context;
-
translation_unit_sptr
read_translation_unit_from_file(const std::string& file_path,
environment& env);
@@ -41,61 +40,49 @@ read_translation_unit_from_istream(std::istream* in,
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> read_context_sptr;
-
-read_context_sptr
-create_native_xml_read_context(const string& path, environment& env);
+read_translation_unit(fe_iface&);
-read_context_sptr
-create_native_xml_read_context(std::istream* in, environment& env);
-const string&
-read_context_get_path(const read_context&);
+ abigail::fe_iface_sptr
+create_reader(const string& path, environment& env);
-corpus_sptr
-read_corpus_from_native_xml(std::istream* in,
- environment& env);
+fe_iface_sptr
+create_reader(std::istream* in, environment& env);
corpus_sptr
-read_corpus_from_native_xml_file(const string& path,
- environment& env);
+read_corpus_from_abixml(std::istream* in,
+ 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<type_base_sptr>*
-get_types_from_type_id(read_context&, const string&);
+get_types_from_type_id(fe_iface&, const string&);
unordered_map<type_or_decl_base*, vector<type_or_decl_base*>>*
-get_artifact_used_by_relation_map(read_context&);
+get_artifact_used_by_relation_map(fe_iface&);
#endif
-}//end xml_reader
+}//end abixml
#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
@@ -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_base> suppression_sptr;
+
+/// Convenience typedef for a vector of @ref suppression_sptr
+typedef vector<suppression_sptr> 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__
@@ -15,6 +15,7 @@
#include <set>
#include <string>
#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<char**>& debug_info_root_paths);
+bool file_has_ctf_debug_info(const string& elf_file_path,
+ const vector<char**>& debug_info_root_paths);
bool is_dir(const string&);
bool dir_exists(const string&);
bool dir_is_empty(const string &);
@@ -313,6 +318,12 @@ build_corpus_group_from_kernel_dist_under(const string& root,
bool verbose,
environment& env,
corpus::origin origin = corpus::DWARF_ORIGIN);
+
+elf_based_reader_sptr
+create_best_elf_based_reader(const string& elf_file_path,
+ const vector<char**>& debug_info_root_paths,
+ environment& env);
+
}// end namespace tools_utils
/// A macro that expands to aborting the program when executed.
@@ -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 \
@@ -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<function_decl*>(fn));
+ add_fn_to_id_fns_map(const_cast<function_decl*>(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_decl*>(var));
+ add_var_to_map(const_cast<var_decl*>(var));
}
}
@@ -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;
@@ -611,10 +611,7 @@ const environment&
corpus::get_environment() const
{return priv_->env;}
-/// Add a translation unit to the current ABI Corpus. Next time
-/// corpus::save is called, all the translation unit that got added to
-/// the corpus are going to be serialized on disk in the file
-/// 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
@@ -622,7 +619,7 @@ corpus::get_environment() const
///
/// @param tu the new translation unit to add.
void
-corpus::add(const translation_unit_sptr tu)
+corpus::add(const translation_unit_sptr& tu)
{
ABG_ASSERT(priv_->members.insert(tu).second);
@@ -988,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.
@@ -23,39 +23,128 @@
#include "abg-internal.h"
#include "abg-ir-priv.h"
-#include "abg-elf-helpers.h"
+#include "abg-symtab-reader.h"
+
+#include "abg-internal.h"
// <headers defining libabigail's API go under here>
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
// </headers defining libabigail's API>
namespace abigail
{
-namespace ctf_reader
+namespace ctf
{
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<ctf_id_t> 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<char**> 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,65 +238,487 @@ 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<char**>& debug_info_root_paths,
- ir::environment& env) :
- ir_env(env), ctfa(nullptr)
+ reader(const string& elf_path,
+ const vector<char**>& debug_info_root_paths,
+ environment& env)
+ : elf_based_reader(elf_path, debug_info_root_paths, env)
{
- initialize(elf_path, debug_info_root_paths);
+ 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<char**>& debug_info_root_paths)
{
- types_map.clear();
- filename = elf_path;
- 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::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<translation_unit>(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;
}
- ~read_context()
+ /// 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;
+
+ corpus::origin origin = corpus()->get_origin();
+ origin |= corpus::CTF_ORIGIN;
+ corp->set_origin(origin);
+
+ if (corpus_group())
+ corpus_group()->add_corpus(corpus());
+
+ slurp_elf_info(status);
+ if (!elf_helpers::is_linux_kernel(elf_handle())
+ && ((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;
+ }
+
+ /// 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> 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.
@@ -336,7 +727,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,
@@ -349,17 +740,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<typedef_decl>(ctxt->lookup_type(ctf_dictionary,
+ result = dynamic_pointer_cast<typedef_decl>(rdr->lookup_type(ctf_dictionary,
ctf_type));
if (result)
return result;
@@ -381,7 +772,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;
@@ -390,7 +781,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.
@@ -398,7 +789,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,
@@ -423,14 +814,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;
@@ -442,7 +833,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 */,
@@ -454,7 +845,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;
@@ -462,15 +853,15 @@ 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;
+ 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))
@@ -481,7 +872,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.
@@ -490,7 +881,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,
@@ -505,8 +896,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;
@@ -521,8 +912,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;
@@ -537,7 +928,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, "",
@@ -547,7 +938,7 @@ process_ctf_function_type(read_context *ctxt,
function_parms.push_back(parm);
}
- result = dynamic_pointer_cast<function_type>(ctxt->lookup_type(ctf_dictionary,
+ result = dynamic_pointer_cast<function_type>(rdr->lookup_type(ctf_dictionary,
ctf_type));
if (result)
return result;
@@ -564,7 +955,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;
@@ -572,7 +963,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.
@@ -580,7 +971,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,
@@ -606,9 +997,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;
@@ -632,14 +1023,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)
@@ -653,24 +1044,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(),
@@ -684,14 +1075,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.
@@ -700,7 +1091,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,
@@ -712,12 +1103,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,
@@ -734,12 +1125,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;
@@ -747,7 +1138,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.
@@ -756,7 +1147,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,
@@ -768,12 +1159,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(),
@@ -788,12 +1179,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;
@@ -801,7 +1192,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.
@@ -810,7 +1201,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,
@@ -831,20 +1222,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<array_type_def>(ctxt->lookup_type(ctf_dictionary,
+ result = dynamic_pointer_cast<array_type_def>(rdr->lookup_type(ctf_dictionary,
ctf_type));
if (result)
return result;
@@ -863,7 +1254,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,
@@ -884,7 +1275,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;
@@ -892,14 +1283,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,
@@ -908,12 +1299,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<type_base>(ctxt->lookup_type(ctf_dictionary,
+ result = dynamic_pointer_cast<type_base>(rdr->lookup_type(ctf_dictionary,
ctf_type));
if (result)
return result;
@@ -937,7 +1328,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;
@@ -945,7 +1336,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.
@@ -954,7 +1345,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,
@@ -965,13 +1356,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<pointer_type_def>(ctxt->lookup_type(ctf_dictionary,
+ result = dynamic_pointer_cast<pointer_type_def>(rdr->lookup_type(ctf_dictionary,
ctf_type));
if (result)
return result;
@@ -983,7 +1374,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;
@@ -991,7 +1382,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.
@@ -1000,7 +1391,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)
@@ -1009,7 +1400,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;
@@ -1019,7 +1410,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,
@@ -1050,154 +1441,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;
}
@@ -1256,162 +1502,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<translation_unit>(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.
///
@@ -1419,13 +1509,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_Scn*>(elf_section),
+ §ion_header_mem);
+ section_data = elf_getdata(const_cast<Elf_Scn*>(elf_section), 0);
ABG_ASSERT (section_header != NULL);
ABG_ASSERT (section_data != NULL);
@@ -1436,326 +1527,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<char**>::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<char**>::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<char**>& 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)
+elf_based_reader_sptr
+create_reader(const std::string& elf_path,
+ const vector<char**>& debug_info_root_paths,
+ environment& env)
{
- corpus_sptr corp
- = std::make_shared<corpus>(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)
-{
- 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.
@@ -1768,15 +1560,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,
+reset_reader(elf_based_reader& rdr,
+ const std::string& elf_path,
const vector<char**>& debug_info_root_path)
{
- if (ctxt)
- ctxt->initialize(elf_path, debug_info_root_path);
+ ctf::reader& r = dynamic_cast<reader&>(rdr);
+ r.initialize(elf_path, debug_info_root_path);
}
/// Returns a key to be use in types_map dict conformed by
@@ -1792,7 +1584,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;
@@ -1804,5 +1596,5 @@ dic_type_key(ctf_dict_t *dic, ctf_id_t ctf_type)
return key.str();
}
-} // End of namespace ctf_reader
+} // End of namespace ctf
} // End of namespace abigail
@@ -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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -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"
// <headers defining libabigail's API go under here>
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
// </headers defining libabigail's API>
@@ -56,7 +56,6 @@ ABG_END_EXPORT_DECLARATIONS
#endif
using std::string;
-using namespace abigail::elf_reader;
namespace abigail
{
@@ -64,7 +63,7 @@ namespace abigail
using std::cerr;
/// The namespace for the DWARF reader.
-namespace dwarf_reader
+namespace dwarf
{
using std::dynamic_pointer_cast;
@@ -91,16 +90,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> dwfl_sptr;
/// A convenience typedef for a vector of Dwarf_Off.
typedef vector<Dwarf_Off> dwarf_offsets_type;
@@ -143,13 +132,6 @@ typedef unordered_map<interned_string,
hash_interned_string>
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<GElf_Addr, elf_symbol_sptr> addr_elf_symbol_sptr_map_type;
-
-/// Convenience typedef for a set of ELF addresses.
-typedef unordered_set<GElf_Addr> 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 +226,23 @@ typedef unordered_map<std::pair<offset_type, offset_type>,
/// A convenience typedef for a vector of pairs of offset_type.
typedef vector<std::pair<offset_type, offset_type>> 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_type> 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_type> addr_elf_symbol_sptr_map_sptr;
@@ -379,13 +363,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 +452,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 +494,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,
@@ -535,32 +519,27 @@ get_internal_anonymous_die_name(Dwarf_Die *die,
size_t anonymous_type_index);
static string
-build_internal_underlying_enum_type_name(const string &base_name,
- bool is_anonymous,
- 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 +550,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 +558,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 +566,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 +593,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<char**> 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<char**>::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<char**> 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.
///
@@ -1533,120 +1309,6 @@ lookup_public_function_symbol_from_elf(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<string>& 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<string> 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;
- }
-}
-
// ---------------------------------------
// <location expression evaluation types>
// ---------------------------------------
@@ -2004,35 +1666,18 @@ struct dwarf_expr_eval_context
// </location expression evaluation types>
// ---------------------------------------
-/// 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> 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::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(environment& e)
- : env(e),
- 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 +1737,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 +1745,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 +1762,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<die_source_dependant_container_set*>(this)->
- get_container(ctxt, die);
+ get_container(rdr, die);
}
/// Clear the container set.
@@ -2133,28 +1778,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<char**> 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 +1834,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 +1850,6 @@ public:
offset_offset_map_type alternate_die_parent_map_;
offset_offset_map_type type_section_die_parent_map_;
list<var_decl_sptr> var_decls_to_add_;
- vector<string> 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 +1858,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 +1873,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,37 +1891,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<char**>& debug_info_root_paths,
- ir::environment& environment,
- bool load_all_types,
- bool linux_kernel_mode)
- : options_(environment)
+ reader(const string& elf_path,
+ const vector<char**>& 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,
- 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
@@ -2319,26 +1918,10 @@ public:
/// special linux kernel symbol tables when determining if a symbol
/// is exported or not.
void
- initialize(const string& elf_path,
- const vector<char**>& debug_info_root_paths,
- 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 +1941,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,19 +1951,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_.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();
@@ -2392,27 +1965,348 @@ 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<char**>& 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);
}
- /// Detructor of the @ref read_context type.
- ~read_context()
+ /// 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_sptr
+ create(const std::string& elf_path,
+ const vector<char**>& 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;
+ }
+
+ /// 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::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::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()->get_origin();
+ origin |= corpus::DWARF_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*>(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*>(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
@@ -2443,14 +2337,14 @@ public:
/// @return the current environment.
environment&
env()
- {return options_.env;}
+ {return options().env;}
/// Getter for the current environment.
///
/// @return the current environment.
const environment&
env() const
- {return const_cast<read_context*>(this)->env();}
+ {return const_cast<reader*>(this)->env();}
/// Getter for the flag that tells us if we are dropping functions
/// and variables that have undefined symbols.
@@ -2459,7 +2353,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.
@@ -2467,67 +2361,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<char**>& 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_;}
@@ -2536,47 +2372,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.
@@ -2585,7 +2383,7 @@ public:
/// info.
Elf*
dwarf_elf_handle() const
- {return dwarf_getelf(dwarf());}
+ {return dwarf_getelf(const_cast<Dwarf*>(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
@@ -2598,122 +2396,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<char **>& 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<char*>(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<char**>::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:
@@ -2722,25 +2422,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
@@ -2807,9 +2494,9 @@ public:
{
offset_offset_map_type &canonical_dies =
die_as_type
- ? const_cast<read_context*>(this)->canonical_type_die_offsets_.
+ ? const_cast<reader*>(this)->canonical_type_die_offsets_.
get_container(*this, die)
- : const_cast<read_context*>(this)->canonical_decl_die_offsets_.
+ : const_cast<reader*>(this)->canonical_decl_die_offsets_.
get_container(*this, die);
Dwarf_Die canonical_die;
@@ -2874,13 +2561,14 @@ public:
// with a vector of offsets of potentially equivalent DIEs.
istring_dwarf_offsets_map_type& map =
die_as_type
- ? (const_cast<read_context*>(this)->
+ ? (const_cast<reader*>(this)->
type_die_repr_die_offsets_maps().get_container(source))
- : (const_cast<read_context*>(this)->
+ : (const_cast<reader*>(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*>(dwarf_per_die_source(source)),
+ die_offset, &die));
// The variable repr is the the string representation of 'die'.
//
@@ -2955,9 +2643,9 @@ public:
offset_offset_map_type &canonical_dies =
die_as_type
- ? const_cast<read_context*>(this)->canonical_type_die_offsets_.
+ ? const_cast<reader*>(this)->canonical_type_die_offsets_.
get_container(source)
- : const_cast<read_context*>(this)->canonical_decl_die_offsets_.
+ : const_cast<reader*>(this)->canonical_decl_die_offsets_.
get_container(source);
Dwarf_Off die_offset = dwarf_dieoffset(const_cast<Dwarf_Die*>(die));
@@ -2972,9 +2660,9 @@ public:
// with a vector of offsets of potentially equivalent DIEs.
istring_dwarf_offsets_map_type& map =
die_as_type
- ? (const_cast<read_context*>(this)->
+ ? (const_cast<reader*>(this)->
type_die_repr_die_offsets_maps().get_container(*this, die))
- : (const_cast<read_context*>(this)->
+ : (const_cast<reader*>(this)->
decl_die_repr_die_offsets_maps().get_container(*this, die));
// The variable repr is the the string representation of 'die'.
@@ -3000,7 +2688,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<read_context&>(*this),
+ if (compare_dies_during_canonicalization(const_cast<reader&>(*this),
die, &canonical_die,
/*update_canonical_dies_on_the_fly=*/true))
{
@@ -3047,9 +2735,9 @@ public:
offset_offset_map_type &canonical_dies =
die_as_type
- ? const_cast<read_context*>(this)->canonical_type_die_offsets_.
+ ? const_cast<reader*>(this)->canonical_type_die_offsets_.
get_container(source)
- : const_cast<read_context*>(this)->canonical_decl_die_offsets_.
+ : const_cast<reader*>(this)->canonical_decl_die_offsets_.
get_container(source);
Dwarf_Off initial_die_offset = dwarf_dieoffset(const_cast<Dwarf_Die*>(die));
@@ -3069,9 +2757,9 @@ public:
// with a vector of offsets of potentially equivalent DIEs.
istring_dwarf_offsets_map_type& map =
die_as_type
- ? (const_cast<read_context*>(this)->
+ ? (const_cast<reader*>(this)->
type_die_repr_die_offsets_maps().get_container(*this, die))
- : (const_cast<read_context*>(this)->
+ : (const_cast<reader*>(this)->
decl_die_repr_die_offsets_maps().get_container(*this, die));
// The variable repr is the the string representation of 'die'.
@@ -3107,7 +2795,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<read_context&>(*this),
+ if (compare_dies_during_canonicalization(const_cast<reader&>(*this),
die, &canonical_die,
/*update_canonical_dies_on_the_fly=*/true))
{
@@ -3190,10 +2878,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;
@@ -3218,9 +2906,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*>(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*>(dwarf_per_die_source(source)),
+ offset, die));
}
public:
@@ -3323,8 +3013,8 @@ public:
if (i == map.end())
{
- read_context& ctxt = *const_cast<read_context*>(this);
- string qualified_name = die_qualified_name(ctxt, die, where_offset);
+ reader& rdr = *const_cast<reader*>(this);
+ string qualified_name = die_qualified_name(rdr, die, where_offset);
interned_string istr = env().intern(qualified_name);
map[die_offset] = istr;
return istr;
@@ -3348,7 +3038,7 @@ public:
interned_string
get_die_qualified_name(Dwarf_Die *die, size_t where_offset) const
{
- return const_cast<read_context*>(this)->
+ return const_cast<reader*>(this)->
get_die_qualified_name(die, where_offset);
}
@@ -3379,7 +3069,7 @@ public:
return env().intern("");
die_istring_map_type& map =
- die_qualified_name_maps_.get_container(*const_cast<read_context*>(this),
+ die_qualified_name_maps_.get_container(*const_cast<reader*>(this),
die);
size_t die_offset = dwarf_dieoffset(const_cast<Dwarf_Die*>(die));
@@ -3388,7 +3078,7 @@ public:
if (i == map.end())
{
- read_context& ctxt = *const_cast<read_context*>(this);
+ reader& rdr = *const_cast<reader*>(this);
string qualified_name;
int tag = dwarf_tag(const_cast<Dwarf_Die*>(die));
if ((tag == DW_TAG_structure_type
@@ -3402,7 +3092,7 @@ 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);
map[die_offset] = istr;
@@ -3434,7 +3124,7 @@ public:
{
ABG_ASSERT(die);
die_istring_map_type& map =
- die_pretty_type_repr_maps_.get_container(*const_cast<read_context*>(this),
+ die_pretty_type_repr_maps_.get_container(*const_cast<reader*>(this),
die);
size_t die_offset = dwarf_dieoffset(const_cast<Dwarf_Die*>(die));
@@ -3442,9 +3132,9 @@ public:
if (i == map.end())
{
- read_context& ctxt = *const_cast<read_context*>(this);
+ reader& rdr = *const_cast<reader*>(this);
string pretty_representation =
- die_pretty_print_type(ctxt, die, where_offset);
+ die_pretty_print_type(rdr, die, where_offset);
interned_string istr = env().intern(pretty_representation);
map[die_offset] = istr;
return istr;
@@ -3471,7 +3161,7 @@ public:
ABG_ASSERT(die);
die_istring_map_type& map =
- die_pretty_repr_maps_.get_container(*const_cast<read_context*>(this),
+ die_pretty_repr_maps_.get_container(*const_cast<reader*>(this),
die);
size_t die_offset = dwarf_dieoffset(const_cast<Dwarf_Die*>(die));
@@ -3479,9 +3169,9 @@ public:
if (i == map.end())
{
- read_context& ctxt = *const_cast<read_context*>(this);
+ reader& rdr = *const_cast<reader*>(this);
string pretty_representation =
- die_pretty_print(ctxt, die, where_offset);
+ die_pretty_print(rdr, die, where_offset);
interned_string istr = env().intern(pretty_representation);
map[die_offset] = istr;
return istr;
@@ -3696,7 +3386,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*>(dwarf_per_die_source(source)),
+ die_offset, &die));
return odr_is_relevant(&die);
}
@@ -3854,9 +3545,9 @@ public:
{
offset_offset_map_type &canonical_dies =
die_as_type
- ? const_cast<read_context*>(this)->canonical_type_die_offsets_.
+ ? const_cast<reader*>(this)->canonical_type_die_offsets_.
get_container(source)
- : const_cast<read_context*>(this)->canonical_decl_die_offsets_.
+ : const_cast<reader*>(this)->canonical_decl_die_offsets_.
get_container(source);
set_canonical_die_offset(canonical_dies,
@@ -3924,9 +3615,9 @@ public:
{
offset_offset_map_type &canonical_dies =
die_as_type
- ? const_cast<read_context*>(this)->canonical_type_die_offsets_.
+ ? const_cast<reader*>(this)->canonical_type_die_offsets_.
get_container(source)
- : const_cast<read_context*>(this)->canonical_decl_die_offsets_.
+ : const_cast<reader*>(this)->canonical_decl_die_offsets_.
get_container(source);
return get_canonical_die_offset(canonical_dies, die_offset);
@@ -3950,9 +3641,9 @@ public:
{
offset_offset_map_type &canonical_dies =
die_as_type
- ? const_cast<read_context*>(this)->canonical_type_die_offsets_.
+ ? const_cast<reader*>(this)->canonical_type_die_offsets_.
get_container(source)
- : const_cast<read_context*>(this)->canonical_decl_die_offsets_.
+ : const_cast<reader*>(this)->canonical_decl_die_offsets_.
get_container(source);
return canonical_dies.erase(die_offset);
@@ -3991,7 +3682,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.
///
@@ -4012,7 +3703,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.
///
@@ -4068,7 +3759,7 @@ public:
/// built.
const die_class_or_union_map_type&
die_wip_classes_map(die_source source) const
- {return const_cast<read_context*>(this)->die_wip_classes_map(source);}
+ {return const_cast<reader*>(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
@@ -4105,7 +3796,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<read_context*>(this)->die_wip_function_types_map(source);}
+ {return const_cast<reader*>(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
@@ -4321,7 +4012,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;
@@ -4557,7 +4248,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;
@@ -4686,7 +4377,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;
@@ -4724,7 +4415,7 @@ public:
void
fixup_functions_with_no_symbols()
{
- corpus_sptr corp = current_corpus();
+ corpus_sptr corp = corpus();
if (!corp)
return;
@@ -4808,7 +4499,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.
@@ -4819,9 +4510,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();
}
@@ -4842,7 +4533,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();
@@ -4862,9 +4553,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";
}
}
@@ -4940,7 +4631,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<read_context*>(this)->tu_die_imported_unit_points_map(source);}
+ {return const_cast<reader*>(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.
@@ -4967,127 +4658,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<read_context*>(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.
@@ -5097,7 +4673,7 @@ public:
/// @return the DIE -> parent map.
const offset_offset_map_type&
die_parent_map(die_source source) const
- {return const_cast<read_context*>(this)->die_parent_map(source);}
+ {return const_cast<reader*>(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.
@@ -5202,11 +4778,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.
@@ -5237,70 +4809,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.
@@ -5339,94 +4847,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<string>&
- 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<string> 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.
///
@@ -5661,159 +5081,12 @@ public:
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))
- return false;
-
- return suppr::suppression_matches_type_name_or_location(s, type_name,
- type_location);
- }
-
/// Getter of the exported decls builder object.
///
/// @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
@@ -5822,7 +5095,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
@@ -5831,15 +5104,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.
///
@@ -5849,7 +5122,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.
///
@@ -5859,7 +5132,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.
///
@@ -5869,44 +5142,16 @@ public:
/// return the "do_log" flag.
bool
do_log() const
- {return options_.do_log;}
-
- /// Setter of the "do_log" flag.
- ///
- /// This flag tells if we should log about various internal details.
- ///
- /// @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);
- }
+ {return options().do_log;}
- /// If a given variable decl is suitable for the set of exported
- /// variables of the current corpus, this variable adds it to that
- /// set.
+ /// Setter of the "do_log" flag.
+ ///
+ /// This flag tells if we should log about various internal details.
///
- /// @param fn the variable to consider for inclusion into the set of
- /// exported variables of the current corpus.
+ /// @param f the new value of the flag.
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);
- }
+ do_log(bool f)
+ {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
@@ -6039,13 +5284,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*>(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*>(dwarf_debug_info()),
+ die_offset, &cu))
continue;
uint64_t l = 0;
@@ -6062,13 +5309,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<Dwarf*>(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<Dwarf*>(alternate_dwarf_debug_info()),
+ die_offset, &cu))
continue;
cur_tu_die(&cu);
@@ -6084,13 +5333,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*>(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*>(dwarf_debug_info()),
+ die_offset, &cu))
continue;
cur_tu_die(&cu);
imported_unit_points_type& imported_units =
@@ -6107,7 +5358,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*>(dwarf_debug_info()),
+ offset, &next_offset, &header_size,
NULL, NULL, &address_size, NULL,
&type_signature, &type_offset) == 0);
offset = next_offset)
@@ -6115,7 +5367,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*>(dwarf_debug_info()),
+ die_offset, &cu))
continue;
cur_tu_die(&cu);
imported_unit_points_type& imported_units =
@@ -6124,7 +5377,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.
///
@@ -6138,8 +5391,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_;
@@ -6153,8 +5406,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
@@ -6369,13 +5622,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);
}
@@ -6406,32 +5659,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_++;
}
}
@@ -6469,7 +5722,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,
@@ -6478,13 +5731,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,
@@ -6494,7 +5747,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,
@@ -6503,25 +5756,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,
@@ -6529,20 +5782,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);
@@ -6551,78 +5804,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
///
@@ -6972,13 +6154,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();
@@ -6989,7 +6171,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;
}
@@ -7010,7 +6192,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.
///
@@ -7020,13 +6202,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);
}
@@ -7142,7 +6324,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))
@@ -7154,7 +6336,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);
@@ -7394,7 +6576,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.
///
@@ -7402,7 +6584,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)
@@ -7412,7 +6594,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;
@@ -7420,7 +6602,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.
///
@@ -7432,12 +6614,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;
@@ -7448,7 +6630,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.
///
@@ -7460,7 +6642,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)
@@ -7470,7 +6652,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;
@@ -7870,7 +7052,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.
///
@@ -7884,12 +7066,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);
@@ -8020,7 +7202,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.
///
@@ -8041,7 +7223,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,
@@ -8069,7 +7251,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
@@ -8082,7 +7264,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;
@@ -9433,14 +8615,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)
{
@@ -9481,7 +8663,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;
}
}
@@ -9498,7 +8680,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;
@@ -9664,29 +8846,6 @@ build_internal_anonymous_die_name(const string &base_name,
return name;
}
-/// Build the internal name of the underlying type of an enum.
-///
-/// @param base_name the (unqualified) name of the enum the underlying
-/// type is destined to.
-///
-/// @param is_anonymous true if the underlying type of the enum is to
-/// be anonymous.
-static string
-build_internal_underlying_enum_type_name(const string &base_name,
- bool is_anonymous,
- uint64_t size)
-{
- std::ostringstream o;
-
- if (is_anonymous)
- o << "unnamed-enum";
- else
- o << "enum-" << base_name;
-
- o << "-underlying-type-" << size;
-
- return o.str();
-}
/// Build a full internal anonymous type name.
///
@@ -9717,7 +8876,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.
///
@@ -9726,7 +8885,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)
{
@@ -9742,10 +8901,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 ? "::" : ".";
@@ -9828,7 +8987,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";
@@ -9861,7 +9020,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())
@@ -9891,7 +9050,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<read_context&>(ctxt),
+ build_subrange_type(const_cast<reader&>(rdr),
die, where_offset,
/*associate_die_to_type=*/false);
repr += s->as_string();
@@ -9904,12 +9063,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<read_context&>(ctxt),
+ build_subranges_from_array_type_die(const_cast<reader&>(rdr),
die, subranges, where_offset,
/*associate_type_to_die=*/false);
@@ -9927,7 +9086,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,
@@ -9977,7 +9136,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.
///
@@ -9985,7 +9144,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)
{
@@ -9995,10 +9154,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;
@@ -10012,7 +9171,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:
@@ -10038,7 +9197,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.
///
@@ -10046,12 +9205,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 "";
}
@@ -10062,7 +9221,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.
///
@@ -10073,7 +9232,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)
{
@@ -10096,19 +9255,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;
@@ -10126,7 +9285,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.
@@ -10152,7 +9311,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,
@@ -10169,22 +9328,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;
@@ -10215,8 +9374,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;
@@ -10240,11 +9399,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);
}
}
}
@@ -10252,7 +9411,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.
///
@@ -10261,14 +9420,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
@@ -10291,7 +9450,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())
@@ -10299,8 +9458,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;
@@ -10310,7 +9469,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);
@@ -10365,7 +9524,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.
///
@@ -10375,7 +9534,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)
{
@@ -10405,17 +9564,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;
@@ -10428,13 +9587,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;
@@ -10443,7 +9602,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;
@@ -10451,7 +9610,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;
@@ -10462,12 +9621,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;
@@ -10485,7 +9644,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;
@@ -10498,7 +9657,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,
@@ -10507,7 +9666,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;
@@ -10532,7 +9691,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.
///
@@ -10542,7 +9701,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)
{
@@ -10555,7 +9714,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:
@@ -10564,15 +9723,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:
@@ -10590,7 +9749,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.
///
@@ -10598,12 +9757,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 "";
}
@@ -10667,7 +9826,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.
///
@@ -10676,11 +9835,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))
@@ -10703,7 +9862,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.
///
@@ -10711,7 +9870,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)
{
@@ -10730,7 +9889,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;
@@ -10745,7 +9904,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.
///
@@ -10754,12 +9913,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;
@@ -10774,7 +9933,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.
///
@@ -10783,7 +9942,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)
{
@@ -10802,8 +9961,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;
@@ -10824,7 +9983,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.
///
@@ -10847,7 +10006,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,
@@ -10857,20 +10016,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)
@@ -11077,7 +10236,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.
@@ -11085,7 +10244,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)
{
@@ -11096,7 +10255,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
@@ -11106,7 +10265,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.
@@ -11114,7 +10273,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)
{
@@ -11125,8 +10284,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<Dwarf_Die*>(l));
Dwarf_Off r_offset = dwarf_dieoffset(const_cast<Dwarf_Die*>(r));
@@ -11137,12 +10296,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));
@@ -11152,14 +10311,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_++;
}
}
@@ -11214,7 +10373,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?
@@ -11279,7 +10438,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;
@@ -11291,7 +10450,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.
}
}
@@ -11333,7 +10492,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;
@@ -11341,7 +10500,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.
///
@@ -11363,7 +10522,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)
@@ -11371,8 +10530,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 =
{
@@ -11398,7 +10557,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;
@@ -11411,7 +10570,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,
@@ -11436,7 +10595,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;
@@ -11448,7 +10607,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;
@@ -11485,14 +10644,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
{
@@ -11500,7 +10659,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<Dwarf_Die*>(l),
&l_enumtor) == 0,
found_r_enumtor = dwarf_child(const_cast<Dwarf_Die*>(r),
@@ -11543,9 +10702,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
{
@@ -11554,7 +10713,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;
@@ -11578,7 +10737,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);
@@ -11614,7 +10773,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;
@@ -11631,7 +10790,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)
@@ -11649,7 +10808,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)
@@ -11699,22 +10858,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
@@ -11727,7 +10886,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)))
@@ -11754,7 +10913,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)
@@ -11796,7 +10955,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);
@@ -11812,8 +10971,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);
}
@@ -11824,7 +10983,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);
@@ -11839,7 +10998,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)
@@ -11857,8 +11016,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);
}
@@ -11874,7 +11033,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)
@@ -11882,7 +11041,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)
@@ -11941,7 +11100,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;
@@ -11953,7 +11112,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.
///
@@ -11968,25 +11127,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.
///
@@ -11997,20 +11156,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)
{
@@ -12020,7 +11179,7 @@ compare_dies_during_canonicalization(read_context& ctxt,
<< ", r: " << dwarf_dieoffset(const_cast<Dwarf_Die*>(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;
@@ -12028,7 +11187,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);
}
@@ -12039,7 +11198,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
@@ -12071,7 +11230,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,
@@ -12080,7 +11239,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);
@@ -12114,7 +11273,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,
@@ -12135,7 +11294,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,
@@ -12156,7 +11315,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
@@ -12174,7 +11333,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)
@@ -12182,7 +11341,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<Dwarf_Die*>(ctxt.cur_tu_die()),
+ if (dwarf_child(const_cast<Dwarf_Die*>(rdr.cur_tu_die()),
&first_die_of_tu) != 0)
return false;
@@ -12192,7 +11351,7 @@ find_import_unit_point_before_die(const read_context& ctxt,
cu_die = dwarf_diecu(const_cast<Dwarf_Die*>(&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,
@@ -12218,7 +11377,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.
///
@@ -12233,16 +11392,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<Dwarf_Die*>(die)));
@@ -12252,13 +11411,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<Dwarf*>(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<Dwarf*>(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<Dwarf*>(rdr.dwarf_debug_info()),
+ i->second, &parent_die));
break;
case NO_DEBUG_INFO_DIE_SOURCE:
case NUMBER_OF_DIE_SOURCES:
@@ -12269,12 +11431,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);
@@ -12283,15 +11445,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<Dwarf*>(rdr.dwarf_debug_info()),
+ import_point_offset,
+ &import_point_die));
+ return get_parent_die(rdr, &import_point_die,
parent_die, where_offset);
}
}
@@ -12310,7 +11472,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.
///
@@ -12319,12 +11481,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<Dwarf_Die*>(die)) != DW_TAG_member);
return dwarf_diecu(const_cast<Dwarf_Die*>(die), &scope_die, 0, 0);
@@ -12335,15 +11497,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;
}
@@ -12358,7 +11520,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.
///
@@ -12370,36 +11532,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
@@ -12410,7 +11572,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
@@ -12420,10 +11582,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;
@@ -12440,7 +11602,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))
@@ -12450,23 +11612,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<scope_decl>(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<class_decl>(d);
if (cl && cl->get_is_declaration_only())
@@ -12681,7 +11843,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.
///
@@ -12690,7 +11852,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)
{
@@ -12702,9 +11864,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 == "<artificial>")
@@ -12729,23 +11891,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)
@@ -12756,17 +11918,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<var_decl_sptr>::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))
@@ -12787,7 +11949,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)
{
@@ -12817,7 +11979,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);
@@ -12831,7 +11993,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.
@@ -12844,7 +12006,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)
{
@@ -12857,25 +12019,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
@@ -12884,14 +12046,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.
///
@@ -12899,7 +12061,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;
@@ -12918,21 +12080,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;
@@ -12942,19 +12104,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.
@@ -12965,7 +12127,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)
@@ -12974,11 +12136,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<type_decl>(d);
ABG_ASSERT(result);
@@ -12988,7 +12150,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.
///
@@ -13001,7 +12163,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,
@@ -13017,7 +12179,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.
@@ -13032,7 +12194,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
@@ -13043,10 +12205,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);
@@ -13054,14 +12216,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;
}
}
@@ -13087,7 +12249,7 @@ 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(n, val));
@@ -13100,7 +12262,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);
@@ -13108,9 +12270,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;
}
@@ -13127,12 +12289,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);
@@ -13229,7 +12391,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
@@ -13238,7 +12400,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())
@@ -13252,7 +12414,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.
///
@@ -13263,12 +12425,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);
@@ -13297,7 +12459,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.
@@ -13309,7 +12471,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)
@@ -13321,7 +12483,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)
@@ -13384,7 +12546,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.
///
@@ -13396,11 +12558,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();
@@ -13435,7 +12597,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.
@@ -13449,17 +12611,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));
@@ -13468,7 +12630,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;
}
@@ -13483,7 +12645,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.
@@ -13509,7 +12671,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,
@@ -13522,7 +12684,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);
@@ -13531,8 +12693,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);
@@ -13542,7 +12704,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())
@@ -13560,7 +12722,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
@@ -13580,7 +12742,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
@@ -13598,7 +12760,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;
@@ -13620,7 +12782,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));
@@ -13662,16 +12824,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)
@@ -13685,13 +12847,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<scope_decl>(res);
ABG_ASSERT(scop);
- ctxt.scope_stack().push(scop.get());
+ rdr.scope_stack().push(scop.get());
if (has_child && !is_incomplete_type)
{
@@ -13714,12 +12876,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));
}
@@ -13739,14 +12901,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);
@@ -13761,7 +12923,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
@@ -13778,19 +12940,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);
@@ -13826,18 +12988,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
@@ -13867,34 +13029,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.
///
@@ -13917,7 +13079,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,
@@ -13934,11 +13096,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);
@@ -13948,7 +13110,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())
@@ -13971,7 +13133,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);
@@ -13980,7 +13142,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;
}
}
@@ -13993,7 +13155,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;
@@ -14007,7 +13169,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)
@@ -14024,23 +13186,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<scope_decl>(result);
ABG_ASSERT(scop);
- ctxt.scope_stack().push(scop.get());
+ rdr.scope_stack().push(scop.get());
if (has_child)
{
@@ -14056,7 +13218,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
@@ -14067,7 +13229,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);
@@ -14093,14 +13255,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));
@@ -14110,31 +13272,31 @@ add_or_update_union_type(read_context& ctxt,
function_decl_sptr f = dynamic_pointer_cast<function_decl>(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);
}
}
@@ -14144,7 +13306,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.
///
@@ -14159,7 +13321,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)
@@ -14181,10 +13343,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)
@@ -14192,10 +13354,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;
}
@@ -14215,7 +13377,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;
}
@@ -14231,22 +13393,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))
{
@@ -14256,13 +13418,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);
}
}
@@ -14278,12 +13440,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;
@@ -14305,7 +13467,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();
@@ -14316,7 +13478,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);
@@ -14350,7 +13512,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);
}
}
@@ -14360,7 +13522,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.
///
@@ -14375,7 +13537,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)
@@ -14395,12 +13557,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)
@@ -14408,7 +13570,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);
@@ -14421,7 +13583,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.
@@ -14429,19 +13591,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.
///
@@ -14456,7 +13618,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)
@@ -14476,7 +13638,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)
@@ -14484,7 +13646,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);
@@ -14497,29 +13659,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.
///
@@ -14534,7 +13696,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)
@@ -14547,12 +13709,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);
@@ -14562,21 +13724,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
@@ -14587,9 +13749,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;
}
}
@@ -14602,7 +13764,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);
@@ -14620,7 +13782,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);
@@ -14637,20 +13799,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;
@@ -14665,7 +13827,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.
@@ -14675,7 +13837,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)
@@ -14692,7 +13854,7 @@ build_function_type(read_context& ctxt,
bool is_artificial = die_is_artificial(&child);
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=*/"",
@@ -14717,23 +13879,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.
///
@@ -14754,8 +13916,8 @@ 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,
- const Dwarf_Die* die,
+build_subrange_type(reader& rdr,
+ const Dwarf_Die* die,
size_t where_offset,
bool associate_type_to_die)
{
@@ -14777,7 +13939,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));
@@ -14791,7 +13953,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;
@@ -14847,7 +14009,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,
@@ -14863,7 +14025,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;
}
@@ -14872,7 +14034,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.
@@ -14885,7 +14047,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,
@@ -14907,7 +14069,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);
@@ -14916,7 +14078,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)
@@ -14929,7 +14091,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.
///
@@ -14944,7 +14106,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)
@@ -14962,7 +14124,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)
@@ -14970,7 +14132,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);
@@ -14982,7 +14144,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()));
@@ -14991,7 +14153,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.
///
@@ -15006,7 +14168,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)
@@ -15022,9 +14184,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);
@@ -15035,11 +14197,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));
@@ -15060,20 +14222,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.
///
@@ -15094,7 +14256,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,
@@ -15102,7 +14264,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))
@@ -15112,13 +14274,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.
///
@@ -15135,7 +14297,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)
@@ -15154,7 +14316,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)
@@ -15168,7 +14330,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));
@@ -15188,13 +14350,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)
@@ -15220,7 +14384,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.
///
@@ -15230,9 +14394,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)
@@ -15243,7 +14407,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);
@@ -15254,13 +14418,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())
@@ -15277,14 +14442,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
@@ -15300,7 +14464,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.
///
@@ -15323,7 +14487,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,
@@ -15331,7 +14495,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);
@@ -15355,11 +14519,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;
}
@@ -15378,7 +14542,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;
}
@@ -15387,7 +14551,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.
///
@@ -15398,9 +14562,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)
@@ -15412,7 +14576,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);
@@ -15424,10 +14588,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())
@@ -15444,16 +14609,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.
///
@@ -15466,9 +14632,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)
@@ -15482,10 +14648,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);
@@ -15493,9 +14660,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.
///
@@ -15503,14 +14670,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
@@ -15520,7 +14687,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.
///
@@ -15534,7 +14701,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)
@@ -15553,7 +14720,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;
@@ -15567,8 +14734,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)
@@ -15578,7 +14745,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,
@@ -15586,8 +14753,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;
}
}
@@ -15595,8 +14762,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)
@@ -15605,7 +14772,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,
@@ -15649,7 +14816,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.
///
@@ -15661,7 +14828,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)
@@ -15674,16 +14841,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)
{
@@ -15704,12 +14871,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,
@@ -15726,16 +14893,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();
@@ -15745,7 +14913,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);
@@ -15758,250 +14926,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<corpus>(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.
@@ -16015,10 +14943,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;
@@ -16040,9 +14968,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);
}
@@ -16112,10 +15040,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.
///
@@ -16144,7 +15072,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,
@@ -16161,7 +15089,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. */;
@@ -16172,12 +15100,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())
@@ -16196,10 +15124,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;
@@ -16210,7 +15138,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);
@@ -16218,7 +15146,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;
@@ -16226,15 +15154,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;
@@ -16243,16 +15171,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;
@@ -16262,7 +15190,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)
@@ -16270,7 +15198,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);
@@ -16278,10 +15206,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;
@@ -16290,7 +15218,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
@@ -16299,19 +15227,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);
}
}
}
@@ -16322,7 +15250,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)
{
@@ -16332,8 +15260,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)
{
@@ -16343,12 +15271,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,
@@ -16359,7 +15287,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,
@@ -16369,7 +15297,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,
@@ -16379,16 +15307,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,
@@ -16396,7 +15324,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;
}
@@ -16405,29 +15333,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;
}
@@ -16437,13 +15365,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;
@@ -16471,7 +15399,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:
@@ -16481,21 +15409,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,
@@ -16507,26 +15435,26 @@ build_ir_node_from_die(read_context& ctxt,
dynamic_pointer_cast<var_decl>(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))
@@ -16536,8 +15464,8 @@ build_ir_node_from_die(read_context& ctxt,
v = dynamic_pointer_cast<var_decl>(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;
@@ -16571,7 +15499,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)
@@ -16582,7 +15510,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,
@@ -16603,14 +15531,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);
@@ -16633,18 +15561,18 @@ build_ir_node_from_die(read_context& ctxt,
class_decl_sptr klass(static_cast<class_decl*>(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;
@@ -16709,11 +15637,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())
@@ -16724,46 +15652,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();
+ 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();
+ 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.
///
@@ -16782,7 +15712,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)
@@ -16790,10 +15720,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);
@@ -16808,34 +15738,35 @@ 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.
///
-/// @param elf_path the path to the elf file the context is to be used for.
+/// @param elf_path the path to the elf file the reader is to be used
+/// for.
///
-/// @param debug_info_root_paths a pointer to the path to the root
-/// directory under which the debug info is to be found for @p
-/// elf_path. Leave this to NULL if the debug info is not in a split
-/// file.
+/// @param debug_info_root_paths a vector to the paths to the
+/// directories under which the debug info is to be found for @p
+/// elf_path. Pass an empty vector 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
+/// 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
@@ -16847,33 +15778,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,
- const vector<char**>& debug_info_root_paths,
- ir::environment& environment,
- bool load_all_types,
- bool linux_kernel_mode)
+/// @return a smart pointer to the resulting dwarf::reader.
+elf_based_reader_sptr
+create_reader(const std::string& elf_path,
+ const vector<char**>& debug_info_root_paths,
+ 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<elf_based_reader>(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.
@@ -16884,14 +15809,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
@@ -16903,136 +15828,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<char**>& debug_info_root_path,
- bool read_all_types,
- bool linux_kernel_mode)
-{
- if (ctxt)
- ctxt->initialize(elf_path, debug_info_root_path,
- 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.
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_reader(elf_based_reader& rdr,
+ const std::string& elf_path,
+ const vector<char**>&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<reader&>(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
@@ -17051,7 +15857,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
@@ -17072,14 +15878,14 @@ read_corpus_from_elf(const std::string& elf_path,
const vector<char**>& debug_info_root_paths,
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::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
@@ -17171,219 +15977,6 @@ lookup_public_function_symbol_from_elf(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<char**> di_roots;
- di_roots.push_back(debug_info_root_path);
- environment env;
- read_context_sptr c = create_read_context(elf_path, di_roots, env);
- 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 dwarf
}// end namespace abigail
new file mode 100644
@@ -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"
+
+// <headers defining libabigail's API go under here>
+ABG_BEGIN_EXPORT_DECLARATIONS
+
+#include "abg-elf-based-reader.h"
+
+ABG_END_EXPORT_DECLARATIONS
+// </headers defining libabigail's API>
+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<char**>& debug_info_root_paths,
+ environment& env)
+ : elf::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<char**>& debug_info_root_paths)
+{
+ elf::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
@@ -6,11 +6,13 @@
/// @file
///
/// This contains the definitions of the ELF utilities for the dwarf reader.
-
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <elfutils/libdwfl.h>
#include "abg-elf-helpers.h"
-
-#include <elf.h>
-
#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<string>& 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
@@ -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> dwfl_sptr;
+
+/// Convenience typedef for a map which key is an elf address and
+/// which value is an elf_symbol_sptr.
+typedef unordered_map<GElf_Addr, elf_symbol_sptr> addr_elf_symbol_sptr_map_type;
+
+/// Convenience typedef for a set of ELF addresses.
+typedef unordered_set<GElf_Addr> address_set_type;
+
+/// Convenience typedef for a shared pointer to an @ref address_set_type.
+typedef shared_ptr<address_set_type> 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<string>& dt_tag_data);
+
+bool
+get_soname_of_elf_file(const string& path, string &soname);
} // end namespace elf_helpers
} // end namespace abigail
deleted file mode 100644
@@ -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"
-
-// <headers defining libabigail's API go under here>
-ABG_BEGIN_EXPORT_DECLARATIONS
-
-#include "abg-elf-reader-common.h"
-
-ABG_END_EXPORT_DECLARATIONS
-// </headers defining libabigail's API>
-
-namespace abigail
-{
-
-namespace elf_reader
-{
-
-status
-operator|(status l, status r)
-{
- return static_cast<status>(static_cast<unsigned>(l)
- | static_cast<unsigned>(r));
-}
-
-status
-operator&(status l, status r)
-{
- return static_cast<status>(static_cast<unsigned>(l)
- & static_cast<unsigned>(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
new file mode 100644
@@ -0,0 +1,954 @@
+// 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 <fcntl.h> /* For open(3) */
+#include <unistd.h>
+#include <iostream>
+#include <cstring>
+#include <libgen.h>
+#include <fcntl.h>
+#include <elfutils/libdwfl.h>
+
+
+#include "abg-symtab-reader.h"
+#include "abg-suppression-priv.h"
+#include "abg-elf-helpers.h"
+
+// <headers defining libabigail's API go under here>
+ABG_BEGIN_EXPORT_DECLARATIONS
+#include "abg-elf-reader.h"
+#include "abg-tools-utils.h"
+ABG_END_EXPORT_DECLARATIONS
+// </headers defining libabigail's API>
+namespace abigail
+{
+
+using namespace elf_helpers;
+
+namespace elf
+{
+
+/// 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<char**> 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<char**>::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<char**> 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 type.
+struct reader::priv
+{
+ reader& rdr;
+ Elf* elf_handle = nullptr;
+ Elf_Scn* symtab_section = nullptr;
+ string elf_architecture;
+ vector<string> 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<char**> 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<char**>& debug_info_roots)
+ : rdr(reeder)
+ {
+ rdr.corpus_path(elf_path);
+ initialize(debug_info_roots);
+ }
+
+ /// Reset the private data of @elf elf::reader.
+ ///
+ /// @param debug_info_roots the vector of new directories where to
+ /// look for split debug info file.
+ void
+ initialize(const vector<char**>& 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<char*>(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::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<char**>::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 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<char**>& 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 type.
+reader::~reader()
+{delete priv_;}
+
+/// Resets (erase) the resources used by the current @ref
+/// elf::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<char**>& 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<char**>&
+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<string>&
+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.
+///
+/// @return the 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.
+///
+/// @return the 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;
+}
+
+/// Test if a given function symbol has been exported.
+///
+/// @param name the name of the symbol we are looking for.
+///
+/// @return the elf symbol if found, or nil otherwise.
+elf_symbol_sptr
+reader::function_symbol_is_exported(const string& name) const
+{
+ const elf_symbols& syms = symtab()->lookup_symbol(name);
+ for (auto s : syms)
+ {
+ if (s->is_function() && s->is_public())
+ {
+ 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 (s->is_in_ksymtab())
+ return s;
+ }
+ else
+ return s;
+ }
+ }
+ return elf_symbol_sptr();
+}
+
+/// Test if a given variable symbol has been exported.
+///
+/// @param name the name of the symbol we are looking
+/// for.
+///
+/// @return the elf symbol if found, or nil otherwise.
+elf_symbol_sptr
+reader::variable_symbol_is_exported(const string& name) const
+{
+ const elf_symbols& syms = symtab()->lookup_symbol(name);
+ for (auto s : syms)
+ {
+ if (s->is_variable() && s->is_public())
+ {
+ 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 (s->is_in_ksymtab())
+ return s;
+ }
+ else
+ return s;
+ }
+ }
+ return elf_symbol_sptr();
+}
+/// 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<string> 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;
+
+ corpus::origin origin = corpus()->get_origin();
+ origin |= corpus::ELF_ORIGIN;
+ if (is_linux_kernel(elf_handle()))
+ origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN;
+ corpus()->set_origin(origin);
+
+ 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::elf_type
+elf_file_type(Elf* elf)
+{
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr *header = gelf_getehdr (elf, &ehdr_mem);
+ vector<string> 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::ELF_TYPE_PI_EXEC;
+ else
+ return elf::ELF_TYPE_DSO;
+ case ET_EXEC:
+ return elf::ELF_TYPE_EXEC;
+ case ET_REL:
+ return elf::ELF_TYPE_RELOCATABLE;
+ default:
+ return elf::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::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
+} // end namespace abigail
new file mode 100644
@@ -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"
+// <headers defining libabigail's API go under here>
+ABG_BEGIN_EXPORT_DECLARATIONS
+
+#include "abg-corpus.h"
+#include "abg-fe-iface.h"
+
+ABG_END_EXPORT_DECLARATIONS
+// </headers defining libabigail's API>
+
+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<ir::corpus>(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<fe_iface*>(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<fe_iface*>(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<fe_iface::status>(static_cast<unsigned>(l)
+ | static_cast<unsigned>(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<fe_iface::status>(static_cast<unsigned>(l)
+ & static_cast<unsigned>(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
@@ -1,5 +1,5 @@
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-// -*- mode: C++ -*-
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -*- mode:
+// C++ -*-
//
// Copyright (C) 2013-2022 Red Hat, Inc.
//
@@ -28,11 +28,11 @@ 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
// </headers defining libabigail's API>
+#include "abg-corpus-priv.h"
#include "abg-tools-utils.h"
#include "abg-comp-filter.h"
#include "abg-ir-priv.h"
@@ -26244,6 +26244,30 @@ get_function_parameter(const decl_base* fun,
return parms[parm_index].get();
}
+/// Build the internal name of the underlying type of an enum.
+///
+/// @param base_name the (unqualified) name of the enum the underlying
+/// type is destined to.
+///
+/// @param is_anonymous true if the underlying type of the enum is to
+/// be anonymous.
+string
+build_internal_underlying_enum_type_name(const string &base_name,
+ bool is_anonymous,
+ uint64_t size)
+{
+ std::ostringstream o;
+
+ if (is_anonymous)
+ o << "unnamed-enum";
+ else
+ o << "enum-" << base_name;
+
+ o << "-underlying-type-" << size;
+
+ return o.str();
+}
+
bool
ir_traversable_base::traverse(ir_node_visitor&)
{return true;}
@@ -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 <assert.h>
@@ -25,7 +25,7 @@
#include "abg-suppression-priv.h"
#include "abg-internal.h"
-#include "abg-tools-utils.h"
+#include "abg-symtab-reader.h"
// <headers defining libabigail's API go under here>
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
// </headers defining libabigail's API>
@@ -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
{
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<string>& 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<xmlNodePtr, decl_base_sptr> xml_node_decl_base_sptr_map;
- friend vector<type_base_sptr>* get_types_from_type_id(read_context&,
+ friend vector<type_base_sptr>* get_types_from_type_id(reader&,
const string&);
friend unordered_map<type_or_decl_base*, vector<type_or_decl_base*>>*
- 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<string, vector<type_base_sptr> > m_types_map;
unordered_map<string, shared_ptr<function_tdecl> > m_fn_tmpl_map;
unordered_map<string, shared_ptr<class_tdecl> > m_class_tmpl_map;
@@ -120,10 +145,6 @@ private:
xml::reader_sptr m_reader;
xmlNodePtr m_corp_node;
deque<shared_ptr<decl_base> > 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<type_or_decl_base*>> m_artifact_used_by_map;
#endif
- read_context();
+ reader();
public:
- read_context(xml::reader_sptr reader,
+ reader(xml::reader_sptr reader,
environment& env)
- : m_env(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,31 +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.
environment&
get_environment()
- {return m_env;}
+ {return options().env;}
/// Getter for the environment of this reader.
///
/// @return the environment of this reader.
const environment&
get_environment() const
- {return const_cast<read_context*>(this)->get_environment();}
+ {return const_cast<reader*>(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
@@ -742,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.
@@ -782,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<read_context*>(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.
@@ -829,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,
@@ -840,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
@@ -916,8 +844,8 @@ public:
void
maybe_check_abixml_canonical_type_stability(type_base_sptr& t)
{
- if (!get_environment().self_comparison_debug_is_on()
- || get_environment().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))
@@ -929,15 +857,15 @@ public:
// Let's get the type-id of this type as recorded in the
// originating abixml file.
string type_id =
- get_environment().get_type_id_from_pointer(reinterpret_cast<uintptr_t>(t.get()));
+ get_environment()->get_type_id_from_pointer(reinterpret_cast<uintptr_t>(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 = get_environment().get_type_id_canonical_type_map().find(type_id);
- if (j == get_environment().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: '"
@@ -1081,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())
@@ -1122,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.
///
@@ -1226,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<char*>(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<char*>(architecture_str.get()));
+
+ xml::xml_char_sptr soname_str =
+ XML_READER_GET_ATTRIBUTE(xml_reader, "soname");
+ string soname;
+
+ if (soname_str)
+ {
+ soname = reinterpret_cast<char*>(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) = <soname-or-file-name>
+ 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<char*>(path_str.get()));
+
+ xml::xml_char_sptr architecture_str =
+ XML_NODE_GET_ATTRIBUTE(node, "architecture");
+ if (architecture_str)
+ corp.set_architecture_name
+ (reinterpret_cast<char*>(architecture_str.get()));
+
+ xml::xml_char_sptr soname_str =
+ XML_NODE_GET_ATTRIBUTE(node, "soname");
+ if (soname_str)
+ corp.set_soname(reinterpret_cast<char*>(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<string> 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> 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&);
@@ -1257,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);
// <build a c++ class from an instance of xmlNodePtr>
//
@@ -1267,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<type_decl>
-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<pointer_type_def>
-build_pointer_type_def(read_context&, const xmlNodePtr, bool);
+build_pointer_type_def(reader&, const xmlNodePtr, bool);
static shared_ptr<reference_type_def>
-build_reference_type_def(read_context&, const xmlNodePtr, bool);
+build_reference_type_def(reader&, const xmlNodePtr, bool);
static shared_ptr<function_type>
-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<typedef_decl>
-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<function_tdecl>
-build_function_tdecl(read_context&, const xmlNodePtr, bool);
+build_function_tdecl(reader&, const xmlNodePtr, bool);
static shared_ptr<class_tdecl>
-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.
@@ -1364,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<type_base>
-build_type(read_context&, const xmlNodePtr, bool);
+build_type(reader&, const xmlNodePtr, bool);
// </build a c++ class from an instance of xmlNodePtr>
-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.
@@ -1416,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;
@@ -1470,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);
@@ -1521,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());
}
@@ -1534,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;
@@ -1550,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& rdr = dynamic_cast<abixml::reader&>(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");
@@ -1588,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;
}
@@ -1619,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;
@@ -1638,18 +1680,18 @@ get_or_read_and_add_translation_unit(read_context& ctxt, xmlNodePtr node)
tu_path = reinterpret_cast<char*>(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();
@@ -1659,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& rdr = dynamic_cast<abixml::reader&>(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;
@@ -1679,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")))
@@ -1692,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))
{
@@ -1706,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;
@@ -1729,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.
@@ -1739,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;
@@ -1773,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")))
@@ -1789,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;
}
@@ -1842,27 +1886,27 @@ build_needed(xmlNode* node, vector<string>& 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<string>& 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;
@@ -1877,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))
{
@@ -1893,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;
@@ -1918,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& rdr = dynamic_cast<abixml::reader&>(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.
@@ -1954,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<type_base_sptr>*
-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<xml_reader::reader&>(iface);
+ auto it = rdr.m_types_map.find(type_id);
+ if (it == rdr.m_types_map.end())
return nullptr;
return &it->second;
}
@@ -1971,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<type_or_decl_base*, vector<type_or_decl_base*>>*
-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<xml_reader::reader&>(iface);
+ return &rdr.m_artifact_used_by_map;
+}
#endif
/// Read the "version" attribute from the current XML element which is
@@ -2009,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<corpus>(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<char*>(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<char*>(architecture_str.get()));
-
- xml::xml_char_sptr soname_str =
- XML_READER_GET_ATTRIBUTE(reader, "soname");
- string soname;
-
- if (soname_str)
- {
- soname = reinterpret_cast<char*>(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) = <soname-or-file-name>
- 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<corpus>(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<char*>(path_str.get()));
-
- xml::xml_char_sptr architecture_str =
- XML_NODE_GET_ATTRIBUTE(node, "architecture");
- if (architecture_str)
- corp.set_architecture_name
- (reinterpret_cast<char*>(architecture_str.get()));
-
- xml::xml_char_sptr soname_str =
- XML_NODE_GET_ATTRIBUTE(node, "soname");
- if (soname_str)
- corp.set_soname(reinterpret_cast<char*>(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<string> 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& rdr = dynamic_cast<abixml::reader&>(iface);
+ xml::reader_sptr reader = rdr.get_libxml_reader();
if (!reader)
return nil;
@@ -2227,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);
@@ -2254,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
@@ -2278,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_reader(in, env);
+ return read_corpus_group_from_input(*rdr);
}
/// De-serialize an ABI corpus group from an XML document file which
@@ -2300,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,
+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_reader(path, env);
+ corpus_group_sptr group = read_corpus_group_from_input(*rdr);
return group;
}
@@ -2321,10 +2176,10 @@ translation_unit_sptr
read_translation_unit_from_file(const string& input_file,
environment& env)
{
- read_context ctxt(xml::new_reader_from_file(input_file), env);
- translation_unit_sptr tu = read_translation_unit_from_input(ctxt);
+ 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);
- ctxt.perform_late_type_canonicalizing();
+ rdr.perform_late_type_canonicalizing();
env.canonicalization_is_done(true);
return tu;
}
@@ -2343,10 +2198,10 @@ translation_unit_sptr
read_translation_unit_from_buffer(const string& buffer,
environment& env)
{
- read_context ctxt(xml::new_reader_from_buffer(buffer), env);
- translation_unit_sptr tu = read_translation_unit_from_input(ctxt);
+ reader rdr(xml::new_reader_from_buffer(buffer), env);
+ translation_unit_sptr tu = read_translation_unit_from_input(rdr);
env.canonicalization_is_done(false);
- ctxt.perform_late_type_canonicalizing();
+ rdr.perform_late_type_canonicalizing();
env.canonicalization_is_done(true);
return tu;
}
@@ -2354,17 +2209,18 @@ read_translation_unit_from_buffer(const string& buffer,
/// 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& rdr = dynamic_cast<abixml::reader&>(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;
}
@@ -2373,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);
@@ -2431,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)
{
@@ -2448,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<read_context&>(ctxt);
+ reader& c = const_cast<reader&>(rdr);
loc = c.get_translation_unit()->get_loc_mgr().create_new_location(file_path,
line,
column);
@@ -2470,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)
{
@@ -2491,7 +2347,7 @@ read_artificial_location(const read_context& ctxt,
if (node->doc)
file_path = reinterpret_cast<const char*>(node->doc->URL);
- read_context& c = const_cast<read_context&>(ctxt);
+ reader& c = const_cast<reader&>(rdr);
loc =
c.get_translation_unit()->get_loc_mgr().create_new_location(file_path,
line, column);
@@ -2507,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.
///
@@ -2515,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;
@@ -3076,7 +2932,7 @@ maybe_map_type_with_type_id(const type_base_sptr& t,
if (!t)
return false;
- const environment& env = t->get_environment();
+ const environment&env = t->get_environment();
if (!env.self_comparison_debug_is_on()
|| is_non_canonicalized_type(t.get()))
return false;
@@ -3093,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)
{
@@ -3108,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);
}
@@ -3119,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
@@ -3130,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)
{
@@ -3138,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<namespace_decl>(d);
ABG_ASSERT(result);
@@ -3150,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;
}
@@ -3171,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.
///
@@ -3180,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;
@@ -3244,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,
@@ -3274,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.
///
@@ -3283,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;
@@ -3303,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)
@@ -3317,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.
///
@@ -3325,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)
{
@@ -3343,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<xmlNodePtr, elf_symbol_sptr>
xml_node_ptr_elf_symbol_sptr_map_type;
@@ -3353,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;
@@ -3407,7 +3263,7 @@ build_elf_symbol_db(read_context& ctxt,
///
/// @param node the xml 'parameter' element node to de-serialize from.
static shared_ptr<function_decl::parameter>
-build_function_parameter(read_context& ctxt, const xmlNodePtr node)
+build_function_parameter(reader& rdr, const xmlNodePtr node)
{
shared_ptr<function_decl::parameter> nil;
@@ -3432,11 +3288,11 @@ 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);
@@ -3445,7 +3301,7 @@ build_function_parameter(read_context& ctxt, const xmlNodePtr node)
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,
@@ -3456,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.
///
@@ -3473,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)
@@ -3502,13 +3358,14 @@ 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();
std::vector<function_decl::parameter_sptr> parms;
type_base_sptr return_type = env.get_void_type();
@@ -3519,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")))
@@ -3529,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);
}
}
@@ -3553,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;
}
@@ -3577,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.
///
@@ -3595,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;
}
@@ -3617,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.
@@ -3625,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"))
@@ -3635,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.
///
@@ -3686,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"))
@@ -3715,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.
///
@@ -3733,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<var_decl>
-build_var_decl(read_context& ctxt,
+build_var_decl(reader& rdr,
const xmlNodePtr node,
bool add_to_current_scope)
{
@@ -3767,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);
@@ -3782,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())
@@ -3809,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.
///
@@ -3819,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<type_decl>
-build_type_decl(read_context& ctxt,
+build_type_decl(reader& rdr,
const xmlNodePtr node,
bool add_to_current_scope)
{
@@ -3828,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<type_decl>(d);
ABG_ASSERT(result);
@@ -3856,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.
@@ -3874,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;
}
@@ -3891,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.
///
@@ -3901,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)
{
@@ -3909,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<qualified_type_def>(d);
@@ -3924,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;
@@ -3955,11 +3812,11 @@ build_qualified_type_decl(read_context& ctxt,
ABG_ASSERT(!type_id.empty());
shared_ptr<type_base> 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);
@@ -3967,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.
///
@@ -3989,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)
{
@@ -3999,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<pointer_type_def>(d);
@@ -4012,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);
@@ -4023,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.
///
@@ -4065,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<reference_type_def>
-build_reference_type_def(read_context& ctxt,
+build_reference_type_def(reader& rdr,
const xmlNodePtr node,
bool add_to_current_scope)
{
@@ -4074,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<reference_type_def>(d);
@@ -4087,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);
@@ -4095,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);
@@ -4112,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;
}
@@ -4135,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.
///
@@ -4145,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*/)
{
@@ -4165,10 +4022,10 @@ 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);
- const environment& env = ctxt.get_environment();
+ const environment& env = rdr.get_environment();
std::vector<shared_ptr<function_decl::parameter> > parms;
type_base_sptr return_type = env.get_void_type();
@@ -4176,12 +4033,11 @@ build_function_type(read_context& ctxt,
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,
/*is_const=*/false,
@@ -4189,9 +4045,9 @@ build_function_type(read_context& ctxt,
: 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;
@@ -4200,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")))
@@ -4210,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));
}
}
@@ -4222,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.
@@ -4231,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;
@@ -4239,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<array_type_def::subrange_type>(d);
@@ -4256,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);
@@ -4298,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.
@@ -4325,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;
@@ -4336,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.
///
@@ -4346,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)
{
@@ -4356,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<array_type_def>(d);
@@ -4369,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);
@@ -4386,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<array_type_def>(d);
@@ -4419,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);
@@ -4428,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);
}
@@ -4442,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
@@ -4496,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.
@@ -4509,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.
///
@@ -4531,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)
{
@@ -4540,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<enum_type_decl>(d);
@@ -4557,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);
@@ -4613,21 +4469,21 @@ build_enum_type_decl(read_context& ctxt,
}
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;
}
@@ -4636,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<typedef_decl>
-build_typedef_decl(read_context& ctxt,
+build_typedef_decl(reader& rdr,
const xmlNodePtr node,
bool add_to_current_scope)
{
@@ -4652,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);
@@ -4664,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);
@@ -4676,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.
///
@@ -4707,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;
}
@@ -4721,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.
///
@@ -4730,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.
///
@@ -4753,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)
{
@@ -4762,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<class_decl>(d);
ABG_ASSERT(result);
@@ -4787,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;
@@ -4809,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);
@@ -4817,7 +4673,7 @@ build_class_decl(read_context& ctxt,
const vector<type_base_sptr> *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
@@ -4849,7 +4705,7 @@ build_class_decl(read_context& ctxt,
return previous_declaration;
}
- const environment& env = ctxt.get_environment();
+ const environment& env = rdr.get_environment();
if (!is_decl_only && previous_definition)
// We are in the case where we've read this class definition
@@ -4875,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;
@@ -4885,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;
@@ -4930,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;
@@ -4955,7 +4811,7 @@ build_class_decl(read_context& ctxt,
type_id = CHAR_STR(s);
shared_ptr<class_decl> b =
dynamic_pointer_cast<class_decl>
- (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()))
@@ -4986,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
@@ -5030,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))
{
@@ -5040,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.
@@ -5062,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);
}
}
}
@@ -5074,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
@@ -5102,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);
@@ -5121,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
@@ -5140,7 +4996,7 @@ build_class_decl(read_context& ctxt,
p = xmlNextElementSibling(p))
{
if (shared_ptr<function_tdecl> f =
- build_function_tdecl(ctxt, p,
+ build_function_tdecl(rdr, p,
/*add_to_current_scope=*/true))
{
shared_ptr<member_function_template> m
@@ -5150,7 +5006,7 @@ build_class_decl(read_context& ctxt,
decl->add_member_function_template(m);
}
else if (shared_ptr<class_tdecl> 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,
@@ -5163,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.
///
@@ -5181,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)
{
@@ -5190,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<union_decl>(d);
ABG_ASSERT(result);
@@ -5215,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;
@@ -5233,7 +5089,7 @@ build_union_decl(read_context& ctxt,
union_decl_sptr previous_definition, previous_declaration;
const vector<type_base_sptr> *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
@@ -5265,7 +5121,7 @@ build_union_decl(read_context& ctxt,
return previous_declaration;
}
- const environment& env = ctxt.get_environment();
+ const environment& env = rdr.get_environment();
if (!is_decl_only && previous_definition)
// We are in the case where we've read this class definition
@@ -5287,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;
@@ -5298,7 +5154,7 @@ build_union_decl(read_context& ctxt,
if (!def_id.empty())
{
class_decl_sptr d =
- dynamic_pointer_cast<class_decl>(ctxt.get_type_decl(def_id));
+ dynamic_pointer_cast<class_decl>(rdr.get_type_decl(def_id));
if (d && d->get_is_declaration_only())
{
is_def_of_decl = true;
@@ -5343,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;
@@ -5359,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);
@@ -5397,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))
{
@@ -5407,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,
@@ -5427,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);
}
}
}
@@ -5439,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);
@@ -5455,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);
@@ -5471,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);
@@ -5487,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
@@ -5497,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,
@@ -5510,7 +5366,7 @@ build_union_decl(read_context& ctxt,
}
}
- ctxt.pop_scope_or_abort(decl);
+ rdr.pop_scope_or_abort(decl);
return decl;
}
@@ -5518,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.
///
@@ -5528,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<function_tdecl>
-build_function_tdecl(read_context& ctxt,
+build_function_tdecl(reader& rdr,
const xmlNodePtr node,
bool add_to_current_scope)
{
@@ -5540,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);
@@ -5552,12 +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();
+ 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);
@@ -5565,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;
}
@@ -5584,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.
///
@@ -5594,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<class_tdecl>
-build_class_tdecl(read_context& ctxt,
+build_class_tdecl(reader& rdr,
const xmlNodePtr node,
bool add_to_current_scope)
{
@@ -5606,21 +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();
+ 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);
@@ -5628,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;
}
@@ -5651,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.
///
@@ -5664,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)
@@ -5678,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<type_tparameter>
- (ctxt.build_or_get_type_decl(type_id, true))))
+ (rdr.build_or_get_type_decl(type_id, true))))
abort();
string name;
@@ -5693,19 +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<decl_base>(result),
+ rdr.push_decl_to_current_scope(dynamic_pointer_cast<decl_base>(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);
-
- ctxt.maybe_canonicalize_type(result, /*force_delay=*/false);
+ rdr.maybe_canonicalize_type(result, /*force_delay=*/false);
return result;
}
@@ -5713,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.
///
@@ -5725,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)
@@ -5737,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<decl_base>(result),
+ rdr.push_decl_to_current_scope(dynamic_pointer_cast<decl_base>(result),
/*add_to_current_scope=*/true);
for (xmlNodePtr n = xmlFirstElementChild(node);
@@ -5745,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;
@@ -5770,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.
///
@@ -5783,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)
@@ -5798,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;
@@ -5806,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<decl_base>(r),
+ maybe_set_artificial_location(rdr, node, r);
+ rdr.push_decl_to_current_scope(dynamic_pointer_cast<decl_base>(r),
/*add_to_current_scope=*/true);
return r;
@@ -5819,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.
///
@@ -5831,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)
@@ -5853,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<template_tparameter>
- (ctxt.build_or_get_type_decl(type_id, true))))
+ (rdr.build_or_get_type_decl(type_id, true))))
abort();
string name;
@@ -5861,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;
@@ -5874,7 +5729,7 @@ build_template_tparameter(read_context& ctxt,
n;
n = xmlNextElementSibling(n))
if (shared_ptr<template_parameter> p =
- build_template_parameter(ctxt, n, parm_index, result))
+ build_template_parameter(rdr, n, parm_index, result))
{
result->add_template_parameter(p);
++parm_index;
@@ -5882,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;
@@ -5892,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.
///
@@ -5905,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<template_parameter> 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);
@@ -5961,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;
}
@@ -6234,8 +6089,8 @@ handle_class_tdecl(read_context& ctxt,
translation_unit_sptr
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<typename T>
struct array_deleter
@@ -6248,21 +6103,20 @@ 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_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->corpus());
@@ -6271,7 +6125,7 @@ create_native_xml_read_context(const string& path, environment& env)
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.
@@ -6279,14 +6133,13 @@ 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_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->corpus());
@@ -6294,13 +6147,6 @@ create_native_xml_read_context(std::istream* in, environment& env)
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'.
///
@@ -6314,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_reader(in, env);
+ fe_iface::status sts;
+ return rdr->read_corpus(sts);
}
/// De-serialize an ABI corpus from an XML document file which root
@@ -6335,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_reader(path, env);
+ fe_iface::status sts;
+ corpus_sptr corp = rdr->read_corpus(sts);
return corp;
}
@@ -6357,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<xml_reader::reader&>(iface)
+
xmlDocPtr doc = xmlReadFile(file_path.c_str(), NULL, XML_PARSE_NOERROR);
if (!doc)
return false;
@@ -6423,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;
@@ -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 <typename ReadContextType>
-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;
-}
-// </function_suppression stuff>
-
// <variable_suppression stuff>
/// 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 <typename ReadContextType>
-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;
-}
-
// </variable_suppression stuff>
// <type_suppression stuff>
@@ -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 <typename ReadContextType>
-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 <typename ReadContextType>
-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<typename ReadContextType>
-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;
-}
-
// </type_suppression stuff>
}// end namespace suppr
@@ -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
// </headers defining libabigail's API>
@@ -2932,78 +2933,6 @@ operator|(function_suppression::change_kind l,
(static_cast<unsigned>(l) | static_cast<unsigned>(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;
+}
// </variable_suppression stuff>
// <file_suppression stuff>
@@ -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());
}
-
// </file_suppression stuff>
+
+/// 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
@@ -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<char**>& debug_info_root_paths)
+{
+ if (guess_file_type(elf_file_path) != FILE_TYPE_ELF)
+ return false;
+
+ environment env;
+ elf::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<char**>& debug_info_root_paths)
+{
+ if (guess_file_type(elf_file_path) != FILE_TYPE_ELF)
+ return false;
+
+ environment env;
+ elf::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<string>& suppr_paths,
vector<string>& 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
@@ -2542,15 +2592,16 @@ maybe_load_vmlinux_dwarf_corpus(corpus::origin origin,
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,
- /*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::create_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();
@@ -2561,7 +2612,7 @@ maybe_load_vmlinux_dwarf_corpus(corpus::origin origin,
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 '"
@@ -2569,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)
@@ -2594,18 +2645,17 @@ maybe_load_vmlinux_dwarf_corpus(corpus::origin origin,
<< "/" << total_nb_modules
<< ") ... " << std::flush;
- reset_read_context(ctxt, *m, di_roots,
- /*read_all_types=*/false,
- /*linux_kernel_mode=*/true);
+ dwarf::reset_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 '"
@@ -2656,11 +2706,13 @@ maybe_load_vmlinux_ctf_corpus(corpus::origin origin,
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);
+ abigail::fe_iface::status status = abigail::fe_iface::STATUS_OK;
+ elf_based_reader_sptr rdr =
+ ctf::create_reader(vmlinux, di_roots, env);
+ ABG_ASSERT(rdr);
+
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 '"
@@ -2668,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)
@@ -2693,12 +2745,11 @@ maybe_load_vmlinux_ctf_corpus(corpus::origin origin,
<< "/" << total_nb_modules
<< ") ... " << std::flush;
- reset_read_context(ctxt, *m, di_roots);
- set_read_context_corpus_group(*ctxt, group);
+ ctf::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 '"
@@ -2799,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<char**>& 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::create_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::create_reader(elf_file_path,
+ debug_info_root_paths,
+ env);
+#endif
+ else
+ result = dwarf::create_reader(elf_file_path,
+ debug_info_root_paths,
+ env);
+
+ return result;
+}
+
}//end namespace tools_utils
using abigail::ir::function_decl;
@@ -1,4 +1,7 @@
<abi-corpus version='2.1' path='data/test-read-ctf/test0'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='__libc_csu_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='__libc_csu_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -1,4 +1,7 @@
<abi-corpus version='2.1' path='data/test-read-ctf/test0'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='__libc_csu_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='__libc_csu_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -1,4 +1,7 @@
<abi-corpus version='2.1' path='data/test-read-ctf/test1.so'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='fn' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
@@ -1,4 +1,7 @@
<abi-corpus version='2.1' path='data/test-read-ctf/test1.so'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='fn' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
@@ -1,4 +1,7 @@
<abi-corpus version='2.1' path='data/test-read-ctf/test2.so'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='bar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -1,4 +1,7 @@
<abi-corpus version='2.1' path='data/test-read-ctf/test2.so'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='bar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -1,4 +1,7 @@
-<abi-corpus version='2.1' path='data/test-read-common/test3.so'>
+<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='__foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='__foo__' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -1,4 +1,7 @@
-<abi-corpus version='2.1' path='data/test-read-common/test3.so'>
+<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='__foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='__foo__' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -1,4 +1,7 @@
<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
@@ -1,4 +1,7 @@
<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
+ <elf-needed>
+ <dependency name='libc.so.6'/>
+ </elf-needed>
<elf-function-symbols>
<elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
@@ -24,7 +24,6 @@ using abigail::comparison::compute_diff;
using abigail::comparison::print_diff_tree;
using abigail::comparison::apply_filters;
using namespace abigail;
-using namespace abigail::dwarf_reader;
struct options
{
@@ -101,24 +100,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 env;
vector<char**> di_roots;
- 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)
+ c1 = dwarf::read_corpus_from_elf(opts.elf1, di_roots, env,
+ /*load_all_types=*/false,
+ c1_status);
+ 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,
- /*load_all_types=*/false,
- c2_status);
- if (c2_status != elf_reader::STATUS_OK)
+ c2 = dwarf::read_corpus_from_elf(opts.elf2, di_roots, env,
+ /*load_all_types=*/false,
+ c2_status);
+ if (c2_status != fe_iface::STATUS_OK)
{
cerr << "Failed to read elf file " << opts.elf2 << "\n";
return 1;
@@ -171,15 +171,14 @@ 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::comparison::corpus_diff_sptr;
using abigail::comparison::translation_unit_diff_sptr;
using abigail::comparison::compute_diff;
using abigail::comparison::diff_context_sptr;
using abigail::comparison::diff_context;
+using namespace abigail;
+
int
main(int, char*[])
{
@@ -217,12 +216,12 @@ main(int, char*[])
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);
+ tu1 = abixml::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);
+ corpus1 = abixml::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_nat