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-2024 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 id to a
57/// libabigail ABI artifact.
58typedef std::unordered_map<int, type_or_decl_base_sptr>
59btf_type_id_to_abi_artifact_map_type;
60
61/// The BTF front-end abstraction type.
62class reader : public elf_based_reader
63{
64 ::btf* btf_handle_ = nullptr;
66 vector<type_base_sptr> types_to_canonicalize_;
67 btf_type_id_to_abi_artifact_map_type btf_type_id_to_artifacts_;
68
69 /// Getter of the handle to the BTF data as returned by libbpf.
70 ///
71 /// @return the handle to the BTF data as returned by libbpf.
72 ::btf*
73 btf_handle()
74 {
75 if (btf_handle_ == nullptr)
76 {
77 btf_handle_ = btf__parse(corpus_path().c_str(), nullptr);
78 if (!btf_handle_)
79 std::cerr << "Could not parse BTF information from file '"
80 << corpus_path().c_str() << "'" << std::endl;
81 }
82 return btf_handle_;
83 }
84
85 /// Getter of the environment of the current front-end.
86 ///
87 /// @return The environment of the current front-end.
88 environment&
89 env()
90 {return options().env;}
91
92 /// Getter of the environment of the current front-end.
93 ///
94 /// @return The environment of the current front-end.
95 const environment&
96 env() const
97 {return const_cast<reader*>(this)->env();}
98
99 /// Getter of the current translation unit being built.
100 ///
101 /// Actually, BTF doesn't keep track of the translation unit each
102 /// ABI artifact originates from. So an "artificial" translation
103 /// unit is built. It contains all the ABI artifacts of the binary.
104 ///
105 /// @return The current translation unit being built.
107 cur_tu()
108 {return cur_tu_;}
109
110 /// Getter of the current translation unit being built.
111 ///
112 /// Actually, BTF doesn't keep track of the translation unit each
113 /// ABI artifact originates from. So an "artificial" translation
114 /// unit is built. It contains all the ABI artifacts of the binary.
115 ///
116 /// @return The current translation unit being built.
118 cur_tu() const
119 {return cur_tu_;}
120
121 /// Getter of the current translation unit being built.
122 ///
123 /// Actually, BTF doesn't keep track of the translation unit each
124 /// ABI artifact originates from. So an "artificial" translation
125 /// unit is built. It contains all the ABI artifacts of the binary.
126 ///
127 /// @return The current translation unit being built.
128 void
129 cur_tu(const translation_unit_sptr& tu)
130 {cur_tu_ = tu;}
131
132 /// Getter of the map that associates a BTF type ID to an ABI
133 /// artifact.
134 ///
135 /// @return The map that associates a BTF type ID to an ABI
136 /// artifact.
137 btf_type_id_to_abi_artifact_map_type&
138 btf_type_id_to_artifacts()
139 {return btf_type_id_to_artifacts_;}
140
141 /// Getter of the map that associates a BTF type ID to an ABI
142 /// artifact.
143 ///
144 /// @return The map that associates a BTF type ID to an ABI
145 /// artifact.
146 const btf_type_id_to_abi_artifact_map_type&
147 btf_type_id_to_artifacts() const
148 {return btf_type_id_to_artifacts_;}
149
150 /// Get the ABI artifact that is associated to a given BTF type ID.
151 ///
152 /// If no ABI artifact is associated to the BTF type id, then return
153 /// nil.
154 ///
155 /// @return the ABI artifact that is associated to a given BTF type
156 /// id.
158 lookup_artifact_from_btf_id(int btf_id)
159 {
160 auto i = btf_type_id_to_artifacts().find(btf_id);
161 if (i != btf_type_id_to_artifacts().end())
162 return i->second;
163 return type_or_decl_base_sptr();
164 }
165
166 /// Associate an ABI artifact to a given BTF type ID.
167 ///
168 /// @param artifact the ABI artifact to consider.
169 ///
170 /// @param btf_type_id the BTF type ID to associate to @p artifact.
171 void
172 associate_artifact_to_btf_type_id(const type_or_decl_base_sptr& artifact,
173 int btf_type_id)
174 {btf_type_id_to_artifacts()[btf_type_id] = artifact;}
175
176 /// Schecule a type for canonicalization at the end of the debug
177 /// info loading.
178 ///
179 /// @param t the type to schedule.
180 void
181 schedule_type_for_canonocalization(const type_base_sptr& t)
182 {types_to_canonicalize_.push_back(t);}
183
184 /// Canonicalize all the types scheduled for canonicalization using
185 /// abigail::ir::canonicalize_types() which performs some sanity
186 /// checking around type canonicalization if necessary.
187 void
189 {
190 ir::canonicalize_types(types_to_canonicalize_.begin(),
191 types_to_canonicalize_.end(),
192 [](const vector<type_base_sptr>::const_iterator& i)
193 {return *i;});
194 }
195
196 uint64_t
197 nr_btf_types() const
198 {
199#ifdef WITH_BTF__GET_NR_TYPES
200#define GET_NB_TYPES btf__get_nr_types
201#endif
202
203#ifdef WITH_BTF__TYPE_CNT
204#undef GET_NB_TYPES
205#define GET_NB_TYPES btf__type_cnt
206#endif
207
208#ifndef GET_NB_TYPES
210 return 0;
211#endif
212
213 return GET_NB_TYPES(const_cast<reader*>(this)->btf_handle());
214 }
215
216protected:
217 reader() = delete;
218
219 /// Initializer of the current instance of @ref btf::reader.
220 ///
221 /// This frees the resources used by the current instance of @ref
222 /// btf::reader and gets it ready to analyze another ELF
223 /// file.
224 ///
225 /// @param elf_path the path to the ELF file to read from.
226 ///
227 /// @param debug_info_root_paths the paths where to look for
228 /// seperate debug info.
229 ///
230 /// @param load_all_types if true, then load all the types described
231 /// in the binary, rather than loading only the types reachable from
232 /// the exported decls.
233 ///
234 /// @param linux_kernel_mode
235 void
236 initialize(const string& elf_path,
237 const vector<char**>& debug_info_root_paths,
238 bool load_all_types,
239 bool linux_kernel_mode)
240 {
241 btf__free(btf_handle_);
242 btf_handle_ = nullptr;
243 elf_based_reader::initialize(elf_path, debug_info_root_paths);
244 options().load_all_types = load_all_types;
245 options().load_in_linux_kernel_mode = linux_kernel_mode;
246 }
247
248 /// Constructor of the btf::reader type.
249 ///
250 /// @param elf_path the path to the ELF file to analyze.
251 ///
252 /// @param debug_info_root_paths the set of directory where to look
253 /// debug info from, for cases where the debug is split.
254 ///
255 /// @param environment the environment of the current front-end.
256 ///
257 /// @param load_all_types if true load all the types described by
258 /// the BTF debug info, as opposed to loading only the types
259 /// reachable from the decls that are defined and exported.
260 ///
261 /// @param linux_kernel_mode if true, then consider the binary being
262 /// analyzed as a linux kernel binary.
263 reader(const string& elf_path,
264 const vector<char**>& debug_info_root_paths,
265 environment& environment,
266 bool load_all_types,
267 bool linux_kernel_mode)
268 : elf_based_reader(elf_path,
269 debug_info_root_paths,
270 environment)
271 {
272 initialize(elf_path, debug_info_root_paths,
273 load_all_types, linux_kernel_mode);
274 }
275
276public:
277
278 /// Constructor of the btf::reader type.
279 ///
280 /// @param elf_path the path to the ELF file to analyze.
281 ///
282 /// @param debug_info_root_paths the set of directory where to look
283 /// debug info from, for cases where the debug is split.
284 ///
285 /// @param environment the environment of the current front-end.
286 ///
287 /// @param load_all_types if true load all the types described by
288 /// the BTF debug info, as opposed to loading only the types
289 /// reachable from the decls that are defined and exported.
290 ///
291 /// @param linux_kernel_mode if true, then consider the binary being
292 /// analyzed as a linux kernel binary.
293 static btf::reader_sptr
294 create(const string& elf_path,
295 const vector<char**>& debug_info_root_paths,
296 environment& environment,
297 bool load_all_types,
298 bool linux_kernel_mode)
299 {
300 reader_sptr result(new reader(elf_path, debug_info_root_paths, environment,
301 load_all_types, linux_kernel_mode));
302 return result;
303 }
304
305 /// Destructor of the btf::reader type.
306 ~reader()
307 {
308 btf__free(btf_handle_);
309 btf_handle_ = nullptr;
310 }
311
312 /// Read the ELF information as well as the BTF type information to
313 /// build an ABI corpus.
314 ///
315 /// @param status output parameter. The status of the analysis.
316 ///
317 /// @return the resulting ABI corpus.
318 corpus_sptr
319 read_corpus(status& status)
320 {
321 // Read the properties of the ELF file.
323
324 corpus::origin origin = corpus()->get_origin();
325 origin |= corpus::BTF_ORIGIN;
326 corpus()->set_origin(origin);
327
328 if ((status & STATUS_NO_SYMBOLS_FOUND)
329 || !(status & STATUS_OK))
330 // Either we couldn't find ELF symbols or something went badly
331 // wrong. There is nothing we can do with this ELF file. Bail
332 // out.
333 return corpus_sptr();
334
335 if (find_btf_section() == nullptr)
336 status |= STATUS_DEBUG_INFO_NOT_FOUND;
337
338 read_debug_info_into_corpus();
339
340 status |= STATUS_OK;
341
342 return corpus();
343 }
344
345 /// Read the BTF debug info to construct the ABI corpus.
346 ///
347 /// @return the resulting ABI corpus.
348 corpus_sptr
349 read_debug_info_into_corpus()
350 {
351 if (!btf_handle())
352 return corpus_sptr();
353
354 translation_unit_sptr artificial_tu
355 (new translation_unit(env(), "", /*address_size=*/64));
356 corpus()->add(artificial_tu);
357 cur_tu(artificial_tu);
358
359 int number_of_types = nr_btf_types();
360 int first_type_id = 1;
361
362 // Let's cycle through whatever is described in the BTF section
363 // and emit libabigail IR for it.
364 for (int type_id = first_type_id;
365 type_id < number_of_types;
366 ++type_id)
367 {
368 // Build IR nodes only for decls (functions and variables)
369 // that have associated ELF symbols that are publicly defined
370 // and exported, unless the user asked to load all types.
371
372 bool do_construct_ir_node = false;
373
374 const btf_type* t = btf__type_by_id(btf_handle(), type_id);
375 string name;
376 if (t->name_off)
377 name = btf_offset_to_string(btf_handle(), t->name_off);
378
379 int kind = btf_kind(t);
380 if (kind == BTF_KIND_FUNC)
381 {
382 ABG_ASSERT(!name.empty());
383 if (btf_vlen(t) == BTF_FUNC_GLOBAL
384 || btf_vlen(t) == BTF_FUNC_EXTERN
385 || function_symbol_is_exported(name))
386 do_construct_ir_node = true;
387 }
388 else if (kind == BTF_KIND_VAR)
389 {
390 ABG_ASSERT(!name.empty());
391 if (btf_vlen(t) == BTF_VAR_GLOBAL_ALLOCATED
392 || btf_vlen(t) == BTF_VAR_GLOBAL_EXTERN
393 || variable_symbol_is_exported(name))
394 do_construct_ir_node = true;
395 }
396 else if (options().load_all_types)
397 do_construct_ir_node = true;
398
399 if (do_construct_ir_node)
400 build_ir_node_from_btf_type(type_id);
401 }
402
404 corpus()->sort_functions();
405 corpus()->sort_variables();
406 return corpus();
407 }
408
409 /// Build an abigail IR node for a given type described by a BTF
410 /// type ID. The node is added to the ABI corpus.
411 ///
412 /// @param type_id the ID of the type to build and IR node for.
413 ///
414 /// @return the IR node representing the type @p type_id.
416 build_ir_node_from_btf_type(int type_id)
417 {
419 const btf_type *t = nullptr;
420
421 if ((result = lookup_artifact_from_btf_id(type_id)))
422 return result;
423
424 if (type_id == 0)
425 result = build_ir_node_for_void_type();
426 else
427 t = btf__type_by_id(btf_handle(), type_id);
428
429 if (!result)
430 {
431 ABG_ASSERT(t);
432 int type_kind = btf_kind(t);
433
434 switch(type_kind)
435 {
436 case BTF_KIND_INT/* Integer */:
437 result = build_int_type(type_id);
438 break;
439
440 case BTF_KIND_FLOAT/* Floating point */:
441 result = build_float_type(type_id);
442 break;
443
444 case BTF_KIND_TYPEDEF/* Typedef*/:
445 result = build_typedef_type(type_id);
446 break;
447
448 case BTF_KIND_PTR/* Pointer */:
449 result = build_pointer_type(type_id);
450 break;
451
452 case BTF_KIND_ARRAY/* Array */:
453 result = build_array_type(type_id);
454 break;
455
456 case BTF_KIND_ENUM/* Enumeration up to 32-bit values */:
457#ifdef WITH_BTF_ENUM64
458 case BTF_KIND_ENUM64/* Enumeration up to 64-bit values */:
459#endif
460 result = build_enum_type(type_id);
461 break;
462
463 case BTF_KIND_STRUCT/* Struct */:
464 case BTF_KIND_UNION/* Union */:
465 result = build_class_or_union_type(type_id);
466 break;
467
468 case BTF_KIND_FWD/* Forward */:
469 result = build_class_or_union_type(type_id);
470 break;
471
472 case BTF_KIND_CONST/* Const */:
473 case BTF_KIND_VOLATILE/* Volatile */:
474 case BTF_KIND_RESTRICT/* Restrict */:
475 result = build_qualified_type(type_id);
476 break;
477
478 case BTF_KIND_FUNC/* Function */:
479 result = build_function_decl(type_id);
480 break;
481
482 case BTF_KIND_FUNC_PROTO/* Function Proto */:
483 result = build_function_type(type_id);
484 break;
485
486 case BTF_KIND_VAR/* Variable */:
487 result = build_variable_decl(type_id);
488 break;
489
490#ifdef WITH_BTF_KIND_TYPE_TAG
491 case BTF_KIND_TYPE_TAG/* Type Tag */:
492 break;
493#endif
494#ifdef WITH_BTF_KIND_DECL_TAG
495 case BTF_KIND_DECL_TAG/* Decl Tag */:
496 break;
497#endif
498 case BTF_KIND_DATASEC/* Section */:
499 break;
500 case BTF_KIND_UNKN/* Unknown */:
501 break;
502 default:
504 break;
505 }
506 }
507
508 add_decl_to_scope(is_decl(result), cur_tu()->get_global_scope());
509
510 if (type_base_sptr type = is_type(result))
511 schedule_type_for_canonocalization(type);
512
513 associate_artifact_to_btf_type_id(result, type_id);
514
515 if (function_decl_sptr fn = is_function_decl(result))
516 add_fn_to_exported_or_undefined_decls(fn.get());
517 else if (var_decl_sptr var = is_var_decl(result))
518 add_var_to_exported_or_undefined_decls(var.get());
519
520 return result;
521 }
522
523 /// Build an IR node for the "void" type.
524 ///
525 /// @return the IR node for the void type.
526 type_base_sptr
527 build_ir_node_for_void_type()
528 {
529 type_base_sptr t = env().get_void_type();
531 canonicalize(t);
532 return t;
533 }
534
535 /// Build an IR node for the "void" type.
536 ///
537 /// @return the IR node for the void type.
538 type_base_sptr
539 build_ir_node_for_void_pointer_type()
540 {
541 type_base_sptr t = env().get_void_pointer_type();
543 canonicalize(t);
544 return t;
545 }
546
547 /// Build an IR node for the "variadic parameter" type.
548 ///
549 /// @return the IR node for the "variadic parameter" type.
550 type_base_sptr
551 build_ir_node_for_variadic_parameter_type()
552 {
553 type_base_sptr t = env().get_variadic_parameter_type();
555 decl_base_sptr t_decl = get_type_declaration(t);
556 canonicalize(t);
557 return t;
558 }
559
560 /// Build an IR node for an integer type expressed in BTF.
561 ///
562 /// @param t a pointer a BTF type describing an integer.
563 ///
564 /// @return a pointer to @ref type_decl representing an integer
565 /// type.
567 build_int_type(int type_id)
568 {
569 type_decl_sptr result;
570
571 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
572 ABG_ASSERT(btf_kind(t) == BTF_KIND_INT);
573
574 uint32_t info = *reinterpret_cast<const uint32_t*>(t + 1);
575 uint64_t byte_size = 0, bit_size = 0;
576 string type_name;
577
578 byte_size = t->size;
579 bit_size = byte_size * 8;
580
581 if (BTF_INT_ENCODING(info) & BTF_INT_CHAR)
582 {
583 if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
584 type_name = "unsigned ";
585 type_name += "char";
586 }
587 else if (BTF_INT_ENCODING(info) & BTF_INT_BOOL)
588 type_name = "bool";
589 else if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
590 {
591 type_name = "unsigned ";
592 type_name += btf_offset_to_string(btf_handle(), t->name_off);
593 }
594 else
595 type_name = btf_offset_to_string(btf_handle(), t->name_off);
596
597 location loc;
598 result.reset(new type_decl(env(), type_name,
599 bit_size, /*alignment=*/0,
600 loc, type_name));
601
602 return result;
603 }
604
605 /// Build an IR node for a float type expressed in BTF.
606 ///
607 /// @return a pointer to @ref type_decl representing a float type.
609 build_float_type(int type_id)
610 {
611 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
612 ABG_ASSERT(btf_kind(t) == BTF_KIND_FLOAT);
613
614 string type_name = btf_offset_to_string(btf_handle(), t->name_off);;
615 uint64_t byte_size = t->size, bit_size = byte_size * 8;
616 location loc;
617 type_decl_sptr result(new type_decl(env(), type_name, bit_size,
618 /*alignment=*/0, loc, type_name));
619
620 return result;
621 }
622
623 /// Build an IR type that represents the underlying type of an enum type.
624 ///
625 /// This is a sub-routine of the build_enum_type() function.
626 ///
627 /// @param enum_name the name of the enum type this type is an
628 /// underlying type for.
629 ///
630 /// @param enum_size the size of the enum.
631 ///
632 /// @param is_anonymous if true, the enum type is anonymous.
633 ///
634 /// @return a pointer to type_decl that represents a integer type
635 /// that is the underlying type of an enum type.
637 build_enum_underlying_type(const string enum_name, uint64_t enum_size,
638 bool is_anonymous = true)
639 {
640 string underlying_type_name =
642 is_anonymous,
643 enum_size);
644 type_decl_sptr result(new type_decl(env(), underlying_type_name,
645 enum_size, enum_size, location()));
646 result->set_is_anonymous(is_anonymous);
647 result->set_is_artificial(true);
648 add_decl_to_scope(result, cur_tu()->get_global_scope());
649 canonicalize(result);
650 return result;
651 }
652
653 /// Build an IR node that represents an enum type expressed in BTF.
654 ///
655 /// @param type_id the ID of the BTF representation of the enum.
656 ///
657 /// @return a pointer to @ref enum_type_decl representing @p t.
659 build_enum_type(int type_id)
660 {
661 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
662 int kind = btf_kind(t);
663#ifdef WITH_BTF_ENUM64
664 ABG_ASSERT(kind == BTF_KIND_ENUM || kind == BTF_KIND_ENUM64);
665#else
666 ABG_ASSERT(kind == BTF_KIND_ENUM);
667#endif
668
669 int byte_size = t->size, bit_size = byte_size * 8;
670
671 string enum_name;
672 if (t->name_off)
673 enum_name = btf_offset_to_string(btf_handle(), t->name_off);
674 bool is_anonymous = enum_name.empty();
675
676 int num_enms = btf_vlen(t);
678 string e_name;
679 if (kind == BTF_KIND_ENUM)
680 {
681 const struct btf_enum* e = btf_enum(t);
682 uint32_t e_value = 0;
683 for (int i = 0; i < num_enms; ++i, ++e)
684 {
685 e_name = btf_offset_to_string(btf_handle(), e->name_off);
686 e_value = e->val;
687 enms.push_back(enum_type_decl::enumerator(e_name, e_value));
688 }
689 }
690#ifdef WITH_BTF_ENUM64
691 else if (kind == BTF_KIND_ENUM64)
692 {
693 const struct btf_enum64* e =
694 reinterpret_cast<const struct btf_enum64*>(t + 1);
695 uint64_t e_value = 0;
696 for (int i = 0; i < num_enms; ++i, ++e)
697 {
698 e_name = btf_offset_to_string(btf_handle(), e->name_off);
699 e_value = (static_cast<uint64_t>(e->val_hi32) << 32) | e->val_lo32;
700 enms.push_back(enum_type_decl::enumerator(e_name, e_value));
701 }
702 }
703#endif
704 else
706
707 type_decl_sptr underlying_type =
708 build_enum_underlying_type(enum_name, bit_size, is_anonymous);
709 enum_type_decl_sptr result(new enum_type_decl(enum_name,
710 location(),
711 underlying_type,
712 enms, enum_name));
713 result->set_is_anonymous(is_anonymous);
714 return result;
715 }
716
717 /// Build an IR node for a typedef that is expressed in BTF.
718 ///
719 /// @param type_id the ID of the BTF representation of a typedef.
720 ///
721 /// @return a pointer to @ref typedef_decl representing @p t.
723 build_typedef_type(int type_id)
724 {
725 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
726 int kind = btf_kind(t);
727 ABG_ASSERT(kind == BTF_KIND_TYPEDEF);
728
729 string type_name = btf_offset_to_string(btf_handle(), t->name_off);
730 type_base_sptr underlying_type =
731 is_type(build_ir_node_from_btf_type(t->type));
732 if (!underlying_type)
733 return type_or_decl_base_sptr();
734
735 typedef_decl_sptr result(new typedef_decl(type_name, underlying_type,
736 location(),
737 /*linkage_name=*/type_name));
738 if ((is_class_or_union_type(underlying_type)
739 || is_enum_type(underlying_type))
740 && is_anonymous_type(underlying_type))
741 get_type_declaration(underlying_type)->set_naming_typedef(result);
742
743 return result;
744 }
745
746 /// Build an IR node representing a pointer described in BTF.
747 ///
748 /// @param type_id the ID of a BTF representation of a pointer type.
749 ///
750 /// @return a pointer to pointer_type_def that represents @p t.
752 build_pointer_type(int type_id)
753 {
754 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
755 int kind = btf_kind(t);
756 ABG_ASSERT(kind == BTF_KIND_PTR);
757
758 type_base_sptr underlying_type =
759 is_type(build_ir_node_from_btf_type(t->type));
760 if (!underlying_type)
761 return type_or_decl_base_sptr();
762 if (env().is_void_type(underlying_type))
763 // Recognize a pointer to void and return a special unique IR
764 // for it.
765 return build_ir_node_for_void_pointer_type();
766
767 int size = elf_helpers::get_architecture_word_size(elf_handle());
768 size *= 8;
769 pointer_type_def_sptr result(new pointer_type_def(underlying_type, size,
770 /*alignment=*/0,
771 location()));
772 return result;
773 }
774
775 /// Build an IR node representing an array type described in BTF.
776 ///
777 /// @param type_id the ID of the BTF representation of an array
778 /// type.
779 ///
780 /// return a pointer to @ref array_type_def representing @p t.
782 build_array_type(int type_id)
783 {
784 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
785 int kind = btf_kind(t);
786 ABG_ASSERT(kind == BTF_KIND_ARRAY);
787
788 const struct btf_array* arr = btf_array(t);
789
790 type_base_sptr underlying_type =
791 is_type(build_ir_node_from_btf_type(arr->type));
792 if (!underlying_type)
793 return type_or_decl_base_sptr();
794
795 uint64_t lower_bound = 0;
796 // Note that arr->nelems can be 0;
797 uint64_t upper_bound = arr->nelems ? arr->nelems - 1: 0;
798
799 array_type_def::subrange_sptr subrange(new array_type_def::subrange_type
800 (env(), /*name=*/"",
801 lower_bound, upper_bound,
802 location()));
803 subrange->is_non_finite(!arr->nelems);
804 subrange->set_size_in_bits(cur_tu()->get_address_size());
805 add_decl_to_scope(subrange, cur_tu()->get_global_scope());
806 canonicalize(subrange);
807 array_type_def::subranges_type subranges = {subrange};
808 array_type_def_sptr result(new array_type_def(underlying_type,
809 subranges, location()));
810
811 return result;
812 }
813
814 /// Build an IR node representing a qualified type described in BTF.
815 ///
816 /// @param type_id the ID of the BTF representation of an array
817 /// type.
818 ///
819 /// @return a pointer to a qualified_type_def representing @ t.
821 build_qualified_type(int type_id)
822 {
823 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
824 int kind = btf_kind(t);
825 ABG_ASSERT(kind == BTF_KIND_CONST
826 || kind == BTF_KIND_VOLATILE
827 || kind == BTF_KIND_RESTRICT);
828
829 type_base_sptr underlying_type =
830 is_type(build_ir_node_from_btf_type(t->type));
831 if (!underlying_type)
832 return type_or_decl_base_sptr();
833
834 qualified_type_def::CV qual = qualified_type_def::CV_NONE;
835 if (kind == BTF_KIND_CONST)
836 qual |= qualified_type_def::CV_CONST;
837 else if (kind == BTF_KIND_VOLATILE)
838 qual |= qualified_type_def::CV_VOLATILE;
839 else if (kind == BTF_KIND_RESTRICT)
840 qual |= qualified_type_def::CV_RESTRICT;
841 else
843
844 qualified_type_def_sptr result(new qualified_type_def(underlying_type,
845 qual, location()));
846 return result;
847 }
848
849 /// Build an IR node for a class or union type expressed in BTF.
850 ///
851 /// @param type_id the ID of a pointer to a BTF type describing a
852 /// class or union type.
853 ///
854 /// @return a pointer to either a @ref class_decl or a @ref
855 /// union_decl type representing the type expressed by @p t.
857 build_class_or_union_type(int type_id)
858 {
859 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
860
861 int kind = btf_kind(t);
862 ABG_ASSERT(kind == BTF_KIND_STRUCT
863 || kind == BTF_KIND_UNION
864 || kind == BTF_KIND_FWD);
865
866 string type_name;
867 if (t->name_off)
868 type_name = btf_offset_to_string(btf_handle(), t->name_off);
869
870 bool is_anonymous = type_name.empty();
871 uint64_t size = t->size;
872 size *= 8;
873
874 bool is_decl_only = (kind == BTF_KIND_FWD);
875
876 class_or_union_sptr result;
877 if (kind == BTF_KIND_STRUCT
878 || (kind == BTF_KIND_FWD
879 && BTF_INFO_KFLAG(t->info) == 0 /*struct*/))
880 result.reset(new class_decl(env(), type_name, size,
881 /*alignment=*/0,
882 /*is_struct=*/true,
883 location(),
884 decl_base::VISIBILITY_DEFAULT,
885 is_anonymous));
886 else if (kind == BTF_KIND_UNION
887 || (kind == BTF_KIND_FWD
888 && BTF_INFO_KFLAG(t->info) == 1/*union*/))
889 result.reset(new union_decl(env(), type_name, size, location(),
890 decl_base::VISIBILITY_DEFAULT,
891 is_anonymous));
892 else
894
895 if (is_decl_only)
896 result->set_is_declaration_only(is_decl_only);
897
898 add_decl_to_scope(result, cur_tu()->get_global_scope());
899
900 associate_artifact_to_btf_type_id(result, type_id);
901
902 // For defined classes and unions, add data members to the type
903 // being built.
904 if (!is_decl_only)
905 {
906 const struct btf_member *m =
907 reinterpret_cast<const struct btf_member*>(t + 1);
908 uint64_t nb_members = btf_vlen(t);
909
910 for (uint64_t i = 0; i < nb_members; ++i, ++m)
911 {
912 type_base_sptr member_type =
913 is_type(build_ir_node_from_btf_type(m->type));
914 if (!member_type)
915 continue;
916
917 string member_name;
918 if (m->name_off)
919 member_name = btf_offset_to_string(btf_handle(), m->name_off);
920 var_decl_sptr data_member(new var_decl(member_name,
921 member_type,
922 location(),
923 /*linkage_name=*/""));
924 uint64_t offset_in_bits =
925 BTF_INFO_KFLAG(t->info)
926 ? BTF_MEMBER_BIT_OFFSET(m->offset)
927 : m->offset;
928
929 result->add_data_member(data_member,
930 public_access,
931 /*is_laid_out=*/true,
932 /*is_static=*/false,
933 offset_in_bits);
934 }
935 }
936 return result;
937 }
938
939 /// Build an IR node for a function type expressed in BTF.
940 ///
941 /// @param type_id the ID of a pointer to a BTF type describing a
942 /// function type.
943 ///
944 /// @return a pointer to a @ref function_type representing the
945 /// function type expressed by @p t.
947 build_function_type(int type_id)
948 {
949 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
950 int kind = btf_kind(t);
951 ABG_ASSERT(kind == BTF_KIND_FUNC_PROTO);
952
953 type_base_sptr return_type = is_type(build_ir_node_from_btf_type(t->type));
954 if (return_type == nullptr)
955 return type_or_decl_base_sptr();
956
957 int address_size = elf_helpers::get_architecture_word_size(elf_handle());
958 address_size *= 8;
959 function_type_sptr result(new function_type(env(), address_size,
960 /*alignment=*/0));
961 result->set_return_type(return_type);
962
963 associate_artifact_to_btf_type_id(result, type_id);
964
965 uint16_t nb_parms = btf_vlen(t);
966 const struct btf_param* parm =
967 reinterpret_cast<const struct btf_param*>(t + 1);
968
969 function_decl::parameters function_parms;
970 for (uint16_t i = 0; i < nb_parms; ++i, ++parm)
971 {
972 type_base_sptr parm_type;
973 string parm_name;
974 bool is_variadic = false;
975
976 if (parm->name_off == 0 && parm->type == 0)
977 {
978 is_variadic = true;
979 parm_type = build_ir_node_for_variadic_parameter_type();
980 }
981 else
982 {
983 parm_name = btf_offset_to_string(btf_handle(), parm->name_off);
984 parm_type = is_type(build_ir_node_from_btf_type(parm->type));
985 }
986
987 if (!parm_type)
988 continue;
989
991 (new function_decl::parameter(parm_type, parm_name,
992 location(), is_variadic));
993 function_parms.push_back(p);
994 }
995 result->set_parameters(function_parms);
996
997 cur_tu()->bind_function_type_life_time(result);
998
999 return result;
1000 }
1001
1002 /// Build an IR node for a function declaration expressed in BTF.
1003 ///
1004 /// @param type_id the ID of a pointer to a BTF "type" which realy
1005 /// describes a function declaration.
1006 ///
1007 /// @return a pointer to a @ref function_decl representing the
1008 /// function declaration expressed by @p t.
1010 build_function_decl(int type_id)
1011 {
1012 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1013 int kind = btf_kind(t);
1014 ABG_ASSERT(kind == BTF_KIND_FUNC);
1015
1016 function_decl_sptr result;
1017
1018 string fn_name = btf_offset_to_string(btf_handle(), t->name_off);
1019
1020 type_base_sptr fn_type = is_type(build_ir_node_from_btf_type(t->type));
1021 if (!fn_type)
1022 return result;
1023
1024 result.reset(new function_decl(fn_name, fn_type, /*is_inline=*/false,
1025 location(), /*linkage_name=*/fn_name));
1026
1027 elf_symbol_sptr fn_sym;
1028 if ((fn_sym = function_symbol_is_exported(fn_name))
1029 || (fn_sym = function_symbol_is_undefined(fn_name)))
1030 {
1031 result->set_symbol(fn_sym);
1032 if (fn_sym->is_defined())
1033 result->set_is_in_public_symbol_table(true);
1034 }
1035 return result;
1036 }
1037
1038 /// Build an IR node for a variable declaration expressed in BTF.
1039 ///
1040 /// @param t a pointer to a BTF "type" describing a variable
1041 /// declaration.
1042 ///
1043 /// @return a pointer to @ref var_decl representing the variable
1044 /// declaration expressed by @p t.
1046 build_variable_decl(int type_id)
1047 {
1048 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1049 int kind = btf_kind(t);
1050 ABG_ASSERT(kind == BTF_KIND_VAR);
1051
1052 var_decl_sptr result;
1053
1054 string var_name = btf_offset_to_string(btf_handle(), t->name_off);
1055
1056 type_base_sptr var_type = is_type(build_ir_node_from_btf_type(t->type));
1057 if (!var_type)
1058 return result;
1059
1060 result.reset(new var_decl(var_name, var_type, location(),
1061 /*linkage_name=*/var_name));
1062
1063 elf_symbol_sptr var_sym;
1064 if ((var_sym = variable_symbol_is_exported(var_name))
1065 || (var_sym = variable_symbol_is_undefined(var_name)))
1066 {
1067 result->set_symbol(var_sym);
1068 if (var_sym->is_defined())
1069 result->set_is_in_public_symbol_table(true);
1070 }
1071 return result;
1072 }
1073
1074}; // end class reader.
1075
1076/// Create and return a BTF reader (or front-end) which is an instance
1077/// of @ref btf::reader.
1078///
1079/// @param elf_path the path to the path to the elf file the reader is
1080/// to be used for.
1081///
1082/// @param debug_info_root_paths a vector to the paths to the
1083/// directories under which the debug info is to be found for @p
1084/// elf_path. Pass an empty vector if th debug info is not in a split
1085/// file.
1086///
1087/// @param environment the environment used by the current context.
1088/// This environment contains resources needed by the BTF reader and
1089/// by the types and declarations that are to be created later. Note
1090/// that ABI artifacts that are to be compared all need to be created
1091/// within the same environment.
1092///
1093/// Please also note that the life time of this environment object
1094/// must be greater than the life time of the resulting @ref
1095/// reader the context uses resources that are allocated in the
1096/// environment.
1097///
1098/// @param load_all_types if set to false only the types that are
1099/// reachable from publicly exported declarations (of functions and
1100/// variables) are read. If set to true then all types found in the
1101/// debug information are loaded.
1102///
1103/// @param linux_kernel_mode if set to true, then consider the special
1104/// linux kernel symbol tables when determining if a symbol is
1105/// exported or not.
1106///
1107/// @return a smart pointer to the resulting btf::reader.
1108elf_based_reader_sptr
1109create_reader(const std::string& elf_path,
1110 const vector<char**>& debug_info_root_paths,
1111 environment& env,
1112 bool load_all_types,
1113 bool linux_kernel_mode)
1114{
1115 reader_sptr rdr = reader::create(elf_path, debug_info_root_paths, env,
1116 load_all_types, linux_kernel_mode);
1117 return rdr;
1118}
1119
1120} // end namespace btf
1121} // end namespace abigail
1122
1123#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:1714
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:2537
std::vector< subrange_sptr > subranges_type
Convenience typedef for a vector of subrange_sptr.
Definition: abg-ir.h:2540
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:4718
std::vector< enumerator > enumerators
Convenience typedef for a list of enumerator.
Definition: abg-ir.h:2766
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3135
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3138
CV
Bit field values representing the cv qualifiers of the underlying type.
Definition: abg-ir.h:2245
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:270
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10410
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition: abg-ir.h:888
shared_ptr< array_type_def > array_type_def_sptr
Convenience typedef for a shared pointer on a array_type_def.
Definition: abg-fwd.h:245
bool is_anonymous_type(const type_base *t)
Test whether a declaration is a type.
Definition: abg-ir.cc:10461
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:10923
void canonicalize_types(const input_iterator &begin, const input_iterator &end, deref_lambda deref)
Compute the canonical type for all the IR types of the system.
Definition: abg-ir-priv.h:1610
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition: abg-fwd.h:211
shared_ptr< typedef_decl > typedef_decl_sptr
Convenience typedef for a shared pointer on a typedef_decl.
Definition: abg-fwd.h:168
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:10642
const global_scope * get_global_scope(const decl_base &decl)
return the global scope as seen by a given declaration.
Definition: abg-ir.cc:8462
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:257
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:121
shared_ptr< translation_unit > translation_unit_sptr
Convenience typedef for a shared pointer on a translation_unit type.
Definition: abg-fwd.h:137
type_base_sptr canonicalize(type_base_sptr t)
Compute the canonical type of a given type.
Definition: abg-ir.cc:15627
shared_ptr< pointer_type_def > pointer_type_def_sptr
Convenience typedef for a shared pointer on a pointer_type_def.
Definition: abg-fwd.h:227
var_decl * is_var_decl(const type_or_decl_base *tod)
Tests if a declaration is a variable declaration.
Definition: abg-ir.cc:11586
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10350
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:8370
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:28238
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
Definition: abg-fwd.h:176
const decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition: abg-ir.cc:10043
shared_ptr< type_decl > type_decl_sptr
Convenience typedef for a shared pointer on a type_decl.
Definition: abg-fwd.h:162
function_decl * is_function_decl(const type_or_decl_base *d)
Test whether a declaration is a function_decl.
Definition: abg-ir.cc:10298
void initialize()
This function needs to be called before any libabigail function.
Toplevel namespace for libabigail.