libabigail
abg-btf-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) 2022-2025 Red Hat, Inc.
5//
6// Author: Dodji Seketeli
7
8/// @file
9///
10/// This file contains the definitions of the front-end to analyze the
11/// BTF information contained in an ELF file.
12
13#include "abg-internal.h"
14
15#ifdef WITH_BTF
16
17#include <bpf/btf.h>
18#include <iostream>
19#include <unordered_map>
20
21#include "abg-elf-helpers.h"
22#include "abg-ir-priv.h"
23
24// <headers defining libabigail's API go under here>
25ABG_BEGIN_EXPORT_DECLARATIONS
26
27#include "abg-btf-reader.h"
28#include "abg-ir.h"
29#include "abg-tools-utils.h"
30
31ABG_END_EXPORT_DECLARATIONS
32// </headers defining libabigail's API>
33
34namespace abigail
35{
36using namespace ir;
37
38/// Namespace of the reader for the BTF debug information.
39namespace btf
40{
41
42class reader;
43
44/// A convenience typedef for a shared pointer to
45/// abigail::btf::reader.
46typedef shared_ptr<reader> reader_sptr;
47
48static const char*
49btf_offset_to_string(const ::btf* btf, uint32_t offset)
50{
51 if (!offset)
52 return "__anonymous__";
53 return btf__name_by_offset(btf, offset) ?: "(invalid string offset)";
54}
55
56/// A convenience typedef of a map that associates a btf type to a
57/// libabigail ABI artifact. The type is allocated inside a given btf
58/// handle (of type ::btf*). All handles (one for each kernel binary)
59/// should be kept around until a complete corpus group is built.
60typedef std::unordered_map<const btf_type*, type_or_decl_base_sptr>
61btf_type_to_abi_artifact_map_type;
62
63/// The BTF front-end abstraction type.
64///
65/// Note that one instance of front-end is meant to analyze one
66/// vmlinux file and all its associated modules. For now, the
67/// front-end doesn't know how to analyze a module without having
68/// analyzed a vmlinux first.
69///
70/// The BTF information of a vmlinux is parsed with the btf__parse
71/// function. The result is called a "base BTF" handle.
72///
73/// The BTF information of a kernel module is parsed with the function
74/// btf__parse_split. The result is called a "split BTF" handle. A
75/// split BTF handle references information that are in the base BTF
76/// handle. The base BTF handle can be retrieved from a split BTF
77/// handle using btf__base_btf.
78class reader : public elf_based_reader
79{
80 ::btf* base_btf_handle_ = nullptr;
81 // The path to the binary that contains the base BTF information
82 // held in base_btf_handle_
83 string base_btf_file_name_;
84 ::btf* split_btf_handle_ = nullptr;
85 // The path to the binary that contains the split BTF information
86 // held in split_btf_handle_
87 string split_btf_file_name_;
88 // A vector of (split) BTF objects that are to be freed once the
89 // corpus group is built for an entire kernel (vmliunx + modules).
90 vector<::btf*> split_btfs_to_free_;
92 vector<type_base_sptr> types_to_canonicalize_;
93 btf_type_to_abi_artifact_map_type btf_type_to_artifacts_;
94
95 /// Getter of the "do_log" flag.
96 ///
97 /// This flag tells if we should log about various internal
98 /// details.
99 ///
100 /// return the "do_log" flag.
101 bool
102 do_log() const
103 {return options().do_log;}
104
105 /// Setter of the "do_log" flag.
106 ///
107 /// This flag tells if we should log about various internal details.
108 ///
109 /// @param f the new value of the flag.
110 void
111 do_log(bool f)
112 {options().do_log = f;}
113
114 /// Getter of the "show_stats" flag.
115 ///
116 /// This flag tells if we should emit statistics about various
117 /// internal stuff.
118 ///
119 /// @return the value of the flag.
120 bool
121 show_stats() const
122 {return options().show_stats;}
123
124 /// Setter of the "show_stats" flag.
125 ///
126 /// This flag tells if we should emit statistics about various
127 /// internal stuff.
128 ///
129 /// @param f the value of the flag.
130 void
131 show_stats(bool f)
132 {options().show_stats = f;}
133
134 /// Getter of the handle to the base BTF object of the current
135 /// binary being analyzed.
136 ///
137 /// The base BTF object ALWAYS represents the BTF information of the
138 /// vmlinux binary, even if the current binary being analyzed is a
139 /// kernel module.
140 ///
141 /// @return handle to the base BTF object of the current binary
142 /// being analyzed.
143 ::btf*
144 base_btf_handle()
145 {
146 if (base_btf_handle_ == nullptr)
147 {
148 base_btf_handle_ = btf__parse(corpus_path().c_str(), nullptr);
149 if (!base_btf_handle_)
150 {
151 std::cerr << "Could not parse base BTF information from file '"
152 << corpus_path().c_str() << "'" << std::endl;
153 return nullptr;
154 }
155 base_btf_file_name_ = corpus_path();
156 }
157 return base_btf_handle_;
158 }
159
160 /// Read the BTF information of the current binary which path is
161 /// @ref fe_iface::corpus_path() and return its associated object
162 /// handle. This is called the split BTF object.
163 ///
164 /// Note that this function expects the base BTF object (the one for
165 /// the vmlinux binary) to be already present, otherwise, it returns
166 /// nullptr.
167 ///
168 /// @return the split BTF object for the file designed by
169 /// fe_iface::corpus_path().
170 ::btf*
171 read_split_btf()
172 {
173 if (!base_btf_handle_)
174 {
175 std::cerr << "Base BTF information not present. "
176 << "Not attempting to parse split BTF information"
177 << std::endl;
178 return nullptr;
179 }
180
181 if (corpus_path().empty() || corpus_path() == base_btf_file_name_)
182 {
183 std::cerr << "BTF reader not initialized with split file name. "
184 << "Not attending to read split BTF information"
185 << std::endl;
186 return nullptr;
187 }
188
189 split_btf_handle_ = btf__parse_split(corpus_path().c_str(),
190 base_btf_handle());
191 if (!split_btf_handle_)
192 {
193 std::cerr << "Could not read split BTF information from file "
194 << corpus_path() << std::endl;
195 return nullptr;
196 }
197 split_btf_file_name_ = corpus_path();
198
199 return split_btf_handle_;
200 }
201
202 /// Getter of the handle to the BTF object as returned by libbpf.
203 ///
204 /// This returns the handle to the current BTF object. If the
205 /// current BTF object is for a vmlinux binary, then it's the base
206 /// BTF object that is returned. Otherwise, if the current BTF
207 /// object if for a kernel module then it's the split BTF object
208 /// that is returned.
209 ///
210 /// @return the handle to the BTF object of the current binary being
211 /// analyeed by this front-end.
212 ::btf*
213 btf_handle()
214 {
215 if (split_btf_handle_)
216 return split_btf_handle_;
217
218 if (!base_btf_handle_)
219 return base_btf_handle();
220
221 if (corpus_path() != base_btf_file_name_)
222 // The reader was re-initialized with a corpus_path that is
223 // different from the the BTF base file. That means we are
224 // instructed to read a split BTF file information.
225 return read_split_btf();
226
227 return base_btf_handle();
228 }
229
230 /// Getter of the environment of the current front-end.
231 ///
232 /// @return The environment of the current front-end.
233 environment&
234 env()
235 {return options().env;}
236
237 /// Getter of the environment of the current front-end.
238 ///
239 /// @return The environment of the current front-end.
240 const environment&
241 env() const
242 {return const_cast<reader*>(this)->env();}
243
244 /// Getter of the current translation unit being built.
245 ///
246 /// Actually, BTF doesn't keep track of the translation unit each
247 /// ABI artifact originates from. So an "artificial" translation
248 /// unit is built. It contains all the ABI artifacts of the binary.
249 ///
250 /// @return The current translation unit being built.
252 cur_tu()
253 {return cur_tu_;}
254
255 /// Getter of the current translation unit being built.
256 ///
257 /// Actually, BTF doesn't keep track of the translation unit each
258 /// ABI artifact originates from. So an "artificial" translation
259 /// unit is built. It contains all the ABI artifacts of the binary.
260 ///
261 /// @return The current translation unit being built.
263 cur_tu() const
264 {return cur_tu_;}
265
266 /// Getter of the current translation unit being built.
267 ///
268 /// Actually, BTF doesn't keep track of the translation unit each
269 /// ABI artifact originates from. So an "artificial" translation
270 /// unit is built. It contains all the ABI artifacts of the binary.
271 ///
272 /// @return The current translation unit being built.
273 void
274 cur_tu(const translation_unit_sptr& tu)
275 {cur_tu_ = tu;}
276
277 /// Getter of the map that associates a BTF type to the internal
278 /// representation of an ABI artifact.
279 ///
280 /// @return The map that associates a BTF type to the IR of an ABI
281 /// artifact.
282 btf_type_to_abi_artifact_map_type&
283 btf_type_to_artifacts()
284 {return btf_type_to_artifacts_;}
285
286 /// Getter of the map that associates a BTF type to the IR of an ABI
287 /// artifact.
288 ///
289 /// @return The map that associates a BTF type to the IR of an ABI
290 /// artifact.
291 const btf_type_to_abi_artifact_map_type&
292 btf_type_to_artifacts() const
293 {return btf_type_to_artifacts_;}
294
295 /// Get the IR of the ABI artifact that is associated to a given BTF
296 /// type.
297 ///
298 /// If no ABI artifact is associated to the BTF type, then return
299 /// nullptr.
300 ///
301 /// @return the ABI artifact that is associated to a given BTF type.
303 lookup_artifact_from_btf_type(const btf_type* t)
304 {
305 auto i = btf_type_to_artifacts().find(t);
306 if (i != btf_type_to_artifacts().end())
307 return i->second;
308 return type_or_decl_base_sptr();
309 }
310
311 /// Associate an ABI artifact to a given BTF type.
312 ///
313 /// @param artifact the ABI artifact to consider.
314 ///
315 /// @param btf_type_id the BTF type to associate to @p artifact.
316 void
317 associate_artifact_to_btf_type(const type_or_decl_base_sptr& artifact,
318 const btf_type* t)
319 {btf_type_to_artifacts()[t] = artifact;}
320
321 /// Schecule a type for canonicalization at the end of the debug
322 /// info loading.
323 ///
324 /// @param t the type to schedule.
325 void
326 schedule_type_for_canonicalization(const type_base_sptr& t)
327 {
328 if (t && !t->get_naked_canonical_type())
329 types_to_canonicalize_.push_back(t);
330 }
331
332 /// Canonicalize all the types scheduled for canonicalization using
333 /// abigail::ir::canonicalize_types() which performs some sanity
334 /// checking around type canonicalization if necessary.
335 void
337 {
338 tools_utils::timer cn_timer;
339 if (do_log())
340 {
341 std::cerr << "BTF Reader is going to canonicalize "
342 << std::dec
343 << types_to_canonicalize_.size()
344 << " types";
345 corpus_sptr c = corpus();
346 if (c)
347 std::cerr << " from corpus " << corpus()->get_path() << "\n";
348 cn_timer.start();
349 }
350
351 ir::hash_and_canonicalize_types(types_to_canonicalize_.begin(),
352 types_to_canonicalize_.end(),
353 [](const vector<type_base_sptr>::const_iterator& i)
354 {return *i;}, do_log(), show_stats());
355
356 if (do_log())
357 {
358 cn_timer.stop();
359 std::cerr << "BTF Reader finished types "
360 << "sorting, hashing & canonicalizing in: "
361 << cn_timer << "\n";
362 }
363
364 }
365
366 /// Getter of the number of types carried by a given BTF object.
367 ///
368 /// @param handle the BTF object to consider.
369 ///
370 /// @return the number of types carried by a given BTF object.
371 uint64_t
372 nr_btf_types(const ::btf* handle) const
373 {
374#ifdef WITH_BTF__GET_NR_TYPES
375#define GET_NB_TYPES btf__get_nr_types
376#endif
377
378#ifdef WITH_BTF__TYPE_CNT
379#undef GET_NB_TYPES
380#define GET_NB_TYPES btf__type_cnt
381#endif
382
383#ifndef GET_NB_TYPES
385 return 0;
386#endif
387
388 return GET_NB_TYPES(handle);
389 }
390
391protected:
392 reader() = delete;
393
394 /// Initializer of the current instance of @ref btf::reader.
395 ///
396 /// This frees the resources used by the current instance of @ref
397 /// btf::reader and gets it ready to analyze another ELF
398 /// file.
399 ///
400 /// @param elf_path the path to the ELF file to read from.
401 ///
402 /// @param debug_info_root_paths the paths where to look for
403 /// seperate debug info.
404 ///
405 /// @param load_all_types if true, then load all the types described
406 /// in the binary, rather than loading only the types reachable from
407 /// the exported decls.
408 ///
409 /// @param linux_kernel_mode
410 void
411 initialize(const string& elf_path,
412 const vector<char**>& debug_info_root_paths,
413 bool load_all_types,
414 bool linux_kernel_mode)
415 {
416 if (split_btf_handle_)
417 {
418 // We need to keep this split_btf_handle_ on the side so that
419 // we can free it when we are done analyzing all the kernel
420 // modules. We cannot free it right now because the memory of
421 // all btf types lives in it.
422 split_btfs_to_free_.push_back(split_btf_handle_);
423 split_btf_handle_ = nullptr;
424 }
425
426 split_btf_file_name_.clear();
427 types_to_canonicalize_.clear();
428 cur_tu_.reset();
429 elf_based_reader::initialize(elf_path, debug_info_root_paths);
430 corpus_path(elf_path);
431 options().load_all_types = load_all_types;
432 options().load_in_linux_kernel_mode = linux_kernel_mode;
433 }
434
435 /// Constructor of the btf::reader type.
436 ///
437 /// @param elf_path the path to the ELF file to analyze.
438 ///
439 /// @param debug_info_root_paths the set of directory where to look
440 /// debug info from, for cases where the debug is split.
441 ///
442 /// @param environment the environment of the current front-end.
443 ///
444 /// @param load_all_types if true load all the types described by
445 /// the BTF debug info, as opposed to loading only the types
446 /// reachable from the decls that are defined and exported.
447 ///
448 /// @param linux_kernel_mode if true, then consider the binary being
449 /// analyzed as a linux kernel binary.
450 reader(const string& elf_path,
451 const vector<char**>& debug_info_root_paths,
452 environment& environment,
453 bool load_all_types,
454 bool linux_kernel_mode)
455 : elf_based_reader(elf_path,
456 debug_info_root_paths,
457 environment)
458 {
459 initialize(elf_path, debug_info_root_paths,
460 load_all_types, linux_kernel_mode);
461 }
462
463public:
464
465 /// Constructor of the btf::reader type.
466 ///
467 /// @param elf_path the path to the ELF file to analyze.
468 ///
469 /// @param debug_info_root_paths the set of directory where to look
470 /// debug info from, for cases where the debug is split.
471 ///
472 /// @param environment the environment of the current front-end.
473 ///
474 /// @param load_all_types if true load all the types described by
475 /// the BTF debug info, as opposed to loading only the types
476 /// reachable from the decls that are defined and exported.
477 ///
478 /// @param linux_kernel_mode if true, then consider the binary being
479 /// analyzed as a linux kernel binary.
480 static btf::reader_sptr
481 create(const string& elf_path,
482 const vector<char**>& debug_info_root_paths,
483 environment& environment,
484 bool load_all_types,
485 bool linux_kernel_mode)
486 {
487 reader_sptr result(new reader(elf_path, debug_info_root_paths, environment,
488 load_all_types, linux_kernel_mode));
489 return result;
490 }
491
492 /// Destructor of the btf::reader type.
493 ~reader()
494 {
495 for (auto b : split_btfs_to_free_)
496 btf__free(b);
497 btf__free(split_btf_handle_);
498 btf__free(base_btf_handle_);
499 split_btf_handle_ = nullptr;
500 base_btf_handle_ = nullptr;
501 }
502
503 /// Read the ELF information as well as the BTF type information to
504 /// build an ABI corpus.
505 ///
506 /// @param status output parameter. The status of the analysis.
507 ///
508 /// @return the resulting ABI corpus.
509 corpus_sptr
510 read_corpus(status& status)
511 {
512 // Read the properties of the ELF file.
514
515 corpus::origin origin = corpus()->get_origin();
516 origin |= corpus::BTF_ORIGIN;
517 corpus()->set_origin(origin);
518 if (corpus_group())
519 {
520 origin |= corpus_group()->get_origin();
521 corpus_group()->set_origin(origin);
522 }
523
524 if ((status & STATUS_NO_SYMBOLS_FOUND)
525 || !(status & STATUS_OK))
526 // Either we couldn't find ELF symbols or something went badly
527 // wrong. There is nothing we can do with this ELF file. Bail
528 // out.
529 return corpus_sptr();
530
531 if (find_btf_section() == nullptr)
532 status |= STATUS_DEBUG_INFO_NOT_FOUND;
533
534 read_debug_info_into_corpus();
535
536 status |= STATUS_OK;
537
538 return corpus();
539 }
540
541 /// Read the BTF debug info to construct the ABI corpus.
542 ///
543 /// @return the resulting ABI corpus.
544 corpus_sptr
545 read_debug_info_into_corpus()
546 {
547 if (!btf_handle())
548 return corpus_sptr();
549
550 translation_unit_sptr artificial_tu
551 (new translation_unit(env(), "", /*address_size=*/64));
552 corpus()->add(artificial_tu);
553 cur_tu(artificial_tu);
554
555#ifdef WITH_DEBUG_SELF_COMPARISON
556 if (env().self_comparison_debug_is_on())
557 {
558 corpus_group_sptr g = corpus_group();
559 if (g)
560 env().set_self_comparison_debug_input(g);
561 else
562 env().set_self_comparison_debug_input(corpus());
563 }
564#endif
565
566 int number_of_types = nr_btf_types(btf_handle());
567 int first_type_id = 1;
568 // Are we looking at the BTF for a kernel module?
569 const ::btf* base = btf__base_btf(btf_handle());
570 if (base)
571 {
572 // So, base is non-nil. This means we are looking at the BTF
573 // for a kernel module and base points to the BTF for the
574 // corresponding vmlinux. That base BTF should be the same as
575 // base_btf_handle().
576 ABG_ASSERT(base == base_btf_handle());
577
578 // The ID of the first type that is contained in this BTF
579 // representing a kernel module is the number of types
580 // contained in the base BTF (i.e, the BTF for the vmlinux
581 // binary).
582 first_type_id = nr_btf_types(base);
583 }
584
585 // Let's cycle through whatever is described in the BTF section
586 // and emit libabigail IR for it.
587 for (int type_id = first_type_id;
588 type_id < number_of_types;
589 ++type_id)
590 {
591 // Build IR nodes only for decls (functions and variables)
592 // that have associated ELF symbols that are publicly defined
593 // and exported, unless the user asked to load all types.
594
595 bool do_construct_ir_node = false;
596
597 const btf_type* t = btf__type_by_id(btf_handle(), type_id);
598 string name;
599 if (t->name_off)
600 name = btf_offset_to_string(btf_handle(), t->name_off);
601
602 int kind = btf_kind(t);
603 if (kind == BTF_KIND_FUNC)
604 {
605 ABG_ASSERT(!name.empty());
606 if (btf_vlen(t) == BTF_FUNC_GLOBAL
607 || btf_vlen(t) == BTF_FUNC_EXTERN
608 || function_symbol_is_exported(name))
609 do_construct_ir_node = true;
610 }
611 else if (kind == BTF_KIND_VAR)
612 {
613 ABG_ASSERT(!name.empty());
614 if (btf_vlen(t) == BTF_VAR_GLOBAL_ALLOCATED
615 || btf_vlen(t) == BTF_VAR_GLOBAL_EXTERN
616 || variable_symbol_is_exported(name))
617 do_construct_ir_node = true;
618 }
619 else if (options().load_all_types)
620 do_construct_ir_node = true;
621
622 if (do_construct_ir_node)
623 build_ir_node_from_btf_type(type_id);
624 }
625
627 corpus()->sort_functions();
628 corpus()->sort_variables();
629 return corpus();
630 }
631
632 /// Build an abigail IR node for a given type described by a BTF
633 /// type ID. The node is added to the ABI corpus.
634 ///
635 /// @param type_id the ID of the type to build and IR node for.
636 ///
637 /// @return the IR node representing the type @p type_id.
639 build_ir_node_from_btf_type(int type_id)
640 {
642 const btf_type *t = nullptr;
643
644 t = btf__type_by_id(btf_handle(), type_id);
645
646 if ((result = lookup_artifact_from_btf_type(t)))
647 return result;
648
649 if (!result)
650 {
651 ABG_ASSERT(t);
652 int type_kind = btf_kind(t);
653
654 switch(type_kind)
655 {
656 case BTF_KIND_UNKN/* Unknown: This is really for the void
657 type. */:
658 result = build_ir_node_for_void_type();
659 break;
660
661 case BTF_KIND_INT/* Integer */:
662 result = build_int_type(type_id);
663 break;
664
665 case BTF_KIND_FLOAT/* Floating point */:
666 result = build_float_type(type_id);
667 break;
668
669 case BTF_KIND_TYPEDEF/* Typedef*/:
670 result = build_typedef_type(type_id);
671 break;
672
673 case BTF_KIND_PTR/* Pointer */:
674 result = build_pointer_type(type_id);
675 break;
676
677 case BTF_KIND_ARRAY/* Array */:
678 result = build_array_type(type_id);
679 break;
680
681 case BTF_KIND_ENUM/* Enumeration up to 32-bit values */:
682#ifdef WITH_BTF_ENUM64
683 case BTF_KIND_ENUM64/* Enumeration up to 64-bit values */:
684#endif
685 result = build_enum_type(type_id);
686 break;
687
688 case BTF_KIND_STRUCT/* Struct */:
689 case BTF_KIND_UNION/* Union */:
690 result = build_class_or_union_type(type_id);
691 break;
692
693 case BTF_KIND_FWD/* Forward */:
694 result = build_class_or_union_type(type_id);
695 break;
696
697 case BTF_KIND_CONST/* Const */:
698 case BTF_KIND_VOLATILE/* Volatile */:
699 case BTF_KIND_RESTRICT/* Restrict */:
700 result = build_qualified_type(type_id);
701 break;
702
703 case BTF_KIND_FUNC/* Function */:
704 result = build_function_decl(type_id);
705 break;
706
707 case BTF_KIND_FUNC_PROTO/* Function Proto */:
708 result = build_function_type(type_id);
709 break;
710
711 case BTF_KIND_VAR/* Variable */:
712 result = build_variable_decl(type_id);
713 break;
714
715#ifdef WITH_BTF_KIND_TYPE_TAG
716 case BTF_KIND_TYPE_TAG/* Type Tag */:
717 break;
718#endif
719#ifdef WITH_BTF_KIND_DECL_TAG
720 case BTF_KIND_DECL_TAG/* Decl Tag */:
721 break;
722#endif
723 case BTF_KIND_DATASEC/* Section */:
724 break;
725 default:
727 break;
728 }
729 }
730
731 add_decl_to_scope(is_decl(result), cur_tu()->get_global_scope());
732
733 if (type_base_sptr type = is_type(result))
734 schedule_type_for_canonicalization(type);
735
736 associate_artifact_to_btf_type(result, t);
737
738 if (function_decl_sptr fn = is_function_decl(result))
739 add_fn_to_exported_or_undefined_decls(fn.get());
740 else if (var_decl_sptr var = is_var_decl(result))
741 add_var_to_exported_or_undefined_decls(var);
742
743 return result;
744 }
745
746 /// Build an IR node for the "void" type.
747 ///
748 /// @return the IR node for the void type.
749 type_base_sptr
750 build_ir_node_for_void_type()
751 {
752 type_base_sptr t = env().get_void_type();
754 schedule_type_for_canonicalization(t);
755 return t;
756 }
757
758 /// Build an IR node for the "void" type.
759 ///
760 /// @return the IR node for the void type.
761 type_base_sptr
762 build_ir_node_for_void_pointer_type()
763 {
764 type_base_sptr t = env().get_void_pointer_type();
766 schedule_type_for_canonicalization(t);
767 return t;
768 }
769
770 /// Build an IR node for the "variadic parameter" type.
771 ///
772 /// @return the IR node for the "variadic parameter" type.
773 type_base_sptr
774 build_ir_node_for_variadic_parameter_type()
775 {
776 type_base_sptr t = env().get_variadic_parameter_type();
778 decl_base_sptr t_decl = get_type_declaration(t);
779 schedule_type_for_canonicalization(t);
780 return t;
781 }
782
783 /// Build an IR node for an integer type expressed in BTF.
784 ///
785 /// @param t a pointer a BTF type describing an integer.
786 ///
787 /// @return a pointer to @ref type_decl representing an integer
788 /// type.
790 build_int_type(int type_id)
791 {
792 type_decl_sptr result;
793
794 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
795 ABG_ASSERT(btf_kind(t) == BTF_KIND_INT);
796
797 uint32_t info = *reinterpret_cast<const uint32_t*>(t + 1);
798 uint64_t byte_size = 0, bit_size = 0;
799 string type_name;
800
801 byte_size = t->size;
802 bit_size = byte_size * 8;
803
804 if (BTF_INT_ENCODING(info) & BTF_INT_CHAR)
805 {
806 if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
807 type_name = "unsigned ";
808 type_name += "char";
809 }
810 else if (BTF_INT_ENCODING(info) & BTF_INT_BOOL)
811 type_name = "bool";
812 else if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
813 {
814 type_name = "unsigned ";
815 type_name += btf_offset_to_string(btf_handle(), t->name_off);
816 }
817 else
818 type_name = btf_offset_to_string(btf_handle(), t->name_off);
819
820 location loc;
821 result.reset(new type_decl(env(), type_name,
822 bit_size, /*alignment=*/0,
823 loc, type_name));
824
825 return result;
826 }
827
828 /// Build an IR node for a float type expressed in BTF.
829 ///
830 /// @return a pointer to @ref type_decl representing a float type.
832 build_float_type(int type_id)
833 {
834 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
835 ABG_ASSERT(btf_kind(t) == BTF_KIND_FLOAT);
836
837 string type_name = btf_offset_to_string(btf_handle(), t->name_off);;
838 uint64_t byte_size = t->size, bit_size = byte_size * 8;
839 location loc;
840 type_decl_sptr result(new type_decl(env(), type_name, bit_size,
841 /*alignment=*/0, loc, type_name));
842
843 return result;
844 }
845
846 /// Build an IR type that represents the underlying type of an enum type.
847 ///
848 /// This is a sub-routine of the build_enum_type() function.
849 ///
850 /// @param enum_name the name of the enum type this type is an
851 /// underlying type for.
852 ///
853 /// @param enum_size the size of the enum.
854 ///
855 /// @param is_anonymous if true, the enum type is anonymous.
856 ///
857 /// @return a pointer to type_decl that represents a integer type
858 /// that is the underlying type of an enum type.
860 build_enum_underlying_type(const string enum_name, uint64_t enum_size,
861 bool is_anonymous = true)
862 {
863 string underlying_type_name =
865 is_anonymous,
866 enum_size);
867 type_decl_sptr result(new type_decl(env(), underlying_type_name,
868 enum_size, enum_size, location()));
869 result->set_is_anonymous(is_anonymous);
870 result->set_is_artificial(true);
871 add_decl_to_scope(result, cur_tu()->get_global_scope());
872 schedule_type_for_canonicalization(result);
873 return result;
874 }
875
876 /// Build an IR node that represents an enum type expressed in BTF.
877 ///
878 /// @param type_id the ID of the BTF representation of the enum.
879 ///
880 /// @return a pointer to @ref enum_type_decl representing @p t.
882 build_enum_type(int type_id)
883 {
884 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
885 int kind = btf_kind(t);
886#ifdef WITH_BTF_ENUM64
887 ABG_ASSERT(kind == BTF_KIND_ENUM || kind == BTF_KIND_ENUM64);
888#else
889 ABG_ASSERT(kind == BTF_KIND_ENUM);
890#endif
891
892 int byte_size = t->size, bit_size = byte_size * 8;
893
894 string enum_name;
895 if (t->name_off)
896 enum_name = btf_offset_to_string(btf_handle(), t->name_off);
897 bool is_anonymous = enum_name.empty();
898
899 int num_enms = btf_vlen(t);
901 string e_name;
902 if (kind == BTF_KIND_ENUM)
903 {
904 const struct btf_enum* e = btf_enum(t);
905 uint32_t e_value = 0;
906 for (int i = 0; i < num_enms; ++i, ++e)
907 {
908 e_name = btf_offset_to_string(btf_handle(), e->name_off);
909 e_value = e->val;
910 enms.push_back(enum_type_decl::enumerator(e_name, e_value));
911 }
912 }
913#ifdef WITH_BTF_ENUM64
914 else if (kind == BTF_KIND_ENUM64)
915 {
916 const struct btf_enum64* e =
917 reinterpret_cast<const struct btf_enum64*>(t + 1);
918 uint64_t e_value = 0;
919 for (int i = 0; i < num_enms; ++i, ++e)
920 {
921 e_name = btf_offset_to_string(btf_handle(), e->name_off);
922 e_value = (static_cast<uint64_t>(e->val_hi32) << 32) | e->val_lo32;
923 enms.push_back(enum_type_decl::enumerator(e_name, e_value));
924 }
925 }
926#endif
927 else
929
930 type_decl_sptr underlying_type =
931 build_enum_underlying_type(enum_name, bit_size, is_anonymous);
932 enum_type_decl_sptr result(new enum_type_decl(enum_name,
933 location(),
934 underlying_type,
935 enms, enum_name));
936 result->set_is_anonymous(is_anonymous);
937 return result;
938 }
939
940 /// Build an IR node for a typedef that is expressed in BTF.
941 ///
942 /// @param type_id the ID of the BTF representation of a typedef.
943 ///
944 /// @return a pointer to @ref typedef_decl representing @p t.
946 build_typedef_type(int type_id)
947 {
948 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
949 int kind = btf_kind(t);
950 ABG_ASSERT(kind == BTF_KIND_TYPEDEF);
951
952 string type_name = btf_offset_to_string(btf_handle(), t->name_off);
953 type_base_sptr underlying_type =
954 is_type(build_ir_node_from_btf_type(t->type));
955 if (!underlying_type)
956 return type_or_decl_base_sptr();
957
958 typedef_decl_sptr result(new typedef_decl(type_name, underlying_type,
959 location(),
960 /*linkage_name=*/type_name));
961 if ((is_class_or_union_type(underlying_type)
962 || is_enum_type(underlying_type))
963 && is_anonymous_type(underlying_type))
964 get_type_declaration(underlying_type)->set_naming_typedef(result);
965
966 return result;
967 }
968
969 /// Build an IR node representing a pointer described in BTF.
970 ///
971 /// @param type_id the ID of a BTF representation of a pointer type.
972 ///
973 /// @return a pointer to pointer_type_def that represents @p t.
975 build_pointer_type(int type_id)
976 {
977 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
978 int kind = btf_kind(t);
979 ABG_ASSERT(kind == BTF_KIND_PTR);
980
981 type_base_sptr underlying_type =
982 is_type(build_ir_node_from_btf_type(t->type));
983 if (!underlying_type)
984 return type_or_decl_base_sptr();
985 if (env().is_void_type(underlying_type))
986 // Recognize a pointer to void and return a special unique IR
987 // for it.
988 return build_ir_node_for_void_pointer_type();
989
990 int size = elf_helpers::get_architecture_word_size(elf_handle());
991 size *= 8;
992 pointer_type_def_sptr result(new pointer_type_def(underlying_type, size,
993 /*alignment=*/0,
994 location()));
995 return result;
996 }
997
998 /// Build an IR node representing an array type described in BTF.
999 ///
1000 /// @param type_id the ID of the BTF representation of an array
1001 /// type.
1002 ///
1003 /// return a pointer to @ref array_type_def representing @p t.
1005 build_array_type(int type_id)
1006 {
1007 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1008 int kind = btf_kind(t);
1009 ABG_ASSERT(kind == BTF_KIND_ARRAY);
1010
1011 const struct btf_array* arr = btf_array(t);
1012
1013 type_base_sptr underlying_type =
1014 is_type(build_ir_node_from_btf_type(arr->type));
1015 if (!underlying_type)
1016 return type_or_decl_base_sptr();
1017
1018 uint64_t lower_bound = 0;
1019 // Note that arr->nelems can be 0;
1020 uint64_t upper_bound = arr->nelems ? arr->nelems - 1: 0;
1021
1022 array_type_def::subrange_sptr subrange(new array_type_def::subrange_type
1023 (env(), /*name=*/"",
1024 lower_bound, upper_bound,
1025 location()));
1026 subrange->is_non_finite(!arr->nelems);
1027 subrange->set_size_in_bits(cur_tu()->get_address_size());
1028 add_decl_to_scope(subrange, cur_tu()->get_global_scope());
1029 schedule_type_for_canonicalization(subrange);
1030 array_type_def::subranges_type subranges = {subrange};
1031 array_type_def_sptr result(new array_type_def(underlying_type,
1032 subranges, location()));
1033
1034 return result;
1035 }
1036
1037 /// Build an IR node representing a qualified type described in BTF.
1038 ///
1039 /// @param type_id the ID of the BTF representation of an array
1040 /// type.
1041 ///
1042 /// @return a pointer to a qualified_type_def representing @ t.
1044 build_qualified_type(int type_id)
1045 {
1046 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1047 int kind = btf_kind(t);
1048 ABG_ASSERT(kind == BTF_KIND_CONST
1049 || kind == BTF_KIND_VOLATILE
1050 || kind == BTF_KIND_RESTRICT);
1051
1052 type_base_sptr underlying_type =
1053 is_type(build_ir_node_from_btf_type(t->type));
1054 if (!underlying_type)
1055 return type_or_decl_base_sptr();
1056
1057 qualified_type_def::CV qual = qualified_type_def::CV_NONE;
1058 if (kind == BTF_KIND_CONST)
1059 qual |= qualified_type_def::CV_CONST;
1060 else if (kind == BTF_KIND_VOLATILE)
1061 qual |= qualified_type_def::CV_VOLATILE;
1062 else if (kind == BTF_KIND_RESTRICT)
1063 qual |= qualified_type_def::CV_RESTRICT;
1064 else
1066
1067 qualified_type_def_sptr result(new qualified_type_def(underlying_type,
1068 qual, location()));
1069 return result;
1070 }
1071
1072 /// Build an IR node for a class or union type expressed in BTF.
1073 ///
1074 /// @param type_id the ID of a pointer to a BTF type describing a
1075 /// class or union type.
1076 ///
1077 /// @return a pointer to either a @ref class_decl or a @ref
1078 /// union_decl type representing the type expressed by @p t.
1080 build_class_or_union_type(int type_id)
1081 {
1082 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1083
1084 int kind = btf_kind(t);
1085 ABG_ASSERT(kind == BTF_KIND_STRUCT
1086 || kind == BTF_KIND_UNION
1087 || kind == BTF_KIND_FWD);
1088
1089 string type_name;
1090 if (t->name_off)
1091 type_name = btf_offset_to_string(btf_handle(), t->name_off);
1092
1093 bool is_anonymous = type_name.empty();
1094 uint64_t size = t->size;
1095 size *= 8;
1096
1097 bool is_decl_only = (kind == BTF_KIND_FWD);
1098
1099 class_or_union_sptr result;
1100 if (kind == BTF_KIND_STRUCT
1101 || (kind == BTF_KIND_FWD
1102 && BTF_INFO_KFLAG(t->info) == 0 /*struct*/))
1103 result.reset(new class_decl(env(), type_name, size,
1104 /*alignment=*/0,
1105 /*is_struct=*/true,
1106 location(),
1107 decl_base::VISIBILITY_DEFAULT,
1108 is_anonymous));
1109 else if (kind == BTF_KIND_UNION
1110 || (kind == BTF_KIND_FWD
1111 && BTF_INFO_KFLAG(t->info) == 1/*union*/))
1112 result.reset(new union_decl(env(), type_name, size, location(),
1113 decl_base::VISIBILITY_DEFAULT,
1114 is_anonymous));
1115 else
1117
1118 if (is_decl_only)
1119 result->set_is_declaration_only(is_decl_only);
1120
1121 add_decl_to_scope(result, cur_tu()->get_global_scope());
1122
1123 associate_artifact_to_btf_type(result, t);
1124
1125 // For defined classes and unions, add data members to the type
1126 // being built.
1127 if (!is_decl_only)
1128 {
1129 const struct btf_member *m =
1130 reinterpret_cast<const struct btf_member*>(t + 1);
1131 uint64_t nb_members = btf_vlen(t);
1132
1133 for (uint64_t i = 0; i < nb_members; ++i, ++m)
1134 {
1135 type_base_sptr member_type =
1136 is_type(build_ir_node_from_btf_type(m->type));
1137 if (!member_type)
1138 continue;
1139
1140 string member_name;
1141 if (m->name_off)
1142 member_name = btf_offset_to_string(btf_handle(), m->name_off);
1143 var_decl_sptr data_member(new var_decl(member_name,
1144 member_type,
1145 location(),
1146 /*linkage_name=*/""));
1147 uint64_t offset_in_bits =
1148 BTF_INFO_KFLAG(t->info)
1149 ? BTF_MEMBER_BIT_OFFSET(m->offset)
1150 : m->offset;
1151
1152 result->add_data_member(data_member,
1153 public_access,
1154 /*is_laid_out=*/true,
1155 /*is_static=*/false,
1156 offset_in_bits);
1157 }
1158 }
1159 return result;
1160 }
1161
1162 /// Build an IR node for a function type expressed in BTF.
1163 ///
1164 /// @param type_id the ID of a pointer to a BTF type describing a
1165 /// function type.
1166 ///
1167 /// @return a pointer to a @ref function_type representing the
1168 /// function type expressed by @p t.
1170 build_function_type(int type_id)
1171 {
1172 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1173 int kind = btf_kind(t);
1174 ABG_ASSERT(kind == BTF_KIND_FUNC_PROTO);
1175
1176 type_base_sptr return_type = is_type(build_ir_node_from_btf_type(t->type));
1177 if (return_type == nullptr)
1178 return type_or_decl_base_sptr();
1179
1180 int address_size = elf_helpers::get_architecture_word_size(elf_handle());
1181 address_size *= 8;
1182 function_type_sptr result(new function_type(env(), address_size,
1183 /*alignment=*/0));
1184 result->set_return_type(return_type);
1185
1186 associate_artifact_to_btf_type(result, t);
1187
1188 uint16_t nb_parms = btf_vlen(t);
1189 const struct btf_param* parm =
1190 reinterpret_cast<const struct btf_param*>(t + 1);
1191
1192 function_decl::parameters function_parms;
1193 for (uint16_t i = 0; i < nb_parms; ++i, ++parm)
1194 {
1195 type_base_sptr parm_type;
1196 string parm_name;
1197 bool is_variadic = false;
1198
1199 if (parm->name_off == 0 && parm->type == 0)
1200 {
1201 is_variadic = true;
1202 parm_type = build_ir_node_for_variadic_parameter_type();
1203 }
1204 else
1205 {
1206 parm_name = btf_offset_to_string(btf_handle(), parm->name_off);
1207 parm_type = is_type(build_ir_node_from_btf_type(parm->type));
1208 }
1209
1210 if (!parm_type)
1211 continue;
1212
1214 (new function_decl::parameter(parm_type, parm_name,
1215 location(), is_variadic));
1216 function_parms.push_back(p);
1217 }
1218 result->set_parameters(function_parms);
1219
1220 cur_tu()->bind_function_type_life_time(result);
1221
1222 return result;
1223 }
1224
1225 /// Build an IR node for a function declaration expressed in BTF.
1226 ///
1227 /// @param type_id the ID of a pointer to a BTF "type" which realy
1228 /// describes a function declaration.
1229 ///
1230 /// @return a pointer to a @ref function_decl representing the
1231 /// function declaration expressed by @p t.
1233 build_function_decl(int type_id)
1234 {
1235 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1236 int kind = btf_kind(t);
1237 ABG_ASSERT(kind == BTF_KIND_FUNC);
1238
1239 function_decl_sptr result;
1240
1241 string fn_name = btf_offset_to_string(btf_handle(), t->name_off);
1242
1243 type_base_sptr fn_type = is_type(build_ir_node_from_btf_type(t->type));
1244 if (!fn_type)
1245 return result;
1246
1247 result.reset(new function_decl(fn_name, fn_type, /*is_inline=*/false,
1248 location(), /*linkage_name=*/fn_name));
1249
1250 elf_symbol_sptr fn_sym;
1251 if ((fn_sym = function_symbol_is_exported(fn_name))
1252 || (fn_sym = function_symbol_is_undefined(fn_name)))
1253 {
1254 result->set_symbol(fn_sym);
1255 if (fn_sym->is_defined())
1256 result->set_is_in_public_symbol_table(true);
1257 }
1258 return result;
1259 }
1260
1261 /// Build an IR node for a variable declaration expressed in BTF.
1262 ///
1263 /// @param t a pointer to a BTF "type" describing a variable
1264 /// declaration.
1265 ///
1266 /// @return a pointer to @ref var_decl representing the variable
1267 /// declaration expressed by @p t.
1269 build_variable_decl(int type_id)
1270 {
1271 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1272 int kind = btf_kind(t);
1273 ABG_ASSERT(kind == BTF_KIND_VAR);
1274
1275 var_decl_sptr result;
1276
1277 string var_name = btf_offset_to_string(btf_handle(), t->name_off);
1278
1279 type_base_sptr var_type = is_type(build_ir_node_from_btf_type(t->type));
1280 if (!var_type)
1281 return result;
1282
1283 result.reset(new var_decl(var_name, var_type, location(),
1284 /*linkage_name=*/var_name));
1285
1286 elf_symbol_sptr var_sym;
1287 if ((var_sym = variable_symbol_is_exported(var_name))
1288 || (var_sym = variable_symbol_is_undefined(var_name)))
1289 {
1290 result->set_symbol(var_sym);
1291 if (var_sym->is_defined())
1292 result->set_is_in_public_symbol_table(true);
1293 }
1294 return result;
1295 }
1296
1297}; // end class reader.
1298
1299/// Create and return a BTF reader (or front-end) which is an instance
1300/// of @ref btf::reader.
1301///
1302/// @param elf_path the path to the path to the elf file the reader is
1303/// to be used for.
1304///
1305/// @param debug_info_root_paths a vector to the paths to the
1306/// directories under which the debug info is to be found for @p
1307/// elf_path. Pass an empty vector if th debug info is not in a split
1308/// file.
1309///
1310/// @param environment the environment used by the current context.
1311/// This environment contains resources needed by the BTF reader and
1312/// by the types and declarations that are to be created later. Note
1313/// that ABI artifacts that are to be compared all need to be created
1314/// within the same environment.
1315///
1316/// Please also note that the life time of this environment object
1317/// must be greater than the life time of the resulting @ref
1318/// reader the context uses resources that are allocated in the
1319/// environment.
1320///
1321/// @param load_all_types if set to false only the types that are
1322/// reachable from publicly exported declarations (of functions and
1323/// variables) are read. If set to true then all types found in the
1324/// debug information are loaded.
1325///
1326/// @param linux_kernel_mode if set to true, then consider the special
1327/// linux kernel symbol tables when determining if a symbol is
1328/// exported or not.
1329///
1330/// @return a smart pointer to the resulting btf::reader.
1331elf_based_reader_sptr
1332create_reader(const std::string& elf_path,
1333 const vector<char**>& debug_info_root_paths,
1334 environment& env,
1335 bool load_all_types,
1336 bool linux_kernel_mode)
1337{
1338 reader_sptr rdr = reader::create(elf_path, debug_info_root_paths, env,
1339 load_all_types, linux_kernel_mode);
1340 return rdr;
1341}
1342
1343} // end namespace btf
1344} // end namespace abigail
1345
1346#endif //WITH_BTF
This file contains the declarations of the front-end to analyze the BTF information contained in an E...
This contains a set of ELF utilities used by the dwarf reader.
#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:1737
This contains the private implementation of the suppression engine of libabigail.
Types of the main internal representation of libabigail.
#define ABG_ASSERT_NOT_REACHED
A macro that expands to aborting the program when executed.
virtual ir::corpus_sptr read_corpus(status &status)
Read the ELF information associated to the current ELF file and construct an ABI representation from ...
virtual void initialize(const std::string &elf_path, const vector< char ** > &debug_info_root_paths)
(re)Initialize) the resources used by the current reader.
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
origin
This abstracts where the corpus comes from. That is, either it has been read from the native xml form...
Definition: abg-corpus.h:51
void set_naming_typedef(const typedef_decl_sptr &)
Set the naming typedef of the current instance of decl_base.
Definition: abg-ir.cc:4733
std::vector< enumerator > enumerators
Convenience typedef for a list of enumerator.
Definition: abg-ir.h:2801
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3187
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3190
CV
Bit field values representing the cv qualifiers of the underlying type.
Definition: abg-ir.h:2255
elf_based_reader_sptr create_reader(const std::string &elf_path, const vector< char ** > &debug_info_root_paths, environment &env, bool load_all_types=false, bool linux_kernel_mode=false)
Create and return a BTF reader (or front-end) which is an instance of btf::reader.
shared_ptr< function_decl > function_decl_sptr
Convenience typedef for a shared pointer on a function_decl.
Definition: abg-fwd.h:269
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10765
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition: abg-ir.h:926
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
bool is_anonymous_type(const type_base *t)
Test whether a declaration is a type.
Definition: abg-ir.cc:10816
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:11322
void canonicalize_types(const input_iterator &begin, const input_iterator &end, deref_lambda deref, bool do_log=false, bool show_stats=false)
Compute the canonical type for all the IR types of the system.
Definition: abg-ir-priv.h:1461
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
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:11041
const global_scope * get_global_scope(const decl_base &decl)
return the global scope as seen by a given declaration.
Definition: abg-ir.cc:8543
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:256
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
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.
Definition: abg-ir-priv.h:1523
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
var_decl * is_var_decl(const type_or_decl_base *tod)
Tests if a declaration is a variable declaration.
Definition: abg-ir.cc:11985
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10705
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:8450
string build_internal_underlying_enum_type_name(const string &base_name, bool is_anonymous, uint64_t size)
Build the internal name of the underlying type of an enum.
Definition: abg-ir.cc:29019
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 decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition: abg-ir.cc:10229
shared_ptr< type_decl > type_decl_sptr
Convenience typedef for a shared pointer on a type_decl.
Definition: abg-fwd.h:161
function_decl * is_function_decl(const type_or_decl_base *d)
Test whether a declaration is a function_decl.
Definition: abg-ir.cc:10653
void initialize()
This function needs to be called before any libabigail function.
Toplevel namespace for libabigail.