libabigail
Loading...
Searching...
No Matches
abg-reader.cc
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2// -*- mode: C++ -*-
3//
4// Copyright (C) 2013-2026 Red Hat, Inc.
5
6/// @file
7///
8/// This file contains the definitions of the entry points to
9/// de-serialize an instance of @ref abigail::translation_unit from an
10/// ABI Instrumentation file in libabigail native XML format. This
11/// native XML format is named "ABIXML".
12
13#include "config.h"
14#include <assert.h>
15#include <libxml/xmlreader.h>
16#include <libxml/xmlstring.h>
17#include <cerrno>
18#include <cstdlib>
19#include <cstring>
20#include <deque>
21#include <memory>
22#include <sstream>
23#include <unordered_map>
24#include <algorithm>
25
27
28#include "abg-internal.h"
29#include "abg-ir-priv.h"
30#include "abg-symtab-reader.h"
31#include "abg-ir-priv.h"
32
33// <headers defining libabigail's API go under here>
34ABG_BEGIN_EXPORT_DECLARATIONS
35
36#include "abg-libxml-utils.h"
37#include "abg-reader.h"
38#include "abg-corpus.h"
39#include "abg-fe-iface.h"
40#include "abg-tools-utils.h"
41
42ABG_END_EXPORT_DECLARATIONS
43// </headers defining libabigail's API>
44
45namespace abigail
46{
47
49
50/// The namespace for the native XML file format reader.
51namespace abixml
52{
53using std::string;
54using std::deque;
55using std::shared_ptr;
56using std::unordered_map;
57using std::dynamic_pointer_cast;
58using std::vector;
59using std::istream;
60
61/// Convenience typedef for an unordered map of string to a vector of
62/// strings.
63typedef unordered_map<string, vector<string>> string_strings_map_type;
64
65static bool read_is_declaration_only(xmlNodePtr, bool&);
66static bool read_is_artificial(xmlNodePtr, bool&);
67static bool read_tracking_non_reachable_types(xmlNodePtr, bool&);
68static bool read_is_non_reachable_type(xmlNodePtr, bool&);
69static bool read_naming_typedef_id_string(xmlNodePtr, string&);
70static bool read_type_id_string(xmlNodePtr, string&);
71static bool read_name(xmlNodePtr, string&);
72#ifdef WITH_DEBUG_SELF_COMPARISON
73static bool maybe_map_type_with_type_id(const type_base_sptr&,
74 xmlNodePtr);
75static bool maybe_map_type_with_type_id(const type_base_sptr&,
76 const string&);
77
78#define MAYBE_MAP_TYPE_WITH_TYPE_ID(type, xml_node) \
79 maybe_map_type_with_type_id(type, xml_node)
80#else
81#define MAYBE_MAP_TYPE_WITH_TYPE_ID(type, xml_node)
82#endif
83static void maybe_set_naming_typedef(reader& rdr,
84 xmlNodePtr,
85 const decl_base_sptr &);
86static int advance_cursor(reader& rdr);
87
88static void
89handle_version_attribute(xml::reader_sptr& reader, corpus& corp);
90
91static void
92walk_xml_node_to_map_type_ids(reader& rdr, xmlNodePtr node);
93
94static bool
95read_elf_needed_from_input(reader& rdr, vector<string>& needed);
96
97static bool
98read_symbol_db_from_input(reader& rdr,
101 string_strings_map_type& non_resolved_fn_syms_aliases,
102 string_strings_map_type& non_resolved_var_syms_aliases);
103
105read_translation_unit_from_input(fe_iface& rdr);
106
107static decl_base_sptr
108build_ir_node_for_void_type(reader& rdr);
109
110static decl_base_sptr
111build_ir_node_for_void_pointer_type(reader& rdr);
112
113static decl_base_sptr
114build_ir_node_for_variadic_parameter_type(reader& rdr);
115
116static void
117resolve_symbol_aliases(string_elf_symbols_map_sptr& fn_syms,
119 string_strings_map_type& non_resolved_fn_sym_aliases,
120 string_strings_map_type& non_resolved_var_sym_aliases);
121static bool
122read_type_hash_and_cti(xmlNodePtr, uint64_t& hash, uint64_t& cti);
123
124/// The ABIXML reader object.
125///
126/// This abstracts the context in which the current ABI
127/// instrumentation dump is being de-serialized. It carries useful
128/// information needed during the de-serialization, but that does not
129/// make sense to be stored in the final resulting in-memory
130/// representation of ABI Corpus.
131class reader : public fe_iface
132{
133public:
134
135 typedef unordered_map<string, vector<type_base_sptr> >
136 types_map_type;
137
138 typedef unordered_map<string,
139 vector<type_base_sptr> >::const_iterator
140 const_types_map_it;
141
142 typedef unordered_map<string,
143 vector<type_base_sptr> >::iterator
144 types_map_it;
145
146 typedef unordered_map<string,
147 shared_ptr<function_tdecl> >::const_iterator
148 const_fn_tmpl_map_it;
149
150 typedef unordered_map<string,
151 shared_ptr<class_tdecl> >::const_iterator
152 const_class_tmpl_map_it;
153
154 typedef unordered_map<string, xmlNodePtr> string_xml_node_map;
155
156 typedef unordered_map<xmlNodePtr, decl_base_sptr> xml_node_decl_base_sptr_map;
157
158 friend vector<type_base_sptr>* get_types_from_type_id(reader&,
159 const string&);
160
161 friend unordered_map<type_or_decl_base*, vector<type_or_decl_base*>>*
162 get_artifact_used_by_relation_map(reader& rdr);
163
164 types_map_type m_types_map;
165 unordered_map<string, shared_ptr<function_tdecl> > m_fn_tmpl_map;
166 unordered_map<string, shared_ptr<class_tdecl> > m_class_tmpl_map;
167 vector<type_base_sptr> m_types_to_canonicalize;
168 string_xml_node_map m_id_xml_node_map;
169 xml_node_decl_base_sptr_map m_xml_node_decl_map;
170 xml::reader_sptr m_reader;
171 xmlNodePtr m_corp_node;
172 deque<shared_ptr<decl_base> > m_decls_stack;
173 bool m_tracking_non_reachable_types;
174 bool m_drop_undefined_syms;
175 bool m_drop_hash_value;
176#ifdef WITH_SHOW_TYPE_USE_IN_ABILINT
177 unordered_map<type_or_decl_base*,
178 vector<type_or_decl_base*>> m_artifact_used_by_map;
179#endif
180
181 reader();
182
183public:
184 reader(xml::reader_sptr reader,
185 environment& env)
186 : fe_iface("", env),
187 m_reader(reader),
188 m_corp_node(),
189 m_tracking_non_reachable_types(),
190 m_drop_undefined_syms(),
191 m_drop_hash_value()
192 {
193 }
194
195 /// The initializer of the reader.
196 ///
197 /// Resets the reader so that it can be re-used to read another
198 /// binary and build a corpus that is part of the same corpus group.
199 ///
200 /// In other words, the same reader is used to analyse all the
201 /// binaries that are part of the same corpus group.
202 ///
203 /// @param corpus_path the new corpus path.
204 void
205 initialize(const string& corpus_path)
206 {
208 clear_types_to_canonicalize();
209 }
210
211 /// Test if logging was requested.
212 ///
213 /// @return true iff logging was requested.
214 bool
215 do_log() const
216 {return options().do_log;}
217
218 /// Getter for the flag that tells us if we are tracking types that
219 /// are not reachable from global functions and variables.
220 ///
221 /// @return true iff we are tracking types that are not reachable
222 /// from global functions and variables.
223 bool
224 tracking_non_reachable_types() const
225 {return m_tracking_non_reachable_types;}
226
227 /// Setter for the flag that tells us if we are tracking types that
228 /// are not reachable from global functions and variables.
229 ///
230 /// @param f the new value of the flag.
231 /// from global functions and variables.
232 void
233 tracking_non_reachable_types(bool f)
234 {m_tracking_non_reachable_types = f;}
235
236 /// Getter for the flag that tells us if we are dropping functions
237 /// and variables that have undefined symbols.
238 ///
239 /// @return true iff we are dropping functions and variables that have
240 /// undefined symbols.
241 bool
242 drop_undefined_syms() const
243 {return m_drop_undefined_syms;}
244
245 /// Setter for the flag that tells us if we are dropping functions
246 /// and variables that have undefined symbols.
247 ///
248 /// @param f the new value of the flag.
249 void
250 drop_undefined_syms(bool f)
251 {m_drop_undefined_syms = f;}
252
253 /// Getter of the path to the ABI file.
254 ///
255 /// @return the path to the native xml abi file.
256 const string&
257 get_path() const
258 {return corpus_path();}
259
260 /// Setter of the path to the ABI file.
261 ///
262 /// @param the new path to the native ABI file.
263 void
264 set_path(const string& s)
265 {
266 corpus_path(s);
267 }
268
269 /// Getter for the environment of this reader.
270 ///
271 /// @return the environment of this reader.
272 environment&
273 get_environment()
274 {return options().env;}
275
276 /// Getter for the environment of this reader.
277 ///
278 /// @return the environment of this reader.
279 const environment&
280 get_environment() const
281 {return const_cast<reader*>(this)->get_environment();}
282
284 get_libxml_reader() const
285 {return m_reader;}
286
287 /// Getter of the current XML node in the corpus element sub-tree
288 /// that needs to be processed.
289 ///
290 /// @return the current XML node in the corpus element sub-tree that
291 /// needs to be processed.
292 xmlNodePtr
293 get_corpus_node() const
294 {return m_corp_node;}
295
296 /// Setter of the current XML node in the corpus element sub-tree
297 /// that needs to be processed.
298 ///
299 /// @param node set the current XML node in the corpus element
300 /// sub-tree that needs to be processed.
301 void
302 set_corpus_node(xmlNodePtr node)
303 {m_corp_node = node;}
304
305 const string_xml_node_map&
306 get_id_xml_node_map() const
307 {return m_id_xml_node_map;}
308
309 string_xml_node_map&
310 get_id_xml_node_map()
311 {return m_id_xml_node_map;}
312
313 void
314 clear_id_xml_node_map()
315 {get_id_xml_node_map().clear();}
316
317 const xml_node_decl_base_sptr_map&
318 get_xml_node_decl_map() const
319 {return m_xml_node_decl_map;}
320
321 xml_node_decl_base_sptr_map&
322 get_xml_node_decl_map()
323 {return m_xml_node_decl_map;}
324
325 void
326 map_xml_node_to_decl(xmlNodePtr node,
327 decl_base_sptr decl)
328 {
329 if (node)
330 get_xml_node_decl_map()[node]= decl;
331 }
332
333 decl_base_sptr
334 get_decl_for_xml_node(xmlNodePtr node) const
335 {
336 xml_node_decl_base_sptr_map::const_iterator i =
337 get_xml_node_decl_map().find(node);
338
339 if (i != get_xml_node_decl_map().end())
340 return i->second;
341
342 return decl_base_sptr();
343 }
344
345 void
346 clear_xml_node_decl_map()
347 {get_xml_node_decl_map().clear();}
348
349 void
350 map_id_and_node (const string& id,
351 xmlNodePtr node)
352 {
353 if (!node)
354 return;
355
356 string_xml_node_map::iterator i = get_id_xml_node_map().find(id);
357 if (i != get_id_xml_node_map().end())
358 {
359 bool is_declaration = false;
360 read_is_declaration_only(node, is_declaration);
361 if (is_declaration)
362 i->second = node;
363 }
364 else
365 get_id_xml_node_map()[id] = node;
366 }
367
368 xmlNodePtr
369 get_xml_node_from_id(const string& id) const
370 {
371 string_xml_node_map::const_iterator i = get_id_xml_node_map().find(id);
372 if (i != get_id_xml_node_map().end())
373 return i->second;
374 return 0;
375 }
376
378 get_scope_for_node(xmlNodePtr node,
379 access_specifier& access);
380
382 get_scope_for_node(xmlNodePtr node);
383
384 scope_decl*
385 get_scope_ptr_for_node(xmlNodePtr node);
386
387 // This is defined later, after build_type() is declared, because it
388 // uses it.
389 type_base_sptr
390 build_or_get_type_decl(const string& id,
391 bool add_decl_to_scope);
392
393 /// Return the first type already seen, that is identified by a
394 /// given ID.
395 ///
396 /// Note that for a type to be "identified" by id, the function
397 /// key_type_decl must have been previously called with that type
398 /// and with id.
399 ///
400 /// @param id the id to consider.
401 ///
402 /// @return the type identified by the unique id id, or a null
403 /// pointer if no type has ever been associated with id before.
404 type_base_sptr
405 get_type_decl(const string& id) const
406 {
407 const_types_map_it i = m_types_map.find(id);
408 if (i == m_types_map.end())
409 return type_base_sptr();
410 type_base_sptr result = i->second[0];
411 return result;
412 }
413
414 /// Return the vector of types already seen, that are identified by
415 /// a given ID.
416 ///
417 /// Note that for a type to be "identified" by id, the function
418 /// key_type_decl must have been previously called with that type
419 /// and with id.
420 ///
421 /// @param id the id to consider.
422 ///
423 /// @return thevector of types already seen, that are identified by
424 /// a given ID, or 0 if no type has ever been associated with @p id
425 /// before.
426 const vector<type_base_sptr>*
427 get_all_type_decls(const string& id) const
428 {
429 const_types_map_it i = m_types_map.find(id);
430 if (i == m_types_map.end())
431 return 0;
432 else
433 return &i->second;
434 }
435
436 /// Return the function template that is identified by a unique ID.
437 ///
438 /// Note that for a function template to be identified by id, the
439 /// function key_fn_tmpl_decl must have been previously called with
440 /// that function template and with id.
441 ///
442 /// @param id the ID to consider.
443 ///
444 /// @return the function template identified by id, or a null
445 /// pointer if no function template has ever been associated with
446 /// id before.
447 shared_ptr<function_tdecl>
448 get_fn_tmpl_decl(const string& id) const
449 {
450 const_fn_tmpl_map_it i = m_fn_tmpl_map.find(id);
451 if (i == m_fn_tmpl_map.end())
452 return shared_ptr<function_tdecl>();
453 return i->second;
454 }
455
456 /// Return the class template that is identified by a unique ID.
457 ///
458 /// Note that for a class template to be identified by id, the
459 /// function key_class_tmpl_decl must have been previously called
460 /// with that class template and with id.
461 ///
462 /// @param id the ID to consider.
463 ///
464 /// @return the class template identified by id, or a null pointer
465 /// if no class template has ever been associated with id before.
466 shared_ptr<class_tdecl>
467 get_class_tmpl_decl(const string& id) const
468 {
469 const_class_tmpl_map_it i = m_class_tmpl_map.find(id);
470 if (i == m_class_tmpl_map.end())
471 return shared_ptr<class_tdecl>();
472 return i->second;
473 }
474
475 /// Return the current lexical scope.
476 scope_decl*
477 get_cur_scope() const
478 {
479 shared_ptr<decl_base> cur_decl = get_cur_decl();
480
481 if (dynamic_cast<scope_decl*>(cur_decl.get()))
482 // The current decl is a scope_decl, so it's our lexical scope.
483 return dynamic_pointer_cast<scope_decl>(cur_decl).get();
484 else if (cur_decl)
485 // The current decl is not a scope_decl, so our lexical scope is
486 // the scope of this decl.
487 return cur_decl->get_scope();
488 else
489 // We have no scope set.
490 return 0;
491 }
492
493 decl_base_sptr
494 get_cur_decl() const
495 {
496 if (m_decls_stack.empty())
497 return shared_ptr<decl_base>(static_cast<decl_base*>(0));
498 return m_decls_stack.back();
499 }
500
501 translation_unit*
503 {
504 const global_scope* global = 0;
505 for (deque<shared_ptr<decl_base> >::reverse_iterator i =
506 m_decls_stack.rbegin();
507 i != m_decls_stack.rend();
508 ++i)
509 if (decl_base_sptr d = *i)
510 if ((global = get_global_scope(d)))
511 break;
512
513 if (global)
514 return global->get_translation_unit();
515
516 return 0;
517 }
518
519 /// Test if a given type is from the current translation unit.
520 ///
521 /// @param type the type to consider.
522 ///
523 /// @return true iff the type is from the current translation unit.
524 bool
525 type_is_from_translation_unit(type_base_sptr type)
526 {
527 decl_base_sptr d = get_type_declaration(type);
528 if (d)
530 else if (function_type_sptr fn_type = is_function_type(type))
531 return bool(lookup_function_type(fn_type, *get_translation_unit()));
532 else
533 return false;
534 }
535
536 void
537 push_decl(decl_base_sptr d)
538 {
539 m_decls_stack.push_back(d);
540 }
541
542 decl_base_sptr
543 pop_decl()
544 {
545 if (m_decls_stack.empty())
546 return decl_base_sptr();
547
548 shared_ptr<decl_base> t = get_cur_decl();
549 m_decls_stack.pop_back();
550 return t;
551 }
552
553 /// Pop all decls until a give scope is popped.
554 ///
555 /// @param scope the scope to pop.
556 ///
557 /// @return true if the scope was popped, false otherwise. Note
558 /// that if the scope wasn't found, it might mean that many other
559 /// decls were popped.
560 bool
561 pop_scope(scope_decl_sptr scope)
562 {
563 decl_base_sptr d;
564 do
565 {
566 d = pop_decl();
567 scope_decl_sptr s = dynamic_pointer_cast<scope_decl>(d);
568 if (s == scope)
569 break;
570 }
571 while (d);
572
573 if (!d)
574 return false;
575
576 return dynamic_pointer_cast<scope_decl>(d) == scope;
577 }
578
579 /// like @ref pop_scope, but if the scope couldn't be popped, the
580 /// function aborts the execution of the process.
581 ///
582 /// @param scope the scope to pop.
583 void
584 pop_scope_or_abort(scope_decl_sptr scope)
585 {ABG_ASSERT(pop_scope(scope));}
586
587 void
588 clear_decls_stack()
589 {m_decls_stack.clear();}
590
591 void
592 clear_type_map()
593 {m_types_map.clear();}
594
595 /// Clean the vector of types to canonicalize after the translation
596 /// unit has been read.
597 void
598 clear_types_to_canonicalize()
599 {m_types_to_canonicalize.clear();}
600
601
602 /// Test if two types are equal, without comparing them structurally.
603 ///
604 /// This either tests that type pointers are equal, or it tests
605 /// their names. This is because it might be two early to compare
606 /// types structurally because we are not necessarily done building
607 /// them yet.
608 ///
609 /// @param t1 the first type to compare.
610 ///
611 /// @param t2 the second type to compare.
612 ///
613 /// @return true iff the types are equal.
614 bool
615 types_equal(type_base_sptr t1, type_base_sptr t2)
616 {
617 if (t1.get() == t2.get())
618 return true;
619
620 // We are going to test qualified names only if both types have
621 // already been added to their scope.
622 bool qualified = (get_type_scope(t1) && get_type_scope(t2));
623
624 return (get_type_name(t1, qualified)
625 == get_type_name(t2, qualified));
626 }
627
628 /// Associate an ID with a type.
629 ///
630 /// @param type the type to associate with the ID.
631 ///
632 /// @param id the ID to associate to the type.
633 ///
634 /// @return true upon successful completion.
635 bool
636 key_type_decl(const type_base_sptr& type, const string& id)
637 {
638 if (!type)
639 return false;
640
641 m_types_map[id].push_back(type);
642
643 return true;
644 }
645
646 /// Associate an ID to a function template.
647 ///
648 /// @param fn_tmpl_decl the function template to consider.
649 ///
650 /// @param id the ID to associate to the function template.
651 ///
652 /// @return true upon successful completion, false otherwise. Note
653 /// that the function returns false if an ID was previously
654 /// associated to the function template.
655 bool
656 key_fn_tmpl_decl(shared_ptr<function_tdecl> fn_tmpl_decl,
657 const string& id)
658 {
659 ABG_ASSERT(fn_tmpl_decl);
660
661 const_fn_tmpl_map_it i = m_fn_tmpl_map.find(id);
662 if (i != m_fn_tmpl_map.end())
663 return false;
664
665 m_fn_tmpl_map[id] = fn_tmpl_decl;
666 return true;
667 }
668
669 /// Associate an ID to a class template.
670 ///
671 /// @param class_tmpl_decl the class template to consider.
672 ///
673 /// @param id the ID to associate to the class template.
674 ///
675 /// @return true upon successful completion, false otherwise. Note
676 /// that the function returns false if an ID was previously
677 /// associated to the class template.
678 bool
679 key_class_tmpl_decl(shared_ptr<class_tdecl> class_tmpl_decl,
680 const string& id)
681 {
682 ABG_ASSERT(class_tmpl_decl);
683
684 const_class_tmpl_map_it i = m_class_tmpl_map.find(id);
685 if (i != m_class_tmpl_map.end())
686 return false;
687
688 m_class_tmpl_map[id] = class_tmpl_decl;
689 return true;
690 }
691
692#ifdef WITH_SHOW_TYPE_USE_IN_ABILINT
693 /// Record that an artifact is used by another one.
694 ///
695 /// If a type is "used" by another one (as in the type is a sub-type
696 /// of another one), this function records that relation.
697 ///
698 /// @param used the type that is used.
699 ///
700 /// @param user the type that uses @p used.
701 void
702 record_artifact_as_used_by(type_or_decl_base* used,
703 type_or_decl_base* user)
704 {
705 if (m_artifact_used_by_map.find(used) == m_artifact_used_by_map.end())
706 {
707 vector<type_or_decl_base*> v;
708 m_artifact_used_by_map[used] = v;
709 }
710 m_artifact_used_by_map[used].push_back(user);
711 }
712
713 /// Record that an artifact is used by another one.
714 ///
715 /// If a type is "used" by another one (as in the type is a sub-type
716 /// of another one), this function records that relation.
717 ///
718 /// @param used the type that is used.
719 ///
720 /// @param user the type that uses @p used.
721 void
722 record_artifact_as_used_by(const type_or_decl_base_sptr& used,
723 const type_or_decl_base_sptr& user)
724 {record_artifact_as_used_by(used.get(), user.get());}
725
726 /// Record the sub-types of a fn-decl as being used by the fn-decl.
727 ///
728 /// @param fn the function decl to consider.
729 void
730 record_artifacts_as_used_in_fn_decl(const function_decl *fn)
731 {
732 if (!fn)
733 return;
734
735 type_base_sptr t = fn->get_return_type();
736 record_artifact_as_used_by(t.get(), const_cast<function_decl*>(fn));
737
738 for (auto pit : fn->get_parameters())
739 {
740 type_base_sptr t = pit->get_type();
741 record_artifact_as_used_by(t.get(), const_cast<function_decl*>(fn));
742 }
743 }
744
745 /// Record the sub-types of a function decl as being used by it.
746 ///
747 /// @param fn the function decl to consider.
748 void
749 record_artifacts_as_used_in_fn_decl(const function_decl_sptr& fn)
750 {record_artifacts_as_used_in_fn_decl(fn.get());}
751
752 /// Record the sub-types of a function type as being used by it.
753 ///
754 /// @param fn_type the function decl to consider.
755 void
756 record_artifacts_as_used_in_fn_type(const function_type *fn_type)
757 {
758 if (!fn_type)
759 return;
760
761 type_base_sptr t = fn_type->get_return_type();
762 record_artifact_as_used_by(t.get(), const_cast<function_type*>(fn_type));
763
764 for (auto pit : fn_type->get_parameters())
765 {
766 type_base_sptr t = pit->get_type();
767 record_artifact_as_used_by(t.get(),
768 const_cast<function_type*>(fn_type));
769 }
770 }
771
772 /// Record the sub-types of a function type as being used by it.
773 ///
774 /// @param fn_type the function decl to consider.
775 void
776 record_artifacts_as_used_in_fn_type(const function_type_sptr& fn_type)
777 {record_artifacts_as_used_in_fn_type(fn_type.get());}
778#endif
779
780 /// This function must be called on each declaration that is created
781 /// during the parsing. It adds the declaration to the scope that
782 /// its XML node belongs to and updates the state of the parsing
783 /// context accordingly.
784 ///
785 /// @param decl the newly created declaration.
786 ///
787 /// @param node the xml node @p decl originated from.
788 void
789 push_decl_to_scope(const decl_base_sptr& decl, xmlNodePtr node)
790 {
791 scope_decl* scope = nullptr;
792 scope = get_scope_ptr_for_node(node);
793 return push_decl_to_scope(decl, scope);
794 }
795
796 /// This function must be called on each declaration that is created during
797 /// the parsing. It adds the declaration to the current scope, and updates
798 /// the state of the parsing context accordingly.
799 ///
800 /// @param decl the newly created declaration.
801 void
802 push_decl_to_scope(const decl_base_sptr& decl,
803 scope_decl* scope)
804 {
805 ABG_ASSERT(decl);
806 if (scope)
807 {
808 add_decl_to_scope(decl, scope);
809 if (!decl->get_translation_unit())
810 decl->set_translation_unit(get_translation_unit());
811 ABG_ASSERT(decl->get_translation_unit());
812 }
813 push_decl(decl);
814 }
815
816 /// This function must be called on each type decl that is created
817 /// during the parsing. It adds the type decl to the current scope
818 /// and associates a unique ID to it.
819 ///
820 /// @param t type_decl
821 ///
822 /// @param id the unique ID to be associated to t
823 ///
824 /// @param scope the scope to add the type to.
825 ///
826 /// @return true upon successful completion.
827 ///
828 bool
829 push_and_key_type_decl(const type_base_sptr& t,
830 const string& id,
831 scope_decl* scope)
832 {
833 decl_base_sptr decl = get_type_declaration(t);
834 ABG_ASSERT(decl);
835
836 push_decl_to_scope(decl, scope);
837 if (!t->get_translation_unit())
838 t->set_translation_unit(get_translation_unit());
839 ABG_ASSERT(t->get_translation_unit());
840 key_type_decl(t, id);
841 return true;
842 }
843
844 /// This function must be called on each type decl that is created
845 /// during the parsing. It adds the type decl to the current scope
846 /// and associates a unique ID to it.
847 ///
848 /// @param t the type to consider.
849 ///
850 /// @param node the XML it originates from.
851 ///
852 /// @return true upon successful completion.
853 ///
854 bool
855 push_and_key_type_decl(const type_base_sptr& t,
856 const xmlNodePtr node,
857 bool add_to_current_scope)
858 {
859 string id;
860 if (!read_type_id_string(node, id))
861 return false;
862
863 scope_decl* scope = nullptr;
864 if (add_to_current_scope && !is_unique_type(t))
865 scope = get_scope_ptr_for_node(node);
866 return push_and_key_type_decl(t, id, scope);
867 }
868
869 /// Getter for the object that determines if a given declaration
870 /// ought to be put in the set of exported decls of the current
871 /// corpus.
872 ///
873 /// @return the exported decls builder.
874 corpus::exported_decls_builder*
875 get_exported_decls_builder()
876 {return corpus()->get_exported_decls_builder().get();}
877
878 /// Test if there are suppression specifications (associated to the
879 /// current corpus) that match a given SONAME or file name.
880 ///
881 /// @param soname the SONAME to consider.
882 ///
883 /// @param the file name to consider.
884 ///
885 /// @return true iff there are suppression specifications (associated to the
886 /// current corpus) that match the SONAME denoted by @p soname or
887 /// the file name denoted by @p filename.
888 bool
889 corpus_is_suppressed_by_soname_or_filename(const string& soname,
890 const string& filename)
891 {
895
896 for (suppressions_type::const_iterator s = suppressions().begin();
897 s != suppressions().end();
898 ++s)
901 *suppr))
902 return true;
903
904 return false;
905 }
906
907 /// Clear all the data that must absolutely be cleared at the end of
908 /// the parsing of a translation unit.
909 void
910 clear_per_translation_unit_data()
911 {
912 }
913
914#ifdef WITH_DEBUG_SELF_COMPARISON
915 /// Perform a debugging routine for the "self-comparison" mode.
916 ///
917 /// This is done when this command is on:
918 ///
919 /// "abidw --debug-abidiff".
920 ///
921 /// Consider a type 't' built from an XML element from the abixml
922 /// reader and that has just been canonicalized.
923 ///
924 /// This function checks if the canonical type of 't' is the same as
925 /// the canonical type of the type which was saved into the abixml
926 /// with the same "type-id" as the one of 't'.
927 ///
928 /// Note that at abixml saving time, a debugging file was saved on
929 /// disk to record the mapping of canonical type pointers and their
930 /// type-ids. Right before reading the abixml again, that file was
931 /// read again and the mapping was loaded in the map returned by
932 /// environment::get_type_id_canonical_type_map().
933 void
934 maybe_check_abixml_canonical_type_stability(type_base_sptr& t)
935 {
936 if (!get_environment().self_comparison_debug_is_on()
937 || get_environment().get_type_id_canonical_type_map().empty())
938 return ;
939
941 if (odr_is_relevant(*c) && c->get_is_declaration_only())
942 // Declaration-only classes don't have canonical types in
943 // environments where ODR is relevant (like in C++).
944 return;
945
946 // Let's get the type-id of this type as recorded in the
947 // originating abixml file.
948 string type_id =
949 get_environment().get_type_id_from_pointer(reinterpret_cast<uintptr_t>(t.get()));
950
951 if (!type_id.empty())
952 {
953 // Now let's get the canonical type that initially led to the
954 // serialization of a type with this type-id, when the abixml
955 // was being serialized.
956 auto j = get_environment().get_type_id_canonical_type_map().find(type_id);
957 if (j == get_environment().get_type_id_canonical_type_map().end())
958 {
959 if (t->get_naked_canonical_type())
960 std::cerr << "error: no type with type-id: '"
961 << type_id
962 << "' could be read back from the typeid file\n";
963 }
964 else if (j->second
965 != reinterpret_cast<uintptr_t>(t->get_canonical_type().get()))
966 // So the canonical type of 't' (at abixml de-serialization
967 // time) is different from the canonical type that led to
968 // the serialization of 't' at abixml serialization time.
969 // Report this because it needs further debugging.
970 std::cerr << "error: canonical type for type '"
971 << t->get_pretty_representation(/*internal=*/true,
972 /*qualified=*/true)
973 << "' of type-id '" << type_id
974 << "' changed from '" << std::hex
975 << j->second << "' to '" << std::hex
976 << reinterpret_cast<uintptr_t>(t->get_canonical_type().get())
977 << std::dec
978 << "'\n";
979 }
980 }
981#endif
982
983 /// Schedule a type for being canonicalized after the current
984 /// translation unit is read.
985 ///
986 /// @param t the type to consider for canonicalization.
987 void
988 schedule_type_for_canonicalization(type_base_sptr t)
989 {
990 if (t)
991 m_types_to_canonicalize.push_back(t);
992 }
993
994 /// Perform the canonicalizing of types that ought to be done after
995 /// the current translation unit is read. This function is called
996 /// when the current corpus is fully built.
997 void
998 perform_type_canonicalization()
999 {
1000 tools_utils::timer cn_timer;
1001 if (do_log())
1002 {
1003 std::cerr << "ABIXML Reader is going to canonicalize "
1004 << m_types_to_canonicalize.size()
1005 << " types";
1006 corpus_sptr c = corpus();
1007 if (c)
1008 std::cerr << " of corpus " << corpus()->get_path() << "\n";
1009 cn_timer.start();
1010 }
1011
1012
1013 ir::hash_and_canonicalize_types(m_types_to_canonicalize.begin(),
1014 m_types_to_canonicalize.end(),
1015 [](const vector<type_base_sptr>::const_iterator& i)
1016 {return *i;},
1017 do_log());
1018
1019 if (do_log())
1020 {
1021 cn_timer.stop();
1022 std::cerr << "ABIXML Reader: canonicalized all types in: " << cn_timer << "\n";
1023 }
1024 }
1025
1026 /// Test whether if a given function suppression matches a function
1027 /// designated by a regular expression that describes its name.
1028 ///
1029 /// @param s the suppression specification to evaluate to see if it
1030 /// matches a given function name.
1031 ///
1032 /// @param fn_name the name of the function of interest. Note that
1033 /// this name must be *non* qualified.
1034 ///
1035 /// @return true iff the suppression specification @p s matches the
1036 /// function whose name is @p fn_name.
1037 bool
1038 suppression_matches_function_name(const suppr::function_suppression_sptr& s,
1039 const string& fn_name) const
1040 {
1041 if (!s)
1042 return false;
1043 return suppression_matches_function_name(*s, fn_name);
1044 }
1045
1046 /// Tests if a suppression specification can match ABI artifacts
1047 /// coming from the ABI corpus being analyzed.
1048 ///
1049 /// This tests if the suppression matches the soname of and binary
1050 /// name of the corpus being analyzed.
1051 ///
1052 /// @param s the suppression specification to consider.
1053 bool
1054 suppression_can_match(const suppr::suppression_base& s) const
1055 {
1056 corpus_sptr corp = corpus();
1057
1058 if (!s.priv_->matches_soname(corp->get_soname()))
1059 if (s.has_soname_related_property())
1060 // The suppression has some SONAME related properties, but
1061 // none of them match the SONAME of the current binary. So
1062 // the suppression cannot match the current binary.
1063 return false;
1064
1065 if (!s.priv_->matches_binary_name(corp->get_path()))
1066 if (s.has_file_name_related_property())
1067 // The suppression has some file_name related properties, but
1068 // none of them match the file name of the current binary. So
1069 // the suppression cannot match the current binary.
1070 return false;
1071
1072 return true;
1073 }
1074
1075 /// Test whether if a given function suppression matches a function
1076 /// designated by a regular expression that describes its name.
1077 ///
1078 /// @param s the suppression specification to evaluate to see if it
1079 /// matches a given function name.
1080 ///
1081 /// @param fn_name the name of the function of interest. Note that
1082 /// this name must be *non* qualified.
1083 ///
1084 /// @return true iff the suppression specification @p s matches the
1085 /// function whose name is @p fn_name.
1086 bool
1087 suppression_matches_function_name(const suppr::function_suppression& s,
1088 const string& fn_name) const
1089 {
1090 if (!s.get_drops_artifact_from_ir()
1091 || !suppression_can_match(s))
1092 return false;
1093
1094 return suppr::suppression_matches_function_name(s, fn_name);
1095 }
1096
1097 /// Test if a given type suppression specification matches a type
1098 /// designated by its name and location.
1099 ///
1100 /// @param s the suppression specification to consider.
1101 ///
1102 /// @param type_name the fully qualified type name to consider.
1103 ///
1104 /// @param type_location the type location to consider.
1105 ///
1106 /// @return true iff the type suppression specification matches a
1107 /// type of a given name and location.
1108 bool
1109 suppression_matches_type_name_or_location(const suppr::type_suppression& s,
1110 const string& type_name,
1111 const location& type_location) const
1112 {
1113 if (!suppression_can_match(s))
1114 return false;
1115
1117 type_location);
1118 }
1119
1120 virtual ir::corpus_sptr
1121 read_corpus(fe_iface::status& status)
1122 {
1123 tools_utils::timer global_timer;
1124 global_timer.start();
1125
1126 corpus_sptr nil;
1127
1128 xml::reader_sptr xml_reader = get_libxml_reader();
1129 if (!xml_reader)
1130 return nil;
1131
1132 // This is to remember to call xmlTextReaderNext if we ever call
1133 // xmlTextReaderExpand.
1134 bool call_reader_next = false;
1135
1136 xmlNodePtr node = get_corpus_node();
1137 if (!node)
1138 {
1139 // The document must start with the abi-corpus node.
1140 int status = 1;
1141 while (status == 1
1142 && XML_READER_GET_NODE_TYPE(xml_reader) != XML_READER_TYPE_ELEMENT)
1143 status = advance_cursor (*this);
1144
1145 if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(xml_reader).get(),
1146 BAD_CAST("abi-corpus")))
1147 return nil;
1148
1149#ifdef WITH_DEBUG_SELF_COMPARISON
1150 if (get_environment().self_comparison_debug_is_on())
1151 get_environment().set_self_comparison_debug_input(corpus());
1152#endif
1153
1154 ir::corpus& corp = *corpus();
1155
1156 corp.set_origin(corpus::NATIVE_XML_ORIGIN);
1157
1158 handle_version_attribute(xml_reader, corp);
1159
1160 maybe_drop_hash_values();
1161
1162 xml::xml_char_sptr path_str = XML_READER_GET_ATTRIBUTE(xml_reader, "path");
1163 string path;
1164
1165 if (path_str)
1166 {
1167 path = reinterpret_cast<char*>(path_str.get());
1168 corpus_path(path);
1169 corp.set_path(path);
1170 }
1171
1172 xml::xml_char_sptr architecture_str =
1173 XML_READER_GET_ATTRIBUTE(xml_reader, "architecture");
1174 if (architecture_str)
1175 corp.set_architecture_name
1176 (reinterpret_cast<char*>(architecture_str.get()));
1177
1178 xml::xml_char_sptr soname_str =
1179 XML_READER_GET_ATTRIBUTE(xml_reader, "soname");
1180 string soname;
1181
1182 if (soname_str)
1183 {
1184 soname = reinterpret_cast<char*>(soname_str.get());
1185 dt_soname(soname);
1186 corp.set_soname(soname);
1187 }
1188
1189 // Apply suppression specifications here to honour:
1190 //
1191 // [suppress_file]
1192 // (soname_regexp
1193 // |soname_not_regexp
1194 // |file_name_regexp
1195 // |file_name_not_regexp) = <soname-or-file-name>
1196 if ((!soname.empty() || !path.empty())
1197 && corpus_is_suppressed_by_soname_or_filename(soname, path))
1198 return nil;
1199
1200 node = xmlTextReaderExpand(xml_reader.get());
1201 if (!node)
1202 return nil;
1203
1204 call_reader_next = true;
1205 }
1206 else
1207 {
1208#ifdef WITH_DEBUG_SELF_COMPARISON
1209 if (get_environment().self_comparison_debug_is_on())
1210 get_environment().set_self_comparison_debug_input(corpus());
1211#endif
1212
1213 ir::corpus& corp = *corpus();
1214 corp.set_origin(corpus::NATIVE_XML_ORIGIN);
1215
1216 xml::xml_char_sptr path_str = XML_NODE_GET_ATTRIBUTE(node, "path");
1217 if (path_str)
1218 corp.set_path(reinterpret_cast<char*>(path_str.get()));
1219
1220 xml::xml_char_sptr architecture_str =
1221 XML_NODE_GET_ATTRIBUTE(node, "architecture");
1222 if (architecture_str)
1223 corp.set_architecture_name
1224 (reinterpret_cast<char*>(architecture_str.get()));
1225
1226 xml::xml_char_sptr soname_str =
1227 XML_NODE_GET_ATTRIBUTE(node, "soname");
1228 if (soname_str)
1229 corp.set_soname(reinterpret_cast<char*>(soname_str.get()));
1230 }
1231
1232 // If the corpus element node has children nodes, make
1233 // get_corpus_node() returns the first child element node of
1234 // the corpus element that *needs* to be processed.
1235 if (node->children)
1236 {
1237 xmlNodePtr n = xmlFirstElementChild(node);
1238 set_corpus_node(n);
1239 }
1240
1241 ir::corpus& corp = *corpus();
1242
1243 tools_utils::timer t;
1244
1245 if (do_log())
1246 {
1247 std::cerr << "ABIXML Reader: mapping XML nodes to type ID "
1248 << "for corpus " << corp.get_path()
1249 << "...\n";
1250 t.start();
1251 }
1252
1253 walk_xml_node_to_map_type_ids(*this, node);
1254
1255 if (do_log())
1256 {
1257 t.stop();
1258 std::cerr << "ABIXML Reader: mapped XML nodes to type ID "
1259 << "for corpus " << corp.get_path()
1260 << " in: "
1261 << t
1262 << "\n";
1263 }
1264
1265 // Read the needed element
1266 vector<string> needed;
1267 read_elf_needed_from_input(*this, needed);
1268 if (!needed.empty())
1269 corp.set_needed(needed);
1270
1272 var_sym_db(new string_elf_symbols_map_type);
1273
1274 if (do_log())
1275 {
1276 std::cerr << "ABIXML Reader: reading symbols information "
1277 << "for corpus " << corp.get_path()
1278 << " ...\n";
1279 t.start();
1280 }
1281
1282 // Read the symbol databases.
1283 string_strings_map_type non_resolved_fn_syms_aliases, non_resolved_var_syms_aliases;
1284 read_symbol_db_from_input(*this, fn_sym_db, var_sym_db,
1285 non_resolved_fn_syms_aliases,
1286 non_resolved_var_syms_aliases);
1287 resolve_symbol_aliases(fn_sym_db, var_sym_db,
1288 non_resolved_fn_syms_aliases,
1289 non_resolved_var_syms_aliases);
1290
1291 // Note that it's possible that both fn_sym_db and var_sym_db are nil,
1292 // due to potential suppression specifications. That's fine.
1293 corp.set_symtab(symtab_reader::symtab::load(fn_sym_db, var_sym_db));
1294
1295 if (do_log())
1296 {
1297 t.stop();
1298 std::cerr << "ABIXML Reader: read symbols information "
1299 << "for corpus " << corp.get_path()
1300 << " in: "
1301 << t
1302 << "\n";
1303 }
1304
1305 get_environment().canonicalization_is_done(false);
1306
1307 if (do_log())
1308 {
1309 std::cerr << "ABIXML Reader: building IR "
1310 << "for corpus " << corp.get_path()
1311 << "...\n";
1312 t.start();
1313 }
1314
1315 // Read the translation units.
1316 while (read_translation_unit_from_input(*this))
1317 ;
1318
1319 if (do_log())
1320 {
1321 t.stop();
1322 std::cerr << "ABIXML Reader: built IR "
1323 << "for corpus " << corp.get_path()
1324 << " in: " << t << "\n";
1325 }
1326
1327 if (tracking_non_reachable_types())
1328 {
1329 bool is_tracking_non_reachable_types = false;
1330 read_tracking_non_reachable_types(node, is_tracking_non_reachable_types);
1331
1333 (corp.recording_types_reachable_from_public_interface_supported()
1334 == is_tracking_non_reachable_types);
1335 }
1336
1337
1338 if (do_log())
1339 {
1340 std::cerr << "ABIXML Reader: canonicalizing types "
1341 << "for corpus " << corp.get_path()
1342 << " ...\n";
1343 t.start();
1344 }
1345
1346 perform_type_canonicalization();
1347
1348 if (do_log())
1349 {
1350 t.stop();
1351 std::cerr << "ABIXML Reader: canonicalized types for corpus "
1352 << corpus()->get_path()
1353 << " in :" << t << "\n";
1354 }
1355
1356 get_environment().canonicalization_is_done(true);
1357
1358 if (call_reader_next)
1359 {
1360 // This is the necessary counter-part of the xmlTextReaderExpand()
1361 // call at the beginning of the function.
1362 xmlTextReaderNext(xml_reader.get());
1363 // The call above invalidates the xml node returned by
1364 // xmlTextReaderExpand, which is can still be accessed via
1365 // set_corpus_node.
1366 set_corpus_node(0);
1367 }
1368 else
1369 {
1370 node = get_corpus_node();
1371 node = xmlNextElementSibling(node);
1372 if (!node)
1373 {
1374 node = get_corpus_node();
1375 if (node)
1376 node = xmlNextElementSibling(node->parent);
1377 }
1378 set_corpus_node(node);
1379 }
1380
1381 if (do_log())
1382 {
1383 std::cerr << "ABIXML Reader: sorting functions and variables for corpus "
1384 << corp.get_path()
1385 << "\n";
1386 t.start();
1387 }
1388
1389 corpus()->sort_functions();
1390 corpus()->sort_variables();
1391
1392 if (do_log())
1393 {
1394 t.stop();
1395 std::cerr << "ABIXML Reader: sorted functions and variables for corpus "
1396 << corpus()->get_path()
1397 << " in " << t
1398 << "\n";
1399 }
1400
1401 if (do_log())
1402 {
1403 global_timer.stop();
1404 std::cerr << "ABIXML Reader: Analyzed corpus " << corpus()->get_path()
1405 << " in " << global_timer << "\n";
1406 std::cerr << "======================================================\n";
1407 }
1408
1409 status = STATUS_OK;
1410 return corpus();
1411 }
1412
1413 /// Test if the reader should drop the hash values coming from the
1414 /// ABIXML on the floor.
1415 ///
1416 /// If the minor version number of the ABIXML document is older than
1417 /// the current minor abixml version of the document being read,
1418 /// then the hash values are dropped and new ones are going to be
1419 /// computed by ir::hash_and_canonicalize_types.
1420 void
1421 maybe_drop_hash_values()
1422 {
1423 string current_major, current_minor;
1424 abigail::abigail_get_abixml_version(current_major, current_minor);
1425
1426 if (current_major.empty() || current_minor.empty())
1427 return;
1428
1429 ir::corpus& corp = *corpus();
1430 bool drop_hash_values_from_abixml = false;
1431 if (current_major > corp.get_format_major_version_number()
1432 || current_minor > corp.get_format_minor_version_number())
1433 drop_hash_values_from_abixml = true;
1434
1435 if (drop_hash_values_from_abixml)
1436 m_drop_hash_value = true;
1437 }
1438
1439 /// Read the hash value from an XML node and set it onto an IR node.
1440 ///
1441 /// @param node the XML node to read the hash value from.
1442 ///
1443 /// @param ir_node output parameter. The IR node to set the hash
1444 /// value read from @p node onto.
1445 void
1446 read_hash_and_stash(const xmlNodePtr node,
1447 const type_or_decl_base_sptr& ir_node)
1448 {
1449 uint64_t hash = 0, cti = 0;
1450 if (!m_drop_hash_value
1451 && read_type_hash_and_cti(node, hash, cti))
1452 {
1453 ir_node->priv_->force_set_hash_value(hash);
1454 type_base_sptr type;
1455 if (function_decl_sptr fn = is_function_decl(ir_node))
1456 type = fn->get_type();
1457 else
1458 type = is_type(ir_node);
1459
1460 if (type)
1461 {
1462 type->type_or_decl_base::priv_->force_set_hash_value(hash);
1463 type->priv_->canonical_type_index = cti;
1464 }
1465 }
1466 }
1467};// end class reader
1468
1469/// Convert a @ref abigail:fe_iface into an abigail::abixml::reader.
1470///
1471/// @param f the interface to convert.
1472///
1473/// @return the resulting abigail::abixml::reader.
1474reader_sptr
1475is_reader(fe_iface_sptr iface)
1476{return dynamic_pointer_cast<reader>(iface);}
1477
1478static int advance_cursor(reader&);
1479static bool read_translation_unit(fe_iface&, translation_unit&, xmlNodePtr);
1480static translation_unit_sptr get_or_read_and_add_translation_unit(reader&, xmlNodePtr);
1481static translation_unit_sptr read_translation_unit_from_input(fe_iface&);
1482static bool read_symbol_db_from_input(reader&,
1487static bool read_location(const reader&, xmlNodePtr, location&);
1488static bool read_artificial_location(const reader&,
1489 xmlNodePtr, location&);
1490static bool maybe_set_artificial_location(const reader&,
1491 xmlNodePtr,
1493static bool read_visibility(xmlNodePtr, decl_base::visibility&);
1494static bool read_binding(xmlNodePtr, decl_base::binding&);
1495static bool read_access(xmlNodePtr, access_specifier&);
1496static bool read_size_and_alignment(xmlNodePtr, size_t&, size_t&);
1497static bool read_static(xmlNodePtr, bool&);
1498static bool read_offset_in_bits(xmlNodePtr, size_t&);
1499static bool read_cdtor_const(xmlNodePtr, bool&, bool&, bool&);
1500static bool read_is_virtual(xmlNodePtr, bool&);
1501static bool read_is_struct(xmlNodePtr, bool&);
1502static bool read_is_anonymous(xmlNodePtr, bool&);
1503static bool read_elf_symbol_type(xmlNodePtr, elf_symbol::type&);
1504static bool read_elf_symbol_binding(xmlNodePtr, elf_symbol::binding&);
1505static bool read_elf_symbol_visibility(xmlNodePtr,
1508build_namespace_decl(reader&, const xmlNodePtr, bool);
1509
1510// <build a c++ class from an instance of xmlNodePtr>
1511//
1512// Note that whenever a new function to build a type is added here,
1513// you should make sure to call it from the build_type function, which
1514// should be the last function of the list of declarated function
1515// below.
1516
1517static elf_symbol_sptr
1518build_elf_symbol(reader&, const xmlNodePtr, bool);
1519
1520static elf_symbol_sptr
1521build_elf_symbol_from_reference(reader&, const xmlNodePtr);
1522
1523static bool
1524build_elf_symbol_db(reader&, const xmlNodePtr, bool,
1527
1529build_function_parameter (reader&, const xmlNodePtr);
1530
1531static function_decl_sptr
1532build_function_decl(reader&, const xmlNodePtr,
1533 class_or_union_sptr, bool, bool);
1534
1535static function_decl_sptr
1536build_function_decl_if_not_suppressed(reader&, const xmlNodePtr,
1537 class_or_union_sptr, bool, bool);
1538
1539static bool
1540function_is_suppressed(const reader& rdr,
1541 xmlNodePtr node);
1542
1543static var_decl_sptr
1544build_var_decl_if_not_suppressed(reader&, const xmlNodePtr, bool);
1545
1546static var_decl_sptr
1547build_var_decl(reader&, const xmlNodePtr, bool);
1548
1549static bool
1550variable_is_suppressed(const reader& rdr,
1551 xmlNodePtr node);
1552
1553static shared_ptr<type_decl>
1554build_type_decl(reader&, const xmlNodePtr, bool);
1555
1556static qualified_type_def_sptr
1557build_qualified_type_decl(reader&, const xmlNodePtr, bool);
1558
1559static shared_ptr<pointer_type_def>
1560build_pointer_type_def(reader&, const xmlNodePtr, bool);
1561
1562static shared_ptr<reference_type_def>
1563build_reference_type_def(reader&, const xmlNodePtr, bool);
1564
1566build_ptr_to_mbr_type(reader&, const xmlNodePtr, bool);
1567
1568static shared_ptr<function_type>
1569build_function_type(reader&, const xmlNodePtr, bool);
1570
1572build_subrange_type(reader&, const xmlNodePtr, bool);
1573
1575build_array_type_def(reader&, const xmlNodePtr, bool);
1576
1578build_enum_type_decl(reader&, const xmlNodePtr, bool);
1579
1580static shared_ptr<typedef_decl>
1581build_typedef_decl(reader&, const xmlNodePtr, bool);
1582
1583static class_decl_sptr
1584build_class_decl(reader&, const xmlNodePtr, bool);
1585
1586static union_decl_sptr
1587build_union_decl(reader&, const xmlNodePtr, bool);
1588
1589static shared_ptr<function_tdecl>
1590build_function_tdecl(reader&, const xmlNodePtr, bool);
1591
1592static shared_ptr<class_tdecl>
1593build_class_tdecl(reader&, const xmlNodePtr, bool);
1594
1596build_type_tparameter(reader&, const xmlNodePtr,
1597 unsigned, template_decl_sptr);
1598
1600build_type_composition(reader&, const xmlNodePtr,
1601 unsigned, template_decl_sptr);
1602
1604build_non_type_tparameter(reader&, const xmlNodePtr,
1605 unsigned, template_decl_sptr);
1606
1608build_template_tparameter(reader&, const xmlNodePtr,
1609 unsigned, template_decl_sptr);
1610
1612build_template_parameter(reader&, const xmlNodePtr,
1613 unsigned, template_decl_sptr);
1614
1615// Please make this build_type function be the last one of the list.
1616// Note that it should call each type-building function above. So
1617// please make sure to update it accordingly, whenever a new
1618// type-building function is added here.
1619static shared_ptr<type_base>
1620build_type(reader&, const xmlNodePtr, bool);
1621// </build a c++ class from an instance of xmlNodePtr>
1622
1623static type_or_decl_base_sptr handle_element_node(reader&, xmlNodePtr, bool);
1624static decl_base_sptr handle_type_decl(reader&, xmlNodePtr, bool);
1625static decl_base_sptr handle_namespace_decl(reader&, xmlNodePtr, bool);
1626static decl_base_sptr handle_qualified_type_decl(reader&,
1627 xmlNodePtr, bool);
1628static decl_base_sptr handle_pointer_type_def(reader&,
1629 xmlNodePtr, bool);
1630static decl_base_sptr handle_reference_type_def(reader&,
1631 xmlNodePtr, bool);
1632static type_base_sptr handle_function_type(reader&,
1633 xmlNodePtr, bool);
1634static decl_base_sptr handle_array_type_def(reader&,
1635 xmlNodePtr, bool);
1636static decl_base_sptr handle_enum_type_decl(reader&, xmlNodePtr, bool);
1637static decl_base_sptr handle_typedef_decl(reader&, xmlNodePtr, bool);
1638static decl_base_sptr handle_var_decl(reader&, xmlNodePtr, bool);
1639static decl_base_sptr handle_function_decl(reader&, xmlNodePtr, bool);
1640static decl_base_sptr handle_class_decl(reader&, xmlNodePtr, bool);
1641static decl_base_sptr handle_union_decl(reader&, xmlNodePtr, bool);
1642static decl_base_sptr handle_function_tdecl(reader&, xmlNodePtr, bool);
1643static decl_base_sptr handle_class_tdecl(reader&, xmlNodePtr, bool);
1644
1645#ifdef WITH_SHOW_TYPE_USE_IN_ABILINT
1646#define RECORD_ARTIFACT_AS_USED_BY(rdr, used, user) \
1647 rdr.record_artifact_as_used_by(used,user)
1648#define RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(rdr, fn) \
1649 rdr.record_artifacts_as_used_in_fn_decl(fn)
1650#define RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(rdr, fn_type)\
1651 rdr.record_artifacts_as_used_in_fn_type(fn_type)
1652#else
1653#define RECORD_ARTIFACT_AS_USED_BY(rdr, used, user)
1654#define RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(rdr, fn)
1655#define RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(rdr, fn_type)
1656#endif
1657
1658/// Get the IR node representing the scope for a given XML node.
1659///
1660/// This function might trigger the building of a full sub-tree of IR.
1661///
1662/// @param node the XML for which to return the scope decl. If its
1663/// parent XML node has no corresponding IR node, that IR node is constructed.
1664///
1665/// @param access the access specifier of the node in its scope, if
1666/// applicable. If the node doesn't have any access specifier
1667/// provided in its scope, then the parameter is set to no_access.
1668///
1669/// @return the IR node representing the scope of the IR node for the
1670/// XML node given in argument.
1672reader::get_scope_for_node(xmlNodePtr node, access_specifier& access)
1673{
1674 scope_decl_sptr nil, scope;
1675 if (!node)
1676 return nil;
1677
1678 xmlNodePtr parent = node->parent;
1679 access = no_access;
1680 if (parent
1681 && (xmlStrEqual(parent->name, BAD_CAST("data-member"))
1682 || xmlStrEqual(parent->name, BAD_CAST("member-type"))
1683 || xmlStrEqual(parent->name, BAD_CAST("member-function"))
1684 || xmlStrEqual(parent->name, BAD_CAST("member-template"))
1685 || xmlStrEqual(parent->name, BAD_CAST("template-parameter-type-composition"))
1686 || xmlStrEqual(parent->name, BAD_CAST("array-type-def"))))
1687 {
1688 read_access(parent, access);
1689 parent = parent->parent;
1690 }
1691
1692 xml_node_decl_base_sptr_map::const_iterator i =
1693 get_xml_node_decl_map().find(parent);
1694 if (i == get_xml_node_decl_map().end())
1695 {
1696 if (xmlStrEqual(parent->name, BAD_CAST("abi-instr")))
1697 {
1699 get_or_read_and_add_translation_unit(*this, parent);
1700 return tu->get_global_scope();
1701 }
1702
1703 access_specifier a = no_access;
1704 scope_decl_sptr parent_scope = get_scope_for_node(parent, a);
1705 push_decl(parent_scope);
1706 scope = dynamic_pointer_cast<scope_decl>
1707 (handle_element_node(*this, parent, /*add_decl_to_scope=*/true));
1708 ABG_ASSERT(scope);
1709 pop_scope_or_abort(parent_scope);
1710 }
1711 else
1712 scope = dynamic_pointer_cast<scope_decl>(i->second);
1713
1714 return scope;
1715}
1716
1717/// Get the IR node representing the scope for a given XML node.
1718///
1719/// This function might trigger the building of a full sub-tree of IR.
1720///
1721/// @param node the XML for which to return the scope decl. If its
1722/// parent XML node has no corresponding IR node, that IR node is constructed.
1723///
1724/// @return the IR node representing the scope of the IR node for the
1725/// XML node given in argument.
1727reader::get_scope_for_node(xmlNodePtr node)
1728{
1729 access_specifier access;
1730 return get_scope_for_node(node, access);
1731}
1732
1733/// Get the IR node representing the scope for a given XML node.
1734///
1735/// This function might trigger the building of a full sub-tree of IR.
1736///
1737/// @param node the XML for which to return the scope decl. If its
1738/// parent XML node has no corresponding IR node, that IR node is constructed.
1739///
1740/// @return the IR node representing the scope of the IR node for the
1741/// XML node given in argument.
1742scope_decl*
1743reader::get_scope_ptr_for_node(xmlNodePtr node)
1744{
1745 scope_decl_sptr scope = get_scope_for_node(node);
1746 if (scope)
1747 return scope.get();
1748 return nullptr;
1749}
1750
1751/// Get the type declaration IR node that matches a given XML type node ID.
1752///
1753/// If no IR node has been built for this ID, this function builds the
1754/// type declaration IR node and returns it. Subsequent invocation of
1755/// this function with this ID will just return that ID previously returned.
1756///
1757/// @param id the XML node ID to consider.
1758///
1759/// @return the type declaration for the ID given in parameter.
1760type_base_sptr
1761reader::build_or_get_type_decl(const string& id, bool add_decl_to_scope)
1762{
1763 type_base_sptr t = get_type_decl(id);
1764
1765 if (!t)
1766 {
1767 xmlNodePtr n = get_xml_node_from_id(id);
1768 ABG_ASSERT(n);
1769
1770 scope_decl_sptr scope;
1771 access_specifier access = no_access;
1773 {
1774 scope = get_scope_for_node(n, access);
1775 /// In some cases, if for instance the scope of 'n' is a
1776 /// namespace, get_scope_for_node() can trigger the building
1777 /// of what is underneath of the namespace, if that has not
1778 /// already been done. So after that, the IR node for 'n'
1779 /// might have been built; let's try to see if we are in
1780 /// that case. Otherwise, we'll just build the IR node for
1781 /// 'n' ourselves.
1782 if ((t = get_type_decl(id)))
1783 return t;
1784 ABG_ASSERT(scope);
1785 push_decl(scope);
1786 }
1787
1788 t = build_type(*this, n, add_decl_to_scope);
1789 ABG_ASSERT(t);
1790 if (is_member_type(t) && access != no_access)
1791 {
1793 decl_base_sptr d = get_type_declaration(t);
1794 ABG_ASSERT(d);
1795 set_member_access_specifier(d, access);
1796 }
1797 map_xml_node_to_decl(n, get_type_declaration(t));
1798
1800 pop_scope_or_abort(scope);
1801
1802 schedule_type_for_canonicalization(t);
1803 }
1804 return t;
1805}
1806
1807/// Moves the xmlTextReader cursor to the next xml node in the input
1808/// document. Return 1 of the parsing was successful, 0 if no input
1809/// xml token is left, or -1 in case of error.
1810///
1811/// @param rdr the ABIXML reader
1812///
1813static int
1814advance_cursor(reader& rdr)
1815{
1816 xml::reader_sptr reader = rdr.get_libxml_reader();
1817 return xmlTextReaderRead(reader.get());
1818}
1819
1820/// Walk an entire XML sub-tree to build a map where the key is the
1821/// the value of the 'id' attribute (for type definitions) and the value
1822/// is the xml node containing the 'id' attribute.
1823///
1824/// @param rdr the context of the reader.
1825///
1826/// @param node the XML sub-tree node to walk. It must be an element
1827/// node.
1828static void
1829walk_xml_node_to_map_type_ids(reader& rdr,
1830 xmlNodePtr node)
1831{
1832 xmlNodePtr n = node;
1833
1834 if (!n || n->type != XML_ELEMENT_NODE)
1835 return;
1836
1837 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(n, "id"))
1838 {
1839 string id = CHAR_STR(s);
1840 rdr.map_id_and_node(id, n);
1841 }
1842
1843 for (n = xmlFirstElementChild(n); n; n = xmlNextElementSibling(n))
1844 walk_xml_node_to_map_type_ids(rdr, n);
1845}
1846
1847static bool
1848read_translation_unit(fe_iface& iface, translation_unit& tu, xmlNodePtr node)
1849{
1850 abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
1851
1852 if (!rdr.corpus()->is_empty())
1853 tu.set_corpus(rdr.corpus().get());
1854
1855 xml::xml_char_sptr addrsize_str =
1856 XML_NODE_GET_ATTRIBUTE(node, "address-size");
1857 if (addrsize_str)
1858 {
1859 char address_size = atoi(reinterpret_cast<char*>(addrsize_str.get()));
1860 tu.set_address_size(address_size);
1861 }
1862
1863 xml::xml_char_sptr path_str = XML_NODE_GET_ATTRIBUTE(node, "path");
1864 if (path_str)
1865 tu.set_path(reinterpret_cast<char*>(path_str.get()));
1866
1867 xml::xml_char_sptr comp_dir_path_str =
1868 XML_NODE_GET_ATTRIBUTE(node, "comp-dir-path");
1869 if (comp_dir_path_str)
1870 tu.set_compilation_dir_path(reinterpret_cast<char*>
1871 (comp_dir_path_str.get()));
1872
1873 xml::xml_char_sptr language_str = XML_NODE_GET_ATTRIBUTE(node, "language");
1874 if (language_str)
1876 (reinterpret_cast<char*>(language_str.get())));
1877
1878
1879 // We are at global scope, as we've just seen the top-most
1880 // "abi-instr" element.
1881 rdr.push_decl(tu.get_global_scope());
1882 rdr.map_xml_node_to_decl(node, tu.get_global_scope());
1883
1884 if (rdr.get_id_xml_node_map().empty()
1885 || !rdr.corpus())
1886 walk_xml_node_to_map_type_ids(rdr, node);
1887
1888 for (xmlNodePtr n = xmlFirstElementChild(node);
1889 n;
1890 n = xmlNextElementSibling(n))
1891 handle_element_node(rdr, n, /*add_decl_to_scope=*/true);
1892
1893 rdr.pop_scope_or_abort(tu.get_global_scope());
1894
1895 xml::reader_sptr reader = rdr.get_libxml_reader();
1896 if (!reader)
1897 return false;
1898
1899 rdr.clear_per_translation_unit_data();
1900
1901 return true;
1902}
1903
1904/// Read a given xml node representing a tranlsation unit.
1905///
1906/// If the current corpus already contains a translation unit of the
1907/// path of the xml node we need to look at, then return that
1908/// translation unit. Otherwise, read the translation unit, build a
1909/// @ref translation_unit out of it, add it to the current corpus and
1910/// return it.
1911///
1912/// @param rdr the ABIXML reader.
1913///
1914/// @param node the XML node to consider.
1915///
1916/// @return the resulting translation unit.
1918get_or_read_and_add_translation_unit(reader& rdr, xmlNodePtr node)
1919{
1920 corpus_sptr corp = rdr.corpus();
1921
1923 string tu_path;
1924 xml::xml_char_sptr path_str = XML_NODE_GET_ATTRIBUTE(node, "path");
1925
1926 if (corp && !corp->is_empty())
1927 {
1928 if (path_str.get())
1929 tu_path = reinterpret_cast<char*>(path_str.get());
1930 tu = corp->find_translation_unit(tu_path);
1931 if (tu)
1932 return tu;
1933 }
1934
1935 tu.reset(new translation_unit(rdr.get_environment(), tu_path));
1936 if (corp && !corp->is_empty())
1937 corp->add(tu);
1938
1939 if (read_translation_unit(rdr, *tu, node))
1940 return tu;
1941
1942 return translation_unit_sptr();
1943}
1944
1945/// Parse the input XML document containing a translation_unit,
1946/// represented by an 'abi-instr' element node, associated to the current
1947/// context.
1948///
1949/// @param rdr the current input context
1950///
1951/// @return the translation unit resulting from the parsing upon
1952/// successful completion, or nil.
1954read_translation_unit_from_input(fe_iface& iface)
1955{
1956 translation_unit_sptr tu, nil;
1957
1958 abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
1959
1960 xmlNodePtr node = rdr.get_corpus_node();
1961 if (!node)
1962 {
1963 xml::reader_sptr reader = rdr.get_libxml_reader();
1964 if (!reader)
1965 return nil;
1966
1967 // The document must start with the abi-instr node.
1968 int status = 1;
1969 while (status == 1
1970 && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT)
1971 status = advance_cursor (rdr);
1972
1973 if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
1974 BAD_CAST("abi-instr")))
1975 return nil;
1976
1977 node = xmlTextReaderExpand(reader.get());
1978 if (!node)
1979 return nil;
1980 }
1981 else
1982 {
1983 node = 0;
1984 for (xmlNodePtr n = rdr.get_corpus_node();
1985 n;
1986 n = xmlNextElementSibling(n))
1987 {
1988 if (!xmlStrEqual(n->name, BAD_CAST("abi-instr")))
1989 return nil;
1990 node = n;
1991 break;
1992 }
1993 }
1994
1995 if (node == 0)
1996 return nil;
1997
1998 tu = get_or_read_and_add_translation_unit(rdr, node);
1999
2000 if (rdr.get_corpus_node())
2001 {
2002 // We are not in the mode where the current corpus node came
2003 // from a local invocation of xmlTextReaderExpand. So let's set
2004 // rdr.get_corpus_node to the next child element node of the
2005 // corpus that needs to be processed.
2006 node = xmlNextElementSibling(node);
2007 rdr.set_corpus_node(node);
2008 }
2009
2010 return tu;
2011}
2012
2013/// Parse the input XML document that may contain function symbol and
2014/// variable symbol databases.
2015///
2016/// A function symbols database is an XML element named
2017/// "elf-function-symbols" or "undefined-elf-function-symbols" and a
2018/// variable symbols database is an XML element named
2019/// "elf-variable-symbols." or "undefined-elf-variable-symbols". They
2020/// contains "elf-symbol" XML elements.
2021///
2022/// @param rdr the reader to use for the parsing.
2023///
2024/// @param fn_symdb any resulting function symbol database object, if
2025/// elf-function-symbols was present.
2026///
2027/// @param var_symdb any resulting variable symbol database object, if
2028/// elf-variable-symbols was present.
2029///
2030/// @param non_resolved_fn_syms_aliases this is a map that associates
2031/// a function symbol name N to a vector of alias symbol names that
2032/// are aliases to N. Normally, N is a function symbol that has
2033/// aliases that are other symbols that are usually function symbols
2034/// that should be found (or resolved) in @p fn_symdb. If all symbol
2035/// aliases resolve to symbols in @p fn_symdb then this map is empty.
2036/// Otherwise, if these alias symbols are not found in @p fn_symbd,
2037/// then they are stored in this map. The caller of this function
2038/// might then subsequently try to resolve these elf alias symbols to
2039/// variable symbols found in @p var_symdb. Note that a function
2040/// symbol aliasing variable symbols is a feature found in ELF
2041/// binaries emitted from the OCaml language on platforms like s390x
2042/// or ppcle.
2043///
2044/// @param non_resolved_var_syms_aliases this is a map that associates
2045/// a variable symbol name N to a vector of alias symbol names that
2046/// are aliases to N. Normally, N is a variable symbol that has
2047/// aliases that are other symbols that are usually variable symbols
2048/// that should be found (or resolved) in @p var_symdb. If all symbol
2049/// aliases resolve to symbols in @p var_symdb then this map is empty.
2050/// Otherwise, if these alias symbols are not found in @p var_symbd,
2051/// then they are stored in this map. The caller of this function
2052/// might then subsequently try to resolve these elf alias symbols to
2053/// function symbols found in @p fn_symdb. Note that a variable
2054/// symbol aliasing function symbols is a feature found in ELF
2055/// binaries emitted from the OCaml language on platforms like s390x
2056/// or ppcle.
2057///
2058/// @return true upon successful parsing, false otherwise.
2059static bool
2060read_symbol_db_from_input(reader& rdr,
2062 string_elf_symbols_map_sptr& var_symdb,
2063 string_strings_map_type& non_resolved_fn_syms_aliases,
2064 string_strings_map_type& non_resolved_var_syms_aliases)
2065{
2066 xml::reader_sptr reader = rdr.get_libxml_reader();
2067 if (!reader)
2068 return false;
2069
2070 if (!rdr.get_corpus_node())
2071 for (;;)
2072 {
2073 int status = 1;
2074 while (status == 1
2075 && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT)
2076 status = advance_cursor (rdr);
2077
2078 if (status != 1)
2079 return false;
2080
2081 bool has_fn_syms = false, has_undefined_fn_syms = false,
2082 has_var_syms = false, has_undefined_var_syms = false;
2083 if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
2084 BAD_CAST("elf-function-symbols")))
2085 has_fn_syms = true;
2086 else if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
2087 BAD_CAST("elf-variable-symbols")))
2088 has_var_syms = true;
2089 else if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
2090 BAD_CAST("undefined-elf-function-symbols")))
2091 has_undefined_fn_syms = true;
2092 else if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
2093 BAD_CAST("undefined-elf-variable-symbols")))
2094 has_undefined_var_syms = true;
2095 else
2096 break;
2097
2098 xmlNodePtr node = xmlTextReaderExpand(reader.get());
2099 if (!node)
2100 return false;
2101
2102 if (has_fn_syms)
2103 build_elf_symbol_db(rdr, node, /*function_sym=*/true, fn_symdb,
2104 non_resolved_fn_syms_aliases);
2105 else if (has_undefined_fn_syms)
2106 build_elf_symbol_db(rdr, node, /*function_sym=*/true, fn_symdb,
2107 non_resolved_fn_syms_aliases);
2108 else if (has_var_syms)
2109 build_elf_symbol_db(rdr, node, /*function_sym=*/false, var_symdb,
2110 non_resolved_var_syms_aliases);
2111 else if (has_undefined_var_syms)
2112 build_elf_symbol_db(rdr, node, /*function_sym=*/false, var_symdb,
2113 non_resolved_var_syms_aliases);
2114
2115 xmlTextReaderNext(reader.get());
2116 }
2117 else
2118 for (xmlNodePtr n = rdr.get_corpus_node(); n; n = xmlNextElementSibling(n))
2119 {
2120 bool has_fn_syms = false, has_undefined_fn_syms = false,
2121 has_var_syms = false, has_undefined_var_syms = false;
2122 if (xmlStrEqual(n->name, BAD_CAST("elf-function-symbols")))
2123 has_fn_syms = true;
2124 else if (xmlStrEqual(n->name, BAD_CAST("undefined-elf-function-symbols")))
2125 has_undefined_fn_syms = true;
2126 else if (xmlStrEqual(n->name, BAD_CAST("elf-variable-symbols")))
2127 has_var_syms = true;
2128 else if (xmlStrEqual(n->name,
2129 BAD_CAST("undefined-elf-variable-symbols")))
2130 has_undefined_var_syms = true;
2131 else
2132 {
2133 rdr.set_corpus_node(n);
2134 break;
2135 }
2136
2137 if (has_fn_syms)
2138 build_elf_symbol_db(rdr, n, /*function_sym=*/true, fn_symdb,
2139 non_resolved_fn_syms_aliases);
2140 else if (has_undefined_fn_syms)
2141 build_elf_symbol_db(rdr, n, /*function_sym=*/true, fn_symdb,
2142 non_resolved_fn_syms_aliases);
2143 else if (has_var_syms)
2144 build_elf_symbol_db(rdr, n, /*function_sym=*/false, var_symdb,
2145 non_resolved_var_syms_aliases);
2146 else if (has_undefined_var_syms)
2147 build_elf_symbol_db(rdr, n, /*function_sym=*/false, var_symdb,
2148 non_resolved_var_syms_aliases);
2149 else
2150 break;
2151 }
2152
2153 return true;
2154}
2155
2156/// From an "elf-needed" XML_ELEMENT node, build a vector of strings
2157/// representing the vector of the dependencies needed by a given
2158/// corpus.
2159///
2160/// @param node the XML_ELEMENT node of name "elf-needed".
2161///
2162/// @param needed the output vector of string to populate with the
2163/// vector of dependency names found on the xml node @p node.
2164///
2165/// @return true upon successful completion, false otherwise.
2166static bool
2167build_needed(xmlNode* node, vector<string>& needed)
2168{
2169 if (!node || !xmlStrEqual(node->name,BAD_CAST("elf-needed")))
2170 return false;
2171
2172 for (xmlNodePtr n = xmlFirstElementChild(node);
2173 n;
2174 n = xmlNextElementSibling(n))
2175 {
2176 if (!xmlStrEqual(n->name, BAD_CAST("dependency")))
2177 continue;
2178
2179 string name;
2180 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(n, "name"))
2182
2183 if (!name.empty())
2184 needed.push_back(name);
2185 }
2186
2187 return true;
2188}
2189
2190/// Move to the next xml element node and expext it to be named
2191/// "elf-needed". Then read the sub-tree to made of that node and
2192/// extracts a vector of needed dependencies name from it.
2193///
2194/// @param rdr the ABIXML reader used to the xml reading.
2195///
2196/// @param needed the resulting vector of dependency names.
2197///
2198/// @return true upon successful completion, false otherwise.
2199static bool
2200read_elf_needed_from_input(reader& rdr,
2201 vector<string>& needed)
2202{
2203 xml::reader_sptr reader = rdr.get_libxml_reader();
2204 if (!reader)
2205 return false;
2206
2207 xmlNodePtr node = 0;
2208
2209 if (rdr.get_corpus_node() == 0)
2210 {
2211 int status = 1;
2212 while (status == 1
2213 && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT)
2214 status = advance_cursor (rdr);
2215
2216 if (status != 1)
2217 return false;
2218
2219 if (!xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
2220 BAD_CAST("elf-needed")))
2221 return false;
2222
2223 node = xmlTextReaderExpand(reader.get());
2224 if (!node)
2225 return false;
2226 }
2227 else
2228 {
2229 for (xmlNodePtr n = rdr.get_corpus_node();
2230 n;
2231 n = xmlNextElementSibling(n))
2232 {
2233 if (!xmlStrEqual(n->name, BAD_CAST("elf-needed")))
2234 return false;
2235 node = n;
2236 break;
2237 }
2238 }
2239
2240 bool result = false;
2241 if (node)
2242 {
2243 result = build_needed(node, needed);
2244 node = xmlNextElementSibling(node);
2245 rdr.set_corpus_node(node);
2246 }
2247
2248 return result;
2249}
2250
2251/// Add suppressions specifications to the set of suppressions to be
2252/// used during the construction of the ABI internal representation
2253/// (the ABI corpus) from ELF and DWARF.
2254///
2255/// During the construction of the ABI corpus, ABI artifacts that
2256/// match the a given suppression specification are dropped on the
2257/// floor; that is, they are discarded and won't be part of the final
2258/// ABI corpus. This is a way to reduce the amount of data held by
2259/// the final ABI corpus.
2260///
2261/// Note that the suppression specifications provided to this function
2262/// are only considered during the construction of the ABI corpus.
2263/// For instance, they are not taken into account during e.g
2264/// comparisons of two ABI corpora that might happen later. If you
2265/// want to apply suppression specifications to the comparison (or
2266/// reporting) of ABI corpora please refer to the documentation of the
2267/// @ref diff_context type to learn how to set suppressions that are
2268/// to be used in that context.
2269///
2270/// @param rdr the context that is going to be used by functions that
2271/// read types and declarations information to construct and ABI
2272/// corpus.
2273///
2274/// @param supprs the suppression specifications to be applied during
2275/// the construction of the ABI corpus.
2276void
2278 const suppr::suppressions_type& supprs)
2279{
2280 for (suppr::suppressions_type::const_iterator i = supprs.begin();
2281 i != supprs.end();
2282 ++i)
2283 if ((*i)->get_drops_artifact_from_ir())
2284 rdr.suppressions().push_back(*i);
2285}
2286
2287/// Configure the @ref reader so that types not reachable from
2288/// public interface are taken into account when the abixml file is
2289/// read.
2290///
2291/// @param rdr the @reader to consider.
2292///
2293/// @param flag if yes, then types not reachable from public interface
2294/// are taken into account when the abixml file is read.
2295void
2297{
2298 abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
2299 rdr.tracking_non_reachable_types(flag);
2300}
2301
2302#ifdef WITH_SHOW_TYPE_USE_IN_ABILINT
2303/// Get the vector of types that have a given type-id.
2304///
2305/// This function is available only if the project has been configured
2306/// with --enable-show-type-use-in-abilint.
2307///
2308/// @param rdr the abixml reader to use.
2309///
2310/// @param type_id the type-id to consider.
2311vector<type_base_sptr>*
2312get_types_from_type_id(fe_iface& iface, const string& type_id)
2313{
2314 reader& rdr = dynamic_cast<reader&>(iface);
2315 auto it = rdr.m_types_map.find(type_id);
2316 if (it == rdr.m_types_map.end())
2317 return nullptr;
2318 return &it->second;
2319}
2320
2321/// Get the map that associates an artififact to its users.
2322///
2323/// This function is available only if the project has been configured
2324/// with --enable-show-type-use-in-abilint.
2325///
2326/// @param rdr the abixml text reader context to use.
2327unordered_map<type_or_decl_base*, vector<type_or_decl_base*>>*
2328get_artifact_used_by_relation_map(fe_iface& iface)
2329{
2330 reader& rdr = dynamic_cast<reader&>(iface);
2331 return &rdr.m_artifact_used_by_map;
2332}
2333#endif
2334
2335/// Read the "version" attribute from the current XML element which is
2336/// supposed to be a corpus or a corpus group and set the format
2337/// version to the corpus object accordingly.
2338///
2339/// Note that this is a subroutine of read_corpus_from_input and
2340/// read_corpus_group_from_input.
2341///
2342/// @param reader the XML reader to consider. That reader must be
2343/// set to an XML element representing a corpus or a corpus group.
2344///
2345/// @param corp output parameter. The corpus object which format
2346/// version string is going to be set according to the value of the
2347/// "version" attribute found on the current XML element.
2348static void
2349handle_version_attribute(xml::reader_sptr& reader, corpus& corp)
2350{
2351 string version_string;
2352 if (xml_char_sptr s = XML_READER_GET_ATTRIBUTE(reader, "version"))
2353 xml::xml_char_sptr_to_string(s, version_string);
2354
2355 vector<string> v;
2356 if (version_string.empty())
2357 {
2358 v.push_back("1");
2359 v.push_back("0");
2360 }
2361 else
2362 tools_utils::split_string(version_string, ".", v);
2363 corp.set_format_major_version_number(v[0]);
2364 corp.set_format_minor_version_number(v[1]);
2365}
2366
2367/// Parse the input XML document containing an ABI corpus group,
2368/// represented by an 'abi-corpus-group' element node, associated to
2369/// the current context.
2370///
2371/// @param rdr the current input context.
2372///
2373/// @return the corpus group resulting from the parsing
2374corpus_group_sptr
2376{
2377 corpus_group_sptr nil;
2378
2379 abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
2380 xml::reader_sptr reader = rdr.get_libxml_reader();
2381 if (!reader)
2382 return nil;
2383
2384 // The document must start with the abi-corpus-group node.
2385 int status = 1;
2386 while (status == 1
2387 && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT)
2388 status = advance_cursor (rdr);
2389
2390 if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
2391 BAD_CAST("abi-corpus-group")))
2392 return nil;
2393
2395
2396 if (!rdr.corpus_group())
2397 {
2398 corpus_group_sptr g(new corpus_group(rdr.get_environment(),
2399 rdr.get_path()));
2400 g->set_origin(corpus::NATIVE_XML_ORIGIN);
2401 rdr.corpus_group(g);
2402 }
2403
2404 corpus_group_sptr group = rdr.corpus_group();
2405
2406 handle_version_attribute(reader, *group);
2407
2408 xml::xml_char_sptr path_str = XML_READER_GET_ATTRIBUTE(reader, "path");
2409 if (path_str)
2410 group->set_path(reinterpret_cast<char*>(path_str.get()));
2411
2412 if (rdr.do_log())
2413 {
2414 std::cerr << "ABIXML Reader: reading corpus group : '"
2415 << group->get_path()
2416 << "' ...\n";
2417 t.start();
2418 }
2419
2420 xmlNodePtr node = xmlTextReaderExpand(reader.get());
2421 if (!node)
2422 return nil;
2423
2424 node = xmlFirstElementChild(node);
2425 rdr.set_corpus_node(node);
2426
2427 corpus_sptr corp;
2428 fe_iface::status sts;
2429 while ((corp = rdr.read_corpus(sts)))
2430 {
2431 rdr.corpus_group()->add_corpus(corp);
2432 node = xmlNextElementSibling(node);
2433 if (!node || !xmlStrEqual(node->name, BAD_CAST("abi-corpus")))
2434 break;
2435 rdr.initialize("");
2436 rdr.set_corpus_node(node);
2437 }
2438
2439 xmlTextReaderNext(reader.get());
2440
2441 if (rdr.do_log())
2442 {
2443 t.stop();
2444 std::cerr << "ABIXML Reader: Read corpus group : "
2445 << group->get_path()
2446 << " in: " << t << "\n";
2447 }
2448
2449 return rdr.corpus_group();
2450}
2451
2452/// De-serialize an ABI corpus group from an input XML document which
2453/// root node is 'abi-corpus-group'.
2454///
2455/// @param in the input stream to read the XML document from.
2456///
2457/// @param env the environment to use. Note that the life time of
2458/// this environment must be greater than the lifetime of the
2459/// resulting corpus as the corpus uses resources that are allocated
2460/// in the environment.
2461///
2462/// @return the resulting corpus group de-serialized from the parsing.
2463/// This is non-null iff the parsing resulted in a valid corpus group.
2464corpus_group_sptr
2466 environment& env)
2467{
2468 fe_iface_sptr rdr = create_reader(in, env);
2469 return read_corpus_group_from_input(*rdr);
2470}
2471
2472/// De-serialize an ABI corpus group from an XML document file which
2473/// root node is 'abi-corpus-group'.
2474///
2475/// @param path the path to the input file to read the XML document
2476/// from.
2477///
2478/// @param env the environment to use. Note that the life time of
2479/// this environment must be greater than the lifetime of the
2480/// resulting corpus as the corpus uses resources that are allocated
2481/// in the environment.
2482///
2483/// @return the resulting corpus group de-serialized from the parsing.
2484/// This is non-null if the parsing successfully resulted in a corpus
2485/// group.
2486corpus_group_sptr
2488 environment& env)
2489{
2490 fe_iface_sptr rdr = create_reader(path, env);
2491 corpus_group_sptr group = read_corpus_group_from_input(*rdr);
2492 return group;
2493}
2494
2495/// Parse an ABI instrumentation file (in XML format) at a given path.
2496///
2497/// @param input_file a path to the file containing the xml document
2498/// to parse.
2499///
2500/// @param env the environment to use.
2501///
2502/// @return the translation unit resulting from the parsing upon
2503/// successful completion, or nil.
2505read_translation_unit_from_file(const string& input_file,
2506 environment& env)
2507{
2508 reader rdr(xml::new_reader_from_file(input_file), env);
2509 translation_unit_sptr tu = read_translation_unit_from_input(rdr);
2510 env.canonicalization_is_done(false);
2511 rdr.perform_type_canonicalization();
2512 env.canonicalization_is_done(true);
2513 return tu;
2514}
2515
2516/// Parse an ABI instrumentation file (in XML format) from an
2517/// in-memory buffer.
2518///
2519/// @param buffer the in-memory buffer containing the xml document to
2520/// parse.
2521///
2522/// @param env the environment to use.
2523///
2524/// @return the translation unit resulting from the parsing upon
2525/// successful completion, or nil.
2528 environment& env)
2529{
2530 reader rdr(xml::new_reader_from_buffer(buffer), env);
2531 translation_unit_sptr tu = read_translation_unit_from_input(rdr);
2532 env.canonicalization_is_done(false);
2533 rdr.perform_type_canonicalization();
2534 env.canonicalization_is_done(true);
2535 return tu;
2536}
2537
2538/// Parse a translation unit from an abixml input from a given
2539/// context.
2540///
2541/// @param rdr the @ref reader to consider.
2542///
2543/// @return the constructed @ref translation_unit from the content of
2544/// the input abixml.
2546read_translation_unit(fe_iface& iface)
2547{
2548 abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
2549 translation_unit_sptr tu = read_translation_unit_from_input(rdr);
2550 rdr.options().env.canonicalization_is_done(false);
2551 rdr.perform_type_canonicalization();
2552 rdr.options().env.canonicalization_is_done(true);
2553 return tu;
2554}
2555
2556/// This function is called by @ref read_translation_unit_from_input.
2557/// It handles the current xml element node of the reading context.
2558/// The result of the "handling" is to build the representation of the
2559/// xml node and tied it to the current translation unit.
2560///
2561/// @param rdr the current parsing context.
2562///
2563/// @return true upon successful completion, false otherwise.
2565handle_element_node(reader& rdr, xmlNodePtr node,
2566 bool add_to_current_scope)
2567{
2569 if (!node)
2570 return decl;
2571
2572 ((decl = handle_namespace_decl(rdr, node, add_to_current_scope))
2573 ||(decl = handle_type_decl(rdr, node, add_to_current_scope))
2574 ||(decl = handle_qualified_type_decl(rdr, node,
2575 add_to_current_scope))
2576 ||(decl = handle_pointer_type_def(rdr, node,
2577 add_to_current_scope))
2578 || (decl = handle_reference_type_def(rdr, node, add_to_current_scope))
2579 || (decl = handle_function_type(rdr, node, add_to_current_scope))
2580 || (decl = handle_array_type_def(rdr, node, add_to_current_scope))
2581 || (decl = handle_enum_type_decl(rdr, node,
2582 add_to_current_scope))
2583 || (decl = handle_typedef_decl(rdr, node,
2584 add_to_current_scope))
2585 || (decl = handle_var_decl(rdr, node,
2586 add_to_current_scope))
2587 || (decl = handle_function_decl(rdr, node,
2588 add_to_current_scope))
2589 || (decl = handle_class_decl(rdr, node,
2590 add_to_current_scope))
2591 || (decl = handle_union_decl(rdr, node,
2592 add_to_current_scope))
2593 || (decl = handle_function_tdecl(rdr, node,
2594 add_to_current_scope))
2595 || (decl = handle_class_tdecl(rdr, node,
2596 add_to_current_scope)));
2597
2598 // If the user wants us to track non-reachable types, then read the
2599 // 'is-non-reachable-type' attribute on type elements and record
2600 // reachable types accordingly.
2601 if (rdr.tracking_non_reachable_types())
2602 {
2603 if (type_base_sptr t = is_type(decl))
2604 {
2605 corpus_sptr abi = rdr.corpus();
2606 ABG_ASSERT(abi);
2607 bool is_non_reachable_type = false;
2608 read_is_non_reachable_type(node, is_non_reachable_type);
2609 if (!is_non_reachable_type)
2610 abi->record_type_as_reachable_from_public_interfaces(*t);
2611 }
2612 }
2613
2614 return decl;
2615}
2616
2617/// Parses location attributes on an xmlNodePtr.
2618///
2619///@param rdr the current parsing context
2620///
2621///@param loc the resulting location.
2622///
2623/// @return true upon sucessful parsing, false otherwise.
2624static bool
2625read_location(const reader& rdr,
2626 xmlNodePtr node,
2627 location& loc)
2628{
2629 string file_path;
2630 size_t line = 0, column = 0;
2631
2632 if (xml_char_sptr f = xml::build_sptr(xmlGetProp(node, BAD_CAST("filepath"))))
2633 file_path = CHAR_STR(f);
2634
2635 if (file_path.empty())
2636 return read_artificial_location(rdr, node, loc);
2637
2638 if (xml_char_sptr l = xml::build_sptr(xmlGetProp(node, BAD_CAST("line"))))
2639 line = atoi(CHAR_STR(l));
2640 else
2641 return read_artificial_location(rdr, node, loc);
2642
2643 if (xml_char_sptr c = xml::build_sptr(xmlGetProp(node, BAD_CAST("column"))))
2644 column = atoi(CHAR_STR(c));
2645
2646 reader& c = const_cast<reader&>(rdr);
2647 loc = c.get_translation_unit()->get_loc_mgr().create_new_location(file_path,
2648 line,
2649 column);
2650 return true;
2651}
2652
2653/// Parses the artificial location attributes on an xmlNodePtr.
2654///
2655/// The artificial location is the line number of the xmlNode as well
2656/// as the URI of the node.
2657///
2658///@param rdr the current parsing context
2659///
2660///@param loc the resulting location.
2661///
2662/// @return true upon sucessful parsing, false otherwise.
2663static bool
2664read_artificial_location(const reader& rdr,
2665 xmlNodePtr node,
2666 location& loc)
2667{
2668 if (!node)
2669 return false;
2670
2671 string file_path;
2672 size_t line = 0, column = 0;
2673
2674 line = node->line;
2675
2676 if (node->doc)
2677 file_path = reinterpret_cast<const char*>(node->doc->URL);
2678
2679 reader& c = const_cast<reader&>(rdr);
2680 loc =
2681 c.get_translation_unit()->get_loc_mgr().create_new_location(file_path,
2682 line, column);
2683 loc.set_is_artificial(true);
2684 return true;
2685}
2686
2687/// Set the artificial location of a xmlNode to an artifact.
2688///
2689/// The artificial location is the line number of the xmlNode as well
2690/// as the URI of the node.
2691///
2692/// The function sets the artificial location only if the artifact
2693/// doesn"t already have one.
2694///
2695///@param rdr the current parsing context
2696///
2697///@param node the XML node to consider.
2698///
2699///@param artifact the ABI artifact.
2700///
2701/// @return true iff the location was set on the artifact.
2702static bool
2703maybe_set_artificial_location(const reader& rdr,
2704 xmlNodePtr node,
2705 type_or_decl_base_sptr artefact)
2706{
2707 if (artefact && !artefact->has_artificial_location())
2708 {
2709 location l;
2710 if (read_artificial_location(rdr, node, l))
2711 {
2712 artefact->set_artificial_location(l);
2713 return true;
2714 }
2715 }
2716 return false;
2717}
2718
2719/// Parse the visibility attribute.
2720///
2721/// @param node the xml node to read from.
2722///
2723/// @param vis the resulting visibility.
2724///
2725/// @return true upon successful completion, false otherwise.
2726static bool
2727read_visibility(xmlNodePtr node, decl_base::visibility& vis)
2728{
2729 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "visibility"))
2730 {
2731 string v = CHAR_STR(s);
2732
2733 if (v == "default")
2734 vis = decl_base::VISIBILITY_DEFAULT;
2735 else if (v == "hidden")
2736 vis = decl_base::VISIBILITY_HIDDEN;
2737 else if (v == "internal")
2738 vis = decl_base::VISIBILITY_INTERNAL;
2739 else if (v == "protected")
2740 vis = decl_base::VISIBILITY_PROTECTED;
2741 else
2742 vis = decl_base::VISIBILITY_DEFAULT;
2743 return true;
2744 }
2745 return false;
2746}
2747
2748/// Parse the "binding" attribute on the current element.
2749///
2750/// @param node the xml node to build parse the bind from.
2751///
2752/// @param bind the resulting binding attribute.
2753///
2754/// @return true upon successful completion, false otherwise.
2755static bool
2756read_binding(xmlNodePtr node, decl_base::binding& bind)
2757{
2758 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "binding"))
2759 {
2760 string b = CHAR_STR(s);
2761
2762 if (b == "global")
2763 bind = decl_base::BINDING_GLOBAL;
2764 else if (b == "local")
2765 bind = decl_base::BINDING_LOCAL;
2766 else if (b == "weak")
2767 bind = decl_base::BINDING_WEAK;
2768 else
2769 bind = decl_base::BINDING_GLOBAL;
2770 return true;
2771 }
2772
2773 return false;
2774}
2775
2776/// Read the 'access' attribute on the current xml node.
2777///
2778/// @param node the xml node to consider.
2779///
2780/// @param access the access attribute. Set iff the function returns true.
2781///
2782/// @return true upon sucessful completion, false otherwise.
2783static bool
2784read_access(xmlNodePtr node, access_specifier& access)
2785{
2786 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "access"))
2787 {
2788 string a = CHAR_STR(s);
2789
2790 if (a == "private")
2791 access = private_access;
2792 else if (a == "protected")
2793 access = protected_access;
2794 else if (a == "public")
2795 access = public_access;
2796 else
2797 /// If there is an access specifier of an unsupported value,
2798 /// we should not assume anything and abort.
2799 abort();
2800
2801 return true;
2802 }
2803 return false;
2804}
2805
2806/// Parse 'size-in-bits' and 'alignment-in-bits' attributes of a given
2807/// xmlNodePtr reprensting an xml element.
2808///
2809/// @param node the xml element node to consider.
2810///
2811/// @param size_in_bits the resulting value for the 'size-in-bits'
2812/// attribute. This set only if this function returns true and the if
2813/// the attribute was present on the xml element node.
2814///
2815/// @param align_in_bits the resulting value for the
2816/// 'alignment-in-bits' attribute. This set only if this function
2817/// returns true and the if the attribute was present on the xml
2818/// element node.
2819///
2820/// @return true if either one of the two attributes above were set,
2821/// false otherwise.
2822static bool
2823read_size_and_alignment(xmlNodePtr node,
2824 size_t& size_in_bits,
2825 size_t& align_in_bits)
2826{
2827
2828 bool got_something = false;
2829 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "size-in-bits"))
2830 {
2831 size_in_bits = atoll(CHAR_STR(s));
2832 got_something = true;
2833 }
2834
2835 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "alignment-in-bits"))
2836 {
2837 align_in_bits = atoll(CHAR_STR(s));
2838 got_something = true;
2839 }
2840 return got_something;
2841}
2842
2843/// Parse the 'static' attribute of a given xml element node.
2844///
2845/// @param node the xml element node to consider.
2846///
2847/// @param is_static the resulting the parsing. Is set if the
2848/// function returns true.
2849///
2850/// @return true if the xml element node has the 'static' attribute
2851/// set, false otherwise.
2852static bool
2853read_static(xmlNodePtr node, bool& is_static)
2854{
2855 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "static"))
2856 {
2857 string b = CHAR_STR(s);
2858 is_static = b == "yes";
2859 return true;
2860 }
2861 return false;
2862}
2863
2864/// Parse the 'layout-offset-in-bits' attribute of a given xml element node.
2865///
2866/// @param offset_in_bits set to true if the element node contains the
2867/// attribute.
2868///
2869/// @return true iff the xml element node contains the attribute.
2870static bool
2871read_offset_in_bits(xmlNodePtr node,
2872 size_t& offset_in_bits)
2873{
2874 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "layout-offset-in-bits"))
2875 {
2876 offset_in_bits = strtoull(CHAR_STR(s), 0, 0);
2877 return true;
2878 }
2879 return false;
2880}
2881
2882/// Parse the 'constructor', 'destructor' and 'const' attribute of a
2883/// given xml node.
2884///
2885/// @param is_constructor the resulting value of the parsing of the
2886/// 'constructor' attribute. Is set if the xml node contains the
2887/// attribute and if the function returns true.
2888///
2889/// @param is_destructor the resulting value of the parsing of the
2890/// 'destructor' attribute. Is set if the xml node contains the
2891/// attribute and if the function returns true.
2892///
2893/// @param is_const the resulting value of the parsing of the 'const'
2894/// attribute. Is set if the xml node contains the attribute and if
2895/// the function returns true.
2896///
2897/// @return true if at least of the attributes above is set, false
2898/// otherwise.
2899///
2900/// Note that callers of this function should initialize
2901/// is_constructor, is_destructor and is_const prior to passing them
2902/// to this function.
2903static bool
2904read_cdtor_const(xmlNodePtr node,
2905 bool& is_constructor,
2906 bool& is_destructor,
2907 bool& is_const)
2908{
2909 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "constructor"))
2910 {
2911 string b = CHAR_STR(s);
2912 if (b == "yes")
2913 is_constructor = true;
2914 else
2915 is_constructor = false;
2916
2917 return true;
2918 }
2919
2920 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "destructor"))
2921 {
2922 string b = CHAR_STR(s);
2923 if (b == "yes")
2924 is_destructor = true;
2925 else
2926 is_destructor = false;
2927
2928 return true;
2929 }
2930
2931 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "const"))
2932 {
2933 string b = CHAR_STR(s);
2934 if (b == "yes")
2935 is_const = true;
2936 else
2937 is_const = false;
2938
2939 return true;
2940 }
2941
2942 return false;
2943}
2944
2945/// Read the "is-declaration-only" attribute of the current xml node.
2946///
2947/// @param node the xml node to consider.
2948///
2949/// @param is_decl_only is set to true iff the "is-declaration-only" attribute
2950/// is present and set to "yes".
2951///
2952/// @return true iff the is_decl_only attribute was set.
2953static bool
2954read_is_declaration_only(xmlNodePtr node, bool& is_decl_only)
2955{
2956 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-declaration-only"))
2957 {
2958 string str = CHAR_STR(s);
2959 if (str == "yes")
2960 is_decl_only = true;
2961 else
2962 is_decl_only = false;
2963 return true;
2964 }
2965 return false;
2966}
2967
2968/// Read the "is-artificial" attribute of the current XML node.
2969///
2970/// @param node the XML node to consider.
2971///
2972/// @param is_artificial this output parameter is set to true iff the
2973/// "is-artificial" parameter is present and set to 'yes'.
2974///
2975/// @return true iff the "is-artificial" parameter was present on the
2976/// XML node.
2977static bool
2978read_is_artificial(xmlNodePtr node, bool& is_artificial)
2979{
2980 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-artificial"))
2981 {
2982 string is_artificial_str = CHAR_STR(s) ? CHAR_STR(s) : "";
2983 is_artificial = is_artificial_str == "yes";
2984 return true;
2985 }
2986 return false;
2987}
2988
2989/// Read the 'tracking-non-reachable-types' attribute on the current
2990/// XML element.
2991///
2992/// @param node the current XML element.
2993///
2994/// @param tracking_non_reachable_types output parameter. This is set
2995/// to true iff the 'tracking-non-reachable-types' attribute is
2996/// present on the current XML node and set to 'yes'. In that case,
2997/// the function returns true.
2998///
2999/// @return true iff the 'tracking-non-reachable-types' attribute is
3000/// present on the current XML node and set to 'yes'.
3001static bool
3002read_tracking_non_reachable_types(xmlNodePtr node,
3003 bool& tracking_non_reachable_types)
3004{
3005 if (xml_char_sptr s =
3006 XML_NODE_GET_ATTRIBUTE(node, "tracking-non-reachable-types"))
3007 {
3008 string tracking_non_reachable_types_str = CHAR_STR(s) ? CHAR_STR(s) : "";
3009 tracking_non_reachable_types =
3010 (tracking_non_reachable_types_str == "yes")
3011 ? true
3012 : false;
3013 return true;
3014 }
3015 return false;
3016}
3017
3018/// Read the 'is-non-reachable' attribute on the current XML element.
3019///
3020/// @param node the current XML element.
3021///
3022/// @param is_non_reachable_type output parameter. This is set to true
3023/// iff the 'is-non-reachable' attribute is present on the current XML
3024/// element with a value se to 'yes'.
3025///
3026/// @return true iff the 'is-non-reachable' attribute is present on
3027/// the current XML element with a value se to 'yes'.
3028static bool
3029read_is_non_reachable_type(xmlNodePtr node, bool& is_non_reachable_type)
3030{
3031 if (xml_char_sptr s =
3032 XML_NODE_GET_ATTRIBUTE(node, "is-non-reachable"))
3033 {
3034 string is_non_reachable_type_str = CHAR_STR(s) ? CHAR_STR(s) : "";
3035 is_non_reachable_type =
3036 (is_non_reachable_type_str == "yes")
3037 ? true
3038 : false;
3039 return true;
3040 }
3041 return false;
3042}
3043
3044/// Read the "naming-typedef-id" property from an XML node.
3045///
3046/// @param node the XML node to consider.
3047///
3048/// @param naming_typedef_id output parameter. It's set to the
3049/// content of the "naming-typedef-id" property, if it's present.
3050///
3051/// @return true iff the "naming-typedef-id" property exists and was
3052/// read from @p node.
3053static bool
3054read_naming_typedef_id_string(xmlNodePtr node, string& naming_typedef_id)
3055{
3056 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "naming-typedef-id"))
3057 {
3058 naming_typedef_id = xml::unescape_xml_string(CHAR_STR(s));
3059 return true;
3060 }
3061 return false;
3062}
3063
3064/// Read the "is-virtual" attribute of the current xml node.
3065///
3066/// @param node the xml node to read the attribute from
3067///
3068/// @param is_virtual is set to true iff the "is-virtual" attribute is
3069/// present and set to "yes".
3070///
3071/// @return true iff the is-virtual attribute is present.
3072static bool
3073read_is_virtual(xmlNodePtr node, bool& is_virtual)
3074{
3075 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-virtual"))
3076 {
3077 string str = CHAR_STR(s);
3078 if (str == "yes")
3079 is_virtual = true;
3080 else
3081 is_virtual = false;
3082 return true;
3083 }
3084 return false;
3085}
3086
3087/// Read the 'is-struct' attribute.
3088///
3089/// @param node the xml node to read the attribute from.
3090///
3091/// @param is_struct is set to true iff the "is-struct" attribute is
3092/// present and set to "yes".
3093///
3094/// @return true iff the "is-struct" attribute is present.
3095static bool
3096read_is_struct(xmlNodePtr node, bool& is_struct)
3097{
3098 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-struct"))
3099 {
3100 string str = CHAR_STR(s);
3101 if (str == "yes")
3102 is_struct = true;
3103 else
3104 is_struct = false;
3105 return true;
3106 }
3107 return false;
3108}
3109
3110/// Read the 'is-anonymous' attribute.
3111///
3112/// @param node the xml node to read the attribute from.
3113///
3114/// @param is_anonymous is set to true iff the "is-anonymous" is present
3115/// and set to "yes".
3116///
3117/// @return true iff the "is-anonymous" attribute is present.
3118static bool
3119read_is_anonymous(xmlNodePtr node, bool& is_anonymous)
3120{
3121 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-anonymous"))
3122 {
3123 string str = CHAR_STR(s);
3124 is_anonymous = (str == "yes");
3125 return true;
3126 }
3127 return false;
3128}
3129
3130/// Read the 'type' attribute of the 'elf-symbol' element.
3131///
3132/// @param node the XML node to read the attribute from.
3133///
3134/// @param t the resulting elf_symbol::type.
3135///
3136/// @return true iff the function completed successfully.
3137static bool
3138read_elf_symbol_type(xmlNodePtr node, elf_symbol::type& t)
3139{
3140 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type"))
3141 {
3142 string str;
3144 if (!string_to_elf_symbol_type(str, t))
3145 return false;
3146 return true;
3147 }
3148 return false;
3149}
3150
3151/// Read the 'binding' attribute of the of the 'elf-symbol' element.
3152///
3153/// @param node the XML node to read the attribute from.
3154///
3155/// @param b the XML the resulting elf_symbol::binding.
3156///
3157/// @return true iff the function completed successfully.
3158static bool
3159read_elf_symbol_binding(xmlNodePtr node, elf_symbol::binding& b)
3160{
3161 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "binding"))
3162 {
3163 string str;
3165 if (!string_to_elf_symbol_binding(str, b))
3166 return false;
3167 return true;
3168 }
3169 return false;
3170}
3171
3172/// Read the 'visibility' attribute of the of the 'elf-symbol'
3173/// element.
3174///
3175/// @param node the XML node to read the attribute from.
3176///
3177/// @param b the XML the resulting elf_symbol::visibility.
3178///
3179/// @return true iff the function completed successfully.
3180static bool
3181read_elf_symbol_visibility(xmlNodePtr node, elf_symbol::visibility& v)
3182{
3183 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "visibility"))
3184 {
3185 string str;
3188 return false;
3189 return true;
3190 }
3191 return false;
3192}
3193/// Read the value of the 'id' attribute from a given XML node.
3194///
3195/// @param node the XML node to consider.
3196///
3197/// @param type_id the string to set the 'id' to.
3198///
3199/// @return true iff @p type_id was successfully set.
3200static bool
3201read_type_id_string(xmlNodePtr node, string& type_id)
3202{
3203 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
3204 {
3205 type_id = CHAR_STR(s);
3206 return true;
3207 }
3208 return false;
3209}
3210
3211/// Read of the value of the "name" attribute from a given XML node.
3212///
3213/// @param node the XML node to consider.
3214///
3215/// @param name the value of the "name" attribute read, iff the
3216/// function returns true.
3217///
3218/// @return true iff a the "name" attribute was found an its value
3219/// could be read and set to the @p name parameter.
3220static bool
3221read_name(xmlNodePtr node, string& name)
3222{
3223 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3224 {
3225 name = CHAR_STR(s);
3226 return true;
3227 }
3228 return false;
3229}
3230
3231/// Read the hash value and a the CTI from a (type) node.
3232///
3233/// The value of the 'hash' property has the form:
3234/// '<hash-value-in-hexa>#cti-in-decimal'.
3235///
3236/// @param node the XML node to read the hash value from.
3237///
3238/// @param hash output parameter. This is set to the hash value read
3239/// from the XML node @p node iff the function returns true.
3240///
3241/// @param cti output parameter. This is set to the value of the CTI
3242/// read from the CTI part of the value of the 'hash' property.
3243///
3244/// @return true iff the function read a hash value and set it into
3245/// the @p hash output parameter.
3246static bool
3247read_type_hash_and_cti(xmlNodePtr node, uint64_t& hash, uint64_t& cti)
3248{
3249 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "hash"))
3250 {
3251 string str = CHAR_STR(s);
3252 vector<string> parts;
3253 tools_utils::split_string(str, "#", parts);
3254 if (!parts.empty() && !parts.front().empty())
3255 {
3256 ABG_ASSERT(hashing::deserialize_hash(parts[0], hash));
3257 if (parts.size() > 1)
3258 cti = atoll(parts[1].c_str());
3259 return true;
3260 }
3261 }
3262 return false;
3263}
3264
3265#ifdef WITH_DEBUG_SELF_COMPARISON
3266/// Associate a type-id string with the type that was constructed from
3267/// it.
3268///
3269/// Note that if we are not in "self comparison debugging" mode or if
3270/// the type we are looking at is not canonicalized, then this
3271/// function does nothing.
3272///
3273/// @param t the type built from the a type XML node that has a
3274/// particular type-id.
3275///
3276/// @param type_id the type-id of type @p t.
3277///
3278/// @return true if the association was performed.
3279static bool
3280maybe_map_type_with_type_id(const type_base_sptr& t,
3281 const string& type_id)
3282{
3283 if (!t)
3284 return false;
3285
3286 const environment& env = t->get_environment();
3287 if (!env.self_comparison_debug_is_on()
3288 || is_non_canonicalized_type(t.get()))
3289 return false;
3290
3291 const_cast<environment&>(env).
3292 get_pointer_type_id_map()[reinterpret_cast<uintptr_t>(t.get())] = type_id;
3293
3294 return true;
3295}
3296
3297/// Associate a type-id string with the type that was constructed from
3298/// it.
3299///
3300/// Note that if we are not in "self comparison debugging" mode or if
3301/// the type we are looking at is not canonicalized, then this
3302/// function does nothing.
3303///
3304/// @param t the type built from the a type XML node that has a
3305/// particular type-id.
3306///
3307/// @param type_id the type-id of type @p t.
3308///
3309/// @return true if the association was performed.
3310static bool
3311maybe_map_type_with_type_id(const type_base_sptr& t,
3312 xmlNodePtr node)
3313{
3314 if (!t)
3315 return false;
3316
3317 const environment&env = t->get_environment();
3318 if (!env.self_comparison_debug_is_on()
3319 || is_non_canonicalized_type(t.get()))
3320 return false;
3321
3322 string type_id;
3323 if (!read_type_id_string(node, type_id) || type_id.empty())
3324 return false;
3325
3326 return maybe_map_type_with_type_id(t, type_id);
3327}
3328
3329#endif
3330
3331/// Set the naming typedef to a given decl depending on the content of
3332/// the "naming-typedef-id" property of its descriptive XML element.
3333///
3334/// @param rdr the current ABIXML reader.
3335///
3336/// @param node the XML node to read from.
3337///
3338/// @param decl the decl to set the naming typedef to.
3339static void
3340maybe_set_naming_typedef(reader& rdr,
3341 xmlNodePtr node,
3342 const decl_base_sptr& decl)
3343{
3344 string naming_typedef_id;
3345 read_naming_typedef_id_string(node, naming_typedef_id);
3346 if (!naming_typedef_id.empty())
3347 {
3348 typedef_decl_sptr naming_typedef =
3349 is_typedef(rdr.build_or_get_type_decl(naming_typedef_id, true));
3350 ABG_ASSERT(naming_typedef);
3351 decl->set_naming_typedef(naming_typedef);
3352 }
3353}
3354
3355/// Build a @ref namespace_decl from an XML element node which name is
3356/// "namespace-decl". Note that this function recursively reads the
3357/// content of the namespace and builds the proper IR nodes
3358/// accordingly.
3359///
3360/// @param rdr the ABIXML reader to use.
3361///
3362/// @param node the XML node to consider. It must constain the
3363/// content of the namespace, that is, children XML nodes representing
3364/// what is inside the namespace, unless the namespace is empty.
3365///
3366/// @param add_to_current_scope if set to yes, the resulting
3367/// namespace_decl is added to the IR being currently built.
3368///
3369/// @return a pointer to the the resulting @ref namespace_decl.
3371build_namespace_decl(reader& rdr,
3372 const xmlNodePtr node,
3373 bool add_to_current_scope)
3374{
3376 if (!node || !xmlStrEqual(node->name, BAD_CAST("namespace-decl")))
3377 return nil;
3378
3379 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
3380 {
3381 namespace_decl_sptr result = dynamic_pointer_cast<namespace_decl>(d);
3382 ABG_ASSERT(result);
3383 return result;
3384 }
3385
3386 string name;
3387 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3388 name = xml::unescape_xml_string(CHAR_STR(s));
3389
3390 location loc;
3391 read_location(rdr, node, loc);
3392
3393 const environment& env = rdr.get_environment();
3394 namespace_decl_sptr decl(new namespace_decl(env, name, loc));
3395 maybe_set_artificial_location(rdr, node, decl);
3396 rdr.push_decl_to_scope(decl,
3397 add_to_current_scope
3398 ? rdr.get_scope_ptr_for_node(node)
3399 : nullptr);
3400 rdr.map_xml_node_to_decl(node, decl);
3401
3402 for (xmlNodePtr n = xmlFirstElementChild(node);
3403 n;
3404 n = xmlNextElementSibling(n))
3405 handle_element_node(rdr, n, /*add_to_current_scope=*/true);
3406
3407 rdr.pop_scope_or_abort(decl);
3408
3409 return decl;
3410}
3411
3412/// Build an instance of @ref elf_symbol from an XML element node
3413/// which name is 'elf-symbol'.
3414///
3415/// @param rdr the context used for reading the XML input.
3416///
3417/// @param node the XML node to read.
3418///
3419/// @param drop_if_suppressed if the elf symbol was suppressed by a
3420/// suppression specification then do not build it.
3421///
3422/// @return the @ref elf_symbol built, or nil if it couldn't be built.
3423static elf_symbol_sptr
3424build_elf_symbol(reader& rdr, const xmlNodePtr node,
3425 bool drop_if_suppressed)
3426{
3427 elf_symbol_sptr nil;
3428
3429 if (!node
3430 || node->type != XML_ELEMENT_NODE
3431 || !xmlStrEqual(node->name, BAD_CAST("elf-symbol")))
3432 return nil;
3433
3434 string name;
3435 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3437
3438 size_t size = 0;
3439 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "size"))
3440 size = strtol(CHAR_STR(s), NULL, 0);
3441
3442 bool is_defined = true;
3443 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-defined"))
3444 {
3445 string value;
3447 if (value == "true" || value == "yes")
3448 is_defined = true;
3449 else
3450 is_defined = false;
3451 }
3452
3453 bool is_common = false;
3454 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-common"))
3455 {
3456 string value;
3458 if (value == "true" || value == "yes")
3459 is_common = true;
3460 else
3461 is_common = false;
3462 }
3463
3464 string version_string;
3465 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "version"))
3466 xml::xml_char_sptr_to_string(s, version_string);
3467
3468 bool is_default_version = false;
3469 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-default-version"))
3470 {
3471 string value;
3473 if (value == "true" || value == "yes")
3474 is_default_version = true;
3475 }
3476
3477 elf_symbol::type type = elf_symbol::NOTYPE_TYPE;
3478 read_elf_symbol_type(node, type);
3479
3480 elf_symbol::binding binding = elf_symbol::GLOBAL_BINDING;
3481 read_elf_symbol_binding(node, binding);
3482
3483 elf_symbol::visibility visibility = elf_symbol::DEFAULT_VISIBILITY;
3484 read_elf_symbol_visibility(node, visibility);
3485
3486 elf_symbol::version version(version_string, is_default_version);
3487
3488 const bool is_suppressed = suppr::is_elf_symbol_suppressed(rdr, name, type);
3489 if (drop_if_suppressed && is_suppressed)
3490 return elf_symbol_sptr();
3491
3492 const environment& env = rdr.get_environment();
3493 elf_symbol_sptr e = elf_symbol::create(env, /*index=*/0,
3494 size, name, type, binding,
3495 is_defined, is_common,
3496 version, visibility);
3497
3498 e->set_is_suppressed(is_suppressed);
3499
3500 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "crc"))
3501 e->set_crc(strtoull(CHAR_STR(s), NULL, 0));
3502
3503 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "namespace"))
3504 {
3505 std::string ns;
3507 e->set_namespace(ns);
3508 }
3509
3510 return e;
3511}
3512
3513/// Build and instance of elf_symbol from an XML attribute named
3514/// 'elf-symbol-id' which value is the ID of a symbol that should
3515/// present in the symbol db of the corpus associated to the current
3516/// context.
3517///
3518/// @param rdr the current context to consider.
3519///
3520/// @param node the xml element node to consider.
3521///
3522/// @param function_symbol is true if we should look for a function
3523/// symbol, is false if we should look for a variable symbol.
3524///
3525/// @return a shared pointer the resutling elf_symbol.
3526static elf_symbol_sptr
3527build_elf_symbol_from_reference(reader& rdr, const xmlNodePtr node)
3528{
3529 elf_symbol_sptr nil;
3530
3531 if (!node)
3532 return nil;
3533
3534 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "elf-symbol-id"))
3535 {
3536 string sym_id;
3538 if (sym_id.empty())
3539 return nil;
3540
3541 string name, ver;
3543 if (name.empty())
3544 return nil;
3545
3546 if (rdr.corpus()->get_symtab())
3547 {
3548 const elf_symbols& symbols =
3549 rdr.corpus()->get_symtab()->lookup_symbol(name);
3550
3551 for (const auto& symbol : symbols)
3552 if (symbol->get_id_string() == sym_id)
3553 return symbol;
3554 }
3555 }
3556
3557 return nil;
3558}
3559
3560/// Build an instance of string_elf_symbols_map_type from an XML
3561/// element representing either a function symbols data base, or a
3562/// variable symbols database.
3563///
3564/// @param rdr the context to take in account.
3565///
3566/// @param node the XML node to consider.
3567///
3568/// @param function_syms true if we should look for a function symbols
3569/// data base, false if we should look for a variable symbols data
3570/// base.
3571///
3572/// @param map a pointer to the map to fill with the symbol database.
3573///
3574/// @param non_resolved_aliases this is a map that associates a
3575/// function symbol name N to a vector of alias symbol names that are
3576/// aliases to N. Normally, N is a function symbol that has aliases
3577/// that are other symbols that are usually function (resp variable)
3578/// symbols that should be found (or resolved) in @p map. If all
3579/// symbol aliases resolve to symbols in @p map then this map is
3580/// empty. Otherwise, if these alias symbols are not found in @p map,
3581/// then they are stored in this map.
3582///
3583/// @return true if some elf symbols were found.
3584static bool
3585build_elf_symbol_db(reader& rdr,
3586 const xmlNodePtr node,
3587 bool function_syms,
3589 string_strings_map_type& non_resolved_aliases)
3590{
3592
3593 if (!node)
3594 return false;
3595
3596 if (function_syms
3597 && !xmlStrEqual(node->name, BAD_CAST("elf-function-symbols"))
3598 && !xmlStrEqual(node->name, BAD_CAST("undefined-elf-function-symbols")))
3599 return false;
3600
3601 if (!function_syms
3602 && !xmlStrEqual(node->name, BAD_CAST("elf-variable-symbols"))
3603 && !xmlStrEqual(node->name, BAD_CAST("undefined-elf-variable-symbols")))
3604 return false;
3605
3606 rdr.set_corpus_node(node);
3607
3608 typedef std::unordered_map<xmlNodePtr, elf_symbol_sptr>
3609 xml_node_ptr_elf_symbol_sptr_map_type;
3610 xml_node_ptr_elf_symbol_sptr_map_type xml_node_ptr_elf_symbol_map;
3611
3612 elf_symbol_sptr sym;
3613 for (xmlNodePtr n = xmlFirstElementChild(node);
3614 n;
3615 n = xmlNextElementSibling(n))
3616 if ((sym = build_elf_symbol(rdr, n, /*drop_if_suppress=*/false)))
3617 {
3618 id_sym_map[sym->get_id_string()] = sym;
3619 xml_node_ptr_elf_symbol_map[n] = sym;
3620 }
3621
3622 if (id_sym_map.empty())
3623 return false;
3624
3625 string_elf_symbols_map_type::iterator it;
3626 for (string_elf_symbol_sptr_map_type::const_iterator i = id_sym_map.begin();
3627 i != id_sym_map.end();
3628 ++i)
3629 (*map)[i->second->get_name()].push_back(i->second);
3630
3631 // Now build the alias relations
3632 for (xml_node_ptr_elf_symbol_sptr_map_type::const_iterator x =
3633 xml_node_ptr_elf_symbol_map.begin();
3634 x != xml_node_ptr_elf_symbol_map.end();
3635 ++x)
3636 {
3637 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(x->first, "alias"))
3638 {
3639 string alias_id = CHAR_STR(s);
3640
3641 // Symbol aliases can be multiple separated by comma(,), split them
3642 std::vector<std::string> elems;
3643 std::stringstream aliases(alias_id);
3644 std::string item;
3645 while (std::getline(aliases, item, ','))
3646 elems.push_back(item);
3647 for (std::vector<string>::iterator alias = elems.begin();
3648 alias != elems.end(); ++alias)
3649 {
3650 string_elf_symbol_sptr_map_type::const_iterator i =
3651 id_sym_map.find(*alias);
3652 if (i == id_sym_map.end())
3653 // This symbol aliases a symbol that is not (yet)
3654 // found in the set of symbols built so far. So let's
3655 // record this information in the "symbol ->
3656 // non-resolved-symbol-aliases" map so that the
3657 // aliases can be resolved later.
3658 non_resolved_aliases[x->second->get_name()].push_back(*alias);
3659 else
3660 {
3661 ABG_ASSERT(i->second->is_main_symbol());
3662 x->second->get_main_symbol()->add_alias(i->second);
3663 }
3664 }
3665 }
3666 }
3667
3668 return true;
3669}
3670
3671/// Resolve symbol aliases to their target symbols.
3672///
3673/// The aliases to be resolved are found in the @p
3674/// non_resolved_fn_syms_aliases and @p non_resolved_var_syms_aliases
3675/// parameters.
3676///
3677/// @param fn_syms the target function symbols to consider.
3678///
3679/// @param var_syms the target variable symbols to consider.
3680///
3681/// @param non_resolved_fn_syms_aliases is a map that associates the
3682/// name of a function symbol F to its alias symbols. The alias
3683/// symbols are either function symbols (as is what is generally the
3684/// case) to be found in @p fn_syms or can be variable symbols (as is
3685/// sometimes the case for the OCaml language on s390x and ppcle, for
3686/// instance) to be found in @p var_syms.
3687///
3688/// @param non_resolved_var_syms_aliases is a map that associates the
3689/// name of a variable symbol V to its alias symbols. The alias
3690/// symbols are either variable symbols (as is what is generally the
3691/// case) to be found in @p var_syms or can be variable symbols (as is
3692/// sometimes the case for the OCaml language on s390x and ppcle, for
3693/// instance) to be found in @p fn_syms.
3694static void
3695resolve_symbol_aliases(string_elf_symbols_map_sptr& fn_syms,
3697 string_strings_map_type& non_resolved_fn_sym_aliases,
3698 string_strings_map_type& non_resolved_var_sym_aliases)
3699{
3700 for (auto& entry : non_resolved_fn_sym_aliases)
3701 {
3702 auto i = fn_syms->find(entry.first);
3703 ABG_ASSERT(i != fn_syms->end());
3704 // Symbol to build the aliases for.
3705 elf_symbol_sptr sym = i->second.front();
3706 ABG_ASSERT(sym);
3707 sym = sym->get_main_symbol();
3708 elf_symbol_sptr alias_sym;
3709 for (string& alias : entry.second)
3710 {
3711 auto fn_a = fn_syms->find(alias);
3712 if (fn_a == fn_syms->end())
3713 {
3714 // no function symbol alias found. Let's see if a
3715 // variable symbol aliases this function symbol.
3716 auto var_a = var_syms->find(alias);
3717 ABG_ASSERT(var_a != var_syms->end());
3718 alias_sym = var_a->second.front();
3719 ABG_ASSERT(alias_sym);
3720 }
3721 else
3722 {
3723 alias_sym = fn_a->second.front();
3724 ABG_ASSERT(alias_sym);
3725 }
3726 sym->add_alias(alias_sym);
3727 }
3728 }
3729
3730 for (auto& entry : non_resolved_var_sym_aliases)
3731 {
3732 auto i = var_syms->find(entry.first);
3733 ABG_ASSERT(i != var_syms->end());
3734 // Symbol to build the aliases for.
3735 elf_symbol_sptr sym = i->second.front();
3736 ABG_ASSERT(sym);
3737 sym = sym->get_main_symbol();
3738 elf_symbol_sptr alias_sym;
3739 for (string& alias : entry.second)
3740 {
3741 auto var_a = var_syms->find(alias);
3742 if (var_a == var_syms->end())
3743 {
3744 // no variable symbol alias found. Let's see if a
3745 // function symbol aliases this variable symbol.
3746 auto fn_a = fn_syms->find(alias);
3747 ABG_ASSERT(fn_a != fn_syms->end());
3748 alias_sym = fn_a->second.front();
3749 ABG_ASSERT(alias_sym);
3750 }
3751 else
3752 {
3753 alias_sym = var_a->second.front();
3754 ABG_ASSERT(alias_sym);
3755 }
3756 sym->add_alias(alias_sym);
3757 }
3758 }
3759}
3760
3761/// Build a function parameter from a 'parameter' xml element node.
3762///
3763/// @param rdr the contexte of the xml parsing.
3764///
3765/// @param node the xml 'parameter' element node to de-serialize from.
3766static shared_ptr<function_decl::parameter>
3767build_function_parameter(reader& rdr, const xmlNodePtr node)
3768{
3769 shared_ptr<function_decl::parameter> nil;
3770
3771 if (!node || !xmlStrEqual(node->name, BAD_CAST("parameter")))
3772 return nil;
3773
3774 bool is_variadic = false;
3775 string is_variadic_str;
3776 if (xml_char_sptr s =
3777 xml::build_sptr(xmlGetProp(node, BAD_CAST("is-variadic"))))
3778 {
3779 is_variadic_str = CHAR_STR(s) ? CHAR_STR(s) : "";
3780 is_variadic = is_variadic_str == "yes";
3781 }
3782
3783 bool is_artificial = false;
3784 read_is_artificial(node, is_artificial);
3785
3786 string type_id;
3787 if (xml_char_sptr a = xml::build_sptr(xmlGetProp(node, BAD_CAST("type-id"))))
3788 type_id = CHAR_STR(a);
3789
3790 type_base_sptr type;
3791 if (is_variadic)
3792 type = is_type(build_ir_node_for_variadic_parameter_type(rdr));
3793 else
3794 {
3795 ABG_ASSERT(!type_id.empty());
3796 type = rdr.build_or_get_type_decl(type_id, true);
3797 }
3798 ABG_ASSERT(type);
3799
3800 string name;
3801 if (xml_char_sptr a = xml::build_sptr(xmlGetProp(node, BAD_CAST("name"))))
3802 name = CHAR_STR(a);
3803
3804 location loc;
3805 read_location(rdr, node, loc);
3806
3808 (new function_decl::parameter(type, name, loc,
3809 is_variadic, is_artificial));
3810
3811 return p;
3812}
3813
3814/// Build a function_decl from a 'function-decl' xml node.
3815///
3816/// @param rdr the context of the parsing.
3817///
3818/// @param node the xml node to build the function_decl from.
3819///
3820/// @param as_method_decl if this is set to a class_decl pointer, it
3821/// means that the 'function-decl' xml node should be parsed as a
3822/// method_decl. The class_decl pointer is the class decl to which
3823/// the resulting method_decl is a member function of. The resulting
3824/// shared_ptr<function_decl> that is returned is then really a
3825/// shared_ptr<method_decl>.
3826///
3827/// @param add_to_current_scope if set to yes, the result of
3828/// this function is added to its current scope.
3829///
3830/// @param add_to_exported_decls if set to yes, the resulting of this
3831/// function is added to the set of decls exported by the current
3832/// corpus being built.
3833///
3834/// @return a pointer to a newly created function_decl upon successful
3835/// completion, a null pointer otherwise.
3836static function_decl_sptr
3837build_function_decl(reader& rdr,
3838 const xmlNodePtr node,
3839 class_or_union_sptr as_method_decl,
3840 bool add_to_current_scope,
3841 bool add_to_exported_decls)
3842{
3844
3845 if (!xmlStrEqual(node->name, BAD_CAST("function-decl")))
3846 return nil;
3847
3848 string name;
3849 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3850 name = xml::unescape_xml_string(CHAR_STR(s));
3851
3852 string mangled_name;
3853 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name"))
3854 mangled_name = xml::unescape_xml_string(CHAR_STR(s));
3855
3856 if (as_method_decl
3857 && !mangled_name.empty()
3858 && as_method_decl->find_member_function_sptr(mangled_name))
3859 {
3860 function_decl_sptr result =
3861 as_method_decl->find_member_function_sptr(mangled_name);
3862 if (result)
3863 return result;
3864 }
3865
3866 string inline_prop;
3867 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "declared-inline"))
3868 inline_prop = CHAR_STR(s);
3869 bool declared_inline = inline_prop == "yes";
3870
3871 decl_base::visibility vis = decl_base::VISIBILITY_NONE;
3872 read_visibility(node, vis);
3873
3874 decl_base::binding bind = decl_base::BINDING_NONE;
3875 read_binding(node, bind);
3876
3877 size_t size = rdr.get_translation_unit()->get_address_size(), align = 0;
3878 read_size_and_alignment(node, size, align);
3879
3880 location loc;
3881 read_location(rdr, node, loc);
3882
3883 const environment& env = rdr.get_environment();
3884
3885 std::vector<function_decl::parameter_sptr> parms;
3886 type_base_sptr return_type = env.get_void_type();
3887
3888 for (xmlNodePtr n = xmlFirstElementChild(node);
3889 n ;
3890 n = xmlNextElementSibling(n))
3891 {
3892 if (xmlStrEqual(n->name, BAD_CAST("parameter")))
3893 {
3895 build_function_parameter(rdr, n))
3896 parms.push_back(p);
3897 }
3898 else if (xmlStrEqual(n->name, BAD_CAST("return")))
3899 {
3900 string type_id;
3901 if (xml_char_sptr s =
3902 xml::build_sptr(xmlGetProp(n, BAD_CAST("type-id"))))
3903 type_id = CHAR_STR(s);
3904 if (!type_id.empty())
3905 return_type = rdr.build_or_get_type_decl(type_id, true);
3906 }
3907 }
3908
3909 function_type_sptr fn_type(as_method_decl
3910 ? new method_type(return_type, as_method_decl,
3911 parms, /*is_const=*/false,
3912 size, align)
3913 : new function_type(return_type,
3914 parms, size, align));
3915
3916 ABG_ASSERT(fn_type);
3917
3918 rdr.read_hash_and_stash(node, fn_type);
3919
3920 fn_type->set_is_artificial(true);
3921
3922 function_decl_sptr fn_decl(as_method_decl
3923 ? new method_decl (name, fn_type,
3924 declared_inline, loc,
3925 mangled_name, vis, bind)
3926 : new function_decl(name, fn_type,
3927 declared_inline, loc,
3928 mangled_name, vis,
3929 bind));
3930
3931 maybe_set_artificial_location(rdr, node, fn_decl);
3932 rdr.push_decl_to_scope(fn_decl,
3933 add_to_current_scope
3934 ? rdr.get_scope_ptr_for_node(node)
3935 : nullptr);
3936 RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(rdr, fn_decl);
3937
3938 elf_symbol_sptr sym = build_elf_symbol_from_reference(rdr, node);
3939 if (sym)
3940 fn_decl->set_symbol(sym);
3941
3942 if (fn_decl->get_symbol() && fn_decl->get_symbol()->is_public())
3943 fn_decl->set_is_in_public_symbol_table(true);
3944
3945 rdr.get_translation_unit()->bind_function_type_life_time(fn_type);
3946
3947 rdr.schedule_type_for_canonicalization(fn_type);
3948
3949 if (add_to_exported_decls)
3950 rdr.add_fn_to_exported_or_undefined_decls(fn_decl.get());
3951
3952 return fn_decl;
3953}
3954
3955/// Build a function_decl from a 'function-decl' xml node if it's not
3956/// been suppressed by a suppression specification that is in the
3957/// context.
3958///
3959/// @param rdr the context of the parsing.
3960///
3961/// @param node the xml node to build the function_decl from.
3962///
3963/// @param as_method_decl if this is set to a class_or_union pointer,
3964/// it means that the 'function-decl' xml node should be parsed as a
3965/// method_decl. The class_or_union pointer is the class or union the
3966/// resulting method_decl is a member function of. The resulting @ref
3967/// function_decl_sptr that is returned is then really a @ref
3968/// method_decl_sptr.
3969///
3970/// @param add_to_current_scope if set to yes, the resulting of
3971/// this function is added to its current scope.
3972///
3973/// @param add_to_exported_decls if set to yes, the resulting of this
3974/// function is added to the set of decls exported by the current
3975/// corpus being built.
3976///
3977/// @return a pointer to a newly created function_decl upon successful
3978/// completion. If the function was suppressed by a suppression
3979/// specification then returns nil.
3980static function_decl_sptr
3981build_function_decl_if_not_suppressed(reader& rdr,
3982 const xmlNodePtr node,
3983 class_or_union_sptr as_method_decl,
3984 bool add_to_current_scope,
3985 bool add_to_exported_decls)
3986{
3988
3989 if (function_is_suppressed(rdr, node))
3990 // The function was suppressed by at least one suppression
3991 // specification associated to the current ABIXML reader. So
3992 // don't build any IR for it.
3993 ;
3994 else
3995 fn = build_function_decl(rdr, node, as_method_decl,
3996 add_to_current_scope,
3997 add_to_exported_decls);
3998 return fn;
3999}
4000
4001/// Test if a given function denoted by its name and linkage name is
4002/// suppressed by any of the suppression specifications associated to
4003/// a given context of native xml reading.
4004///
4005/// @param rdr the native xml reading context of interest.
4006///
4007/// @param note the XML node that represents the fucntion.
4008/// match.
4009///
4010/// @return true iff at least one function specification matches the
4011/// function denoted by the node @p node.
4012static bool
4013function_is_suppressed(const reader& rdr, xmlNodePtr node)
4014{
4015 string fname;
4016 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4017 fname = xml::unescape_xml_string(CHAR_STR(s));
4018
4019 string flinkage_name;
4020 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name"))
4021 flinkage_name = xml::unescape_xml_string(CHAR_STR(s));
4022
4023 scope_decl* scope = rdr.get_cur_scope();
4024
4025 string qualified_name = build_qualified_name(scope, fname);
4026
4027 return suppr::is_function_suppressed(rdr, qualified_name, flinkage_name);
4028}
4029
4030/// Test if a type denoted by its name, context and location is
4031/// suppressed by the suppression specifications that are associated
4032/// to a given ABIXML reader.
4033///
4034/// @param rdr the ABIXML reader to consider.
4035///
4036/// @param note the XML node that represents the type.
4037///
4038/// @return true iff the type designated by @p node is suppressed by
4039/// at least of suppression specifications associated to the current
4040/// ABIXML reader.
4041static bool
4042type_is_suppressed(const reader& rdr, xmlNodePtr node)
4043{
4044 string type_name;
4045 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4046 type_name = xml::unescape_xml_string(CHAR_STR(s));
4047
4048 location type_location;
4049 read_location(rdr, node, type_location);
4050
4051 scope_decl* scope = rdr.get_cur_scope();
4052
4053 string qualified_name = build_qualified_name(scope, type_name);
4054
4055 bool type_is_private = false;
4056 return suppr::is_type_suppressed(rdr, qualified_name, type_location,
4057 type_is_private,
4058 /*require_drop_property=*/true);
4059}
4060
4061/// Build a @ref var_decl out of a an XML node that describes it iff
4062/// the variable denoted by the XML node is not suppressed by a
4063/// suppression specification associated to the current ABIXML reader.
4064///
4065/// @param rdr the ABIXML reader to use.
4066///
4067/// @param node the XML node for the variable to consider.
4068///
4069/// @parm add_to_current_scope whether to add the built @ref var_decl
4070/// to the current scope or not.
4071///
4072/// @return true iff the @ref var_decl was built.
4073static var_decl_sptr
4074build_var_decl_if_not_suppressed(reader& rdr,
4075 const xmlNodePtr node,
4076 bool add_to_current_scope)
4077{
4078 var_decl_sptr var;
4079 if (!variable_is_suppressed(rdr, node))
4080 var = build_var_decl(rdr, node, add_to_current_scope);
4081 return var;
4082}
4083
4084/// Test if a variable denoted by its XML node is suppressed by a
4085/// suppression specification that is present in a given ABIXML reader.
4086///
4087/// @param rdr the ABIXML reader to consider.
4088///
4089/// @param node the XML node of the variable to consider.
4090///
4091/// @return true iff the variable denoted by @p node is suppressed.
4092static bool
4093variable_is_suppressed(const reader& rdr, xmlNodePtr node)
4094{
4095 string name;
4096 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4097 name = xml::unescape_xml_string(CHAR_STR(s));
4098
4099 string linkage_name;
4100 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name"))
4101 linkage_name = xml::unescape_xml_string(CHAR_STR(s));
4102
4103 scope_decl* scope = rdr.get_cur_scope();
4104
4105 string qualified_name = build_qualified_name(scope, name);
4106
4107 return suppr::is_variable_suppressed(rdr, qualified_name, linkage_name);
4108}
4109
4110/// Test if a variable in a particular scope is suppressed by a
4111/// suppression specification that is present in a given ABIXML reader.
4112///
4113/// @parm rdr the ABIXML reader to consider.
4114///
4115/// @param scope the scope of the variable to consider.
4116///
4117/// @param v the variable to consider.
4118///
4119/// @return true iff the variable @p v is suppressed.
4120static bool
4121variable_is_suppressed(const reader& rdr,
4122 const scope_decl* scope,
4123 const var_decl& v)
4124{
4125 string qualified_name = build_qualified_name(scope, v.get_name());
4126 return suppr::is_variable_suppressed(rdr, qualified_name,
4127 v.get_linkage_name());
4128}
4129
4130/// Build pointer to var_decl from a 'var-decl' xml Node
4131///
4132/// @param rdr the context of the parsing.
4133///
4134/// @param node the xml node to build the var_decl from.
4135///
4136/// @return a pointer to a newly built var_decl upon successful
4137/// completion, a null pointer otherwise.
4138static shared_ptr<var_decl>
4139build_var_decl(reader& rdr,
4140 const xmlNodePtr node,
4141 bool add_to_current_scope)
4142{
4143 shared_ptr<var_decl> nil;
4144
4145 if (!xmlStrEqual(node->name, BAD_CAST("var-decl")))
4146 return nil;
4147
4148 string name;
4149 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4150 name = xml::unescape_xml_string(CHAR_STR(s));
4151
4152 string type_id;
4153 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
4154 type_id = CHAR_STR(s);
4155 type_base_sptr underlying_type = rdr.build_or_get_type_decl(type_id,
4156 true);
4157 ABG_ASSERT(underlying_type);
4158
4159 string mangled_name;
4160 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name"))
4161 mangled_name = xml::unescape_xml_string(CHAR_STR(s));
4162
4163 decl_base::visibility vis = decl_base::VISIBILITY_NONE;
4164 read_visibility(node, vis);
4165
4166 decl_base::binding bind = decl_base::BINDING_NONE;
4167 read_binding(node, bind);
4168
4169 location locus;
4170 read_location(rdr, node, locus);
4171
4172 var_decl_sptr decl(new var_decl(name, underlying_type,
4173 locus, mangled_name,
4174 vis, bind));
4175 maybe_set_artificial_location(rdr, node, decl);
4176
4177 elf_symbol_sptr sym = build_elf_symbol_from_reference(rdr, node);
4178 if (sym)
4179 decl->set_symbol(sym);
4180
4181 rdr.push_decl_to_scope(decl,
4182 add_to_current_scope
4183 ? rdr.get_scope_ptr_for_node(node)
4184 : nullptr);
4185 if (add_to_current_scope)
4186 {
4187 // This variable is really being kept in the IR, so let's record
4188 // that it's using its type.
4189 RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, decl);
4190 }
4191
4192 if (decl->get_symbol() && decl->get_symbol()->is_public())
4193 decl->set_is_in_public_symbol_table(true);
4194
4195 return decl;
4196}
4197
4198/// Build the IR node for a void type.
4199///
4200/// @param rdr the ABIXML reader to use.
4201///
4202/// @return the void type node.
4203static decl_base_sptr
4204build_ir_node_for_void_type(reader& rdr)
4205{
4206 const environment& env = rdr.get_environment();
4207
4208 type_base_sptr t = env.get_void_type();
4209 if (!get_type_scope(t))
4210 {
4212 rdr.get_translation_unit()->get_global_scope());
4213 rdr.schedule_type_for_canonicalization(t);
4214 }
4215 decl_base_sptr type_declaration = get_type_declaration(t);
4216 return type_declaration;
4217}
4218
4219/// Build the IR node for a "pointer to void type".
4220///
4221/// That IR node is shared across the ABI corpus.
4222///
4223/// Note that this function just gets that IR node from the
4224/// environment and, if it's not added to any scope yet, adds it to
4225/// the global scope associated to the current translation unit.
4226///
4227/// @param rdr the DWARF reader to consider.
4228///
4229/// @return the IR node.
4230static decl_base_sptr
4231build_ir_node_for_void_pointer_type(reader& rdr)
4232{
4233 const environment& env = rdr.get_environment();
4234
4235 type_base_sptr t = env.get_void_pointer_type();
4236 if (!get_type_scope(t))
4237 {
4239 rdr.get_translation_unit()->get_global_scope());
4240 rdr.schedule_type_for_canonicalization(t);
4241 }
4242 decl_base_sptr type_declaration = get_type_declaration(t);
4243 return type_declaration;
4244}
4245
4246/// Build the IR node for a variadic parameter type.
4247///
4248/// @param rdr the ABIXML reader to use.
4249///
4250/// @return the variadic parameter type.
4251static decl_base_sptr
4252build_ir_node_for_variadic_parameter_type(reader& rdr)
4253{
4254 const environment& env = rdr.get_environment();
4255
4256 type_base_sptr t = env.get_variadic_parameter_type();
4257 if (!get_type_scope(t))
4258 {
4260 rdr.get_translation_unit()->get_global_scope());
4261 rdr.schedule_type_for_canonicalization(t);
4262 }
4263 decl_base_sptr type_declaration = get_type_declaration(t);
4264 return type_declaration;
4265}
4266
4267/// Build a type_decl from a "type-decl" XML Node.
4268///
4269/// @param rdr the context of the parsing.
4270///
4271/// @param node the XML node to build the type_decl from.
4272///
4273/// @param add_to_current_scope if set to yes, the resulting of
4274/// this function is added to its current scope.
4275///
4276/// @return a pointer to type_decl upon successful completion, a null
4277/// pointer otherwise.
4278static type_decl_sptr
4279build_type_decl(reader& rdr,
4280 const xmlNodePtr node,
4281 bool add_to_current_scope)
4282{
4283 shared_ptr<type_decl> nil;
4284
4285 if (!xmlStrEqual(node->name, BAD_CAST("type-decl")))
4286 return nil;
4287
4288 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4289 {
4290 type_decl_sptr result = dynamic_pointer_cast<type_decl>(d);
4291 ABG_ASSERT(result);
4292 return result;
4293 }
4294
4295 string name;
4296 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4297 name = xml::unescape_xml_string(CHAR_STR(s));
4298
4299 string id;
4300 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4301 id = CHAR_STR(s);
4302 ABG_ASSERT(!id.empty());
4303
4304 size_t size_in_bits= 0;
4305 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "size-in-bits"))
4306 size_in_bits = atoi(CHAR_STR(s));
4307
4308 size_t alignment_in_bits = 0;
4309 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "alignment-in-bits"))
4310 alignment_in_bits = atoi(CHAR_STR(s));
4311
4312 bool is_decl_only = false;
4313 read_is_declaration_only(node, is_decl_only);
4314
4315 location loc;
4316 read_location(rdr, node, loc);
4317
4318 bool is_anonymous = false;
4319 read_is_anonymous(node, is_anonymous);
4320
4321 if (type_base_sptr d = rdr.get_type_decl(id))
4322 {
4323 // I've seen instances of DSOs where a type_decl would appear
4324 // several times. Hugh.
4325 type_decl_sptr ty = dynamic_pointer_cast<type_decl>(d);
4326 ABG_ASSERT(ty);
4327 ABG_ASSERT(!name.empty());
4328 ABG_ASSERT(!ty->get_name().empty());
4329 ABG_ASSERT(ty->get_size_in_bits() == size_in_bits);
4330 ABG_ASSERT(ty->get_alignment_in_bits() == alignment_in_bits);
4331 return ty;
4332 }
4333
4334 const environment& env = rdr.get_environment();
4335 type_decl_sptr decl;
4336 if (name == env.get_variadic_parameter_type_name())
4337 decl = is_type_decl(build_ir_node_for_variadic_parameter_type(rdr));
4338 else if (name == "void")
4339 decl = is_type_decl(build_ir_node_for_void_type(rdr));
4340 else
4341 decl.reset(new type_decl(env, name, size_in_bits,
4342 alignment_in_bits, loc));
4343 maybe_set_artificial_location(rdr, node, decl);
4344 decl->set_is_anonymous(is_anonymous);
4345 decl->set_is_declaration_only(is_decl_only);
4346 // Read the stash from the XML node and stash it into the IR node.
4347 rdr.read_hash_and_stash(node, decl);
4348
4349 if (rdr.push_and_key_type_decl(decl, node, add_to_current_scope))
4350 {
4351 rdr.map_xml_node_to_decl(node, decl);
4352 return decl;
4353 }
4354
4355 return nil;
4356}
4357
4358/// Build a qualified_type_def from a 'qualified-type-def' xml node.
4359///
4360/// @param rdr the context of the parsing.
4361///
4362/// @param node the xml node to build the qualified_type_def from.
4363///
4364/// @param add_to_current_scope if set to yes, the resulting of this
4365/// function is added to its current scope.
4366///
4367/// @return a pointer to a newly built qualified_type_def upon
4368/// successful completion, a null pointer otherwise.
4369static qualified_type_def_sptr
4370build_qualified_type_decl(reader& rdr,
4371 const xmlNodePtr node,
4372 bool add_to_current_scope)
4373{
4374 qualified_type_def_sptr nil;
4375 if (!xmlStrEqual(node->name, BAD_CAST("qualified-type-def")))
4376 return nil;
4377
4378 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4379 {
4380 qualified_type_def_sptr result =
4381 dynamic_pointer_cast<qualified_type_def>(d);
4382 ABG_ASSERT(result);
4383 return result;
4384 }
4385
4386 string id;
4387 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE (node, "id"))
4388 id = CHAR_STR(s);
4389
4390 ABG_ASSERT(!id.empty());
4391
4392 location loc;
4393 read_location(rdr, node, loc);
4394
4395 qualified_type_def::CV cv = qualified_type_def::CV_NONE;
4396 string const_str;
4397 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "const"))
4398 const_str = CHAR_STR(s);
4399 bool const_cv = const_str == "yes";
4400
4401 string volatile_str;
4402 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "volatile"))
4403 volatile_str = CHAR_STR(s);
4404 bool volatile_cv = volatile_str == "yes";
4405
4406 string restrict_str;
4407 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "restrict"))
4408 restrict_str = CHAR_STR(s);
4409 bool restrict_cv = restrict_str == "yes";
4410
4411 if (const_cv)
4412 cv = cv | qualified_type_def::CV_CONST;
4413 if (volatile_cv)
4414 cv = cv | qualified_type_def::CV_VOLATILE;
4415 if (restrict_cv)
4416 cv = cv | qualified_type_def::CV_RESTRICT;
4417
4418 string type_id;
4419 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
4420 type_id = CHAR_STR(s);
4421 ABG_ASSERT(!type_id.empty());
4422
4423 shared_ptr<type_base> underlying_type =
4424 rdr.build_or_get_type_decl(type_id, true);
4425 ABG_ASSERT(underlying_type);
4426
4427 if (type_base_sptr t = rdr.get_type_decl(id))
4428 {
4429 qualified_type_def_sptr result = is_qualified_type(t);
4430 ABG_ASSERT(result);
4431 return result;
4432 }
4433
4434 qualified_type_def_sptr decl;
4435 if (type_base_sptr t = rdr.get_type_decl(id))
4436 {
4437 decl = is_qualified_type(t);
4438 ABG_ASSERT(decl);
4439 }
4440 else
4441 {
4442 decl.reset(new qualified_type_def(underlying_type, cv, loc));
4443 maybe_set_artificial_location(rdr, node, decl);
4444 rdr.push_and_key_type_decl(decl, node, add_to_current_scope);
4445 RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, decl);
4446 }
4447 // Read the stash from the XML node and stash it into the IR node.
4448 rdr.read_hash_and_stash(node, decl);
4449
4450 rdr.map_xml_node_to_decl(node, decl);
4451
4452 return decl;
4453}
4454
4455/// Build a pointer_type_def from a 'pointer-type-def' xml node.
4456///
4457/// @param rdr the context of the parsing.
4458///
4459/// @param node the xml node to build the pointer_type_def from.
4460///
4461/// @param add_to_current_scope if set to yes, the resulting of
4462/// this function is added to its current scope.
4463///
4464/// @return a pointer to a newly built pointer_type_def upon
4465/// successful completion, a null pointer otherwise.
4467build_pointer_type_def(reader& rdr,
4468 const xmlNodePtr node,
4469 bool add_to_current_scope)
4470{
4471
4472 shared_ptr<pointer_type_def> nil;
4473
4474 if (!xmlStrEqual(node->name, BAD_CAST("pointer-type-def")))
4475 return nil;
4476
4477 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4478 {
4479 pointer_type_def_sptr result =
4480 dynamic_pointer_cast<pointer_type_def>(d);
4481 ABG_ASSERT(result);
4482 return result;
4483 }
4484
4485 string id;
4486 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4487 id = CHAR_STR(s);
4488 ABG_ASSERT(!id.empty());
4489
4490 if (type_base_sptr t = rdr.get_type_decl(id))
4491 {
4493 ABG_ASSERT(result);
4494 return result;
4495 }
4496
4497 string type_id;
4498 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
4499 type_id = CHAR_STR(s);
4500
4501 size_t size_in_bits = rdr.get_translation_unit()->get_address_size();
4502 size_t alignment_in_bits = 0;
4503 read_size_and_alignment(node, size_in_bits, alignment_in_bits);
4504 location loc;
4505 read_location(rdr, node, loc);
4506
4507 type_base_sptr pointed_to_type =
4508 rdr.build_or_get_type_decl(type_id, true);
4509 ABG_ASSERT(pointed_to_type);
4510
4511 if (type_base_sptr t = rdr.get_type_decl(id))
4512 {
4514 ABG_ASSERT(result);
4515 return result;
4516 }
4517
4519 if (rdr.get_environment().is_void_type(pointed_to_type))
4520 t = is_pointer_type(build_ir_node_for_void_pointer_type(rdr));
4521 else
4522 // Create the pointer type /before/ the pointed-to type. After the
4523 // creation, the type is 'keyed' using rdr.push_and_key_type_decl.
4524 // This means that the type can be retrieved from its type ID. This
4525 // is so that if the pointed-to type indirectly uses this pointer
4526 // type (via recursion) then that is made possible.
4527 t.reset(new pointer_type_def(pointed_to_type,
4528 size_in_bits,
4529 alignment_in_bits,
4530 loc));
4531
4532 maybe_set_artificial_location(rdr, node, t);
4533
4534 rdr.push_and_key_type_decl(t, node, add_to_current_scope);
4535 rdr.map_xml_node_to_decl(node, t);
4536
4537 // Read the stash from the XML node and stash it into the IR node.
4538 rdr.read_hash_and_stash(node, t);
4539
4540 RECORD_ARTIFACT_AS_USED_BY(rdr, pointed_to_type, t);
4541 return t;
4542}
4543
4544/// Build a reference_type_def from a pointer to 'reference-type-def'
4545/// xml node.
4546///
4547/// @param rdr the context of the parsing.
4548///
4549/// @param node the xml node to build the reference_type_def from.
4550///
4551/// @param add_to_current_scope if set to yes, the resulting of
4552/// this function is added to its current scope.
4553///
4554/// @return a pointer to a newly built reference_type_def upon
4555/// successful completio, a null pointer otherwise.
4556static shared_ptr<reference_type_def>
4557build_reference_type_def(reader& rdr,
4558 const xmlNodePtr node,
4559 bool add_to_current_scope)
4560{
4561 shared_ptr<reference_type_def> nil;
4562
4563 if (!xmlStrEqual(node->name, BAD_CAST("reference-type-def")))
4564 return nil;
4565
4566 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4567 {
4569 dynamic_pointer_cast<reference_type_def>(d);
4570 ABG_ASSERT(result);
4571 return result;
4572 }
4573
4574 string id;
4575 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4576 id = CHAR_STR(s);
4577 ABG_ASSERT(!id.empty());
4578
4579 if (type_base_sptr d = rdr.get_type_decl(id))
4580 {
4582 ABG_ASSERT(ty);
4583 return ty;
4584 }
4585
4586 location loc;
4587 read_location(rdr, node, loc);
4588 string kind;
4589 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "kind"))
4590 kind = CHAR_STR(s); // this should be either "lvalue" or "rvalue".
4591 bool is_lvalue = kind == "lvalue";
4592
4593 size_t size_in_bits = rdr.get_translation_unit()->get_address_size();
4594 size_t alignment_in_bits = 0;
4595 read_size_and_alignment(node, size_in_bits, alignment_in_bits);
4596
4597 string type_id;
4598 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
4599 type_id = CHAR_STR(s);
4600 ABG_ASSERT(!type_id.empty());
4601
4602
4603 type_base_sptr pointed_to_type =
4604 rdr.build_or_get_type_decl(type_id, /*add_to_current_scope=*/ true);
4605 ABG_ASSERT(pointed_to_type);
4606
4607 // The call to rdr.build_or_get_type_decl above might have triggered
4608 // the building of the current type. If so, then return it.
4609 if (type_base_sptr t = rdr.get_type_decl(id))
4610 {
4612 ABG_ASSERT(result);
4613 return result;
4614 }
4615
4616 // Create the reference type /before/ the pointed-to type. After
4617 // the creation, the type is 'keyed' using
4618 // rdr.push_and_key_type_decl. This means that the type can be
4619 // retrieved from its type ID. This is so that if the pointed-to
4620 // type indirectly uses this reference type (via recursion) then
4621 // that is made possible.
4622 reference_type_def_sptr t(new reference_type_def(pointed_to_type,
4623 is_lvalue, size_in_bits,
4624 alignment_in_bits, loc));
4625 maybe_set_artificial_location(rdr, node, t);
4626 ABG_ASSERT(rdr.push_and_key_type_decl(t, node, add_to_current_scope));
4627 rdr.map_xml_node_to_decl(node, t);
4628
4629 // Read the stash from the XML node and stash it into the IR node.
4630 rdr.read_hash_and_stash(node, t);
4631
4632 RECORD_ARTIFACT_AS_USED_BY(rdr, pointed_to_type, t);
4633
4634 return t;
4635}
4636
4637/// Build a @ref ptr_to_mbr_type from a pointer to
4638/// 'pointer-to-member-type' xml node.
4639///
4640/// @param rdr the reader used for parsing.
4641///
4642/// @param node the xml node to build the reference_type_def from.
4643///
4644/// @param add_to_current_scope if set to yes, the resulting of
4645/// this function is added to its current scope.
4646///
4647/// @return a pointer to a newly built @ref ptr_to_mbr_type upon
4648/// successful completio, a null pointer otherwise.
4650build_ptr_to_mbr_type(reader& rdr,
4651 const xmlNodePtr node,
4652 bool add_to_current_scope)
4653{
4654 ptr_to_mbr_type_sptr result, nil;
4655
4656 if (!xmlStrEqual(node->name, BAD_CAST("pointer-to-member-type")))
4657 return nil;
4658
4659 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4660 {
4661 result = is_ptr_to_mbr_type(d);
4662 ABG_ASSERT(result);
4663 return result;
4664 }
4665
4666 string id;
4667 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4668 id = CHAR_STR(s);
4669
4670 if (id.empty())
4671 return nil;
4672
4673 if (type_base_sptr d = rdr.get_type_decl(id))
4674 {
4675 result = is_ptr_to_mbr_type(d);
4676 ABG_ASSERT(result);
4677 return result;
4678 }
4679
4680 size_t size_in_bits = rdr.get_translation_unit()->get_address_size();
4681 size_t alignment_in_bits = 0;
4682 read_size_and_alignment(node, size_in_bits, alignment_in_bits);
4683
4684 location loc;
4685 read_location(rdr, node, loc);
4686
4687 string member_type_id;
4688 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "member-type-id"))
4689 member_type_id = CHAR_STR(s);
4690 if (member_type_id.empty())
4691 return nil;
4692 type_base_sptr member_type =
4693 is_type(rdr.build_or_get_type_decl(member_type_id, true));
4694 if (!member_type)
4695 return nil;
4696
4697 if (type_base_sptr t = rdr.get_type_decl(id))
4698 {
4700 ABG_ASSERT(result);
4701 return result;
4702 }
4703
4704 string containing_type_id;
4705 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "containing-type-id"))
4706 containing_type_id = CHAR_STR(s);
4707 if (containing_type_id.empty())
4708 return nil;
4709 type_base_sptr containing_type =
4710 rdr.build_or_get_type_decl(containing_type_id, true);
4712 return nil;
4713
4714 if (type_base_sptr t = rdr.get_type_decl(id))
4715 {
4717 ABG_ASSERT(result);
4718 return result;
4719 }
4720
4721 result.reset(new ptr_to_mbr_type(rdr.get_environment(),
4722 member_type, containing_type,
4723 size_in_bits, alignment_in_bits,
4724 loc));
4725
4726 // Read the stash from the XML node and stash it into the IR node.
4727 rdr.read_hash_and_stash(node, result);
4728
4729 if (rdr.push_and_key_type_decl(result, node, add_to_current_scope))
4730 rdr.map_xml_node_to_decl(node, result);
4731
4732 return result;
4733}
4734
4735/// Build a function_type from a pointer to 'function-type'
4736/// xml node.
4737///
4738/// @param rdr the context of the parsing.
4739///
4740/// @param node the xml node to build the function_type from.
4741///
4742/// @param add_to_current_scope if set to yes, the result of
4743/// this function is added to its current scope.
4744///
4745/// @return a pointer to a newly built function_type upon
4746/// successful completion, a null pointer otherwise.
4747static function_type_sptr
4748build_function_type(reader& rdr,
4749 const xmlNodePtr node,
4750 bool /*add_to_current_scope*/)
4751{
4753
4754 if (!xmlStrEqual(node->name, BAD_CAST("function-type")))
4755 return nil;
4756
4757 string id;
4758 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4759 id = CHAR_STR(s);
4760 ABG_ASSERT(!id.empty());
4761
4762 string method_class_id;
4763 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "method-class-id"))
4764 method_class_id = CHAR_STR(s);
4765
4766 bool is_method_t = !method_class_id.empty();
4767
4768 size_t size = rdr.get_translation_unit()->get_address_size(), align = 0;
4769 read_size_and_alignment(node, size, align);
4770
4771 const environment& env = rdr.get_environment();
4772 std::vector<shared_ptr<function_decl::parameter> > parms;
4773 type_base_sptr return_type = env.get_void_type();
4774
4775 class_or_union_sptr method_class_type;
4776 if (is_method_t)
4777 {
4778 method_class_type =
4779 is_class_or_union_type(rdr.build_or_get_type_decl(method_class_id,
4780 /*add_decl_to_scope=*/true));
4781 ABG_ASSERT(method_class_type);
4782 }
4783
4784 function_type_sptr fn_type(is_method_t
4785 ? new method_type(method_class_type,
4786 /*is_const=*/false,
4787 size, align)
4788 : new function_type(return_type,
4789 parms, size, align));
4790
4791 // Read the stash from the XML node and stash it into the IR node.
4792 rdr.read_hash_and_stash(node, fn_type);
4793
4794 rdr.get_translation_unit()->bind_function_type_life_time(fn_type);
4795 rdr.key_type_decl(fn_type, id);
4796 RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(rdr, fn_type);
4797
4798 for (xmlNodePtr n = xmlFirstElementChild(node);
4799 n;
4800 n = xmlNextElementSibling(n))
4801 {
4802 if (xmlStrEqual(n->name, BAD_CAST("parameter")))
4803 {
4805 build_function_parameter(rdr, n))
4806 parms.push_back(p);
4807 }
4808 else if (xmlStrEqual(n->name, BAD_CAST("return")))
4809 {
4810 string type_id;
4811 if (xml_char_sptr s =
4812 xml::build_sptr(xmlGetProp(n, BAD_CAST("type-id"))))
4813 type_id = CHAR_STR(s);
4814 type_base_sptr ret_type;
4815 if (!type_id.empty())
4816 ret_type = rdr.build_or_get_type_decl (type_id, true);
4817 if (!ret_type)
4818 ret_type = return_type;
4819 fn_type->set_return_type(ret_type);
4820 }
4821 }
4822 if (!fn_type->get_return_type())
4823 fn_type->set_return_type(return_type);
4824
4825 fn_type->set_parameters(parms);
4826
4827 return fn_type;
4828}
4829
4830/// Build a array_type_def::subrange_type from a 'subrange' xml node.
4831///
4832/// @param rdr the context of the parsing.
4833///
4834/// @param node the xml node to build the
4835/// array_type_def::subrange_type from.
4836///
4837///
4838/// @return a pointer to a newly built array_type_def::subrange_type
4839/// upon successful completion, a null pointer otherwise.
4841build_subrange_type(reader& rdr,
4842 const xmlNodePtr node,
4843 bool add_to_current_scope)
4844{
4846
4847 if (!node || !xmlStrEqual(node->name, BAD_CAST("subrange")))
4848 return nil;
4849
4850 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4851 {
4853 dynamic_pointer_cast<array_type_def::subrange_type>(d);
4854 ABG_ASSERT(result);
4855 return result;
4856 }
4857
4858 string id;
4859 // Note that in early implementations, the subrange didn't carry its
4860 // own ID as the subrange was just a detail of an array. So we
4861 // still need to support the abixml emitted by those early
4862 // implementations.
4863 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4864 id = CHAR_STR(s);
4865
4866 if (!id.empty())
4867 if (type_base_sptr d = rdr.get_type_decl(id))
4868 {
4870 ABG_ASSERT(ty);
4871 return ty;
4872 }
4873
4874 string name;
4875 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4876 name = CHAR_STR(s);
4877
4878 uint64_t length = 0;
4879 string length_str;
4880 bool is_non_finite = false;
4881 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "length"))
4882 {
4883 if (string(CHAR_STR(s)) == "infinite" || string(CHAR_STR(s)) == "unknown")
4884 is_non_finite = true;
4885 else
4886 length = strtoull(CHAR_STR(s), NULL, 0);
4887 }
4888
4889 uint64_t size_in_bits = 0;
4890 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "size-in-bits"))
4891 {
4892 char *endptr = nullptr;
4893 size_in_bits = strtoull(CHAR_STR(s), &endptr, 0);
4894 if (*endptr != '\0')
4895 {
4896 if (!strcmp(CHAR_STR(s), "infinite")
4897 ||!strcmp(CHAR_STR(s), "unknown"))
4898 size_in_bits = (size_t) -1;
4899 else
4900 return nil;
4901 }
4902 }
4903
4904 int64_t lower_bound = 0, upper_bound = 0;
4905 bool bounds_present = false;
4906 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "lower-bound"))
4907 {
4908 lower_bound = strtoll(CHAR_STR(s), NULL, 0);
4909 s = XML_NODE_GET_ATTRIBUTE(node, "upper-bound");
4910 if (!string(CHAR_STR(s)).empty())
4911 upper_bound = strtoll(CHAR_STR(s), NULL, 0);
4912 bounds_present = true;
4913 ABG_ASSERT(is_non_finite
4914 || (length == (uint64_t) upper_bound - lower_bound + 1));
4915 }
4916
4917 string underlying_type_id;
4918 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
4919 underlying_type_id = CHAR_STR(s);
4920
4921 type_base_sptr underlying_type;
4922 if (!underlying_type_id.empty())
4923 {
4924 underlying_type = rdr.build_or_get_type_decl(underlying_type_id, true);
4925 ABG_ASSERT(underlying_type);
4926 }
4927
4928 if (type_base_sptr t = rdr.get_type_decl(id))
4929 {
4931 ABG_ASSERT(result);
4932 return result;
4933 }
4934
4935 location loc;
4936 read_location(rdr, node, loc);
4937
4938 // Note that DWARF would actually have a upper_bound of -1 for an
4939 // array of length 0. In the past (before ABIXML version 2.3), the
4940 // IR would reflect that, so let's stay compatible with that.
4941 array_type_def::subrange_type::bound_value max_bound;
4942 array_type_def::subrange_type::bound_value min_bound;
4943 if (!is_non_finite)
4944 if (length > 0)
4945 // By default, if no 'lower-bound/upper-bound' attributes are
4946 // set, we assume that the lower bound is 0 and the upper bound
4947 // is length - 1.
4948 max_bound.set_signed(length - 1);
4949
4950 if (bounds_present)
4951 {
4952 // So lower_bound/upper_bound are set. Let's set them rather
4953 // than assume that mind_bound is zero.
4954 min_bound.set_signed(lower_bound);
4955 max_bound.set_signed(upper_bound);
4956 }
4957
4959 (new array_type_def::subrange_type(rdr.get_environment(),
4960 name, min_bound, max_bound,
4961 underlying_type, loc));
4962 maybe_set_artificial_location(rdr, node, p);
4963 p->is_non_finite(is_non_finite);
4964 if (size_in_bits)
4965 p->set_size_in_bits(size_in_bits);
4966
4967 // Read the stash from the XML node and stash it into the IR node.
4968 rdr.read_hash_and_stash(node, p);
4969
4970 if (rdr.push_and_key_type_decl(p, node, add_to_current_scope))
4971 rdr.map_xml_node_to_decl(node, p);
4972
4973 return p;
4974}
4975
4976/// Build a array_type_def from a 'array-type-def' xml node.
4977///
4978/// @param rdr the context of the parsing.
4979///
4980/// @param node the xml node to build the array_type_def from.
4981///
4982/// @param add_to_current_scope if set to yes, the resulting of
4983/// this function is added to its current scope.
4984///
4985/// @return a pointer to a newly built array_type_def upon
4986/// successful completion, a null pointer otherwise.
4988build_array_type_def(reader& rdr,
4989 const xmlNodePtr node,
4990 bool add_to_current_scope)
4991{
4992
4994
4995 if (!xmlStrEqual(node->name, BAD_CAST("array-type-def")))
4996 return nil;
4997
4998 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4999 {
5000 array_type_def_sptr result =
5001 dynamic_pointer_cast<array_type_def>(d);
5002 ABG_ASSERT(result);
5003 return result;
5004 }
5005
5006 string id;
5007 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5008 id = CHAR_STR(s);
5009 ABG_ASSERT(!id.empty());
5010
5011 if (type_base_sptr d = rdr.get_type_decl(id))
5012 {
5014 ABG_ASSERT(ty);
5015 return ty;
5016 }
5017
5018 int dimensions = 0;
5019 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "dimensions"))
5020 dimensions = atoi(CHAR_STR(s));
5021
5022 string type_id;
5023 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
5024 type_id = CHAR_STR(s);
5025
5026 size_t size_in_bits = 0, alignment_in_bits = 0;
5027 bool has_size_in_bits = false;
5028 char *endptr;
5029
5030 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "size-in-bits"))
5031 {
5032 size_in_bits = strtoull(CHAR_STR(s), &endptr, 0);
5033 if (*endptr != '\0')
5034 {
5035 if (!strcmp(CHAR_STR(s), "infinite")
5036 ||!strcmp(CHAR_STR(s), "unknown"))
5037 size_in_bits = (size_t) -1;
5038 else
5039 return nil;
5040 }
5041 has_size_in_bits = true;
5042 }
5043
5044 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "alignment-in-bits"))
5045 {
5046 alignment_in_bits = strtoull(CHAR_STR(s), &endptr, 0);
5047 if (*endptr != '\0')
5048 return nil;
5049 }
5050
5051 location loc;
5052 read_location(rdr, node, loc);
5054
5055 for (xmlNodePtr n = xmlFirstElementChild(node);
5056 n;
5057 n = xmlNextElementSibling(n))
5058 if (xmlStrEqual(n->name, BAD_CAST("subrange")))
5059 {
5061 build_subrange_type(rdr, n, /*add_to_current_scope=*/true))
5062 {
5063 MAYBE_MAP_TYPE_WITH_TYPE_ID(s, n);
5064 if (add_to_current_scope)
5065 {
5066 add_decl_to_scope(s, rdr.get_cur_scope());
5067 rdr.schedule_type_for_canonicalization(s);
5068 }
5069 subranges.push_back(s);
5070 }
5071 }
5072
5073 // The type of array elements.
5074 type_base_sptr type =
5075 rdr.build_or_get_type_decl(type_id, true);
5076 ABG_ASSERT(type);
5077
5078 // maybe building the type of array elements triggered building this
5079 // one in the mean time ...
5080 if (type_base_sptr t = rdr.get_type_decl(id))
5081 {
5083 ABG_ASSERT(result);
5084 return result;
5085 }
5086
5087 array_type_def_sptr ar_type(new array_type_def(type, subranges, loc));
5088 // Read the stash from the XML node and stash it into the IR node.
5089 rdr.read_hash_and_stash(node, ar_type);
5090
5091 maybe_set_artificial_location(rdr, node, ar_type);
5092 if (rdr.push_and_key_type_decl(ar_type, node, add_to_current_scope))
5093 rdr.map_xml_node_to_decl(node, ar_type);
5094 RECORD_ARTIFACT_AS_USED_BY(rdr, type, ar_type);
5095
5096 if (dimensions != ar_type->get_dimension_count()
5097 || (alignment_in_bits
5098 != ar_type->get_element_type()->get_alignment_in_bits()))
5099 return nil;
5100
5101 if (has_size_in_bits && size_in_bits != (size_t) -1
5102 && size_in_bits != ar_type->get_size_in_bits())
5103 {
5104 // We have a potential discrepancy between calculated and recorded sizes.
5105 size_t element_size = ar_type->get_element_type()->get_size_in_bits();
5106 if (element_size && element_size != (size_t)-1)
5107 {
5108 // Older versions miscalculated multidimensional array sizes.
5109 size_t bad_count = 0;
5110 for (vector<array_type_def::subrange_sptr>::const_iterator i =
5111 subranges.begin();
5112 i != subranges.end();
5113 ++i)
5114 bad_count += (*i)->get_length();
5115 if (size_in_bits == bad_count * element_size)
5116 {
5117 static bool reported = false;
5118 if (!reported)
5119 {
5120 std::cerr << "notice: Found incorrectly calculated array "
5121 << "sizes in XML - this is benign.\nOlder versions "
5122 << "of libabigail miscalculated multidimensional "
5123 << "array sizes." << std::endl;
5124 reported = true;
5125 }
5126 }
5127 else
5128 {
5129 std::cerr << "error: Found incorrectly calculated array size in "
5130 << "XML (id=\"" << id << "\")." << std::endl;
5132 }
5133 }
5134 }
5135
5136 return ar_type;
5137}
5138
5139/// Build an @ref enum_type_decl from the XML node that represents it,
5140/// if it was not suppressed by a supression specification present in
5141/// the current reader.
5142///
5143/// @param rdr the reader to take into account.
5144///
5145/// @param node the XML node representing the @ref enum_type_decl to
5146/// build.
5147///
5148/// @param add_to_current_scope whether to add the built @ref
5149/// enum_type_decl to the current scope.
5150///
5151/// @return the newly built @ref enum_type_decl iff it was effectively
5152/// built.
5154build_enum_type_decl_if_not_suppressed(reader& rdr,
5155 const xmlNodePtr node,
5156 bool add_to_current_scope)
5157{
5158 enum_type_decl_sptr enum_type;
5159 if (!type_is_suppressed(rdr, node))
5160 enum_type = build_enum_type_decl(rdr, node, add_to_current_scope);
5161 return enum_type;
5162}
5163
5164/// Build an enum_type_decl from an 'enum-type-decl' xml node.
5165///
5166/// @param rdr the context of the parsing.
5167///
5168/// @param node the xml node to build the enum_type_decl from.
5169///
5170/// param add_to_current_scope if set to yes, the resulting of this
5171/// function is added to its current scope.
5172///
5173/// @return a pointer to a newly built enum_type_decl upon successful
5174/// completion, a null pointer otherwise.
5176build_enum_type_decl(reader& rdr,
5177 const xmlNodePtr node,
5178 bool add_to_current_scope)
5179{
5181
5182 if (!xmlStrEqual(node->name, BAD_CAST("enum-decl")))
5183 return nil;
5184
5185 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
5186 {
5187 enum_type_decl_sptr result =
5188 dynamic_pointer_cast<enum_type_decl>(d);
5189 ABG_ASSERT(result);
5190 return result;
5191 }
5192
5193 string name;
5194 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
5195 name = xml::unescape_xml_string(CHAR_STR(s));
5196
5197 string linkage_name;
5198 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "linkage-name"))
5199 linkage_name = xml::unescape_xml_string(CHAR_STR(s));
5200
5201 location loc;
5202 read_location(rdr, node, loc);
5203
5204 bool is_decl_only = false;
5205 read_is_declaration_only(node, is_decl_only);
5206
5207 bool is_anonymous = false;
5208 read_is_anonymous(node, is_anonymous);
5209
5210 bool is_artificial = false;
5211 read_is_artificial(node, is_artificial);
5212
5213 string id;
5214 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5215 id = CHAR_STR(s);
5216
5217 ABG_ASSERT(!id.empty());
5218
5219 if (type_base_sptr t = rdr.get_type_decl(id))
5220 {
5222 ABG_ASSERT(result);
5223 return result;
5224 }
5225
5226 string base_type_id;
5228 for (xmlNodePtr n = xmlFirstElementChild(node);
5229 n;
5230 n = xmlNextElementSibling(n))
5231 {
5232 if (xmlStrEqual(n->name, BAD_CAST("underlying-type")))
5233 {
5234 xml_char_sptr a = xml::build_sptr(xmlGetProp(n, BAD_CAST("type-id")));
5235 if (a)
5236 base_type_id = CHAR_STR(a);
5237 continue;
5238 }
5239 else if (xmlStrEqual(n->name, BAD_CAST("enumerator")))
5240 {
5241 string name;
5242 int64_t value = 0;
5243
5244 xml_char_sptr a = xml::build_sptr(xmlGetProp(n, BAD_CAST("name")));
5245 if (a)
5246 name = xml::unescape_xml_string(CHAR_STR(a));
5247
5248 a = xml::build_sptr(xmlGetProp(n, BAD_CAST("value")));
5249 if (a)
5250 {
5251 value = strtoll(CHAR_STR(a), NULL, 0);
5252 // when strtoll encounters overflow or underflow, errno
5253 // is set to ERANGE and the returned value is either
5254 // LLONG_MIN or LLONG_MAX.
5255 if ((errno == ERANGE)
5256 && (value == LLONG_MIN || value == LLONG_MAX))
5257 return nil;
5258 }
5259
5260 enums.push_back(enum_type_decl::enumerator(name, value));
5261 }
5262 }
5263
5264 type_base_sptr underlying_type =
5265 rdr.build_or_get_type_decl(base_type_id, true);
5266 ABG_ASSERT(underlying_type);
5267
5268 if (type_base_sptr t = rdr.get_type_decl(id))
5269 {
5271 ABG_ASSERT(result);
5272 return result;
5273 }
5274
5275 enum_type_decl_sptr t(new enum_type_decl(name, loc,
5276 underlying_type,
5277 enums, linkage_name));
5278 maybe_set_artificial_location(rdr, node, t);
5279 t->set_is_anonymous(is_anonymous);
5280 t->set_is_artificial(is_artificial);
5281 t->set_is_declaration_only(is_decl_only);
5282 // Read the stash from the XML node and stash it into the IR node.
5283 rdr.read_hash_and_stash(node, t);
5284
5285 if (rdr.push_and_key_type_decl(t, node, add_to_current_scope))
5286 {
5287 maybe_set_naming_typedef(rdr, node, t);
5288 rdr.map_xml_node_to_decl(node, t);
5289 RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, t);
5290 return t;
5291 }
5292
5293 return nil;
5294}
5295
5296/// Build a typedef_decl from a 'typedef-decl' xml node.
5297///
5298/// @param rdr the context of the parsing.
5299///
5300/// @param node the xml node to build the typedef_decl from.
5301///
5302/// @return a pointer to a newly built typedef_decl upon successful
5303/// completion, a null pointer otherwise.
5304static shared_ptr<typedef_decl>
5305build_typedef_decl(reader& rdr,
5306 const xmlNodePtr node,
5307 bool add_to_current_scope)
5308{
5309 shared_ptr<typedef_decl> nil;
5310
5311 if (!xmlStrEqual(node->name, BAD_CAST("typedef-decl")))
5312 return nil;
5313
5314 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
5315 {
5316 typedef_decl_sptr result = is_typedef(d);
5317 ABG_ASSERT(result);
5318 return result;
5319 }
5320
5321 string id;
5322 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5323 id = CHAR_STR(s);
5324 ABG_ASSERT(!id.empty());
5325
5326 if (type_base_sptr t = rdr.get_type_decl(id))
5327 {
5328 typedef_decl_sptr result = is_typedef(t);
5329 ABG_ASSERT(result);
5330 return result;
5331 }
5332
5333 string name;
5334 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
5335 name = xml::unescape_xml_string(CHAR_STR(s));
5336
5337 location loc;
5338 read_location(rdr, node, loc);
5339
5340 string type_id;
5341 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
5342 type_id = CHAR_STR(s);
5343 ABG_ASSERT(!type_id.empty());
5344
5345 type_base_sptr underlying_type(rdr.build_or_get_type_decl(type_id, true));
5346 ABG_ASSERT(underlying_type);
5347
5348 // Maybe the building of the underlying type triggered the building
5349 // of the current type. If so, then return it.
5350 if (type_base_sptr t = rdr.get_type_decl(id))
5351 {
5352 typedef_decl_sptr result = is_typedef(t);
5353 ABG_ASSERT(result);
5354 return result;
5355 }
5356
5357 typedef_decl_sptr t(new typedef_decl(name, underlying_type, loc));
5358 maybe_set_artificial_location(rdr, node, t);
5359
5360 // Read the hash from the XML node and stash it into the IR node.
5361 rdr.read_hash_and_stash(node, t);
5362
5363 rdr.push_and_key_type_decl(t, node, add_to_current_scope);
5364 rdr.map_xml_node_to_decl(node, t);
5365 RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, t);
5366
5367 return t;
5368}
5369
5370/// Build a class from its XML node if it is not suppressed by a
5371/// suppression specification that is present in the ABIXML reader.
5372///
5373/// @param rdr the ABIXML reader to consider.
5374///
5375/// @param node the XML node to consider.
5376///
5377/// @param add_to_current_scope whether to add the built class to the
5378/// current context or not.
5379///
5380/// @return true iff the class was built.
5381static class_decl_sptr
5382build_class_decl_if_not_suppressed(reader& rdr,
5383 const xmlNodePtr node,
5384 bool add_to_current_scope)
5385{
5386 class_decl_sptr class_type;
5387 if (!type_is_suppressed(rdr, node))
5388 class_type = build_class_decl(rdr, node, add_to_current_scope);
5389 return class_type;
5390}
5391
5392/// Build a @ref union_decl from its XML node if it is not suppressed
5393/// by a suppression specification that is present in the read
5394/// context.
5395///
5396/// @param rdr the ABIXML reader to consider.
5397///
5398/// @param node the XML node to consider.
5399///
5400/// @param add_to_current_scope whether to add the built @ref
5401/// union_decl to the current context or not.
5402///
5403/// @return true iff the @ref union_decl was built.
5404static union_decl_sptr
5405build_union_decl_if_not_suppressed(reader& rdr,
5406 const xmlNodePtr node,
5407 bool add_to_current_scope)
5408{
5409 union_decl_sptr union_type;
5410 if (!type_is_suppressed(rdr, node))
5411 union_type = build_union_decl(rdr, node, add_to_current_scope);
5412 return union_type;
5413}
5414
5415/// Build a class_decl from a 'class-decl' xml node.
5416///
5417/// @param rdr the context of the parsing.
5418///
5419/// @param node the xml node to build the class_decl from.
5420///
5421/// @param add_to_current_scope if yes, the resulting class node
5422/// hasn't triggered voluntarily the adding of the resulting
5423/// class_decl_sptr to the current scope.
5424///
5425/// @return a pointer to class_decl upon successful completion, a null
5426/// pointer otherwise.
5427static class_decl_sptr
5428build_class_decl(reader& rdr,
5429 const xmlNodePtr node,
5430 bool add_to_current_scope)
5431{
5432 class_decl_sptr nil;
5433
5434 if (!xmlStrEqual(node->name, BAD_CAST("class-decl")))
5435 return nil;
5436
5437 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
5438 {
5439 class_decl_sptr result = dynamic_pointer_cast<class_decl>(d);
5440 ABG_ASSERT(result);
5441 return result;
5442 }
5443
5444 string name;
5445 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
5446 name = xml::unescape_xml_string(CHAR_STR(s));
5447
5448 size_t size_in_bits = 0, alignment_in_bits = 0;
5449 read_size_and_alignment(node, size_in_bits, alignment_in_bits);
5450
5451 decl_base::visibility vis = decl_base::VISIBILITY_NONE;
5452 read_visibility(node, vis);
5453
5454 bool is_artificial = false;
5455 read_is_artificial(node, is_artificial);
5456
5457 string id;
5458 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5459 id = CHAR_STR(s);
5460
5461 location loc;
5462 read_location(rdr, node, loc);
5463
5464 class_decl::member_types mbrs;
5465 class_decl::data_members data_mbrs;
5466 class_decl::member_functions mbr_functions;
5468
5469 class_decl_sptr decl;
5470
5471 bool is_decl_only = false;
5472 read_is_declaration_only(node, is_decl_only);
5473
5474 bool is_struct = false;
5475 read_is_struct(node, is_struct);
5476
5477 bool is_anonymous = false;
5478 read_is_anonymous(node, is_anonymous);
5479
5480 ABG_ASSERT(!id.empty());
5481
5482 class_decl_sptr previous_definition, previous_declaration;
5483 if (!is_anonymous)
5484 if (type_base_sptr t = rdr.get_type_decl(id))
5485 {
5486 previous_definition = is_class_type(t);
5487 ABG_ASSERT(previous_definition);
5488 }
5489
5490 const vector<type_base_sptr> *types_ptr = 0;
5491 if (!is_anonymous && !previous_definition)
5492 types_ptr = rdr.get_all_type_decls(id);
5493 if (types_ptr)
5494 {
5495 // Lets look at the previous declarations and the first previous
5496 // definition of this type that we've already seen while parsing
5497 // this corpus.
5498 for (vector<type_base_sptr>::const_iterator i = types_ptr->begin();
5499 i != types_ptr->end();
5500 ++i)
5501 {
5502 class_decl_sptr klass = is_class_type(*i);
5503 ABG_ASSERT(klass);
5504 if (klass->get_is_declaration_only()
5505 && !klass->get_definition_of_declaration())
5506 previous_declaration = klass;
5507 else if (!klass->get_is_declaration_only()
5508 && !previous_definition)
5509 previous_definition = klass;
5510 if (previous_definition && previous_declaration)
5511 break;
5512 }
5513
5514 if (previous_declaration)
5515 ABG_ASSERT(previous_declaration->get_name() == name);
5516
5517 if (previous_definition)
5518 ABG_ASSERT(previous_definition->get_name() == name);
5519
5520 if (is_decl_only && previous_declaration)
5521 return previous_declaration;
5522 }
5523
5524 const environment& env = rdr.get_environment();
5525
5526 if (!is_decl_only && previous_definition)
5527 // We are in the case where we've read this class definition
5528 // before, but we might need to update it to add some new stuff to
5529 // it; we might thus find the new stuff to add in the current
5530 // (new) incarnation of that definition that we are currently
5531 // reading.
5532 decl = previous_definition;
5533 else
5534 {
5535 if (is_decl_only)
5536 {
5537 decl.reset(new class_decl(env, name, is_struct));
5538 if (size_in_bits)
5539 decl->set_size_in_bits(size_in_bits);
5540 if (is_anonymous)
5541 decl->set_is_anonymous(is_anonymous);
5542 decl->set_location(loc);
5543 }
5544 else
5545 decl.reset(new class_decl(env, name, size_in_bits, alignment_in_bits,
5546 is_struct, loc, vis, bases, mbrs,
5547 data_mbrs, mbr_functions, is_anonymous));
5548 }
5549
5550 maybe_set_artificial_location(rdr, node, decl);
5551 decl->set_is_artificial(is_artificial);
5552
5553 // Read the stash from the XML node and stash it into the IR node.
5554 rdr.read_hash_and_stash(node, decl);
5555
5556 string def_id;
5557 bool is_def_of_decl = false;
5558 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "def-of-decl-id"))
5559 def_id = CHAR_STR(s);
5560
5561 if (!def_id.empty())
5562 {
5563 decl_base_sptr d = is_decl(rdr.get_type_decl(def_id));
5564 if (d && d->get_is_declaration_only())
5565 {
5566 is_def_of_decl = true;
5567 decl->set_earlier_declaration(d);
5568 d->set_definition_of_declaration(decl);
5569 }
5570 }
5571
5572 if (!is_decl_only
5573 && decl
5574 && !decl->get_is_declaration_only()
5575 && previous_declaration)
5576 {
5577 // decl is the definition of the previous declaration
5578 // previous_declaration.
5579 //
5580 // Let's link them.
5581 decl->set_earlier_declaration(is_decl(previous_declaration));
5582 for (vector<type_base_sptr>::const_iterator i = types_ptr->begin();
5583 i != types_ptr->end();
5584 ++i)
5585 {
5587 ABG_ASSERT(d);
5588 if (d->get_is_declaration_only()
5589 && !d->get_definition_of_declaration())
5590 {
5591 previous_declaration->set_definition_of_declaration(decl);
5592 is_def_of_decl = true;
5593 }
5594 }
5595 }
5596
5597 if (is_decl_only && previous_definition)
5598 {
5599 // decl is a declaration of the previous definition
5600 // previous_definition. Let's link them.
5601 ABG_ASSERT(decl->get_is_declaration_only()
5602 && !decl->get_definition_of_declaration());
5603 decl->set_definition_of_declaration(previous_definition);
5604 }
5605
5606 ABG_ASSERT(!is_decl_only || !is_def_of_decl);
5607
5608 rdr.push_decl_to_scope(decl,
5609 add_to_current_scope
5610 ? rdr.get_scope_ptr_for_node(node)
5611 : nullptr);
5612
5613 rdr.map_xml_node_to_decl(node, decl);
5614 rdr.key_type_decl(decl, id);
5615
5616 // If this class has a naming typedef, get it and refer to it.
5617 maybe_set_naming_typedef(rdr, node, decl);
5618
5619 for (xmlNodePtr n = xmlFirstElementChild(node);
5620 n;
5621 n = xmlNextElementSibling(n))
5622 {
5623 if (xmlStrEqual(n->name, BAD_CAST("base-class")))
5624 {
5625 access_specifier access =
5626 is_struct
5627 ? public_access
5628 : private_access;
5629 read_access(n, access);
5630
5631 string type_id;
5632 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(n, "type-id"))
5633 type_id = CHAR_STR(s);
5634 shared_ptr<class_decl> b =
5635 dynamic_pointer_cast<class_decl>
5636 (rdr.build_or_get_type_decl(type_id, true));
5637 ABG_ASSERT(b);
5638
5639 if (decl->find_base_class(b->get_qualified_name()))
5640 // We are in updating mode for this class. The version of
5641 // the class we have already has this base class, so we
5642 // are not going to add it again.
5643 continue;
5644
5645 size_t offset_in_bits = 0;
5646 bool offset_present = read_offset_in_bits (n, offset_in_bits);
5647
5648 bool is_virtual = false;
5649 read_is_virtual (n, is_virtual);
5650
5651 shared_ptr<class_decl::base_spec> base (new class_decl::base_spec
5652 (b, access,
5653 offset_present
5654 ? (long) offset_in_bits
5655 : -1,
5656 is_virtual));
5657 decl->add_base_specifier(base);
5658 }
5659 else if (xmlStrEqual(n->name, BAD_CAST("member-type")))
5660 {
5661 access_specifier access =
5662 is_struct
5663 ? public_access
5664 : private_access;
5665 read_access(n, access);
5666
5667 rdr.map_xml_node_to_decl(n, decl);
5668
5669 for (xmlNodePtr p = xmlFirstElementChild(n);
5670 p;
5671 p = xmlNextElementSibling(p))
5672 {
5673
5674 string member_type_name;
5675 read_name(p, member_type_name);
5676 type_base_sptr t;
5677 if (!member_type_name.empty())
5678 t = decl->find_member_type(member_type_name);
5679 if (t)
5680 continue;
5681
5682 if ((t = build_type(rdr, p, /*add_to_current_scope=*/true)))
5683 {
5684 decl_base_sptr td = get_type_declaration(t);
5685 ABG_ASSERT(td);
5686 if (!td->get_scope())
5687 decl->add_member_type(t);
5688 set_member_access_specifier(td, access);
5689 rdr.schedule_type_for_canonicalization(t);
5691 string id = CHAR_STR(i);
5692 ABG_ASSERT(!id.empty());
5693 rdr.key_type_decl(t, id);
5694 rdr.map_xml_node_to_decl(p, td);
5695 }
5696 }
5697 }
5698 else if (xmlStrEqual(n->name, BAD_CAST("data-member")))
5699 {
5700 rdr.map_xml_node_to_decl(n, decl);
5701
5702 access_specifier access =
5703 is_struct
5704 ? public_access
5705 : private_access;
5706 read_access(n, access);
5707
5708 bool is_laid_out = false;
5709 size_t offset_in_bits = 0;
5710 if (read_offset_in_bits(n, offset_in_bits))
5711 is_laid_out = true;
5712
5713 bool is_static = false;
5714 read_static(n, is_static);
5715
5716 for (xmlNodePtr p = xmlFirstElementChild(n);
5717 p;
5718 p = xmlNextElementSibling(p))
5719 {
5720 if (var_decl_sptr v =
5721 build_var_decl(rdr, p, /*add_to_cur_scope=*/false))
5722 {
5723 if (decl->find_data_member(v))
5724 {
5725 // We are in updating mode and the current
5726 // version of this class already has this data
5727 // member, so we are not going to add it again.
5728 // So we need to discard the data member we have
5729 // built (and that was pushed to the current
5730 // stack of decls built) and move on.
5731 decl_base_sptr d = rdr.pop_decl();
5733 continue;
5734 }
5735
5736 if (!variable_is_suppressed(rdr, decl.get(), *v))
5737 {
5738 decl->add_data_member(v, access,
5739 is_laid_out,
5740 is_static,
5741 offset_in_bits);
5742 if (is_static)
5743 rdr.add_var_to_exported_or_undefined_decls(v);
5744 // Now let's record the fact that the data
5745 // member uses its type and that the class being
5746 // built uses the data member.
5748 // This data member is anonymous so recording
5749 // that it uses its type is useless because we
5750 // can't name it. Rather, let's record that
5751 // the class being built uses the type of the
5752 // (anonymous) data member.
5753 RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), decl);
5754 else
5755 {
5756 RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), v);
5757 RECORD_ARTIFACT_AS_USED_BY(rdr, v, decl);
5758 }
5759 }
5760 }
5761 }
5762 }
5763 else if (xmlStrEqual(n->name, BAD_CAST("member-function")))
5764 {
5765 access_specifier access =
5766 is_struct
5767 ? public_access
5768 : private_access;
5769 read_access(n, access);
5770
5771 bool is_virtual = false;
5772 ssize_t vtable_offset = -1;
5773 if (xml_char_sptr s =
5774 XML_NODE_GET_ATTRIBUTE(n, "vtable-offset"))
5775 {
5776 is_virtual = true;
5777 vtable_offset = atoi(CHAR_STR(s));
5778 }
5779
5780 bool is_static = false;
5781 read_static(n, is_static);
5782
5783 bool is_ctor = false, is_dtor = false, is_const = false;
5784 read_cdtor_const(n, is_ctor, is_dtor, is_const);
5785
5786 for (xmlNodePtr p = xmlFirstElementChild(n);
5787 p;
5788 p = xmlNextElementSibling(p))
5789 {
5790 if (function_decl_sptr f =
5791 build_function_decl_if_not_suppressed(rdr, p, decl,
5792 /*add_to_cur_sc=*/true,
5793 /*add_to_exported_decls=*/false))
5794 {
5795 method_decl_sptr m = is_method_decl(f);
5796 ABG_ASSERT(m);
5797 set_member_access_specifier(m, access);
5798 set_member_is_static(m, is_static);
5799 if (is_virtual)
5800 set_member_function_virtuality(m, is_virtual, vtable_offset);
5801 set_member_function_is_ctor(m, is_ctor);
5802 set_member_function_is_dtor(m, is_dtor);
5803 set_member_function_is_const(m, is_const);
5804 rdr.map_xml_node_to_decl(p, m);
5805 rdr.add_fn_to_exported_or_undefined_decls(f.get());
5806 break;
5807 }
5808 }
5809 }
5810 else if (xmlStrEqual(n->name, BAD_CAST("member-template")))
5811 {
5812 rdr.map_xml_node_to_decl(n, decl);
5813
5814 access_specifier access =
5815 is_struct
5816 ? public_access
5817 : private_access;
5818 read_access(n, access);
5819
5820 bool is_static = false;
5821 read_static(n, is_static);
5822
5823 bool is_ctor = false, is_dtor = false, is_const = false;
5824 read_cdtor_const(n, is_ctor, is_dtor, is_const);
5825
5826 for (xmlNodePtr p = xmlFirstElementChild(n);
5827 p;
5828 p = xmlNextElementSibling(p))
5829 {
5830 if (shared_ptr<function_tdecl> f =
5831 build_function_tdecl(rdr, p,
5832 /*add_to_current_scope=*/true))
5833 {
5834 shared_ptr<member_function_template> m
5835 (new member_function_template(f, access, is_static,
5836 is_ctor, is_const));
5837 ABG_ASSERT(f->get_scope());
5838 decl->add_member_function_template(m);
5839 }
5840 else if (shared_ptr<class_tdecl> c =
5841 build_class_tdecl(rdr, p,
5842 /*add_to_current_scope=*/true))
5843 {
5844 member_class_template_sptr m(new member_class_template(c,
5845 access,
5846 is_static));
5847 ABG_ASSERT(c->get_scope());
5848 decl->add_member_class_template(m);
5849 }
5850 }
5851 }
5852 }
5853
5854 rdr.pop_scope_or_abort(decl);
5855
5856 return decl;
5857}
5858
5859/// Build a union_decl from a 'union-decl' xml node.
5860///
5861/// @param rdr the context of the parsing.
5862///
5863/// @param node the xml node to build the union_decl from.
5864///
5865/// @param add_to_current_scope if yes, the resulting union node
5866/// hasn't triggered voluntarily the adding of the resulting
5867/// union_decl_sptr to the current scope.
5868///
5869/// @return a pointer to union_decl upon successful completion, a null
5870/// pointer otherwise.
5871static union_decl_sptr
5872build_union_decl(reader& rdr,
5873 const xmlNodePtr node,
5874 bool add_to_current_scope)
5875{
5876 union_decl_sptr nil;
5877
5878 if (!xmlStrEqual(node->name, BAD_CAST("union-decl")))
5879 return nil;
5880
5881 if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
5882 {
5883 union_decl_sptr result = dynamic_pointer_cast<union_decl>(d);
5884 ABG_ASSERT(result);
5885 return result;
5886 }
5887
5888 string name;
5889 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
5890 name = xml::unescape_xml_string(CHAR_STR(s));
5891
5892 size_t size_in_bits = 0, alignment_in_bits = 0;
5893 read_size_and_alignment(node, size_in_bits, alignment_in_bits);
5894
5895 decl_base::visibility vis = decl_base::VISIBILITY_NONE;
5896 read_visibility(node, vis);
5897
5898 bool is_artificial = false;
5899 read_is_artificial(node, is_artificial);
5900
5901 string id;
5902 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5903 id = CHAR_STR(s);
5904
5905 location loc;
5906 read_location(rdr, node, loc);
5907
5908 union_decl::member_types mbrs;
5909 union_decl::data_members data_mbrs;
5910 union_decl::member_functions mbr_functions;
5911
5912 union_decl_sptr decl;
5913
5914 bool is_decl_only = false;
5915 read_is_declaration_only(node, is_decl_only);
5916
5917 bool is_anonymous = false;
5918 read_is_anonymous(node, is_anonymous);
5919
5920 ABG_ASSERT(!id.empty());
5921 union_decl_sptr previous_definition, previous_declaration;
5922 const vector<type_base_sptr> *types_ptr = 0;
5923 if (!is_anonymous)
5924 types_ptr = rdr.get_all_type_decls(id);
5925 if (types_ptr)
5926 {
5927 // Lets look at the previous declarations and the first previous
5928 // definition of this type that we've already seen while parsing
5929 // this corpus.
5930 for (vector<type_base_sptr>::const_iterator i = types_ptr->begin();
5931 i != types_ptr->end();
5932 ++i)
5933 {
5934 union_decl_sptr onion = is_union_type(*i);
5935 ABG_ASSERT(onion);
5936 if (onion->get_is_declaration_only()
5937 && !onion->get_definition_of_declaration())
5938 previous_declaration = onion;
5939 else if (!onion->get_is_declaration_only()
5940 && !previous_definition)
5941 previous_definition = onion;
5942 if (previous_definition && previous_declaration)
5943 break;
5944 }
5945
5946 if (previous_declaration)
5947 ABG_ASSERT(previous_declaration->get_name() == name);
5948
5949 if (previous_definition)
5950 ABG_ASSERT(previous_definition->get_name() == name);
5951
5952 if (is_decl_only && previous_declaration)
5953 return previous_declaration;
5954 }
5955
5956 const environment& env = rdr.get_environment();
5957
5958 if (!is_decl_only && previous_definition)
5959 // We are in the case where we've read this class definition
5960 // before, but we might need to update it to add some new stuff to
5961 // it; we might thus find the new stuff to add in the current
5962 // (new) incarnation of that definition that we are currently
5963 // reading.
5964 decl = previous_definition;
5965 else
5966 {
5967 if (is_decl_only)
5968 decl.reset(new union_decl(env, name));
5969 else
5970 decl.reset(new union_decl(env, name,
5971 size_in_bits,
5972 loc, vis, mbrs,
5973 data_mbrs,
5974 mbr_functions,
5975 is_anonymous));
5976 }
5977
5978 // Read the stash from the XML node and stash it into the IR node.
5979 rdr.read_hash_and_stash(node, decl);
5980
5981 maybe_set_artificial_location(rdr, node, decl);
5982 decl->set_is_artificial(is_artificial);
5983
5984 string def_id;
5985 bool is_def_of_decl = false;
5986 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "def-of-decl-id"))
5987 def_id = CHAR_STR(s);
5988
5989 if (!def_id.empty())
5990 {
5991 class_decl_sptr d =
5992 dynamic_pointer_cast<class_decl>(rdr.get_type_decl(def_id));
5993 if (d && d->get_is_declaration_only())
5994 {
5995 is_def_of_decl = true;
5996 decl->set_earlier_declaration(d);
5997 d->set_definition_of_declaration(decl);
5998 }
5999 }
6000
6001 if (!is_decl_only
6002 && decl
6003 && !decl->get_is_declaration_only()
6004 && previous_declaration)
6005 {
6006 // decl is the definition of the previous declaration
6007 // previous_declaration.
6008 //
6009 // Let's link them.
6010 decl->set_earlier_declaration(previous_declaration);
6011 for (vector<type_base_sptr>::const_iterator i = types_ptr->begin();
6012 i != types_ptr->end();
6013 ++i)
6014 {
6015 union_decl_sptr d = is_union_type(*i);
6016 ABG_ASSERT(d);
6017 if (d->get_is_declaration_only()
6018 && !d->get_definition_of_declaration())
6019 {
6020 previous_declaration->set_definition_of_declaration(decl);
6021 is_def_of_decl = true;
6022 }
6023 }
6024 }
6025
6026 if (is_decl_only && previous_definition)
6027 {
6028 // decl is a declaration of the previous definition
6029 // previous_definition. Let's link them.
6030 ABG_ASSERT(decl->get_is_declaration_only()
6031 && !decl->get_definition_of_declaration());
6032 decl->set_definition_of_declaration(previous_definition);
6033 }
6034
6035 ABG_ASSERT(!is_decl_only || !is_def_of_decl);
6036
6037 rdr.push_decl_to_scope(decl,
6038 add_to_current_scope
6039 ? rdr.get_scope_ptr_for_node(node)
6040 : nullptr);
6041
6042 rdr.map_xml_node_to_decl(node, decl);
6043 rdr.key_type_decl(decl, id);
6044
6045 maybe_set_naming_typedef(rdr, node, decl);
6046
6047 for (xmlNodePtr n = xmlFirstElementChild(node);
6048 !is_decl_only && n;
6049 n = xmlNextElementSibling(n))
6050 {
6051 if (xmlStrEqual(n->name, BAD_CAST("member-type")))
6052 {
6053 access_specifier access = private_access;
6054 read_access(n, access);
6055
6056 rdr.map_xml_node_to_decl(n, decl);
6057
6058 for (xmlNodePtr p = xmlFirstElementChild(n);
6059 p;
6060 p = xmlNextElementSibling(p))
6061 {
6062 string member_type_name;
6063 read_name(p, member_type_name);
6064 type_base_sptr t;
6065 if (!member_type_name.empty())
6066 t = decl->find_member_type(member_type_name);
6067 if (t)
6068 continue;
6069 if ((t = build_type(rdr, p, /*add_to_current_scope=*/true)))
6070 {
6071 decl_base_sptr td = get_type_declaration(t);
6072 ABG_ASSERT(td);
6073 if (!td->get_scope())
6074 decl->add_member_type(t);
6075 set_member_access_specifier(td, access);
6076 rdr.schedule_type_for_canonicalization(t);
6077
6079 string id = CHAR_STR(i);
6080 ABG_ASSERT(!id.empty());
6081 rdr.key_type_decl(t, id);
6082 rdr.map_xml_node_to_decl(p, td);
6083 }
6084 }
6085 }
6086 else if (xmlStrEqual(n->name, BAD_CAST("data-member")))
6087 {
6088 rdr.map_xml_node_to_decl(n, decl);
6089
6090 access_specifier access = private_access;
6091 read_access(n, access);
6092
6093 bool is_laid_out = true;
6094 size_t offset_in_bits = 0;
6095 bool is_static = false;
6096 read_static(n, is_static);
6097
6098 for (xmlNodePtr p = xmlFirstElementChild(n);
6099 p;
6100 p = xmlNextElementSibling(p))
6101 {
6102 if (var_decl_sptr v =
6103 build_var_decl(rdr, p, /*add_to_cur_scope=*/false))
6104 {
6105 if (decl->find_data_member(v))
6106 {
6107 // We are in updating mode and the current
6108 // version of this class already has this data
6109 // member, so we are not going to add it again.
6110 // So we need to discard the data member we have
6111 // built (and that was pushed to the current
6112 // stack of decls built) and move on.
6113 decl_base_sptr d = rdr.pop_decl();
6115 continue;
6116 }
6117 if (!is_static
6118 || !variable_is_suppressed(rdr, decl.get(), *v))
6119 {
6120 decl->add_data_member(v, access,
6121 is_laid_out,
6122 is_static,
6123 offset_in_bits);
6124 // Now let's record the fact that the data
6125 // member uses its type and that the union being
6126 // built uses the data member.
6128 // This data member is anonymous so recording
6129 // that it uses its type is useless because we
6130 // can't name it. Rather, let's record that
6131 // the class being built uses the type of the
6132 // (anonymous) data member.
6133 RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), decl);
6134 else
6135 {
6136 RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), v);
6137 RECORD_ARTIFACT_AS_USED_BY(rdr, v, decl);
6138 }
6139 }
6140 }
6141 }
6142 }
6143 else if (xmlStrEqual(n->name, BAD_CAST("member-function")))
6144 {
6145 rdr.map_xml_node_to_decl(n, decl);
6146
6147 access_specifier access = private_access;
6148 read_access(n, access);
6149
6150 bool is_static = false;
6151 read_static(n, is_static);
6152
6153 bool is_ctor = false, is_dtor = false, is_const = false;
6154 read_cdtor_const(n, is_ctor, is_dtor, is_const);
6155
6156 for (xmlNodePtr p = xmlFirstElementChild(n);
6157 p;
6158 p = xmlNextElementSibling(p))
6159 {
6160 if (function_decl_sptr f =
6161 build_function_decl_if_not_suppressed(rdr, p, decl,
6162 /*add_to_cur_sc=*/true,
6163 /*add_to_exported_decls=*/false))
6164 {
6165 method_decl_sptr m = is_method_decl(f);
6166 ABG_ASSERT(m);
6167 set_member_access_specifier(m, access);
6168 set_member_is_static(m, is_static);
6169 set_member_function_is_ctor(m, is_ctor);
6170 set_member_function_is_dtor(m, is_dtor);
6171 set_member_function_is_const(m, is_const);
6172 rdr.add_fn_to_exported_or_undefined_decls(f.get());
6173 break;
6174 }
6175 }
6176 }
6177 else if (xmlStrEqual(n->name, BAD_CAST("member-template")))
6178 {
6179 rdr.map_xml_node_to_decl(n, decl);
6180
6181 access_specifier access = private_access;
6182 read_access(n, access);
6183
6184 bool is_static = false;
6185 read_static(n, is_static);
6186
6187 bool is_ctor = false, is_dtor = false, is_const = false;
6188 read_cdtor_const(n, is_ctor, is_dtor, is_const);
6189
6190 for (xmlNodePtr p = xmlFirstElementChild(n);
6191 p;
6192 p = xmlNextElementSibling(p))
6193 {
6194 if (function_tdecl_sptr f =
6195 build_function_tdecl(rdr, p,
6196 /*add_to_current_scope=*/true))
6197 {
6198 member_function_template_sptr m
6199 (new member_function_template(f, access, is_static,
6200 is_ctor, is_const));
6201 ABG_ASSERT(f->get_scope());
6202 decl->add_member_function_template(m);
6203 }
6204 else if (class_tdecl_sptr c =
6205 build_class_tdecl(rdr, p,
6206 /*add_to_current_scope=*/true))
6207 {
6208 member_class_template_sptr m(new member_class_template(c,
6209 access,
6210 is_static));
6211 ABG_ASSERT(c->get_scope());
6212 decl->add_member_class_template(m);
6213 }
6214 }
6215 }
6216 }
6217
6218 rdr.pop_scope_or_abort(decl);
6219
6220 return decl;
6221}
6222
6223/// Build an intance of function_tdecl, from an
6224/// 'function-template-decl' xml element node.
6225///
6226/// @param rdr the context of the parsing.
6227///
6228/// @param node the xml node to parse from.
6229///
6230/// @param add_to_current_scope if set to yes, the resulting of
6231/// this function is added to its current scope.
6232///
6233/// @return the newly built function_tdecl upon successful
6234/// completion, a null pointer otherwise.
6235static shared_ptr<function_tdecl>
6236build_function_tdecl(reader& rdr,
6237 const xmlNodePtr node,
6238 bool add_to_current_scope)
6239{
6240 shared_ptr<function_tdecl> nil, result;
6241
6242 if (!xmlStrEqual(node->name, BAD_CAST("function-template-decl")))
6243 return nil;
6244
6245 string id;
6246 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
6247 id = CHAR_STR(s);
6248 if (id.empty() || rdr.get_fn_tmpl_decl(id))
6249 return nil;
6250
6251 location loc;
6252 read_location(rdr, node, loc);
6253
6254 decl_base::visibility vis = decl_base::VISIBILITY_NONE;
6255 read_visibility(node, vis);
6256
6257 decl_base::binding bind = decl_base::BINDING_NONE;
6258 read_binding(node, bind);
6259
6260 const environment& env = rdr.get_environment();
6261
6262 function_tdecl_sptr fn_tmpl_decl(new function_tdecl(env, loc, vis, bind));
6263 maybe_set_artificial_location(rdr, node, fn_tmpl_decl);
6264
6265 rdr.push_decl_to_scope(fn_tmpl_decl,
6266 add_to_current_scope
6267 ? rdr.get_scope_ptr_for_node(node)
6268 : nullptr);
6269 rdr.key_fn_tmpl_decl(fn_tmpl_decl, id);
6270 rdr.map_xml_node_to_decl(node, fn_tmpl_decl);
6271
6272 unsigned parm_index = 0;
6273 for (xmlNodePtr n = xmlFirstElementChild(node);
6274 n;
6275 n = xmlNextElementSibling(n))
6276 {
6277 if (template_parameter_sptr parm =
6278 build_template_parameter(rdr, n, parm_index, fn_tmpl_decl))
6279 {
6280 fn_tmpl_decl->add_template_parameter(parm);
6281 ++parm_index;
6282 }
6283 else if (function_decl_sptr f =
6284 build_function_decl_if_not_suppressed(rdr, n, class_decl_sptr(),
6285 /*add_to_current_scope=*/true,
6286 /*add_to_exported_decls=*/true))
6287 fn_tmpl_decl->set_pattern(f);
6288 }
6289
6290 rdr.key_fn_tmpl_decl(fn_tmpl_decl, id);
6291
6292 return fn_tmpl_decl;
6293}
6294
6295/// Build an intance of class_tdecl, from a
6296/// 'class-template-decl' xml element node.
6297///
6298/// @param rdr the context of the parsing.
6299///
6300/// @param node the xml node to parse from.
6301///
6302/// @param add_to_current_scope if set to yes, the resulting of this
6303/// function is added to its current scope.
6304///
6305/// @return the newly built function_tdecl upon successful
6306/// completion, a null pointer otherwise.
6307static class_tdecl_sptr
6308build_class_tdecl(reader& rdr,
6309 const xmlNodePtr node,
6310 bool add_to_current_scope)
6311{
6312 class_tdecl_sptr nil, result;
6313
6314 if (!xmlStrEqual(node->name, BAD_CAST("class-template-decl")))
6315 return nil;
6316
6317 string id;
6318 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
6319 id = CHAR_STR(s);
6320 if (id.empty() || rdr.get_class_tmpl_decl(id))
6321 return nil;
6322
6323 location loc;
6324 read_location(rdr, node, loc);
6325
6326 decl_base::visibility vis = decl_base::VISIBILITY_NONE;
6327 read_visibility(node, vis);
6328
6329 const environment& env = rdr.get_environment();
6330
6331 class_tdecl_sptr class_tmpl (new class_tdecl(env, loc, vis));
6332 maybe_set_artificial_location(rdr, node, class_tmpl);
6333
6334 if (add_to_current_scope)
6335 rdr.push_decl_to_scope(class_tmpl, node);
6336 rdr.key_class_tmpl_decl(class_tmpl, id);
6337 rdr.map_xml_node_to_decl(node, class_tmpl);
6338
6339 unsigned parm_index = 0;
6340 for (xmlNodePtr n = xmlFirstElementChild(node);
6341 n;
6342 n = xmlNextElementSibling(n))
6343 {
6344 if (template_parameter_sptr parm=
6345 build_template_parameter(rdr, n, parm_index, class_tmpl))
6346 {
6347 class_tmpl->add_template_parameter(parm);
6348 ++parm_index;
6349 }
6350 else if (class_decl_sptr c =
6351 build_class_decl_if_not_suppressed(rdr, n,
6352 add_to_current_scope))
6353 {
6354 if (c->get_scope())
6355 rdr.schedule_type_for_canonicalization(c);
6356 class_tmpl->set_pattern(c);
6357 }
6358 }
6359
6360 rdr.key_class_tmpl_decl(class_tmpl, id);
6361
6362 return class_tmpl;
6363}
6364
6365/// Build a type_tparameter from a 'template-type-parameter'
6366/// xml element node.
6367///
6368/// @param rdr the context of the parsing.
6369///
6370/// @param node the xml node to parse from.
6371///
6372/// @param index the index (occurrence index, starting from 0) of the
6373/// template parameter.
6374///
6375/// @param tdecl the enclosing template declaration that holds the
6376/// template type parameter.
6377///
6378/// @return a pointer to a newly created instance of
6379/// type_tparameter, a null pointer otherwise.
6381build_type_tparameter(reader& rdr,
6382 const xmlNodePtr node,
6383 unsigned index,
6384 template_decl_sptr tdecl)
6385{
6386 type_tparameter_sptr nil, result;
6387
6388 if (!xmlStrEqual(node->name, BAD_CAST("template-type-parameter")))
6389 return nil;
6390
6391 string id;
6392 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
6393 id = CHAR_STR(s);
6394 if (!id.empty())
6395 ABG_ASSERT(!rdr.get_type_decl(id));
6396
6397 string type_id;
6398 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
6399 type_id = CHAR_STR(s);
6400 if (!type_id.empty()
6401 && !(result = dynamic_pointer_cast<type_tparameter>
6402 (rdr.build_or_get_type_decl(type_id, true))))
6403 abort();
6404
6405 string name;
6406 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
6407 name = xml::unescape_xml_string(CHAR_STR(s));
6408
6409 location loc;
6410 read_location(rdr, node,loc);
6411
6412 result.reset(new type_tparameter(index, tdecl, name, loc));
6413 maybe_set_artificial_location(rdr, node, result);
6414
6415 if (id.empty())
6416 rdr.push_decl_to_scope(is_decl(result), node);
6417 else
6418 rdr.push_and_key_type_decl(result, node, /*add_to_current_scope=*/true);
6419
6420 rdr.schedule_type_for_canonicalization(result);
6421
6422 return result;
6423}
6424
6425/// Build a tmpl_parm_type_composition from a
6426/// "template-parameter-type-composition" xml element node.
6427///
6428/// @param rdr the context of the parsing.
6429///
6430/// @param node the xml node to parse from.
6431///
6432/// @param index the index of the previous normal template parameter.
6433///
6434/// @param tdecl the enclosing template declaration that holds this
6435/// template parameter type composition.
6436///
6437/// @return a pointer to a new instance of tmpl_parm_type_composition
6438/// upon successful completion, a null pointer otherwise.
6440build_type_composition(reader& rdr,
6441 const xmlNodePtr node,
6442 unsigned index,
6443 template_decl_sptr tdecl)
6444{
6445 type_composition_sptr nil, result;
6446
6447 if (!xmlStrEqual(node->name, BAD_CAST("template-parameter-type-composition")))
6448 return nil;
6449
6450 type_base_sptr composed_type;
6451 result.reset(new type_composition(index, tdecl, composed_type));
6452 rdr.push_decl_to_scope(is_decl(result), node);
6453
6454 for (xmlNodePtr n = xmlFirstElementChild(node);
6455 n;
6456 n = xmlNextElementSibling(n))
6457 {
6458 if ((composed_type =
6459 build_pointer_type_def(rdr, n,
6460 /*add_to_current_scope=*/true))
6461 ||(composed_type =
6462 build_reference_type_def(rdr, n,
6463 /*add_to_current_scope=*/true))
6464 ||(composed_type =
6465 build_array_type_def(rdr, n,
6466 /*add_to_current_scope=*/true))
6467 || (composed_type =
6468 build_qualified_type_decl(rdr, n,
6469 /*add_to_current_scope=*/true)))
6470 {
6471 rdr.schedule_type_for_canonicalization(composed_type);
6472 result->set_composed_type(composed_type);
6473 break;
6474 }
6475 }
6476
6477 return result;
6478}
6479
6480/// Build an instance of non_type_tparameter from a
6481/// 'template-non-type-parameter' xml element node.
6482///
6483/// @param rdr the context of the parsing.
6484///
6485/// @param node the xml node to parse from.
6486///
6487/// @param index the index of the parameter.
6488///
6489/// @param tdecl the enclosing template declaration that holds this
6490/// non type template parameter.
6491///
6492/// @return a pointer to a newly created instance of
6493/// non_type_tparameter upon successful completion, a null
6494/// pointer code otherwise.
6496build_non_type_tparameter(reader& rdr,
6497 const xmlNodePtr node,
6498 unsigned index,
6499 template_decl_sptr tdecl)
6500{
6502
6503 if (!xmlStrEqual(node->name, BAD_CAST("template-non-type-parameter")))
6504 return r;
6505
6506 string type_id;
6507 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
6508 type_id = CHAR_STR(s);
6509 type_base_sptr type;
6510 if (type_id.empty()
6511 || !(type = rdr.build_or_get_type_decl(type_id, true)))
6512 abort();
6513
6514 string name;
6515 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
6516 name = xml::unescape_xml_string(CHAR_STR(s));
6517
6518 location loc;
6519 read_location(rdr, node,loc);
6520
6521 r.reset(new non_type_tparameter(index, tdecl, name, type, loc));
6522 maybe_set_artificial_location(rdr, node, r);
6523 rdr.push_decl_to_scope(is_decl(r), node);
6524
6525 return r;
6526}
6527
6528/// Build an intance of template_tparameter from a
6529/// 'template-template-parameter' xml element node.
6530///
6531/// @param rdr the context of the parsing.
6532///
6533/// @param node the xml node to parse from.
6534///
6535/// @param index the index of the template parameter.
6536///
6537/// @param tdecl the enclosing template declaration that holds this
6538/// template template parameter.
6539///
6540/// @return a pointer to a new instance of template_tparameter
6541/// upon successful completion, a null pointer otherwise.
6543build_template_tparameter(reader& rdr,
6544 const xmlNodePtr node,
6545 unsigned index,
6546 template_decl_sptr tdecl)
6547{
6549
6550 if (!xmlStrEqual(node->name, BAD_CAST("template-template-parameter")))
6551 return nil;
6552
6553 string id;
6554 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
6555 id = CHAR_STR(s);
6556 // Bail out if a type with the same ID already exists.
6557 ABG_ASSERT(!id.empty());
6558
6559 string type_id;
6560 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
6561 type_id = CHAR_STR(s);
6562 // Bail out if no type with this ID exists.
6563 if (!type_id.empty()
6564 && !(dynamic_pointer_cast<template_tparameter>
6565 (rdr.build_or_get_type_decl(type_id, true))))
6566 abort();
6567
6568 string name;
6569 if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
6570 name = xml::unescape_xml_string(CHAR_STR(s));
6571
6572 location loc;
6573 read_location(rdr, node, loc);
6574
6575 template_tparameter_sptr result(new template_tparameter(index, tdecl,
6576 name, loc));
6577 maybe_set_artificial_location(rdr, node, result);
6578 rdr.push_decl_to_scope(result, node);
6579
6580 // Go parse template parameters that are children nodes
6581 int parm_index = 0;
6582 for (xmlNodePtr n = xmlFirstElementChild(node);
6583 n;
6584 n = xmlNextElementSibling(n))
6585 if (shared_ptr<template_parameter> p =
6586 build_template_parameter(rdr, n, parm_index, result))
6587 {
6588 result->add_template_parameter(p);
6589 ++parm_index;
6590 }
6591
6592 if (result)
6593 {
6594 rdr.key_type_decl(result, id);
6595 rdr.schedule_type_for_canonicalization(result);
6596 }
6597
6598 return result;
6599}
6600
6601/// Build a template parameter type from several possible xml elment
6602/// nodes representing a serialized form a template parameter.
6603///
6604/// @param rdr the context of the parsing.
6605///
6606/// @param node the xml element node to parse from.
6607///
6608/// @param index the index of the template parameter we are parsing.
6609///
6610/// @param tdecl the enclosing template declaration that holds this
6611/// template parameter.
6612///
6613/// @return a pointer to a newly created instance of
6614/// template_parameter upon successful completion, a null pointer
6615/// otherwise.
6617build_template_parameter(reader& rdr,
6618 const xmlNodePtr node,
6619 unsigned index,
6620 template_decl_sptr tdecl)
6621{
6622 shared_ptr<template_parameter> r;
6623 ((r = build_type_tparameter(rdr, node, index, tdecl))
6624 || (r = build_non_type_tparameter(rdr, node, index, tdecl))
6625 || (r = build_template_tparameter(rdr, node, index, tdecl))
6626 || (r = build_type_composition(rdr, node, index, tdecl)));
6627
6628 return r;
6629}
6630
6631/// Build a type from an xml node.
6632///
6633/// @param rdr the context of the parsing.
6634///
6635/// @param node the xml node to build the type_base from.
6636///
6637/// @return a pointer to the newly built type_base upon successful
6638/// completion, a null pointer otherwise.
6639static type_base_sptr
6640build_type(reader& rdr,
6641 const xmlNodePtr node,
6642 bool add_to_current_scope)
6643{
6644 type_base_sptr t;
6645
6646 ((t = build_type_decl(rdr, node, add_to_current_scope))
6647 || (t = build_qualified_type_decl(rdr, node, add_to_current_scope))
6648 || (t = build_pointer_type_def(rdr, node, add_to_current_scope))
6649 || (t = build_reference_type_def(rdr, node , add_to_current_scope))
6650 || (t = build_ptr_to_mbr_type(rdr, node , add_to_current_scope))
6651 || (t = build_function_type(rdr, node, add_to_current_scope))
6652 || (t = build_array_type_def(rdr, node, add_to_current_scope))
6653 || (t = build_subrange_type(rdr, node, add_to_current_scope))
6654 || (t = build_enum_type_decl_if_not_suppressed(rdr, node,
6655 add_to_current_scope))
6656 || (t = build_typedef_decl(rdr, node, add_to_current_scope))
6657 || (t = build_class_decl_if_not_suppressed(rdr, node,
6658 add_to_current_scope))
6659 || (t = build_union_decl_if_not_suppressed(rdr, node,
6660 add_to_current_scope)));
6661
6662 if (rdr.tracking_non_reachable_types() && t)
6663 {
6664 corpus_sptr abi = rdr.corpus();
6665 ABG_ASSERT(abi);
6666 bool is_non_reachable_type = false;
6667 read_is_non_reachable_type(node, is_non_reachable_type);
6668 if (!is_non_reachable_type)
6669 abi->record_type_as_reachable_from_public_interfaces(*t);
6670 }
6671
6672 MAYBE_MAP_TYPE_WITH_TYPE_ID(t, node);
6673
6674 if (t)
6675 rdr.schedule_type_for_canonicalization(t);
6676 return t;
6677}
6678
6679/// Parses 'type-decl' xml element.
6680///
6681/// @param rdr the parsing context.
6682///
6683/// @return true upon successful parsing, false otherwise.
6684static decl_base_sptr
6685handle_type_decl(reader& rdr,
6686 xmlNodePtr node,
6687 bool add_to_current_scope)
6688{
6689 type_decl_sptr decl = build_type_decl(rdr, node, add_to_current_scope);
6690 MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
6691 if (decl && decl->get_scope())
6692 rdr.schedule_type_for_canonicalization(decl);
6693 return decl;
6694}
6695
6696/// Parses 'namespace-decl' xml element.
6697///
6698/// @param rdr the parsing context.
6699///
6700/// @return true upon successful parsing, false otherwise.
6701static decl_base_sptr
6702handle_namespace_decl(reader& rdr,
6703 xmlNodePtr node,
6704 bool add_to_current_scope)
6705{
6706 namespace_decl_sptr d = build_namespace_decl(rdr, node,
6707 add_to_current_scope);
6708 return d;
6709}
6710
6711/// Parse a qualified-type-def xml element.
6712///
6713/// @param rdr the parsing context.
6714///
6715/// @return true upon successful parsing, false otherwise.
6716static decl_base_sptr
6717handle_qualified_type_decl(reader& rdr,
6718 xmlNodePtr node,
6719 bool add_to_current_scope)
6720{
6721 qualified_type_def_sptr decl =
6722 build_qualified_type_decl(rdr, node,
6723 add_to_current_scope);
6724 MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
6725 if (decl && decl->get_scope())
6726 rdr.schedule_type_for_canonicalization(decl);
6727 return decl;
6728}
6729
6730/// Parse a pointer-type-decl element.
6731///
6732/// @param rdr the context of the parsing.
6733///
6734/// @return true upon successful completion, false otherwise.
6735static decl_base_sptr
6736handle_pointer_type_def(reader& rdr,
6737 xmlNodePtr node,
6738 bool add_to_current_scope)
6739{
6740 pointer_type_def_sptr decl = build_pointer_type_def(rdr, node,
6741 add_to_current_scope);
6742 MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
6743 if (decl && decl->get_scope())
6744 rdr.schedule_type_for_canonicalization(decl);
6745 return decl;
6746}
6747
6748/// Parse a reference-type-def element.
6749///
6750/// @param rdr the context of the parsing.
6751///
6752/// reference_type_def is added to.
6753static decl_base_sptr
6754handle_reference_type_def(reader& rdr,
6755 xmlNodePtr node,
6756 bool add_to_current_scope)
6757{
6758 reference_type_def_sptr decl = build_reference_type_def(rdr, node,
6759 add_to_current_scope);
6760 MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
6761 if (decl && decl->get_scope())
6762 rdr.schedule_type_for_canonicalization(decl);
6763 return decl;
6764}
6765
6766/// Parse a function-type element.
6767///
6768/// @param rdr the context of the parsing.
6769///
6770/// function_type is added to.
6771static type_base_sptr
6772handle_function_type(reader& rdr,
6773 xmlNodePtr node,
6774 bool add_to_current_scope)
6775{
6776 function_type_sptr type = build_function_type(rdr, node,
6777 add_to_current_scope);
6778 MAYBE_MAP_TYPE_WITH_TYPE_ID(type, node);
6779 rdr.schedule_type_for_canonicalization(type);
6780 return type;
6781}
6782
6783/// Parse a array-type-def element.
6784///
6785/// @param rdr the context of the parsing.
6786///
6787/// array_type_def is added to.
6788static decl_base_sptr
6789handle_array_type_def(reader& rdr,
6790 xmlNodePtr node,
6791 bool add_to_current_scope)
6792{
6793 array_type_def_sptr decl = build_array_type_def(rdr, node,
6794 add_to_current_scope);
6795 MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
6796 rdr.schedule_type_for_canonicalization(decl);
6797 return decl;
6798}
6799
6800/// Parse an enum-decl element.
6801///
6802/// @param rdr the context of the parsing.
6803static decl_base_sptr
6804handle_enum_type_decl(reader& rdr,
6805 xmlNodePtr node,
6806 bool add_to_current_scope)
6807{
6808 enum_type_decl_sptr decl =
6809 build_enum_type_decl_if_not_suppressed(rdr, node,
6810 add_to_current_scope);
6811 MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
6812 if (decl && decl->get_scope())
6813 rdr.schedule_type_for_canonicalization(decl);
6814 return decl;
6815}
6816
6817/// Parse a typedef-decl element.
6818///
6819/// @param rdr the context of the parsing.
6820static decl_base_sptr
6821handle_typedef_decl(reader& rdr,
6822 xmlNodePtr node,
6823 bool add_to_current_scope)
6824{
6825 typedef_decl_sptr decl = build_typedef_decl(rdr, node,
6826 add_to_current_scope);
6827 MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
6828 if (decl && decl->get_scope())
6829 rdr.schedule_type_for_canonicalization(decl);
6830 return decl;
6831}
6832
6833/// Parse a var-decl element.
6834///
6835/// @param rdr the context of the parsing.
6836///
6837/// @param node the node to read & parse from.
6838///
6839/// @param add_to_current_scope if set to yes, the resulting of this
6840/// function is added to its current scope.
6841static decl_base_sptr
6842handle_var_decl(reader& rdr,
6843 xmlNodePtr node,
6844 bool add_to_current_scope)
6845{
6846 decl_base_sptr decl = build_var_decl_if_not_suppressed(rdr, node,
6847 add_to_current_scope);
6848 rdr.add_var_to_exported_or_undefined_decls(is_var_decl(decl));
6849 return decl;
6850}
6851
6852/// Parse a function-decl element.
6853///
6854/// @param rdr the context of the parsing
6855///
6856/// @return true upon successful completion of the parsing, false
6857/// otherwise.
6858static decl_base_sptr
6859handle_function_decl(reader& rdr,
6860 xmlNodePtr node,
6861 bool add_to_current_scope)
6862{
6863 return build_function_decl_if_not_suppressed(rdr, node, class_decl_sptr(),
6864 add_to_current_scope,
6865 /*add_to_exported_decls=*/true);
6866}
6867
6868/// Parse a 'class-decl' xml element.
6869///
6870/// @param rdr the context of the parsing.
6871///
6872/// @return the resulting @ref class_decl built from the XML element
6873/// upon successful completion of the parsing, nil otherwise.
6874static decl_base_sptr
6875handle_class_decl(reader& rdr,
6876 xmlNodePtr node,
6877 bool add_to_current_scope)
6878{
6879 class_decl_sptr decl =
6880 build_class_decl_if_not_suppressed(rdr, node, add_to_current_scope);
6881 MAYBE_MAP_TYPE_WITH_TYPE_ID(is_type(decl), node);
6882 if (decl && decl->get_scope())
6883 rdr.schedule_type_for_canonicalization(decl);
6884 return decl;
6885}
6886
6887/// Parse a 'union-decl' xml element.
6888///
6889/// @param rdr the context of the parsing.
6890///
6891/// @return the resulting @ref union_decl built from the XML element
6892/// upon successful completion of the parsing, nil otherwise.
6893static decl_base_sptr
6894handle_union_decl(reader& rdr,
6895 xmlNodePtr node,
6896 bool add_to_current_scope)
6897{
6898 union_decl_sptr decl =
6899 build_union_decl_if_not_suppressed(rdr, node, add_to_current_scope);
6900 MAYBE_MAP_TYPE_WITH_TYPE_ID(is_type(decl), node);
6901 if (decl && decl->get_scope())
6902 rdr.schedule_type_for_canonicalization(decl);
6903 return decl;
6904}
6905
6906/// Parse a 'function-template-decl' xml element.
6907///
6908/// @param rdr the parsing context.
6909///
6910/// @return true upon successful completion of the parsing, false
6911/// otherwise.
6912static decl_base_sptr
6913handle_function_tdecl(reader& rdr,
6914 xmlNodePtr node,
6915 bool add_to_current_scope)
6916{
6917 function_tdecl_sptr d = build_function_tdecl(rdr, node,
6918 add_to_current_scope);
6919 return d;
6920}
6921
6922/// Parse a 'class-template-decl' xml element.
6923///
6924/// @param rdr the context of the parsing.
6925///
6926/// @return true upon successful completion, false otherwise.
6927static decl_base_sptr
6928handle_class_tdecl(reader& rdr,
6929 xmlNodePtr node,
6930 bool add_to_current_scope)
6931{
6932 class_tdecl_sptr decl = build_class_tdecl(rdr, node,
6933 add_to_current_scope);
6934 return decl;
6935}
6936
6937/// De-serialize a translation unit from an ABI Instrumentation xml
6938/// file coming from an input stream.
6939///
6940/// @param in a pointer to the input stream.
6941///
6942/// @param env the environment to use.
6943///
6944/// @return the translation unit resulting from the parsing upon
6945/// successful completion, or nil.
6948{
6949 reader read_rdr(xml::new_reader_from_istream(in), env);
6950 return read_translation_unit_from_input(read_rdr);
6951}
6952template<typename T>
6953struct array_deleter
6954{
6955 void
6956 operator()(T* a)
6957 {
6958 delete [] a;
6959 }
6960};//end array_deleter
6961
6962
6963/// Create an abixml::reader to read a native XML ABI file.
6964///
6965/// @param path the path to the native XML file to read.
6966///
6967/// @param env the environment to use.
6968///
6969/// @return the created context.
6970fe_iface_sptr
6971create_reader(const string& path, environment& env)
6972{
6973 reader_sptr result(new reader(xml::new_reader_from_file(path),
6974 env));
6975 corpus_sptr corp = result->corpus();
6976 corp->set_origin(corpus::NATIVE_XML_ORIGIN);
6977#ifdef WITH_DEBUG_SELF_COMPARISON
6978 if (env.self_comparison_debug_is_on())
6979 env.set_self_comparison_debug_input(result->corpus());
6980#endif
6981 result->set_path(path);
6982 return result;
6983}
6984
6985/// Create an xml_reader::reader to read a native XML ABI from
6986/// an input stream..
6987///
6988/// @param in the input stream that contains the native XML file to read.
6989///
6990/// @param env the environment to use.
6991///
6992/// @return the created context.
6993fe_iface_sptr
6994create_reader(std::istream* in, environment& env)
6995{
6996 reader_sptr result(new reader(xml::new_reader_from_istream(in),
6997 env));
6998 corpus_sptr corp = result->corpus();
6999 corp->set_origin(corpus::NATIVE_XML_ORIGIN);
7000#ifdef WITH_DEBUG_SELF_COMPARISON
7001 if (env.self_comparison_debug_is_on())
7002 env.set_self_comparison_debug_input(result->corpus());
7003#endif
7004 return result;
7005}
7006
7007/// De-serialize an ABI corpus from an input XML document which root
7008/// node is 'abi-corpus'.
7009///
7010/// @param in the input stream to read the XML document from.
7011///
7012/// @param env the environment to use. Note that the life time of
7013/// this environment must be greater than the lifetime of the
7014/// resulting corpus as the corpus uses resources that are allocated
7015/// in the environment.
7016///
7017/// @return the resulting corpus de-serialized from the parsing. This
7018/// is non-null iff the parsing resulted in a valid corpus.
7019corpus_sptr
7021 environment& env)
7022{
7023 fe_iface_sptr rdr = create_reader(in, env);
7024 fe_iface::status sts;
7025 return rdr->read_corpus(sts);
7026}
7027
7028/// De-serialize an ABI corpus from an XML document file which root
7029/// node is 'abi-corpus'.
7030///
7031/// @param path the path to the input file to read the XML document
7032/// from.
7033///
7034/// @param env the environment to use. Note that the life time of
7035/// this environment must be greater than the lifetime of the
7036/// resulting corpus as the corpus uses resources that are allocated
7037/// in the environment.
7038///
7039/// @return the resulting corpus de-serialized from the parsing. This
7040/// is non-null if the parsing successfully resulted in a corpus.
7041corpus_sptr
7043 environment& env)
7044{
7045 fe_iface_sptr rdr = create_reader(path, env);
7046 fe_iface::status sts;
7047 corpus_sptr corp = rdr->read_corpus(sts);
7048 return corp;
7049}
7050
7051}//end namespace xml_reader
7052
7053#ifdef WITH_DEBUG_SELF_COMPARISON
7054/// Load the map that is stored at
7055/// environment::get_type_id_canonical_type_map().
7056///
7057/// That map associates type-ids to the pointer value of the canonical
7058/// types they correspond to. The map is loaded from a file that was
7059/// stored on disk by some debugging primitive that is activated when
7060/// the command "abidw --debug-abidiff <binary>' is used."
7061///
7062/// The function that stored the map in that file is
7063/// write_canonical_type_ids.
7064///
7065/// @param rdr the ABIXML reader to use.
7066///
7067/// @param file_path the path to the file containing the type-ids <->
7068/// canonical type mapping.
7069///
7070/// @return true iff the loading was successful.
7071bool
7072load_canonical_type_ids(fe_iface& iface, const string &file_path)
7073{
7074 abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
7075
7076 xmlDocPtr doc = xmlReadFile(file_path.c_str(), NULL, XML_PARSE_NOERROR);
7077 if (!doc)
7078 return false;
7079
7080 xmlNodePtr node = xmlDocGetRootElement(doc);
7081 if (!node)
7082 return false;
7083
7084 // We expect a file which content looks like:
7085 //
7086 // <abixml-types-check>
7087 // <type>
7088 // <id>type-id-573</id>
7089 // <c>0x262ee28</c>
7090 // </type>
7091 // <type>
7092 // <id>type-id-569</id>
7093 // <c>0x2628298</c>
7094 // </type>
7095 // <type>
7096 // <id>type-id-575</id>
7097 // <c>0x25f9ba8</c>
7098 // </type>
7099 // <abixml-types-check>
7100 //
7101 // So let's parse it!
7102
7103 if (xmlStrcmp(node->name, (xmlChar*) "abixml-types-check"))
7104 return false;
7105
7106 for (node = xmlFirstElementChild(node);
7107 node;
7108 node = xmlNextElementSibling(node))
7109 {
7110 if (xmlStrcmp(node->name, (xmlChar*) "type"))
7111 continue;
7112
7113 string id, canonical_address;
7114 xmlNodePtr data = xmlFirstElementChild(node);
7115 if (data && !xmlStrcmp(data->name, (xmlChar*) "id")
7116 && data->children && xmlNodeIsText(data->children))
7117 id = (char*) XML_GET_CONTENT(data->children);
7118
7119 data = xmlNextElementSibling(data);
7120 if (data && !xmlStrcmp(data->name, (xmlChar*) "c")
7121 && data->children && xmlNodeIsText(data->children))
7122 {
7123 canonical_address = (char*) XML_GET_CONTENT(data->children);
7124 std::stringstream s;
7125 s << canonical_address;
7126 uintptr_t v = 0;
7127 s >> std::hex >> v;
7128 if (!id.empty()
7129 // 0xdeadbabe is the special value the hash of types
7130 // that are not canonicalized. Look into function
7131 // hash_as_canonical_type_or_constant for the details.
7132 && v != 0xdeadbabe)
7133 rdr.get_environment().get_type_id_canonical_type_map()[id] = v;
7134 }
7135 }
7136 return true;
7137}
7138#endif
7139
7140}//end namespace abigail
This file contains the declarations for the fe_iface a.k.a "Front End Interface".
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects,...
Definition abg-fwd.h:1743
This contains the private implementation of the suppression engine of libabigail.
#define XML_READER_GET_NODE_NAME(reader)
Get the name of the current element node the reader is pointing to. Note that this macro returns an i...
#define XML_READER_GET_ATTRIBUTE(reader, name)
Get the value of attribute 'name' on the current node of 'reader' which is an instance of shared_ptr<...
#define XML_NODE_GET_ATTRIBUTE(node, name)
Get the value of attribute 'name' ont the instance of xmlNodePtr denoted by 'node'.
#define XML_READER_GET_NODE_TYPE(reader)
Get the type of the current node of the shared_ptr<xmlTextReader> passed in argument.
This file contains the declarations of the entry points to de-serialize an instance of abigail::trans...
This contains the private implementation of the suppression engine of libabigail.
This contains the declarations for the symtab reader.
#define ABG_ASSERT_NOT_REACHED
A macro that expands to aborting the program when executed.
The base class of all libabigail front-ends: The Front End Interface.
status
The status of the fe_iface::read_corpus call.
@ STATUS_OK
This status is for when the call went OK.
const options_type & options() const
Getter of the the options of the current Front End Interface.
corpus_sptr corpus()
Getter for the ABI corpus being built by the current front-end.
suppr::suppressions_type & suppressions()
Getter of the vector of suppression specifications associated with the current front-end.
virtual void initialize(const std::string &corpus_path)
Re-initialize the current Front End.
const std::string & corpus_path() const
Getter of the path to the file which an ABI corpus is to be created for.
const string & dt_soname() const
Getter for the SONAME of the analyzed binary.
shared_ptr< subrange_type > subrange_sptr
Convenience typedef for a shared pointer on a function_decl::subrange.
Definition abg-ir.h:2566
std::vector< subrange_sptr > subranges_type
Convenience typedef for a vector of subrange_sptr.
Definition abg-ir.h:2569
vector< base_spec_sptr > base_specs
Convenience typedef.
Definition abg-ir.h:4183
Abstraction of a group of corpora.
Definition abg-corpus.h:386
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
Definition abg-corpus.h:25
binding
ELF binding.
Definition abg-ir.h:1636
visibility
ELF visibility.
Definition abg-ir.h:1626
binding
The binding of a symbol.
Definition abg-ir.h:978
static bool get_name_and_version_from_id(const string &id, string &name, string &ver)
Given the ID of a symbol, get the name and the version of said symbol.
Definition abg-ir.cc:2752
type
The type of a symbol.
Definition abg-ir.h:965
static elf_symbol_sptr create(const environment &e, size_t i, size_t s, const string &n, type t, binding b, bool d, bool c, const version &ve, visibility vi, bool is_in_ksymtab=false, const abg_compat::optional< uint32_t > &crc={}, const abg_compat::optional< std::string > &ns={}, bool is_suppressed=false)
Factory of instances of elf_symbol.
Definition abg-ir.cc:2063
visibility
The visibility of the symbol.
Definition abg-ir.h:987
std::vector< enumerator > enumerators
Convenience typedef for a list of enumerator.
Definition abg-ir.h:2801
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition abg-ir.h:148
bool canonicalization_is_done() const
Test if the canonicalization of types created out of the current environment is done.
Definition abg-ir.cc:3538
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition abg-ir.h:3177
The source location of a token.
Definition abg-ir.h:307
CV
Bit field values representing the cv qualifiers of the underlying type.
Definition abg-ir.h:2255
This is the abstraction of the set of relevant artefacts (types, variable declarations,...
Definition abg-ir.h:695
The base class of both types and declarations.
Definition abg-ir.h:1406
static symtab_ptr load(Elf *elf_handle, const ir::environment &env, symbol_predicate is_suppressed=NULL)
Construct a symtab object and instantiate it from an ELF handle. Also pass in the ir::environment we ...
A type used to time various part of the libabigail system.
bool stop()
Stop the timer.
bool start()
Start the timer.
translation_unit_sptr read_translation_unit_from_buffer(const string &buffer, environment &env)
Parse an ABI instrumentation file (in XML format) from an in-memory buffer.
void add_reader_suppressions(reader &rdr, const suppr::suppressions_type &supprs)
Add suppressions specifications to the set of suppressions to be used during the construction of the ...
unordered_map< string, vector< string > > string_strings_map_type
Convenience typedef for an unordered map of string to a vector of strings.
Definition abg-reader.cc:63
translation_unit_sptr read_translation_unit_from_istream(istream *in, environment &env)
De-serialize a translation unit from an ABI Instrumentation xml file coming from an input stream.
corpus_sptr read_corpus_from_abixml(std::istream *in, environment &env)
De-serialize an ABI corpus from an input XML document which root node is 'abi-corpus'.
corpus_group_sptr read_corpus_group_from_input(fe_iface &iface)
Parse the input XML document containing an ABI corpus group, represented by an 'abi-corpus-group' ele...
corpus_sptr read_corpus_from_abixml_file(const string &path, environment &env)
De-serialize an ABI corpus from an XML document file which root node is 'abi-corpus'.
reader_sptr is_reader(fe_iface_sptr iface)
Convert a abigail:fe_iface into an abigail::abixml::reader.
translation_unit_sptr read_translation_unit_from_file(const string &input_file, environment &env)
Parse an ABI instrumentation file (in XML format) at a given path.
corpus_group_sptr read_corpus_group_from_abixml(std::istream *in, environment &env)
De-serialize an ABI corpus group from an input XML document which root node is 'abi-corpus-group'.
fe_iface_sptr create_reader(const string &path, environment &env)
Create an abixml::reader to read a native XML ABI file.
void consider_types_not_reachable_from_public_interfaces(fe_iface &iface, bool flag)
Configure the reader so that types not reachable from public interface are taken into account when th...
corpus_group_sptr read_corpus_group_from_abixml_file(const string &path, environment &env)
De-serialize an ABI corpus group from an XML document file which root node is 'abi-corpus-group'.
hash_t hash(uint64_t v, uint64_t seed)
Hash an integer value and combine it with a hash previously computed.
Definition abg-hash.cc:196
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...
Definition abg-hash.cc:99
shared_ptr< type_tparameter > type_tparameter_sptr
Convenience typedef for a shared pointer to type_tparameter.
Definition abg-fwd.h:330
shared_ptr< reference_type_def > reference_type_def_sptr
Convenience typedef for a shared pointer on a reference_type_def.
Definition abg-fwd.h:235
bool is_non_canonicalized_type(const type_base *t)
Test if a given type is allowed to be non canonicalized.
Definition abg-ir.cc:28565
shared_ptr< function_decl > function_decl_sptr
Convenience typedef for a shared pointer on a function_decl.
Definition abg-fwd.h:269
access_specifier
Access specifier for class members.
Definition abg-ir.h:917
shared_ptr< class_tdecl > class_tdecl_sptr
Convenience typedef for a shared pointer on a class_tdecl.
Definition abg-fwd.h:289
scope_decl * get_type_scope(type_base *t)
Get the scope of a given type.
Definition abg-ir.cc:8807
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition abg-ir.cc:10817
bool is_anonymous_data_member(const decl_base &d)
Test if a decl is an anonymous data member.
Definition abg-ir.cc:5879
array_type_def::subrange_type * is_subrange_type(const type_or_decl_base *type)
Test if a type is an array_type_def::subrange_type.
Definition abg-ir.cc:12225
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition abg-ir.h:926
shared_ptr< non_type_tparameter > non_type_tparameter_sptr
Convenience typedef for shared pointer to non_type_template_parameter.
Definition abg-fwd.h:320
bool odr_is_relevant(const type_or_decl_base &artifact)
By looking at the language of the TU a given ABI artifact belongs to, test if the ONE Definition Rule...
Definition abg-ir.cc:10214
const ptr_to_mbr_type * is_ptr_to_mbr_type(const type_or_decl_base *t, bool look_through_qualifiers)
Test whether a type is a ptr_to_mbr_type.
Definition abg-ir.cc:11721
bool is_class_type(const type_or_decl_base &t)
Test whether a type is a class.
Definition abg-ir.cc:11175
void set_member_function_virtuality(function_decl &fn, bool is_virtual, ssize_t voffset)
Set the virtual-ness of a member fcuntion.
Definition abg-ir.cc:6722
shared_ptr< array_type_def > array_type_def_sptr
Convenience typedef for a shared pointer on a array_type_def.
Definition abg-fwd.h:244
void set_member_function_is_dtor(function_decl &f, bool d)
Set the destructor-ness property of a member function.
Definition abg-ir.cc:6489
shared_ptr< template_parameter > template_parameter_sptr
Convenience typedef for shared pointer to template parameter.
Definition abg-fwd.h:314
class_or_union * is_class_or_union_type(const type_or_decl_base *t)
Test if a type is a class_or_union.
Definition abg-ir.cc:11406
shared_ptr< class_decl > class_decl_sptr
Convenience typedef for a shared pointer on a class_decl.
Definition abg-fwd.h:193
void set_member_function_is_const(function_decl &f, bool is_const)
set the const-ness property of a member function.
Definition abg-ir.cc:6545
bool string_to_elf_symbol_type(const string &s, elf_symbol::type &t)
Convert a string representing a symbol type into an elf_symbol::type.
Definition abg-ir.cc:3071
const type_decl * is_type_decl(const type_or_decl_base *t)
Test whether a type is a type_decl (a builtin type).
Definition abg-ir.cc:10919
function_type_sptr is_function_type(const type_or_decl_base_sptr &t)
Test whether a type is a function_type.
Definition abg-ir.cc:11868
void set_member_access_specifier(decl_base &d, access_specifier a)
Sets the access specifier for a class member.
Definition abg-ir.cc:5551
typedef_decl_sptr is_typedef(const type_or_decl_base_sptr t)
Test whether a type is a typedef.
Definition abg-ir.cc:11021
shared_ptr< template_tparameter > template_tparameter_sptr
Convenience typedef for a shared_ptr to template_tparameter.
Definition abg-fwd.h:327
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition abg-fwd.h:210
shared_ptr< typedef_decl > typedef_decl_sptr
Convenience typedef for a shared pointer on a typedef_decl.
Definition abg-fwd.h:167
bool is_typedef_of_maybe_qualified_class_or_union_type(const type_base *t)
Test if a type is a typedef of a class or union type, or a typedef of a qualified class or union type...
Definition abg-ir.cc:11624
reference_type_def * is_reference_type(type_or_decl_base *t, bool look_through_qualifiers)
Test whether a type is a reference_type_def.
Definition abg-ir.cc:11661
std::unordered_map< string, elf_symbol_sptr > string_elf_symbol_sptr_map_type
Convenience typedef for a map which key is a string and which value if the elf symbol of the same nam...
Definition abg-ir.h:934
const enum_type_decl * is_enum_type(const type_or_decl_base *d)
Test if a decl is an enum_type_decl.
Definition abg-ir.cc:11110
const global_scope * get_global_scope(const decl_base &decl)
return the global scope as seen by a given declaration.
Definition abg-ir.cc:8550
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition abg-fwd.h:256
shared_ptr< ptr_to_mbr_type > ptr_to_mbr_type_sptr
Convenience typedef for a shared pointer to a ptr_to_mbr_type.
Definition abg-fwd.h:239
shared_ptr< scope_decl > scope_decl_sptr
Convenience typedef for a shared pointer on a scope_decl.
Definition abg-fwd.h:264
bool string_to_elf_symbol_binding(const string &s, elf_symbol::binding &b)
Convert a string representing a an elf symbol binding into an elf_symbol::binding.
Definition abg-ir.cc:3104
shared_ptr< type_or_decl_base > type_or_decl_base_sptr
A convenience typedef for a shared_ptr to type_or_decl_base.
Definition abg-fwd.h:120
shared_ptr< translation_unit > translation_unit_sptr
Convenience typedef for a shared pointer on a translation_unit type.
Definition abg-fwd.h:136
shared_ptr< string_elf_symbols_map_type > string_elf_symbols_map_sptr
Convenience typedef for a shared pointer to string_elf_symbols_map_type.
Definition abg-ir.h:951
void hash_and_canonicalize_types(IteratorType begin, IteratorType end, deref_lambda deref, bool do_log=false, bool show_stats=false)
Hash and canonicalize a sequence of types.
bool string_to_elf_symbol_visibility(const string &s, elf_symbol::visibility &v)
Convert a string representing a an elf symbol visibility into an elf_symbol::visibility.
Definition abg-ir.cc:3129
shared_ptr< pointer_type_def > pointer_type_def_sptr
Convenience typedef for a shared pointer on a pointer_type_def.
Definition abg-fwd.h:226
translation_unit::language string_to_translation_unit_language(const string &l)
Parse a string representing a language into a translation_unit::language enumerator into a string.
Definition abg-ir.cc:1670
var_decl * is_var_decl(const type_or_decl_base *tod)
Tests if a declaration is a variable declaration.
Definition abg-ir.cc:12069
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition abg-ir.cc:10757
method_decl * is_method_decl(const type_or_decl_base *d)
Test if a function_decl is actually a method_decl.
Definition abg-ir.cc:25724
bool is_member_type(const type_base_sptr &t)
Tests if a type is a class member.
Definition abg-ir.cc:5471
decl_base_sptr add_decl_to_scope(decl_base_sptr decl, scope_decl *scope)
Appends a declaration to a given scope, if the declaration doesn't already belong to one and if the d...
Definition abg-ir.cc:8457
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
Definition abg-fwd.h:175
const pointer_type_def * is_pointer_type(const type_or_decl_base *t, bool look_through_qualifiers)
Test whether a type is a pointer_type_def.
Definition abg-ir.cc:11489
translation_unit * get_translation_unit(const type_or_decl_base &t)
Return the translation unit a declaration belongs to.
Definition abg-ir.cc:10510
bool is_union_type(const type_or_decl_base &t)
Test if a type is a union_decl.
Definition abg-ir.cc:11455
shared_ptr< template_decl > template_decl_sptr
Convenience typedef for a shared pointer to template_decl.
Definition abg-fwd.h:306
function_type_sptr lookup_function_type(const interned_string &type_name, const translation_unit &tu)
Lookup a function type from a translation unit.
Definition abg-ir.cc:12850
const decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition abg-ir.cc:10236
shared_ptr< type_composition > type_composition_sptr
Convenience typedef for shared pointer to type_composition.
Definition abg-fwd.h:343
void set_member_is_static(decl_base &d, bool s)
Sets the static-ness property of a class member.
Definition abg-ir.cc:26824
array_type_def * is_array_type(const type_or_decl_base *type, bool look_through_qualifiers)
Test if a type is an array_type_def.
Definition abg-ir.cc:12133
shared_ptr< type_decl > type_decl_sptr
Convenience typedef for a shared pointer on a type_decl.
Definition abg-fwd.h:161
shared_ptr< namespace_decl > namespace_decl_sptr
Convenience typedef for a shared pointer on namespace_decl.
Definition abg-fwd.h:284
bool is_unique_type(const type_base_sptr &t)
Test if a type is unique in the entire environment.
Definition abg-ir.cc:28601
interned_string get_type_name(const type_base_sptr &t, bool qualified, bool internal)
Get the name of a given type and return a copy of it.
Definition abg-ir.cc:8842
function_decl * is_function_decl(const type_or_decl_base *d)
Test whether a declaration is a function_decl.
Definition abg-ir.cc:10705
qualified_type_def * is_qualified_type(const type_or_decl_base *t)
Test whether a type is a reference_type_def.
Definition abg-ir.cc:11848
string build_qualified_name(const scope_decl *scope, const string &name)
Build and return a qualified name from a name and its scope.
Definition abg-ir.cc:8739
shared_ptr< function_tdecl > function_tdecl_sptr
Convenience typedef for a shared pointer on a function_tdecl.
Definition abg-fwd.h:294
void set_member_function_is_ctor(function_decl &f, bool c)
Setter for the is_ctor property of the member function.
Definition abg-ir.cc:6432
shared_ptr< file_suppression > file_suppression_sptr
A convenience typedef for a shared_ptr to file_suppression.
vector< suppression_sptr > suppressions_type
Convenience typedef for a vector of suppression_sptr.
Definition abg-fwd.h:1687
shared_ptr< function_suppression > function_suppression_sptr
Convenience typedef for a shared pointer to function_suppression.
bool suppression_can_match(const fe_iface &fe, const suppression_base &s)
Test if a given suppression specification can match an ABI artifact coming from the corpus being anal...
file_suppression_sptr is_file_suppression(const suppression_sptr s)
Test if a given suppression specification is a file suppression specification.
bool is_elf_symbol_suppressed(const fe_iface &fe, const elf_symbol_sptr &symbol)
Test if an ELF symbol is suppressed by at least one of the suppression specifications associated with...
bool suppression_matches_soname_or_filename(const string &soname, const string &filename, const suppression_base &suppr)
Test if a given SONAME or file name is matched by a given suppression specification.
bool suppression_matches_type_name_or_location(const type_suppression &s, const string &type_name, const location &type_location)
Test if a type suppression matches a type name and location.
bool is_function_suppressed(const fe_iface &fe, const string &fn_name, const string &fn_linkage_name, bool require_drop_property)
Test if a function is matched by at least one suppression specification associated with a given front...
bool is_type_suppressed(const fe_iface &fe, const string &type_name, const location &type_location, bool &type_is_opaque, bool require_drop_property)
Test if a type is matched by at least one suppression specification associated with a given front-end...
bool is_variable_suppressed(const fe_iface &fe, const string &var_name, const string &var_linkage_name, bool require_drop_property)
Test if a variable is matched by at least one suppression specification associated with a given front...
bool split_string(const string &input_string, const string &delims, vector< string > &result)
Split a given string into substrings, given some delimiters.
reader_sptr new_reader_from_file(const std::string &path)
Instantiate an xmlTextReader that parses the content of an on-disk file, wrap it into a smart pointer...
bool xml_char_sptr_to_string(xml_char_sptr &ssptr, std::string &s)
Convert a shared pointer to xmlChar into an std::string.
reader_sptr new_reader_from_buffer(const std::string &buffer)
Instanciate an xmlTextReader that parses the content of an in-memory buffer, wrap it into a smart poi...
shared_ptr< xmlChar > xml_char_sptr
A convenience typedef for a shared pointer of xmlChar.
void unescape_xml_string(const std::string &str, std::string &escaped)
Read a string, detect the 5 predefined XML entities it may contain and un-escape them,...
reader_sptr new_reader_from_istream(std::istream *in)
Instanciate an xmlTextReader that parses a content coming from an input stream.
shared_ptr< xmlTextReader > reader_sptr
A convenience typedef for a shared pointer of xmlTextReader.
Toplevel namespace for libabigail.
void abigail_get_abixml_version(std::string &major, std::string &minor)
Return the version numbers for the ABIXML format.
Definition abg-config.cc:98