11#include "abg-internal.h"
15ABG_BEGIN_EXPORT_DECLARATIONS
20ABG_END_EXPORT_DECLARATIONS
44char_to_int(
char c,
unsigned char& integer)
46 if (c >=
'0' && c <=
'9')
48 else if (c >=
'a' && c <=
'z')
49 integer = 10 + c -
'a';
50 else if (c >=
'A' && c <=
'Z')
51 integer = 10 + c -
'A';
71int_to_char(
unsigned char integer,
unsigned char& c)
75 else if (integer >= 0xA && integer <= 0xF)
76 c =
'a' + (integer - 0xA);
101 unsigned char byte = 0;
102 string xxh64_canonical_form;
103 for (
size_t i = 0; i + 1 < input.size(); i += 2)
105 unsigned char first_nibble = 0, second_nibble = 0;
106 ABG_ASSERT(char_to_int(input[i], first_nibble));
107 ABG_ASSERT(char_to_int(input[i+1], second_nibble));
108 byte = (first_nibble << 4) | second_nibble;
109 xxh64_canonical_form.push_back(
byte);
112 XXH64_canonical_t canonical_hash = {};
113 size_t size =
sizeof(canonical_hash.digest);
114 memcpy(canonical_hash.digest,
115 xxh64_canonical_form.c_str(),
117 hash = XXH64_hashFromCanonical(&canonical_hash);
140 XXH64_canonical_t canonical_output = {};
141 XXH64_canonicalFromHash(&canonical_output,
hash);
142 for (
unsigned i = 0; i <
sizeof(canonical_output.digest); ++i)
144 unsigned char first_nibble = 0, second_nibble = 0;
145 unsigned char byte = canonical_output.digest[i];
146 first_nibble = (0xf0 & byte) >> 4;
147 second_nibble = 0xf & byte;
149 int_to_char(first_nibble, c);
151 int_to_char(second_nibble, c);
175 if (val1.has_value() && val2.has_value())
176 result =
hash(*val2, *val1);
177 else if (val1.has_value())
179 else if (val2.has_value())
201 unsigned char data[
sizeof(uint64_t)] = {};
203 size_t data_size =
sizeof(data);
204 for (
unsigned i = 0; i < data_size; ++i)
206 data[data_size - i - 1] = t & 0xff;
209 hash_t h = XXH3_64bits_withSeed(data, data_size, seed);
221 hash_t h = XXH3_64bits(str.c_str(), str.size());
244 const uint32_t offset_basis = 0x811c9dc5;
246 for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
267 return d->type_or_decl_base::priv_->get_hashing_state();
270 return tod.priv_->get_hashing_state();
287 d->type_or_decl_base::priv_->set_hashing_state(s);
290 tod.priv_->set_hashing_state(s);
309 result = d->type_or_decl_base::priv_->is_recursive_artefact();
312 result = t.type_or_decl_base::priv_->is_recursive_artefact();
333 d->type_or_decl_base::priv_->is_recursive_artefact(f);
336 t.priv_->is_recursive_artefact(f);
349#define MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(type) \
352 if (hashing::get_hashing_state(type) == hashing::HASHING_STARTED_STATE \
353 || hashing::get_hashing_state(type) == hashing::HASHING_SUBTYPE_STATE) \
355 hashing::set_hashing_state(t, hashing::HASHING_CYCLED_TYPE_STATE); \
356 hashing::is_recursive_artefact(type, true); \
359 else if (hashing::get_hashing_state(type) == hashing::HASHING_CYCLED_TYPE_STATE) \
361 else if (hashing::get_hashing_state(type) == hashing::HASHING_FINISHED_STATE) \
362 return peek_hash_value(type); \
366#define MAYBE_FLAG_TYPE_AS_RECURSIVE(type, underlying, h) \
369 if (!h || hashing::is_recursive_artefact(*underlying)) \
370 hashing::is_recursive_artefact(type, true); \
374#define MAYBE_RETURN_EARLY_IF_HASH_EXISTS(type) \
377 if (hashing::get_hashing_state(type) == hashing::HASHING_FINISHED_STATE) \
378 return peek_hash_value(type); \
405{
return operator()(*t);}
413type_base::hash::operator()(
const type_base_sptr t)
const
414{
return operator()(*t);}
451 return operator()(*d);
462 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
489 return operator()(*t);
500 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
509 hash_t v = u->hash_value();
511 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
528 return operator()(*t);
539 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
549 hash_t v = u->hash_value();
551 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
571 return operator()(*t);
582 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
592 hash_t v = u->hash_value();
594 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
613 return operator()(*t);
624 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
634 hash_t v = u->hash_value();
636 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
656 return operator()(*t);
688 return operator()(*s);
699 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
706 hash_t v = hash_as_type_base(t), h = 0;
709 for (vector<array_type_def::subrange_sptr >::const_iterator i =
716 h = (*i)->hash_value();
718 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, *i, h);
727 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, e, h);
745 return operator()(*t);
756 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
763 hash_t v = hash_as_type_base(t);
768 hash_t h = e->hash_value();
770 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, e, h);
796 return operator()(*t);
806{
return operator()(t.get());}
816 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
823 hash_t v = e->hash_value();
825 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, e, v);
834 hash_t v = hash_as_type(t);
840 hash_t h = u->hash_value();
842 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, h);
845 for (enum_type_decl::enumerators::const_iterator i =
869 return operator()(*t);
880 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
886 hash_t v = hash_as_type_base(t), h = 0;
892 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, r, h);
899 type_base_sptr parm_type = (*parm)->get_type();
902 h = parm_type->hash_value();
904 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, parm_type, h);
923 return operator()(*t);
933{
return operator()(t.get());}
943 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
949 hash_t v = hash_as_type_base(t), h = 0;
963 type_base_sptr ty = parm->get_type();
966 h = ty->hash_value();
968 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, ty, h);
984{
return operator()(*t);}
993{
return operator()(t.get());}
1012class_decl::base_spec::hash::operator()(
const base_spec& t)
const
1014 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1020 hash_t v = hash_member(t), h = 0;;
1026 h = b->hash_value();
1042class_decl::base_spec::hash::operator()(
const base_spec* t)
const
1046 return operator()(*t);
1065 hash_t v = cou->hash_value();
1074 hash_t v = hash_as_type_base(t);
1083 ty = (*d)->get_type();
1086 hash_t h = ty->hash_value();
1088 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, ty, h);
1103{
return t ? operator()(*t) : 0;}
1113 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1123 hash_t v = c->hash_value();
1125 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, c, v);
1133 hash_t v = hash_as_class_or_union(t);
1142 hash_t h = (*b)->hash_value();
1144 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, *b, h);
1171 const_cast<class_decl&
>(t).sort_virtual_mem_fns();
1195{
return t ? operator()(*t) : 0;}
1203union_decl::hash::operator()(
const union_decl& t)
const
1205 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1215 hash_t v = u->hash_value();
1217 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
1225 hash_t v = hash_as_class_or_union(t);
1238union_decl::hash::operator()(
const union_decl*t)
const
1242 return operator()(*t);
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects,...
This contains the private implementation of the suppression engine of libabigail.
Types of the main internal representation of libabigail.
The abstraction of an interned string.
Abstraction for an array range type, like in Ada, or just for an array dimension like in C or C++.
int64_t get_upper_bound() const
Getter of the upper bound of the subrange type.
int64_t get_lower_bound() const
Getter of the lower bound of the subrange type.
The abstraction of an array type.
const type_base_sptr get_element_type() const
Getter of the type of an array element.
const std::vector< subrange_sptr > & get_subranges() const
Get the array's subranges.
Abstraction of a base specifier in a class declaration.
class_decl_sptr get_base_class() const
Get the base class referred to by the current base class specifier.
bool get_is_virtual() const
Getter of the "is-virtual" proprerty of the base class specifier.
long get_offset_in_bits() const
Getter of the offset of the base.
Abstracts a class declaration.
const base_specs & get_base_specifiers() const
Get the base specifiers for this class.
const member_functions & get_virtual_mem_fns() const
Get the virtual member functions of this class.
The base type of class_decl and union_decl.
const data_members & get_non_static_data_members() const
Get the non-static data members of this class_or_union.
The base type of all declarations.
virtual const interned_string & get_name() const
Getter for the name of the current decl.
bool get_is_anonymous() const
Test if the current declaration is anonymous.
const decl_base_sptr get_definition_of_declaration() const
If this decl_base is declaration-only, get its definition, if any.
bool get_is_declaration_only() const
Test if a decl_base is a declaration-only decl.
Abstracts a declaration for an enum type.
const enumerators & get_enumerators() const
type_base_sptr get_underlying_type() const
Return the underlying type of the enum.
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Abstraction of a function type.
parameters::const_iterator get_first_parm() const
Get the first parameter of the function.
type_base_sptr get_return_type() const
Getter for the return type of the current instance of function_type.
parameters::const_iterator get_first_non_implicit_parm() const
Get the first parameter of the function.
const parameters & get_parameters() const
Getter for the set of parameters of the current intance of function_type.
The base class for member types, data members and member functions. Its purpose is mainly to carry th...
access_specifier get_access_specifier() const
Getter for the access specifier of this member.
Abstracts the type of a class member function.
The abstraction of a pointer type.
const type_base_sptr get_pointed_to_type() const
Getter of the pointed-to type.
The abstraction of a pointer-to-member type.
const type_base_sptr & get_containing_type() const
Getter of the type containing the member pointed-to by the current ptr_to_mbr_type.
const type_base_sptr & get_member_type() const
Getter of the member type of the current ptr_to_mbr_type.
The abstraction of a qualified type.
CV get_cv_quals() const
Getter of the const/volatile qualifier bit field.
type_base_sptr get_underlying_type() const
Getter of the underlying type.
Abstracts a reference type.
An abstraction helper for type declarations.
virtual size_t get_size_in_bits() const
Getter for the size of the type.
virtual size_t get_alignment_in_bits() const
Getter for the alignment of the type.
A basic type declaration that introduces no scope.
The base class of both types and declarations.
The abstraction of a typedef declaration.
type_base_sptr get_underlying_type() const
Getter of the underlying type of the typedef.
Abstracts a union type declaration.
hash_t combine_hashes(hash_t val1, hash_t val2)
Combine two hash values to produce a third hash value.
hashing::hashing_state get_hashing_state(const type_or_decl_base &tod)
Get the hashing state of an IR node.
void set_hashing_state(const type_or_decl_base &tod, hashing::hashing_state s)
Set the hashing state of an IR node.
hash_t hash(uint64_t v, uint64_t seed)
Hash an integer value and combine it with a hash previously computed.
hashing_state
Enumeration of the different hashing states of an IR node being hashed.
@ HASHING_STARTED_STATE
Hashing started but is not yet finished.
@ HASHING_SUBTYPE_STATE
Hashing a sub-type while hashing another type.
@ HASHING_NOT_DONE_STATE
No hashing has been done/started.
bool deserialize_hash(const string &input, uint64_t &hash)
Read a string of characters representing a string of hexadecimal digits which itself represents a has...
bool serialize_hash(uint64_t hash, string &output)
Serialiaze a hash value computed using the XH64 algorithm (from the xxhash project) into a string of ...
uint32_t fnv_hash(const std::string &str)
Compute a stable string hash.
bool is_recursive_artefact(const type_or_decl_base &t)
Test if an artifact is recursive.
The namespace of the internal representation of ABI artifacts like types and decls.
shared_ptr< method_type > method_type_sptr
Convenience typedef for shared pointer to method_type.
bool get_member_is_static(const decl_base &d)
Gets a flag saying if a class member is static or not.
ssize_t get_member_function_vtable_offset(const function_decl &f)
Get the vtable offset of a member function.
bool is_class_type(const type_or_decl_base &t)
Test whether a type is a class.
class_or_union * is_class_or_union_type(const type_or_decl_base *t)
Test if a type is a class_or_union.
type_base * look_through_decl_only_type(type_base *t)
If a type is is decl-only, then get its definition. Otherwise, just return the initial type.
shared_ptr< class_decl > class_decl_sptr
Convenience typedef for a shared pointer on a class_decl.
decl_base_sptr look_through_decl_only(const decl_base &d)
If a decl is decl-only get its definition. Otherwise, just return nil.
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
const enum_type_decl * is_enum_type(const type_or_decl_base *d)
Test if a decl is an enum_type_decl.
shared_ptr< ptr_to_mbr_type > ptr_to_mbr_type_sptr
Convenience typedef for a shared pointer to a ptr_to_mbr_type.
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
access_specifier get_member_access_specifier(const decl_base &d)
Gets the access specifier for a class member.
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
bool is_union_type(const type_or_decl_base &t)
Test if a type is a union_decl.
bool is_member_decl(const decl_base_sptr d)
Tests if a declaration is a class member.
hash_t do_hash_value(const T &tod)
Compute the hash value of an IR node and return it.
Toplevel namespace for libabigail.
Hasher for the class_or_union type.
The hashing functor for member_base.
Hash functor for instances of type_base.