Implement string interning for Libabigail

This patch implements string interning optimization.  One can read
about the principles of this optimization at
https://en.wikipedia.org/wiki/String_interning.

The patch introduces an abigail::interned_string type, as well as an
abigail::interned_string_pool type.  Each environment type owns a
string pool and strings are interned in that pool for all types and
decls of that environments.  The interned_string has methods to
interact seemingly with std::string including a hashing function.  Of
course hashing and comparing interned_string is faster than for
std::string.

To enable ABI artifacts to intern strings, each constructor of ABI
artifacts now takes the environment it's constructed in as parameter.
From the environment, it can thus use the interned string pool.

The patch then changes declaration names to be of type
interned_string, and performs the necessary adjustments.  The hash
maps that hash strings coming from those declaration names are
adjusted to hash interned_string.

	* include/Makefile.am: Add the new abg-interned-str.h file to
	source distribution.
	* include/abg-corpus.h (corpus::corpus): Re-arrange the order of
	* src/abg-corpus.cc
	(corpus::exported_decls_builder::priv::get_id): Return
	interned_string rather than std::string.
	(corpus::corpus): Re-arrange the order of parameters: take an
	environment as first parameter.  parameters: take an environment
	as first parameter.
	* include/abg-dwarf-reader.h (lookup_symbol_from_elf)
	(lookup_public_function_symbol_from_elf): Likewise.
	* src/abg-dwarf-reader.cc (lookup_symbol_from_sysv_hash_tab)
	(lookup_symbol_from_gnu_hash_tab)
	(lookup_symbol_from_elf_hash_tab, lookup_symbol_from_symtab)
	(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf)
	(lookup_public_variable_symbol_from_elf, lookup_symbol_from_elf)
	(lookup_public_function_symbol_from_elf): Take an environment as
	first parameter and adjust.
	(build_translation_unit_and_add_to_ir)
	(build_namespace_decl_and_add_to_ir, build_type_decl)
	(build_enum_type, finish_member_function_reading)
	(build_class_type_and_add_to_ir, build_function_type)
	(read_debug_info_into_corpus, read_corpus_from_elf): Adjust.
	* include/abg-fwd.h: Include abg-interned-str.h
	(get_type_name, get_function_type_name, get_method_type_name):
	Return a interned_string, rather than a std::string.
	* include/abg-interned-str.h: New declarations for interned strings
	and their pool.
	* include/abg-ir.h (environment::intern): Declare new method.
	(elf_symbol::{g,s}et_environment): Likewise.
	(type_or_decl_base::type_or_decl_base): Make the default
	constructor private.
	({translation, type_or_decl_base}::set_environment)
	(set_environment_for_artifact): Take a const environment*.
	(elf_symbol::elf_symbol)
	(elf_symbol::create)
	(type_or_decl_base::type_or_decl_base)
	(translation::translation, decl_base::decl_base)
	(scope_decl::scope_decl, type_base::type_base)
	(type_decl::type_decl, scope_type_decl::scope_type_decl)
	(namespace_decl::namespace_decl)
	(enum_type_decl::enumerator::enumerator)
	(function_type::function_type, method_type::method_type)
	(template_decl::template_decl, function_tdecl::function_tdecl)
	(class_tdecl::class_tdecl, class_decl::class_decl): Take an
	environment.
	(type_or_decl_base::operator=)
	(enum_type_decl::enumerator::get_environment): Declare new method.
	(decl_base::{peek_qualified_name, peek_temporary_qualified_name,
	get_qualified_name, get_name, get_qualified_parent_name,
	get_linkage_name}, qualified_type_def::get_qualified_name)
	(reference_type_def::get_qualified_name)
	(array_type_def::get_qualified_name)
	(enum_type_decl::enumerator::{get_name, get_qualified_name})
	({var,function}_decl::get_id)
	(function_decl::parameter::{get_type_name, get_name_id}): Return
	an interned_string, rather than a std::string.
	(decl_base::{set_qualified_name, set_temporary_qualified_name,
	get_qualified_name, set_linkage_name})
	(qualified_type_def::get_qualified_name)
	(reference_type_def::get_qualified_name)
	(array_type_def::get_qualified_name)
	(function_decl::parameter::get_qualified_name): Take an
	interned_string, rather than a std::string.
	(class_decl::member_{class,function}_template::member_{class,function}_template):
	Adjust.
	* src/abg-ir.cc (environment_setter::env_): Make this be a pointer
	to const environment.
	(environment_setter::visit_begin): Adjust.
	(interned_string_pool::priv): Define new type.
	(interned_string_pool::*): Define the method declared in
	abg-interned-str. h.
	(operator==, operator!=, operator+): Define operator for interned_string and
	std::string
	(operator<<): Define for interned_string.
	(translation_unit::priv::env_): Make this be a pointer to const
	environment.
	(translation_unit::priv::priv): Take a pointer to const
	environment.
	(elf_symbol::priv::env_): New data member.
	(elf_symbol::priv::priv): Adjust.  Make an overoad take an
	environment.
	(translation_unit::{g,s}et_environment): Adjust.
	(interned_string_bool_map_type): New typedef.
	(environment::priv::classes_being_compared_): Make this hastable
	of string be a hashtable of interned_string.
	(environment::priv::string_pool_): New data member.
	(environment::{get_void_type_decl,
	get_variadic_parameter_type_decl}): Adjust.
	(type_or_decl_base::priv::env_): Make this be a pointer to const
	environment.
	(type_or_decl::base::priv::priv): Adjust.
	(type_or_decl_base::set_environment)
	(set_environment_for_artifact): Take a pointer to const
	environment.
	(elf_symbol::{g,s}et_environment, environment::intern)
	(type_or_decl_base::operator=): Define new methods.
	(decl_base::priv::{name_, qualified_parent_name_,
	temporary_qualified_name_, qualified_name_, linkage_name_}): Make
	these data member be of tpe interned_string.
	(decl_base::priv::priv): Make this take an environment. Adjust.
	(decl_base::{peek_qualified_name, peek_temporary_qualified_name,
	get_linkage_name, get_qualified_parent_name, get_name,
	get_qualified_name}, get_type_name, get_function_type_name)
	(get_method_type_name, get_node_name)
	(qualified_type_def::get_qualified_name)
	(pointer_type_def::get_qualified_name)
	(array_type_def::get_qualified_name)
	(enum_type_decl::enumerator::get_qualified_name)
	(var_decl::get_id, function_decl::get_id)
	(function_decl::parameter::get_{name_id, type_name}): Return an
	interned_string.
	(decl_base::{set_qualified_name, set_temporary_qualified_name})
	(qualified_type_def::get_qualified_name)
	(pointer_type_def::get_qualified_name)
	(reference_type_def::get_qualified_name)
	(array_type_def::get_qualified_name)
	(function_decl::parameter::get_qualified_name): Take an
	interned_string.
	(decl_base::{set_name, set_linkage_name}): Intern the std::string
	passed in parameter.
	(equals): In the overload for decl_base, adjust for a little speed
	optimization that is justified by profiling.
	(pointer_type_def::priv::{internal_qualified_name_,
	temp_internal_qualified_name_}): Make these data member be
	interned_string.
	(enum_type_decl::enumerator::priv::env_): New data member.
	(enum_type_decl::enumerator::priv::{name_, qualified_name}): Make
	these data member be of type interned_string.
	(enum_type_decl::enumerator::get_environment): New method.
	(enum_type_decl::enumerator::priv::priv) Adjust.
	(typedef_decl::operator==): Implement a little speed optimization.
	(var_decl::priv::nake_type_): New data member.
	(var_decl::priv::id_): Make this data member be of type
	interned_string.
	(equals): In the overload for var_decl, function_type,
	function_decl, adjust for the use of interned_string.
	(function_decl::priv::id_): Make this be of type interned_string.
	(scope_decl::{add_member_decl, insert_member_decl})
	(lookup_function_type_in_translation_unit)
	(synthesize_type_from_translation_unit, lookup_node_in_scope)
	(lookup_type_in_scope, scope_decl::scope_decl)
	(qualified_type_def::qualified_type_def)
	(qualified_type_def::get_qualified_name)
	(pointer_type_def::pointer_type_def)
	(reference_type_def::reference_type_def)
	(array_type_def::array_type_def, array_type_def::append_subrange)
	(array_type_def::get_qualified_name)
	(enum_type_decl::enum_type_decl)
	(enum_type_decl::enumerator::get_qualified_name)
	(enum_type_decl::enumerator::set_name)
	(typedef_decl::typedef_decl, var_decl::var_decl)
	(function_type::function_type, method_type::method_type)
	(function_decl::function_decl)
	(function_decl::parameter::parameter)
	(class_decl::priv::comparison_started)
	(class_decl::add_base_specifier)
	(class_decl::base_spec::base_spec)
	(class_decl::method_decl::method_decl)
	(type_tparameter::type_tparameter)
	(non_type_tparameter::non_type_tparameter)
	(template_tparameter::template_tparameter)
	(type_composition::type_composition)
	(function_tdecl::function_tdecl, class_tdecl::class_tdecl)
	(qualified_name_setter::do_update): Adjust.
	(translation_unit::translation_unit, elf_symbol::elf_symbol)
	(elf_symbol::create, type_or_decl_base::type_or_decl_base)
	(decl_base::decl_base, type_base::type_base)
	(type_decl::type_decl, scope_type_decl::scope_type_decl)
	(namespace_decl::namespace_decl)
	(enum_type_decl::enumerator::enumerator, class_decl::class_decl)
	(template_decl::template_decl, function_tdecl::function_tdecl)
	(class_tdecl::class_tdecl): Take an environment.
	* src/abg-comparison.cc
	(function_suppression::suppresses_function): Adjust.
	* src/abg-reader.cc (read_translation_unit)
	(read_corpus_from_input, build_namespace_decl, build_elf_symbol)
	(build_function_parameter, build_function_decl, build_type_decl)
	(build_function_type, build_enum_type_decl, build_enum_type_decl)
	(build_class_decl, build_function_tdecl, build_class_tdecl)
	(read_corpus_from_native_xml): Likewise.
	* src/abg-writer.cc (id_manager::m_cur_id): Make this mutable.
	(id_manager::m_env): New data member.
	(id_manager::id_manager): Adjust.
	(id_manager::get_environment): New method.
	(id_manager::{get_id, get_id_with_prefix}): Return an
	interned_string.
	(type_ptr_map): Make this be a hash map of type_base* ->
	interned_string, rather a type_base* -> string.
	(write_context::m_env): New data member.
	(write_context::m_type_id_map): Make this data member be mutable.
	(write_context::m_emitted_type_id_map): Make this be a hash map of
	interned_string -> bool, rather than string -> bool.
	(write_context::write_context): Take an environment and adjust.
	(write_context::get_environment): New method.
	(write_context::get_id_manager): New const overload.
	(write_context::get_id_for_type): Return an interned_string; adjust.
	(write_context::{record_type_id_as_emitted,
	record_type_as_referenced}): Adjust.
	(write_context::type_id_is_emitted): Take an interned_string.
	(write_context::{type_is_emitted,
	record_decl_only_type_as_emitted}): Adjust.
	(write_translation_unit, write_corpus_to_native_xml, dump):
	Adjust.
	* tools/abisym.cc (main): Adjust.
	* tests/data/test-read-write/test22.xml: Adjust.
	* tests/data/test-read-write/test23.xml: Adjust.
	* tests/data/test-read-write/test26.xml: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2016-02-24 07:44:29 +01:00
parent 445923157d
commit cf8eba68c3
16 changed files with 1458 additions and 600 deletions

View File

@ -1,5 +1,6 @@
pkginclude_HEADERS = \
abg-sptr-utils.h \
abg-interned-str.h \
abg-ir.h \
abg-corpus.h \
abg-reader.h \

View File

@ -81,14 +81,14 @@ private:
public:
corpus(const string&, ir::environment*);
environment*
get_environment();
corpus(ir::environment*, const string&);
const environment*
get_environment() const;
environment*
get_environment();
void
set_environment(environment*) const;

View File

@ -103,13 +103,15 @@ read_corpus_from_elf(const std::string& elf_path,
status&);
bool
lookup_symbol_from_elf(const string& elf_path,
lookup_symbol_from_elf(const environment* env,
const string& elf_path,
const string& symbol_name,
bool demangle,
vector<elf_symbol_sptr>& symbols);
bool
lookup_public_function_symbol_from_elf(const string& path,
lookup_public_function_symbol_from_elf(const environment* env,
const string& path,
const string& symname,
vector<elf_symbol_sptr>& func_syms);

View File

@ -32,6 +32,7 @@
#include <typeinfo>
#include <utility> // for std::rel_ops, at least.
#include <ostream>
#include "abg-interned-str.h"
#include "abg-hash.h"
/// Toplevel namespace for libabigail.
@ -533,37 +534,38 @@ get_type_scope(type_base*);
scope_decl*
get_type_scope(const shared_ptr<type_base>&);
string
interned_string
get_type_name(const shared_ptr<type_base>,
bool qualified = true,
bool internal = false);
string
interned_string
get_type_name(const type_base*,
bool qualified = true,
bool internal = false);
string
interned_string
get_type_name(const type_base&,
bool qualified = true,
bool internal = false);
string
interned_string
get_function_type_name(const shared_ptr<function_type>&,
bool internal = false);
string
interned_string
get_function_type_name(const function_type*, bool internal = false);
string
interned_string
get_function_type_name(const function_type&, bool internal = false);
string
interned_string
get_method_type_name(const shared_ptr<method_type>&, bool internal = false);
string
interned_string
get_method_type_name(const method_type*, bool internal = false);
string
interned_string
get_method_type_name(const method_type&, bool internal = false);
string

247
include/abg-interned-str.h Normal file
View File

@ -0,0 +1,247 @@
// -*- Mode: C++ -*-
//
// Copyright (C) 2016 Red Hat, Inc.
//
// This file is part of the GNU Application Binary Interface Generic
// Analysis and Instrumentation Library (libabigail). This library is
// free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 3, or (at your option) any
// later version.
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Lesser Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this program; see the file COPYING-LGPLV3. If
// not, see <http://www.gnu.org/licenses/>.
//
// Author: Dodji Seketeli
/// @file
///
/// Declaration of types pertaining to the interned string pool used
/// throughout Libabigail, for performance reasons.
///
/// For the record, the concept of the String Interning method is
/// explained at https://en.wikipedia.org/wiki/String_interning.
#ifndef __ABG_INTERNED_STR_H__
#define __ABG_INTERNED_STR_H__
#include <tr1/memory>
#include <tr1/functional>
#include <ostream>
#include <string>
using std::tr1::shared_ptr;
namespace abigail
{
/// The abstraction of an interned string.
///
/// It's a wrapper around a pointer to a std::string, along with a set
/// of method that helps make this string integrate with std::string
/// seamlessly. For instance, the type provides equality operators
/// that help compare it against std::string.
///
/// Note that this @ref interned_string type is design to have the
/// same size as a pointer to a string.
class interned_string
{
std::string* raw_;
/// Constructor.
///
/// @param raw the pointer to string that this interned_string
/// wraps.
interned_string(std::string* raw)
: raw_(raw)
{}
public:
/// Default constructor.
///
/// Constructs an empty pointer to string.
interned_string()
: raw_()
{}
/// Copy constructor.
///
/// @param o the other instance to copy from.
interned_string(const interned_string& o)
{raw_ = o.raw_;}
/// Test if the current instance of @ref interned_string is empty.
///
/// @return true iff the currentisntance of @ref interned_string is
/// empty.
bool
empty() const
{return !raw_;}
/// Return the underlying pointer to std::string that this
/// interned_string wraps.
///
/// @return a pointer to the underlying std::string, or 0 if this
/// interned_string is empty.
const std::string*
raw() const
{return raw_;}
/// Compare the current instance of @ref interned_string against
/// another instance of @ref interned_string.
///
/// Note that this comparison is done in O(1), because it compares
/// the pointer values of the two underlying pointers to std::string
/// held by each instances of @ref interned_string.
///
/// @param o the other @ref interned_string to compare against.
///
/// @return true iff the current instance equals @p o.
bool
operator==(const interned_string& o) const
{return raw_ == o.raw_;}
/// Inequality operator.
///
/// @param o the other @ref interned_string to compare the current
/// instance against.
///
/// @return true iff the current instance is different from the @p
/// o.
bool
operator!=(const interned_string& o) const
{return !operator==(o);}
/// Compare the current instance of @ref interned_string against
/// an instance of std::string.
///
/// Note that this comparison is done in O(N), N being the size (in
/// number of characters) of the strings being compared.
///
/// @param o the instance of std::string to compare against.
///
/// @return true iff the current instance equals @p o.
bool
operator==(const std::string& o) const
{
if (raw_)
return *raw_ == o;
return o.empty();
}
/// Inequality operator.
///
/// Takes the current instance of @ref interned_string and an
/// instance of std::string.
///
/// @param o the instance of std::string to compare the current
/// instance of @ref interned_string against.
///
/// @return true if the current instance of @ref interned_string is
/// different from @p o.
bool
operator!=(const std::string& o) const
{return ! operator==(o);}
/// "Less than" operator.
///
/// Lexicographically compares the current instance of @ref
/// interned_string against another instance.
///
/// @param o the other instance of @ref interned_string to compare
/// against.
///
/// @return true iff the current instance of interned_string is
/// lexicographycally less than the string @p o.
bool
operator<(const interned_string& o) const
{return static_cast<std::string>(*this) < static_cast<std::string>(o);}
/// Conversion operator to string.
///
/// @return the underlying string this instance refers too.
operator std::string() const
{
if (!raw_)
return "";
return *raw_;
}
friend class interned_string_pool;
}; // end class interned_string
bool
operator==(const std::string& l, const interned_string& r);
bool
operator!=(const std::string& l, const interned_string& r);
std::ostream&
operator<<(std::ostream& o, const interned_string& s);
std::string
operator+(const interned_string& s1,const std::string& s2);
std::string
operator+(const std::string& s1, const interned_string& s2);
/// A functor to hash instances of @ref interned_string.
struct hash_interned_string
{
/// The hash operator.
///
/// It's super fast because hashing an interned string amounts to
/// hashing the pointer to it's underlying string. It's because
/// every distinct string is present only in one copy in the
/// environment.
///
/// @param s the instance of @ref interned_string to hash.
///
/// @return the returned hash value.
size_t
operator()(const interned_string& s) const
{
std::tr1::hash<size_t> hash_size_t;
return hash_size_t(reinterpret_cast<size_t>(s.raw()));
}
}; // end struct hash_interned_string
/// The interned string pool.
///
/// This is where all the distinct strings represented by the interned
/// strings leave. The pool is the actor responsible for creating
/// interned strings.
class interned_string_pool
{
struct priv;
typedef shared_ptr<priv> priv_sptr;
priv_sptr priv_;
public:
interned_string_pool();
interned_string
create_string(const std::string&);
bool
has_string(const char* s) const;
const char*
get_string(const char* s) const;
~interned_string_pool();
}; // end class interned_string_pool
} // end namespace abigail
#endif // __ABG_INTERNED_STR_H__

View File

@ -167,6 +167,9 @@ public:
void
canonicalization_is_done(bool);
interned_string
intern(const string&) const;
friend class class_decl;
friend void keep_type_alive(type_base_sptr);
@ -389,9 +392,9 @@ public:
};
public:
translation_unit(const std::string& path,
ir::environment* env,
char address_size = 0);
translation_unit(const ir::environment* env,
const std::string& path,
char address_size = 0);
virtual ~translation_unit();
@ -402,7 +405,7 @@ public:
get_environment();
void
set_environment(environment*);
set_environment(const environment*);
language
get_language() const;
@ -577,7 +580,8 @@ private:
elf_symbol();
elf_symbol(size_t i,
elf_symbol(const environment* e,
size_t i,
size_t s,
const string& n,
type t,
@ -597,14 +601,21 @@ public:
create();
static elf_symbol_sptr
create(size_t i,
size_t s,
const string& n,
type t,
binding b,
bool d,
bool c,
const version& v);
create(const environment* e,
size_t i,
size_t s,
const string& n,
type t,
binding b,
bool d,
bool c,
const version& v);
const environment*
get_environment() const;
void
set_environment(const environment*) const;
size_t
get_index() const;
@ -927,6 +938,8 @@ class type_or_decl_base : public ir_traversable_base
typedef shared_ptr<priv> priv_sptr;
mutable priv_sptr priv_;
type_or_decl_base();
protected:
bool hashing_started() const;
@ -935,7 +948,7 @@ protected:
public:
type_or_decl_base();
type_or_decl_base(const environment*);
type_or_decl_base(const type_or_decl_base&);
@ -948,7 +961,7 @@ public:
get_environment();
void
set_environment(environment*);
set_environment(const environment*);
const corpus*
get_corpus() const;
@ -959,6 +972,9 @@ public:
const translation_unit*
get_translation_unit() const;
type_or_decl_base&
operator=(const type_or_decl_base&);
virtual bool
traverse(ir_node_visitor&);
@ -977,11 +993,11 @@ operator!=(const type_or_decl_base_sptr&, const type_or_decl_base_sptr&);
void
set_environment_for_artifact(type_or_decl_base* artifact,
environment* env);
const environment* env);
void
set_environment_for_artifact(type_or_decl_base_sptr artifact,
environment* env);
const environment* env);
/// The base type of all declarations.
class decl_base : public virtual type_or_decl_base
@ -993,17 +1009,17 @@ class decl_base : public virtual type_or_decl_base
protected:
const string&
const interned_string&
peek_qualified_name() const;
void
set_qualified_name(const string&) const;
set_qualified_name(const interned_string&) const;
const string&
const interned_string&
peek_temporary_qualified_name() const;
void
set_temporary_qualified_name(const string&) const;
set_temporary_qualified_name(const interned_string&) const;
public:
// This is public because some internals of the library need to
@ -1054,11 +1070,19 @@ protected:
set_context_rel(context_rel_sptr c);
public:
decl_base(const std::string& name, const location& locus,
const std::string& mangled_name = "",
decl_base(const environment* e,
const string& name,
const location& locus,
const string& mangled_name = "",
visibility vis = VISIBILITY_DEFAULT);
decl_base(const location&);
decl_base(const environment* e,
const interned_string& name,
const location& locus,
const interned_string& mangled_name = interned_string(),
visibility vis = VISIBILITY_DEFAULT);
decl_base(const environment*, const location&);
decl_base(const decl_base&);
@ -1080,9 +1104,10 @@ public:
get_pretty_representation(bool internal = false) const;
virtual void
get_qualified_name(string& qualified_name, bool internal = false) const;
get_qualified_name(interned_string& qualified_name,
bool internal = false) const;
virtual const string&
virtual const interned_string&
get_qualified_name(bool internal = false) const;
bool
@ -1097,10 +1122,10 @@ public:
void
set_location(const location& l);
const string&
const interned_string&
get_name() const;
const string&
const interned_string&
get_qualified_parent_name() const;
void
@ -1112,11 +1137,11 @@ public:
void
set_is_anonymous(bool);
const string&
const interned_string&
get_linkage_name() const;
virtual void
set_linkage_name(const std::string& m);
set_linkage_name(const string& m);
scope_decl*
get_scope() const;
@ -1230,13 +1255,16 @@ protected:
public:
struct hash;
scope_decl(const std::string& name, const location& locus,
scope_decl(const environment* env,
const string& name, const location& locus,
visibility vis = VISIBILITY_DEFAULT)
: type_or_decl_base(),
decl_base(name, locus, /*mangled_name=*/name, vis)
: type_or_decl_base(env),
decl_base(env, name, locus, /*mangled_name=*/name, vis)
{}
scope_decl(location& l) : decl_base("", l)
scope_decl(const environment* env, location& l)
: type_or_decl_base(env),
decl_base(env, "", l)
{}
virtual size_t
@ -1317,8 +1345,10 @@ class global_scope : public scope_decl
translation_unit* translation_unit_;
global_scope(translation_unit *tu)
: decl_base("", location()), scope_decl("", location()),
translation_unit_(tu)
: type_or_decl_base(tu->get_environment()),
decl_base(tu->get_environment(), "", location()),
scope_decl(tu->get_environment(), "", location()),
translation_unit_(tu)
{}
public:
@ -1373,7 +1403,7 @@ public:
/// runtime type of the type pointed to.
struct shared_ptr_hash;
type_base(size_t s, size_t a);
type_base(const environment* e, size_t s, size_t a);
friend type_base_sptr
canonicalize(type_base_sptr);
@ -1475,12 +1505,13 @@ public:
/// Facility to hash instance of type_decl
struct hash;
type_decl(const std::string& name,
size_t size_in_bits,
size_t alignment_in_bits,
const location& locus,
const std::string& mangled_name = "",
visibility vis = VISIBILITY_DEFAULT);
type_decl(const environment* env,
const string& name,
size_t size_in_bits,
size_t alignment_in_bits,
const location& locus,
const string& mangled_name = "",
visibility vis = VISIBILITY_DEFAULT);
virtual bool
operator==(const type_base&) const;
@ -1521,9 +1552,9 @@ public:
/// Hasher for instances of scope_type_decl
struct hash;
scope_type_decl(const std::string& name, size_t size_in_bits,
size_t alignment_in_bits, const location& locus,
visibility vis = VISIBILITY_DEFAULT);
scope_type_decl(const environment* env, const string& name,
size_t size_in_bits, size_t alignment_in_bits,
const location& locus, visibility vis = VISIBILITY_DEFAULT);
virtual bool
operator==(const decl_base&) const;
@ -1545,8 +1576,8 @@ class namespace_decl : public scope_decl
{
public:
namespace_decl(const std::string& name, const location& locus,
visibility vis = VISIBILITY_DEFAULT);
namespace_decl(const environment* env, const string& name,
const location& locus, visibility vis = VISIBILITY_DEFAULT);
virtual string
get_pretty_representation(bool internal = false) const;
@ -1620,9 +1651,10 @@ public:
get_underlying_type() const;
virtual void
get_qualified_name(string& qualified_name, bool internal = false) const;
get_qualified_name(interned_string& qualified_name,
bool internal = false) const;
virtual const string&
virtual const interned_string&
get_qualified_name(bool internal = false) const;
virtual bool
@ -1687,9 +1719,9 @@ public:
get_pointed_to_type() const;
virtual void
get_qualified_name(string&, bool internal = false) const;
get_qualified_name(interned_string&, bool internal = false) const;
virtual const string&
virtual const interned_string&
get_qualified_name(bool internal = false) const;
virtual bool
@ -1744,9 +1776,10 @@ public:
is_lvalue() const;
virtual void
get_qualified_name(string& qualified_name, bool internal = false) const;
get_qualified_name(interned_string& qualified_name,
bool internal = false) const;
virtual const string&
virtual const interned_string&
get_qualified_name(bool internal = false) const;
virtual bool
@ -1851,9 +1884,10 @@ public:
operator==(const type_base&) const;
virtual void
get_qualified_name(string& qualified_name, bool internal = false) const;
get_qualified_name(interned_string& qualified_name,
bool internal = false) const;
virtual const string&
virtual const interned_string&
get_qualified_name(bool internal = false) const;
const type_base_sptr
@ -1983,7 +2017,7 @@ public:
enumerator();
enumerator(const string& name, int64_t value);
enumerator(const environment* env, const string& name, int64_t value);
enumerator(const enumerator&);
@ -1993,10 +2027,13 @@ public:
bool
operator!=(const enumerator& other) const;
const string&
const environment*
get_environment() const;
const interned_string&
get_name() const;
const string&
const interned_string&
get_qualified_name(bool internal = false) const;
void
@ -2191,7 +2228,7 @@ public:
var_decl_sptr
clone() const;
const string&
interned_string
get_id() const;
virtual size_t
@ -2338,7 +2375,7 @@ public:
virtual size_t
get_hash() const;
const string&
interned_string
get_id() const;
virtual bool
@ -2394,13 +2431,13 @@ public:
const type_base_sptr
get_type()const;
const string
interned_string
get_type_name() const;
const string
get_type_pretty_representation() const;
const string
interned_string
get_name_id() const;
unsigned
@ -2431,7 +2468,8 @@ public:
get_hash() const;
virtual void
get_qualified_name(string& qualified_name, bool internal = false) const;
get_qualified_name(interned_string& qualified_name,
bool internal = false) const;
virtual string
get_pretty_representation(bool internal = false) const;
@ -2494,8 +2532,9 @@ public:
size_t size_in_bits,
size_t alignment_in_bits);
function_type(size_t size_in_bits,
size_t alignment_in_bits);
function_type(const environment* env,
size_t size_in_bits,
size_t alignment_in_bits);
type_base_sptr
get_return_type() const;
@ -2576,7 +2615,8 @@ public:
size_t size_in_bits,
size_t alignment_in_bits);
method_type(size_t size_in_bits,
method_type(const environment* env,
size_t size_in_bits,
size_t alignment_in_bits);
class_decl_sptr
@ -2615,7 +2655,8 @@ public:
/// Hasher.
struct hash;
template_decl(const string& name,
template_decl(const environment* env,
const string& name,
const location& locus,
visibility vis = VISIBILITY_DEFAULT);
@ -2871,7 +2912,8 @@ public:
struct hash;
struct shared_ptr_hash;
function_tdecl(const location& locus,
function_tdecl(const environment* env,
const location& locus,
visibility vis = VISIBILITY_DEFAULT,
binding bind = BINDING_NONE);
@ -2924,7 +2966,8 @@ public:
struct hash;
struct shared_ptr_hash;
class_tdecl(const location& locus, visibility vis = VISIBILITY_DEFAULT);
class_tdecl(const environment* env, const location& locus,
visibility vis = VISIBILITY_DEFAULT);
class_tdecl(class_decl_sptr pattern,
const location& locus,
@ -3010,16 +3053,18 @@ protected:
public:
class_decl(const std::string& name, size_t size_in_bits,
size_t align_in_bits, bool is_struct,
const location& locus, visibility vis,
base_specs& bases, member_types& mbrs,
data_members& data_mbrs, member_functions& member_fns);
class_decl(const environment* env, const string& name,
size_t size_in_bits, size_t align_in_bits,
bool is_struct, const location& locus,
visibility vis, base_specs& bases,
member_types& mbrs, data_members& data_mbrs,
member_functions& member_fns);
class_decl(const std::string& name, size_t size_in_bits,
size_t align_in_bits, bool is_struct,
const location& locus, visibility vis);
class_decl(const std::string& name, bool is_struct,
class_decl(const environment* env, const string& name,
size_t size_in_bits, size_t align_in_bits,
bool is_struct, const location& locus, visibility vis);
class_decl(const environment* env, const string& name, bool is_struct,
bool is_declaration_only = true);
virtual void
@ -3593,7 +3638,8 @@ public:
member_function_template(function_tdecl_sptr f,
access_specifier access, bool is_static,
bool is_constructor, bool is_const)
: decl_base(f->get_name(), location()),
: type_or_decl_base(f->get_environment()),
decl_base(f->get_environment(), f->get_name(), location()),
member_base(access, is_static), is_constructor_(is_constructor),
is_const_(is_const), fn_tmpl_(f)
{}
@ -3643,9 +3689,10 @@ public:
/// Hasher.
struct hash;
member_class_template(shared_ptr<class_tdecl> c,
member_class_template(class_tdecl_sptr c,
access_specifier access, bool is_static)
: decl_base(c->get_name(), location()),
: type_or_decl_base(c->get_environment()),
decl_base(c->get_environment(), c->get_name(), location()),
member_base(access, is_static),
class_tmpl_(c)
{}

View File

@ -2697,8 +2697,9 @@ function_suppression::suppresses_function(const function_decl* fn,
// properties matches.
string fn_return_type_name = fn->get_type()->get_return_type()
? (get_type_declaration(fn->get_type()->get_return_type())
->get_qualified_name())
? static_cast<string>
((get_type_declaration(fn->get_type()->get_return_type())
->get_qualified_name()))
: "";
if (!get_return_type_name().empty())

View File

@ -304,7 +304,7 @@ public:
/// @param fn the function to calculate the ID for.
///
/// @return a reference to a string representing the function ID.
const string&
interned_string
get_id(const function_decl& fn)
{return fn.get_id();}
@ -313,7 +313,7 @@ public:
/// @param var the variable to calculate the ID for.
///
/// @return a reference to a string representing the variable ID.
const string&
interned_string
get_id(const var_decl& var)
{return var.get_id();}
@ -1173,10 +1173,10 @@ corpus::lookup_canonical_type(const string& qualified_name) const
/// Constructor of the @ref corpus type.
///
/// @param path the path to the file containing the ABI corpus.
///
/// @param env the environment of the corpus.
corpus::corpus(const string& path, ir::environment* env)
///
/// @param path the path to the file containing the ABI corpus.
corpus::corpus(ir::environment* env, const string& path)
{priv_.reset(new priv(path, env));}
/// Getter of the enviroment of the corpus.

View File

@ -1192,6 +1192,8 @@ get_version_for_symbol(Elf* elf_handle,
///
/// Use it at your own risks. :-)
///
///@parm env the environment we are operating from.
///
/// @param elf_handle the elf_handle to use.
///
/// @param sym_name the symbol name to look for.
@ -1208,7 +1210,8 @@ get_version_for_symbol(Elf* elf_handle,
/// @param syms_found a vector of symbols found with the name @p
/// sym_name. table.
static bool
lookup_symbol_from_sysv_hash_tab(Elf* elf_handle,
lookup_symbol_from_sysv_hash_tab(const environment* env,
Elf* elf_handle,
const string& sym_name,
size_t ht_index,
size_t sym_tab_index,
@ -1272,7 +1275,8 @@ lookup_symbol_from_sysv_hash_tab(Elf* elf_handle,
/*get_def_version=*/true, ver))
assert(!ver.str().empty());
elf_symbol_sptr symbol_found =
elf_symbol::create(symbol_index,
elf_symbol::create(env,
symbol_index,
sym_size,
sym_name_str,
sym_type,
@ -1473,7 +1477,8 @@ setup_gnu_ht(Elf* elf_handle,
///
/// @return true if a symbol was actually found.
static bool
lookup_symbol_from_gnu_hash_tab(Elf* elf_handle,
lookup_symbol_from_gnu_hash_tab(const environment* env,
Elf* elf_handle,
const string& sym_name,
size_t ht_index,
size_t sym_tab_index,
@ -1547,7 +1552,7 @@ lookup_symbol_from_gnu_hash_tab(Elf* elf_handle,
assert(!ver.str().empty());
elf_symbol_sptr symbol_found =
elf_symbol::create(i, symbol.st_size, sym_name_str,
elf_symbol::create(env, i, symbol.st_size, sym_name_str,
sym_type, sym_binding,
symbol.st_shndx != SHN_UNDEF,
symbol.st_shndx == SHN_COMMON,
@ -1571,6 +1576,8 @@ lookup_symbol_from_gnu_hash_tab(Elf* elf_handle,
/// This function uses the elf hash table (be it the GNU hash table or
/// the sysv hash table) for the symbol lookup.
///
/// @param env the environment we are operating from.
///
/// @param elf_handle the elf handle to use.
///
/// @param ht_kind the kind of hash table to use. This is returned by
@ -1592,7 +1599,8 @@ lookup_symbol_from_gnu_hash_tab(Elf* elf_handle,
/// @return true iff the function found the symbol from the elf hash
/// table.
static bool
lookup_symbol_from_elf_hash_tab(Elf* elf_handle,
lookup_symbol_from_elf_hash_tab(const environment* env,
Elf* elf_handle,
hash_table_kind ht_kind,
size_t ht_index,
size_t symtab_index,
@ -1607,13 +1615,15 @@ lookup_symbol_from_elf_hash_tab(Elf* elf_handle,
return false;
if (ht_kind == SYSV_HASH_TABLE_KIND)
return lookup_symbol_from_sysv_hash_tab(elf_handle, symbol_name,
return lookup_symbol_from_sysv_hash_tab(env,
elf_handle, symbol_name,
ht_index,
symtab_index,
demangle,
syms_found);
else if (ht_kind == GNU_HASH_TABLE_KIND)
return lookup_symbol_from_gnu_hash_tab(elf_handle, symbol_name,
return lookup_symbol_from_gnu_hash_tab(env,
elf_handle, symbol_name,
ht_index,
symtab_index,
demangle,
@ -1623,6 +1633,9 @@ lookup_symbol_from_elf_hash_tab(Elf* elf_handle,
/// Lookup a symbol from the symbol table directly.
///
///
/// @param env the environment we are operating from.
///
/// @param elf_handle the elf handle to use.
///
/// @param sym_name the name of the symbol to look up.
@ -1643,7 +1656,8 @@ lookup_symbol_from_elf_hash_tab(Elf* elf_handle,
///
/// @return true iff the symbol was found.
static bool
lookup_symbol_from_symtab(Elf* elf_handle,
lookup_symbol_from_symtab(const environment* env,
Elf* elf_handle,
const string& sym_name,
size_t sym_tab_index,
bool demangle,
@ -1687,7 +1701,8 @@ lookup_symbol_from_symtab(Elf* elf_handle,
ver))
assert(!ver.str().empty());
elf_symbol_sptr symbol_found =
elf_symbol::create(i, sym->st_size, name_str, sym_type,
elf_symbol::create(env, i, sym->st_size,
name_str, sym_type,
sym_binding, sym_is_defined,
sym_is_common, ver);
syms_found.push_back(symbol_found);
@ -1704,6 +1719,8 @@ lookup_symbol_from_symtab(Elf* elf_handle,
/// Look into the symbol tables of the underlying elf file and see
/// if we find a given symbol.
///
/// @param env the environment we are operating from.
///
/// @param symbol_name the name of the symbol to look for.
///
/// @param demangle if true, try to demangle the symbol name found in
@ -1727,7 +1744,8 @@ lookup_symbol_from_symtab(Elf* elf_handle,
///
/// @return true iff a symbol with the name @p symbol_name was found.
static bool
lookup_symbol_from_elf(Elf* elf_handle,
lookup_symbol_from_elf(const environment* env,
Elf* elf_handle,
const string& symbol_name,
bool demangle,
vector<elf_symbol_sptr>& syms_found)
@ -1745,14 +1763,16 @@ lookup_symbol_from_elf(Elf* elf_handle,
if (!find_symbol_table_section_index(elf_handle, symbol_table_index))
return false;
return lookup_symbol_from_symtab(elf_handle,
return lookup_symbol_from_symtab(env,
elf_handle,
symbol_name,
symbol_table_index,
demangle,
syms_found);
}
return lookup_symbol_from_elf_hash_tab(elf_handle,
return lookup_symbol_from_elf_hash_tab(env,
elf_handle,
ht_kind,
hash_table_index,
symbol_table_index,
@ -1764,6 +1784,8 @@ lookup_symbol_from_elf(Elf* elf_handle,
/// Look into the symbol tables of the underlying elf file and see if
/// we find a given public (global or weak) symbol of function type.
///
/// @param env the environment we are operating from.
///
/// @param elf_handle the elf handle to use for the query.
///
/// @param symbol_name the function symbol to look for.
@ -1773,17 +1795,16 @@ lookup_symbol_from_elf(Elf* elf_handle,
///
/// @return true iff the symbol was found.
static bool
lookup_public_function_symbol_from_elf(Elf* elf_handle,
lookup_public_function_symbol_from_elf(const environment* env,
Elf* elf_handle,
const string& symbol_name,
vector<elf_symbol_sptr>& func_syms)
{
vector<elf_symbol_sptr> syms_found;
bool found = false;
if (lookup_symbol_from_elf(elf_handle,
symbol_name,
/*demangle=*/false,
syms_found))
if (lookup_symbol_from_elf(env, elf_handle, symbol_name,
/*demangle=*/false, syms_found))
{
for (vector<elf_symbol_sptr>::const_iterator i = syms_found.begin();
i != syms_found.end();
@ -1810,6 +1831,8 @@ lookup_public_function_symbol_from_elf(Elf* elf_handle,
/// Look into the symbol tables of the underlying elf file and see if
/// we find a given public (global or weak) symbol of variable type.
///
/// @param env the environment we are operating from.
///
/// @param elf the elf handle to use for the query.
///
/// @param symname the variable symbol to look for.
@ -1818,17 +1841,15 @@ lookup_public_function_symbol_from_elf(Elf* elf_handle,
///
/// @return true iff symbol @p symname was found.
static bool
lookup_public_variable_symbol_from_elf(Elf* elf,
lookup_public_variable_symbol_from_elf(const environment* env,
Elf* elf,
const string& symname,
vector<elf_symbol_sptr>& var_syms)
{
vector<elf_symbol_sptr> syms_found;
bool found = false;
if (lookup_symbol_from_elf(elf,
symname,
/*demangle=*/false,
syms_found))
if (lookup_symbol_from_elf(env, elf, symname, /*demangle=*/false, syms_found))
{
for (vector<elf_symbol_sptr>::const_iterator i = syms_found.begin();
i != syms_found.end();
@ -3087,7 +3108,8 @@ public:
bool demangle,
vector<elf_symbol_sptr>& syms) const
{
return dwarf_reader::lookup_symbol_from_elf(elf_handle(),
return dwarf_reader::lookup_symbol_from_elf(env(),
elf_handle(),
symbol_name,
demangle,
syms);
@ -3139,7 +3161,7 @@ public:
v);
elf_symbol_sptr sym =
elf_symbol::create(symbol_index, s->st_size, name_str,
elf_symbol::create(env(), symbol_index, s->st_size, name_str,
stt_to_elf_symbol_type(GELF_ST_TYPE(s->st_info)),
stb_to_elf_symbol_binding(GELF_ST_BIND(s->st_info)),
sym_is_defined, sym_is_common, v);
@ -3205,7 +3227,8 @@ public:
lookup_public_function_symbol_from_elf(const string& sym_name,
vector<elf_symbol_sptr>& syms)
{
return dwarf_reader::lookup_public_function_symbol_from_elf(elf_handle(),
return dwarf_reader::lookup_public_function_symbol_from_elf(env(),
elf_handle(),
sym_name,
syms);
}
@ -3223,7 +3246,8 @@ public:
lookup_public_variable_symbol_from_elf(const string& sym_name,
vector<elf_symbol_sptr>& syms)
{
return dwarf_reader::lookup_public_variable_symbol_from_elf(elf_handle(),
return dwarf_reader::lookup_public_variable_symbol_from_elf(env(),
elf_handle(),
sym_name,
syms);
}
@ -6651,8 +6675,8 @@ build_translation_unit_and_add_to_ir(read_context& ctxt,
ctxt.cur_tu_die(die);
string path = die_string_attribute(die, DW_AT_name);
result.reset(new translation_unit(path,
ctxt.env(),
result.reset(new translation_unit(ctxt.env(),
path,
address_size));
uint64_t l = 0;
@ -6782,7 +6806,7 @@ build_namespace_decl_and_add_to_ir(read_context& ctxt,
location loc;
die_loc_and_name(ctxt, die, loc, name, linkage_name);
result.reset(new namespace_decl(name, loc));
result.reset(new namespace_decl(ctxt.env(), name, loc));
add_decl_to_scope(result, scope.get());
ctxt.associate_die_to_decl(dwarf_dieoffset(die), die_is_from_alt_di, result);
@ -6835,9 +6859,8 @@ build_type_decl(read_context& ctxt,
location loc;
die_loc_and_name(ctxt, die, loc, type_name, linkage_name);
result.reset(new type_decl(type_name, bit_size,
/*alignment=*/0, loc,
linkage_name));
result.reset(new type_decl(ctxt.env(), type_name, bit_size,
/*alignment=*/0, loc, linkage_name));
ctxt.associate_die_to_type(dwarf_dieoffset(die),
die_is_from_alt_di,
result);
@ -6907,7 +6930,7 @@ build_enum_type(read_context& ctxt,
die_loc_and_name(ctxt, &child, loc, 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));
enms.push_back(enum_type_decl::enumerator(ctxt.env(), n, val));
}
while (dwarf_siblingof(&child, &child) == 0);
}
@ -6916,7 +6939,7 @@ build_enum_type(read_context& ctxt,
// underlying type, so let's create an artificial one here, which
// sole purpose is to be passed to the constructor of the
// enum_type_decl type.
type_decl_sptr t(new type_decl(underlying_type_name,
type_decl_sptr t(new type_decl(ctxt.env(), underlying_type_name,
size, size, location()));
t->set_is_anonymous(enum_underlying_type_is_anonymous);
translation_unit_sptr tu = ctxt.cur_tu();
@ -6958,7 +6981,7 @@ finish_member_function_reading(Dwarf_Die* die,
bool is_ctor = (f->get_name() == klass->get_name());
bool is_dtor = (!f->get_name().empty()
&& f->get_name()[0] == '~');
&& static_cast<string>(f->get_name())[0] == '~');
bool is_virtual = die_is_virtual(die);
size_t vindex = 0;
if (is_virtual)
@ -7097,7 +7120,8 @@ build_class_type_and_add_to_ir(read_context& ctxt,
}
else
{
result.reset(new class_decl(name, size, /*alignment=*/0, is_struct, loc,
result.reset(new class_decl(ctxt.env(), name, size,
/*alignment=*/0, is_struct, loc,
decl_base::VISIBILITY_DEFAULT));
result->set_is_anonymous(is_anonymous);
@ -7647,7 +7671,7 @@ build_function_type(read_context& ctxt,
? new method_type(is_method,
tu->get_address_size(),
/*alignment=*/0)
: new function_type(tu->get_address_size(),
: new function_type(ctxt.env(), tu->get_address_size(),
/*alignment=*/0));
tu->bind_function_type_life_time(result);
ctxt.associate_die_to_type(dwarf_dieoffset(die),
@ -8154,7 +8178,7 @@ read_debug_info_into_corpus(read_context& ctxt)
if (!ctxt.current_corpus())
{
corpus_sptr corp (new corpus(ctxt.elf_path(), ctxt.env()));
corpus_sptr corp (new corpus(ctxt.env(), ctxt.elf_path()));
ctxt.current_corpus(corp);
if (!ctxt.env())
ctxt.env(corp->get_environment());
@ -9060,6 +9084,8 @@ read_corpus_from_elf(const std::string& elf_path,
/// Look into the symbol tables of a given elf file and see if we find
/// a given symbol.
///
/// @param env the environment we are operating from.
///
/// @param elf_path the path to the elf file to consider.
///
/// @param symbol_name the name of the symbol to look for.
@ -9072,7 +9098,8 @@ read_corpus_from_elf(const std::string& elf_path,
/// @return true iff the symbol was found among the publicly exported
/// symbols of the ELF file.
bool
lookup_symbol_from_elf(const string& elf_path,
lookup_symbol_from_elf(const environment* env,
const string& elf_path,
const string& symbol_name,
bool demangle,
vector<elf_symbol_sptr>& syms)
@ -9093,7 +9120,7 @@ lookup_symbol_from_elf(const string& elf_path,
if (elf == 0)
return false;
bool value = lookup_symbol_from_elf(elf, symbol_name,
bool value = lookup_symbol_from_elf(env, elf, symbol_name,
demangle, syms);
elf_end(elf);
close(fd);
@ -9104,6 +9131,8 @@ lookup_symbol_from_elf(const string& elf_path,
/// Look into the symbol tables of an elf file to see if a public
/// function of a given name is found.
///
/// @param env the environment we are operating from.
///
/// @param elf_path the path to the elf file to consider.
///
/// @param symbol_name the name of the function to look for.
@ -9114,7 +9143,8 @@ lookup_symbol_from_elf(const string& elf_path,
/// @return true iff a function with symbol name @p symbol_name is
/// found.
bool
lookup_public_function_symbol_from_elf(const string& path,
lookup_public_function_symbol_from_elf(const environment* env,
const string& path,
const string& symname,
vector<elf_symbol_sptr>& syms)
{
@ -9133,7 +9163,7 @@ lookup_public_function_symbol_from_elf(const string& path,
if (elf == 0)
return false;
bool value = lookup_public_function_symbol_from_elf(elf, symname, syms);
bool value = lookup_public_function_symbol_from_elf(env, elf, symname, syms);
elf_end(elf);
close(fd);

File diff suppressed because it is too large Load Diff

View File

@ -1127,7 +1127,7 @@ read_translation_unit(read_context& ctxt, xmlNodePtr node)
ctxt.set_corpus_node(node);
tu.reset(new translation_unit("", ctxt.get_environment()));
tu.reset(new translation_unit(ctxt.get_environment(), ""));
tu->set_corpus(ctxt.get_corpus().get());
xml::xml_char_sptr addrsize_str =
@ -1465,7 +1465,7 @@ read_corpus_from_input(read_context& ctxt)
if (!ctxt.get_corpus())
{
corpus_sptr c(new corpus("", ctxt.get_environment()));
corpus_sptr c(new corpus(ctxt.get_environment(), ""));
ctxt.set_corpus(c);
}
@ -2059,7 +2059,8 @@ build_namespace_decl(read_context& ctxt,
location loc;
read_location(ctxt, node, loc);
shared_ptr<namespace_decl> decl(new namespace_decl(name, loc));
const environment* env = ctxt.get_environment();
namespace_decl_sptr decl(new namespace_decl(env, name, loc));
ctxt.push_decl_to_current_scope(decl, add_to_current_scope);
ctxt.map_xml_node_to_decl(node, decl);
@ -2078,11 +2079,13 @@ 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 node the XML node to read.
///
/// @return the @ref elf_symbol built, or nil if it couldn't be built.
static elf_symbol_sptr
build_elf_symbol(read_context&, const xmlNodePtr node)
build_elf_symbol(read_context& ctxt, const xmlNodePtr node)
{
elf_symbol_sptr nil;
@ -2142,8 +2145,9 @@ build_elf_symbol(read_context&, const xmlNodePtr node)
elf_symbol::version version(version_string, is_default_version);
elf_symbol_sptr e = elf_symbol::create(/*index=*/0, size,
name, type, binding,
const environment* env = ctxt.get_environment();
elf_symbol_sptr e = elf_symbol::create(env, /*index=*/0, size,
name, type, binding,
is_defined, is_common,
version);
return e;
@ -2344,6 +2348,7 @@ build_function_parameter(read_context& ctxt, const xmlNodePtr node)
type = ctxt.build_or_get_type_decl(type_id, true);
}
assert(type);
assert(type->get_environment() == ctxt.get_environment());
string name;
if (xml_char_sptr a = xml::build_sptr(xmlGetProp(node, BAD_CAST("name"))))
@ -2412,8 +2417,10 @@ build_function_decl(read_context& ctxt,
location loc;
read_location(ctxt, node, loc);
std::vector<shared_ptr<function_decl::parameter> > parms;
type_base_sptr return_type;
environment* env = ctxt.get_environment();
assert(env);
std::vector<function_decl::parameter_sptr> parms;
type_base_sptr return_type = env->get_void_type_decl();
for (xmlNodePtr n = node->children; n ; n = n->next)
{
@ -2437,22 +2444,24 @@ build_function_decl(read_context& ctxt,
}
}
shared_ptr<function_type> fn_type(as_method_decl
? new method_type(return_type,
as_method_decl,
parms, size, align)
: new function_type(return_type,
parms, size, align));
assert(return_type);
shared_ptr<function_decl> fn_decl(as_method_decl
? new class_decl::method_decl
(name, fn_type,
declared_inline, loc,
mangled_name, vis, bind)
: new function_decl(name, fn_type,
declared_inline, loc,
mangled_name, vis,
bind));
function_type_sptr fn_type(as_method_decl
? new method_type(return_type,
as_method_decl,
parms, size, align)
: new function_type(return_type,
parms, size, align));
function_decl_sptr fn_decl(as_method_decl
? new class_decl::method_decl
(name, fn_type,
declared_inline, loc,
mangled_name, vis, bind)
: new function_decl(name, fn_type,
declared_inline, loc,
mangled_name, vis,
bind));
ctxt.push_decl_to_current_scope(fn_decl, add_to_current_scope);
@ -2597,9 +2606,9 @@ build_type_decl(read_context& ctxt,
return ty;
}
type_decl_sptr decl(new type_decl(name, size_in_bits,
alignment_in_bits,
loc));
const environment* env = ctxt.get_environment();
type_decl_sptr decl(new type_decl(env, name, size_in_bits,
alignment_in_bits, loc));
decl->set_is_anonymous(is_anonymous);
if (ctxt.push_and_key_type_decl(decl, id, add_to_current_scope))
{
@ -2910,8 +2919,10 @@ build_function_type(read_context& ctxt,
size_t size = 0, align = 0;
read_size_and_alignment(node, size, align);
environment* env = ctxt.get_environment();
assert(env);
std::vector<shared_ptr<function_decl::parameter> > parms;
type_base_sptr return_type;
type_base_sptr return_type = env->get_void_type_decl();;
function_type_sptr fn_type(new function_type(return_type,
parms, size, align));
@ -3170,6 +3181,9 @@ build_enum_type_decl(read_context& ctxt,
assert(!id.empty());
const environment* env = ctxt.get_environment();
assert(env);
string base_type_id;
enum_type_decl::enumerators enums;
for (xmlNodePtr n = node->children; n; n = n->next)
@ -3202,17 +3216,17 @@ build_enum_type_decl(read_context& ctxt,
return nil;
}
enums.push_back(enum_type_decl::enumerator(name, value));
enums.push_back(enum_type_decl::enumerator(env, name, value));
}
}
shared_ptr<type_base> underlying_type =
type_base_sptr underlying_type =
ctxt.build_or_get_type_decl(base_type_id, true);
assert(underlying_type);
shared_ptr<enum_type_decl> t(new enum_type_decl(name, loc,
underlying_type,
enums, linkage_name));
enum_type_decl_sptr t(new enum_type_decl(name, loc,
underlying_type,
enums, linkage_name));
if (ctxt.push_and_key_type_decl(t, id, add_to_current_scope))
{
ctxt.map_xml_node_to_decl(node, t);
@ -3391,6 +3405,9 @@ build_class_decl(read_context& ctxt,
return previous_declaration;
}
const environment* env = ctxt.get_environment();
assert(env);
if (!is_decl_only && previous_definition)
// We are in the case where we've read this class definition
// before, but we might need to update it to add some new stuff to
@ -3401,11 +3418,11 @@ build_class_decl(read_context& ctxt,
else
{
if (is_decl_only)
decl.reset(new class_decl(name, is_struct));
decl.reset(new class_decl(env, name, is_struct));
else
decl.reset(new class_decl(name, size_in_bits, alignment_in_bits,
is_struct, loc, vis, bases, mbrs, data_mbrs,
mbr_functions));
decl.reset(new class_decl(env, name, size_in_bits, alignment_in_bits,
is_struct, loc, vis, bases, mbrs,
data_mbrs, mbr_functions));
decl->set_is_anonymous(is_anonymous);
}
@ -3724,7 +3741,10 @@ build_function_tdecl(read_context& ctxt,
decl_base::binding bind = decl_base::BINDING_NONE;
read_binding(node, bind);
function_tdecl_sptr fn_tmpl_decl(new function_tdecl(loc, vis, bind));
const environment* env = ctxt.get_environment();
assert(env);
function_tdecl_sptr fn_tmpl_decl(new function_tdecl(env, loc, vis, bind));
ctxt.push_decl_to_current_scope(fn_tmpl_decl, add_to_current_scope);
@ -3785,7 +3805,10 @@ build_class_tdecl(read_context& ctxt,
decl_base::visibility vis = decl_base::VISIBILITY_NONE;
read_visibility(node, vis);
class_tdecl_sptr class_tmpl (new class_tdecl(loc, vis));
const environment* env = ctxt.get_environment();
assert(env);
class_tdecl_sptr class_tmpl (new class_tdecl(env, loc, vis));
ctxt.push_decl_to_current_scope(class_tmpl, add_to_current_scope);
@ -4534,7 +4557,7 @@ read_corpus_from_native_xml(std::istream* in,
environment* env)
{
read_context read_ctxt(xml::new_reader_from_istream(in), env);
corpus_sptr corp(new corpus("", read_ctxt.get_environment()));
corpus_sptr corp(new corpus(env, ""));
read_ctxt.set_corpus(corp);
return read_corpus_from_input(read_ctxt);
}

View File

@ -77,34 +77,45 @@ namespace xml_writer
class id_manager
{
unsigned long long m_cur_id;
const environment* m_env;
mutable unsigned long long m_cur_id;
unsigned long long
get_new_id()
get_new_id() const
{ return ++m_cur_id; }
public:
id_manager() : m_cur_id(0) { }
id_manager(const environment* env)
: m_env(env),
m_cur_id(0) {}
const environment*
get_environment() const
{return m_env;}
/// Return a unique string representing a numerical id.
string
get_id()
interned_string
get_id() const
{
ostringstream o;
o << get_new_id();
return o.str();
const environment* env = get_environment();
assert(env);
return env->intern(o.str());
}
/// Return a unique string representing a numerical ID, prefixed by
/// prefix.
///
/// @param prefix the prefix of the returned unique id.
string
get_id_with_prefix(const string& prefix)
interned_string
get_id_with_prefix(const string& prefix) const
{
ostringstream o;
o << prefix << get_new_id();
return o.str();
const environment* env = get_environment();
assert(env);
return env->intern(o.str());
}
};
@ -119,7 +130,7 @@ struct type_hasher
/// A convenience typedef for a map that associates a pointer to type
/// to a string. The pointer to type is hashed as fast as possible.
typedef unordered_map<type_base*,
string,
interned_string,
type_hasher,
abigail::diff_utils::deep_ptr_eq_functor> type_ptr_map;
@ -133,11 +144,13 @@ typedef unordered_map<shared_ptr<class_tdecl>,
class write_context
{
const environment* m_env;
id_manager m_id_manager;
config m_config;
ostream& m_ostream;
type_ptr_map m_type_id_map;
unordered_map<string, bool> m_emitted_type_id_map;
mutable type_ptr_map m_type_id_map;
mutable unordered_map<interned_string,
bool, hash_interned_string> m_emitted_type_id_map;
type_ptr_map m_emitted_decl_only_map;
// A map of types that are referenced by emitted pointers,
// references or typedefs
@ -151,9 +164,24 @@ class write_context
public:
write_context(ostream& os) : m_ostream(os)
/// Constructor.
///
/// @param env the enviroment we are operating from.
///
/// @param os the output stream to write to.
write_context(const environment* env, ostream& os)
: m_env(env),
m_id_manager(env),
m_ostream(os)
{}
/// Getter of the environment we are operating from.
///
/// @return the environment we are operating from.
const environment*
get_environment() const
{return m_env;}
const config&
get_config() const
{return m_config;}
@ -162,6 +190,14 @@ public:
get_ostream()
{return m_ostream;}
/// Getter of the @ref id_manager.
///
/// @return the @ref id_manager used by the current instance of @ref
/// write_context.
const id_manager&
get_id_manager() const
{return m_id_manager;}
id_manager&
get_id_manager()
{return m_id_manager;}
@ -180,21 +216,22 @@ public:
/// in a hash table, hashing the type. So if the type has no id
/// associated to it, create a new one and return it. Otherwise,
/// return the existing id for that type.
string
get_id_for_type(shared_ptr<type_base> t)
interned_string
get_id_for_type(const type_base_sptr& t)
{return get_id_for_type(t.get());}
/// Associate a unique id to a given type. For that, put the type
/// in a hash table, hashing the type. So if the type has no id
/// associated to it, create a new one and return it. Otherwise,
/// return the existing id for that type.
string
get_id_for_type(type_base* t)
interned_string
get_id_for_type(type_base* t) const
{
type_ptr_map::const_iterator it = m_type_id_map.find(t);
if (it == m_type_id_map.end())
{
string id = get_id_manager().get_id_with_prefix("type-id-");
interned_string id =
get_id_manager().get_id_with_prefix("type-id-");
m_type_id_map[t] = id;
return id;
}
@ -237,7 +274,11 @@ public:
/// @param id the ID of the type.
void
record_type_id_as_emitted(const string& id)
{m_emitted_type_id_map[id] = true;}
{
const environment* env = get_environment();
assert(env);
m_emitted_type_id_map[env->intern(id)] = true;
}
/// Getter of the map of types that were referenced by a pointer,
/// reference or typedef.
@ -254,7 +295,7 @@ public:
/// @param t a shared pointer to a type
void
record_type_as_referenced(const type_base_sptr& t)
{m_referenced_types_map[t.get()] = true;}
{m_referenced_types_map[t.get()] = interned_string();}
/// Test if a given type has been referenced by a pointer, a
/// reference or a typedef type that was emitted to the XML output.
@ -358,7 +399,7 @@ public:
/// @return true if the type has already been emitted, false
/// otherwise.
bool
type_id_is_emitted(const string& id)
type_id_is_emitted(const interned_string& id)
{return m_emitted_type_id_map.find(id) != m_emitted_type_id_map.end();}
/// Test if a given type has been written out to the XML output.
@ -372,7 +413,7 @@ public:
{
if (!type_has_existing_id(t))
return false;
string id = get_id_for_type(t);
const interned_string& id = get_id_for_type(t);
return type_id_is_emitted(id);
}
@ -387,7 +428,7 @@ public:
{
class_decl* cl = is_class_type(t);
assert(cl && cl->get_is_declaration_only());
m_emitted_decl_only_map[t] = true;
m_emitted_decl_only_map[t] = interned_string();
}
/// Record a declaration-only class as being emitted.
@ -1257,7 +1298,7 @@ write_translation_unit(const translation_unit& tu,
&& !ctxt.decl_only_type_is_emitted(type))
// A referenced type that was not emitted at all must be
// emitted now.
referenced_types_to_emit[type.get()] = "";
referenced_types_to_emit[type.get()] = interned_string();
}
// Ok, now let's emit the referenced type for good.
@ -1310,7 +1351,7 @@ write_translation_unit(const translation_unit& tu,
if (get_type_declaration(type)
&& !ctxt.type_is_emitted(type)
&& !ctxt.decl_only_type_is_emitted(type))
referenced_types_to_emit[type.get()] = "";
referenced_types_to_emit[type.get()] = interned_string();
}
}
@ -1350,8 +1391,8 @@ write_translation_unit(const translation_unit& tu,
unsigned indent,
std::ostream& out)
{
write_context ctxt(out);
return write_translation_unit(tu, ctxt, indent);
write_context ctxt(tu.get_environment(), out);
return write_translation_unit(tu, ctxt, indent);
}
/// Serialize a translation unit to a file.
@ -3141,7 +3182,7 @@ write_corpus_to_native_xml(const corpus_sptr corpus,
if (!corpus)
return false;
write_context ctxt(out);
write_context ctxt(corpus->get_environment(), out);
do_indent_to_level(ctxt, indent, 0);
out << "<abi-corpus";
@ -3267,7 +3308,7 @@ using namespace abigail::ir;
void
dump(const decl_base_sptr d, std::ostream& o)
{
xml_writer::write_context ctxt(o);
xml_writer::write_context ctxt(d->get_environment(), o);
write_decl(d, ctxt, /*indent=*/0);
o << "\n";
}
@ -3303,7 +3344,7 @@ dump(const type_base_sptr t)
void
dump(const var_decl_sptr v, std::ostream& o)
{
xml_writer::write_context ctxt(o);
xml_writer::write_context ctxt(v->get_environment(), o);
write_var_decl(v, ctxt, /*linkage_name*/true, /*indent=*/0);
cerr << "\n";
}
@ -3323,7 +3364,7 @@ dump(const var_decl_sptr v)
void
dump(const translation_unit& t, std::ostream& o)
{
xml_writer::write_context ctxt(o);
xml_writer::write_context ctxt(t.get_environment(), o);
write_translation_unit(t, ctxt, /*indent=*/0);
o << "\n";
}

View File

@ -7,13 +7,15 @@
<parameter type-id='type-id-3' name='l' filepath='/home/dodji/test-bidw/test-v0.cc' line='5' column='1'/>
<return type-id='type-id-1'/>
</function-decl>
<type-decl name='void' id='type-id-4'/>
<function-decl name='bar' mangled-name='_Z3bariz' filepath='/home/dodji/test-bidw/test-v0.cc' line='9' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-3' name='c' filepath='/home/dodji/test-bidw/test-v0.cc' line='9' column='1'/>
<parameter is-variadic='yes'/>
</function-decl>
<type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
<function-decl name='main' filepath='/home/dodji/test-bidw/test-v0.cc' line='17' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<return type-id='type-id-4'/>
</function-decl>
<var-decl name='global' type-id='type-id-4' visibility='default' filepath='/home/dodji/test-bidw/test-v0.cc' line='2' column='1'/>
<type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-5'/>
<function-decl name='main' filepath='/home/dodji/test-bidw/test-v0.cc' line='17' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<return type-id='type-id-5'/>
</function-decl>
<var-decl name='global' type-id='type-id-5' visibility='default' filepath='/home/dodji/test-bidw/test-v0.cc' line='2' column='1'/>
</abi-instr>

View File

@ -7,13 +7,15 @@
<parameter type-id='type-id-3' name='l' filepath='/home/dodji/test-bidw/test-v0.cc' line='5' column='1'/>
<return type-id='type-id-1'/>
</function-decl>
<type-decl name='void' id='type-id-4'/>
<function-decl name='bar' mangled-name='_Z3bariz' filepath='/home/dodji/test-bidw/test-v0.cc' line='9' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-3' name='c' filepath='/home/dodji/test-bidw/test-v0.cc' line='9' column='1'/>
<parameter is-variadic='yes'/>
</function-decl>
<type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
<function-decl name='main' filepath='/home/dodji/test-bidw/test-v0.cc' line='17' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<return type-id='type-id-4'/>
</function-decl>
<var-decl name='global' type-id='type-id-4' visibility='default' filepath='/home/dodji/test-bidw/test-v0.cc' line='2' column='1'/>
<type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-5'/>
<function-decl name='main' filepath='/home/dodji/test-bidw/test-v0.cc' line='17' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<return type-id='type-id-5'/>
</function-decl>
<var-decl name='global' type-id='type-id-5' visibility='default' filepath='/home/dodji/test-bidw/test-v0.cc' line='2' column='1'/>
</abi-instr>

View File

@ -24,9 +24,11 @@
</data-member>
</class-decl>
<pointer-type-def type-id='type-id-6' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
<type-decl name='void' id='type-id-8'/>
<function-decl name='foo' mangled-name='foo' filepath='/home/dodji/tests/test-v0.c' line='9' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='foo'>
<parameter type-id='type-id-5' name='p' filepath='/home/dodji/tests/test-v0.c' line='9' column='1'/>
<parameter type-id='type-id-7' name='t' filepath='/home/dodji/tests/test-v0.c' line='10' column='1'/>
<return type-id='type-id-8'/>
</function-decl>
</abi-instr>
</abi-corpus>

View File

@ -40,6 +40,8 @@ using std::ostream;
using std::ostringstream;
using std::vector;
using abigail::ir::environment;
using abigail::ir::environment_sptr;
using abigail::dwarf_reader::lookup_symbol_from_elf;
using abigail::elf_symbol;
using abigail::elf_symbol_sptr;
@ -142,8 +144,9 @@ main(int argc, char* argv[])
&& opts.symbol_name != 0);
string p = opts.elf_path, n = opts.symbol_name;
environment_sptr env(new environment);
vector<elf_symbol_sptr> syms;
if (!lookup_symbol_from_elf(p, n, opts.demangle, syms))
if (!lookup_symbol_from_elf(env.get(), p, n, opts.demangle, syms))
{
cout << "could not find symbol '"
<< opts.symbol_name