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>
25 ABG_BEGIN_EXPORT_DECLARATIONS
26
27 #include "abg-btf-reader.h"
28 #include "abg-ir.h"
29 #include "abg-tools-utils.h"
30
31 ABG_END_EXPORT_DECLARATIONS
32 // </headers defining libabigail's API>
33
34 namespace abigail
35 {
36 using namespace ir;
37
38 namespace btf
39 {
40
41 class reader;
42
43 /// A convenience typedef for a shared pointer to
44 /// abigail::btf::reader.
45 typedef shared_ptr<reader> reader_sptr;
46
47 static const char*
btf_offset_to_string(const::btf * btf,uint32_t offset)48 btf_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.
57 typedef std::unordered_map<int, type_or_decl_base_sptr>
58 btf_type_id_to_abi_artifact_map_type;
59
60 /// The BTF front-end abstraction type.
61 class reader : public elf_based_reader
62 {
63 ::btf* btf_handle_ = nullptr;
64 translation_unit_sptr cur_tu_;
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*
btf_handle()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&
env()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&
env() const95 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.
105 translation_unit_sptr&
cur_tu()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.
116 const translation_unit_sptr&
cur_tu() const117 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
cur_tu(const translation_unit_sptr & tu)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&
btf_type_id_to_artifacts()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&
btf_type_id_to_artifacts() const146 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.
156 type_or_decl_base_sptr
lookup_artifact_from_btf_id(int btf_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
associate_artifact_to_btf_type_id(const type_or_decl_base_sptr & artifact,int btf_type_id)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
schedule_type_for_canonocalization(const type_base_sptr & t)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
canonicalize_types()187 canonicalize_types()
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
nr_btf_types() const196 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
208 ABG_ASSERT_NOT_REACHED;
209 return 0;
210 #endif
211
212 return GET_NB_TYPES(const_cast<reader*>(this)->btf_handle());
213 }
214
215 protected:
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
initialize(const string & elf_path,const vector<char ** > & debug_info_root_paths,bool load_all_types,bool linux_kernel_mode)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.
reader(const string & elf_path,const vector<char ** > & debug_info_root_paths,environment & environment,bool load_all_types,bool linux_kernel_mode)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
274 public:
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
create(const string & elf_path,const vector<char ** > & debug_info_root_paths,environment & environment,bool load_all_types,bool linux_kernel_mode)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.
~reader()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
read_corpus(status & status)316 read_corpus(status& status)
317 {
318 // Read the properties of the ELF file.
319 elf::reader::read_corpus(status);
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
read_debug_info_into_corpus()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
399 canonicalize_types();
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.
410 type_or_decl_base_sptr
build_ir_node_from_btf_type(int type_id)411 build_ir_node_from_btf_type(int type_id)
412 {
413 type_or_decl_base_sptr result;
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:
494 ABG_ASSERT_NOT_REACHED;
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
build_ir_node_for_void_type()524 build_ir_node_for_void_type()
525 {
526 type_base_sptr t = env().get_void_type();
527 add_decl_to_scope(is_decl(t), cur_tu()->get_global_scope());
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
build_ir_node_for_void_pointer_type()536 build_ir_node_for_void_pointer_type()
537 {
538 type_base_sptr t = env().get_void_pointer_type();
539 add_decl_to_scope(is_decl(t), cur_tu()->get_global_scope());
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
build_ir_node_for_variadic_parameter_type()548 build_ir_node_for_variadic_parameter_type()
549 {
550 type_base_sptr t = env().get_variadic_parameter_type();
551 add_decl_to_scope(is_decl(t), cur_tu()->get_global_scope());
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.
563 type_or_decl_base_sptr
build_int_type(int type_id)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.
605 type_or_decl_base_sptr
build_float_type(int type_id)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.
633 type_decl_sptr
build_enum_underlying_type(const string enum_name,uint64_t enum_size,bool is_anonymous=true)634 build_enum_underlying_type(const string enum_name, uint64_t enum_size,
635 bool is_anonymous = true)
636 {
637 string underlying_type_name =
638 build_internal_underlying_enum_type_name(enum_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.
655 type_or_decl_base_sptr
build_enum_type(int type_id)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);
674 enum_type_decl::enumerators enms;
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
702 ABG_ASSERT_NOT_REACHED;
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.
719 type_or_decl_base_sptr
build_typedef_type(int type_id)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.
748 type_or_decl_base_sptr
build_pointer_type(int type_id)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.
778 type_or_decl_base_sptr
build_array_type(int type_id)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_boud = 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_boud, upper_bound,
799 location()));
800 add_decl_to_scope(subrange, cur_tu()->get_global_scope());
801 canonicalize(subrange);
802 array_type_def::subranges_type subranges = {subrange};
803 array_type_def_sptr result(new array_type_def(underlying_type,
804 subranges, location()));
805
806 return result;
807 }
808
809 /// Build an IR node representing a qualified type described in BTF.
810 ///
811 /// @param type_id the ID of the BTF representation of an array
812 /// type.
813 ///
814 /// @return a pointer to a qualified_type_def representing @ t.
815 type_or_decl_base_sptr
build_qualified_type(int type_id)816 build_qualified_type(int type_id)
817 {
818 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
819 int kind = btf_kind(t);
820 ABG_ASSERT(kind == BTF_KIND_CONST
821 || kind == BTF_KIND_VOLATILE
822 || kind == BTF_KIND_RESTRICT);
823
824 type_base_sptr underlying_type =
825 is_type(build_ir_node_from_btf_type(t->type));
826 if (!underlying_type)
827 return type_or_decl_base_sptr();
828
829 qualified_type_def::CV qual = qualified_type_def::CV_NONE;
830 if (kind == BTF_KIND_CONST)
831 qual |= qualified_type_def::CV_CONST;
832 else if (kind == BTF_KIND_VOLATILE)
833 qual |= qualified_type_def::CV_VOLATILE;
834 else if (kind == BTF_KIND_RESTRICT)
835 qual |= qualified_type_def::CV_RESTRICT;
836 else
837 ABG_ASSERT_NOT_REACHED;
838
839 qualified_type_def_sptr result(new qualified_type_def(underlying_type,
840 qual, location()));
841 return result;
842 }
843
844 /// Build an IR node for a class or union type expressed in BTF.
845 ///
846 /// @param type_id the ID of a pointer to a BTF type describing a
847 /// class or union type.
848 ///
849 /// @return a pointer to either a @ref class_decl or a @ref
850 /// union_decl type representing the type expressed by @p t.
851 type_or_decl_base_sptr
build_class_or_union_type(int type_id)852 build_class_or_union_type(int type_id)
853 {
854 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
855
856 int kind = btf_kind(t);
857 ABG_ASSERT(kind == BTF_KIND_STRUCT
858 || kind == BTF_KIND_UNION
859 || kind == BTF_KIND_FWD);
860
861 string type_name;
862 if (t->name_off)
863 type_name = btf_offset_to_string(btf_handle(), t->name_off);
864
865 bool is_anonymous = type_name.empty();
866 uint64_t size = t->size;
867 size *= 8;
868
869 bool is_decl_only = (kind == BTF_KIND_FWD);
870
871 class_or_union_sptr result;
872 if (kind == BTF_KIND_STRUCT
873 || (kind == BTF_KIND_FWD
874 && BTF_INFO_KFLAG(t->info) == 0 /*struct*/))
875 result.reset(new class_decl(env(), type_name, size,
876 /*alignment=*/0,
877 /*is_struct=*/true,
878 location(),
879 decl_base::VISIBILITY_DEFAULT,
880 is_anonymous));
881 else if (kind == BTF_KIND_UNION
882 || (kind == BTF_KIND_FWD
883 && BTF_INFO_KFLAG(t->info) == 1/*union*/))
884 result.reset(new union_decl(env(), type_name, size, location(),
885 decl_base::VISIBILITY_DEFAULT,
886 is_anonymous));
887 else
888 ABG_ASSERT_NOT_REACHED;
889
890 if (is_decl_only)
891 result->set_is_declaration_only(is_decl_only);
892
893 add_decl_to_scope(result, cur_tu()->get_global_scope());
894
895 associate_artifact_to_btf_type_id(result, type_id);
896
897 // For defined classes and unions, add data members to the type
898 // being built.
899 if (!is_decl_only)
900 {
901 const struct btf_member *m =
902 reinterpret_cast<const struct btf_member*>(t + 1);
903 uint64_t nb_members = btf_vlen(t);
904
905 for (uint64_t i = 0; i < nb_members; ++i, ++m)
906 {
907 type_base_sptr member_type =
908 is_type(build_ir_node_from_btf_type(m->type));
909 if (!member_type)
910 continue;
911
912 string member_name;
913 if (m->name_off)
914 member_name = btf_offset_to_string(btf_handle(), m->name_off);
915 var_decl_sptr data_member(new var_decl(member_name,
916 member_type,
917 location(),
918 /*linkage_name=*/""));
919 uint64_t offset_in_bits =
920 BTF_INFO_KFLAG(t->info)
921 ? BTF_MEMBER_BIT_OFFSET(m->offset)
922 : m->offset;
923
924 result->add_data_member(data_member,
925 public_access,
926 /*is_laid_out=*/true,
927 /*is_static=*/false,
928 offset_in_bits);
929 }
930 }
931 return result;
932 }
933
934 /// Build an IR node for a function type expressed in BTF.
935 ///
936 /// @param type_id the ID of a pointer to a BTF type describing a
937 /// function type.
938 ///
939 /// @return a pointer to a @ref function_type representing the
940 /// function type expressed by @p t.
941 type_or_decl_base_sptr
build_function_type(int type_id)942 build_function_type(int type_id)
943 {
944 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
945 int kind = btf_kind(t);
946 ABG_ASSERT(kind == BTF_KIND_FUNC_PROTO);
947
948 type_base_sptr return_type = is_type(build_ir_node_from_btf_type(t->type));
949 if (return_type == nullptr)
950 return type_or_decl_base_sptr();
951
952 int address_size = elf_helpers::get_architecture_word_size(elf_handle());
953 address_size *= 8;
954 function_type_sptr result(new function_type(env(), address_size,
955 /*alignment=*/0));
956 result->set_return_type(return_type);
957
958 associate_artifact_to_btf_type_id(result, type_id);
959
960 uint16_t nb_parms = btf_vlen(t);
961 const struct btf_param* parm =
962 reinterpret_cast<const struct btf_param*>(t + 1);
963
964 function_decl::parameters function_parms;
965 for (uint16_t i = 0; i < nb_parms; ++i, ++parm)
966 {
967 type_base_sptr parm_type;
968 string parm_name;
969 bool is_variadic = false;
970
971 if (parm->name_off == 0 && parm->type == 0)
972 {
973 is_variadic = true;
974 parm_type = build_ir_node_for_variadic_parameter_type();
975 }
976 else
977 {
978 parm_name = btf_offset_to_string(btf_handle(), parm->name_off);
979 parm_type = is_type(build_ir_node_from_btf_type(parm->type));
980 }
981
982 if (!parm_type)
983 continue;
984
985 function_decl::parameter_sptr p
986 (new function_decl::parameter(parm_type, parm_name,
987 location(), is_variadic));
988 function_parms.push_back(p);
989 }
990 result->set_parameters(function_parms);
991
992 cur_tu()->bind_function_type_life_time(result);
993
994 return result;
995 }
996
997 /// Build an IR node for a function declaration expressed in BTF.
998 ///
999 /// @param type_id the ID of a pointer to a BTF "type" which realy
1000 /// describes a function declaration.
1001 ///
1002 /// @return a pointer to a @ref function_decl representing the
1003 /// function declaration expressed by @p t.
1004 type_or_decl_base_sptr
build_function_decl(int type_id)1005 build_function_decl(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_FUNC);
1010
1011 function_decl_sptr result;
1012
1013 string fn_name = btf_offset_to_string(btf_handle(), t->name_off);
1014
1015 type_base_sptr fn_type = is_type(build_ir_node_from_btf_type(t->type));
1016 if (!fn_type)
1017 return result;
1018
1019 result.reset(new function_decl(fn_name, fn_type, /*is_inline=*/false,
1020 location(), /*linkage_name=*/fn_name));
1021
1022 elf_symbol_sptr fn_sym;
1023 if ((fn_sym = function_symbol_is_exported(fn_name)))
1024 {
1025 result->set_symbol(fn_sym);
1026 result->set_is_in_public_symbol_table(true);
1027 }
1028 return result;
1029 }
1030
1031 /// Build an IR node for a variable declaration expressed in BTF.
1032 ///
1033 /// @param t a pointer to a BTF "type" describing a variable
1034 /// declaration.
1035 ///
1036 /// @return a pointer to @ref var_decl representing the variable
1037 /// declaration expressed by @p t.
1038 type_or_decl_base_sptr
build_variable_decl(int type_id)1039 build_variable_decl(int type_id)
1040 {
1041 const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1042 int kind = btf_kind(t);
1043 ABG_ASSERT(kind == BTF_KIND_VAR);
1044
1045 var_decl_sptr result;
1046
1047 string var_name = btf_offset_to_string(btf_handle(), t->name_off);
1048
1049 type_base_sptr var_type = is_type(build_ir_node_from_btf_type(t->type));
1050 if (!var_type)
1051 return result;
1052
1053 result.reset(new var_decl(var_name, var_type, location(),
1054 /*linkage_name=*/var_name));
1055
1056 elf_symbol_sptr var_sym;
1057 if ((var_sym = variable_symbol_is_exported(var_name)))
1058 {
1059 result->set_symbol(var_sym);
1060 result->set_is_in_public_symbol_table(true);
1061 }
1062 return result;
1063 }
1064
1065 }; // end class reader.
1066
1067 /// Create and return a BTF reader (or front-end) which is an instance
1068 /// of @ref btf::reader.
1069 ///
1070 /// @param elf_path the path to the path to the elf file the reader is
1071 /// to be used for.
1072 ///
1073 /// @param debug_info_root_paths a vector to the paths to the
1074 /// directories under which the debug info is to be found for @p
1075 /// elf_path. Pass an empty vector if th debug info is not in a split
1076 /// file.
1077 ///
1078 /// @param environment the environment used by the current context.
1079 /// This environment contains resources needed by the BTF reader and
1080 /// by the types and declarations that are to be created later. Note
1081 /// that ABI artifacts that are to be compared all need to be created
1082 /// within the same environment.
1083 ///
1084 /// Please also note that the life time of this environment object
1085 /// must be greater than the life time of the resulting @ref
1086 /// reader the context uses resources that are allocated in the
1087 /// environment.
1088 ///
1089 /// @param load_all_types if set to false only the types that are
1090 /// reachable from publicly exported declarations (of functions and
1091 /// variables) are read. If set to true then all types found in the
1092 /// debug information are loaded.
1093 ///
1094 /// @param linux_kernel_mode if set to true, then consider the special
1095 /// linux kernel symbol tables when determining if a symbol is
1096 /// exported or not.
1097 ///
1098 /// @return a smart pointer to the resulting btf::reader.
1099 elf_based_reader_sptr
create_reader(const std::string & elf_path,const vector<char ** > & debug_info_root_paths,environment & env,bool load_all_types,bool linux_kernel_mode)1100 create_reader(const std::string& elf_path,
1101 const vector<char**>& debug_info_root_paths,
1102 environment& env,
1103 bool load_all_types,
1104 bool linux_kernel_mode)
1105 {
1106 reader_sptr rdr = reader::create(elf_path, debug_info_root_paths, env,
1107 load_all_types, linux_kernel_mode);
1108 return rdr;
1109 }
1110
1111 } // end namespace btf
1112 } // end namespace abigail
1113
1114 #endif //WITH_BTF
1115