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