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>
25 ABG_BEGIN_EXPORT_DECLARATIONS
26 
27 #include "abg-btf-reader.h"
28 #include "abg-ir.h"
29 #include "abg-tools-utils.h"
30 
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*
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*
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.
116  const translation_unit_sptr&
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 
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
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 
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
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.
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
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  {
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:
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();
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
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
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.
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_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.
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
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.
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
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.
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 
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.
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.
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
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
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:8396
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10469
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition: abg-fwd.h:205
#define ABG_ASSERT_NOT_REACHED
A macro that expands to aborting the program when executed.
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:246
const global_scope * get_global_scope(const decl_base &decl)
return the global scope as seen by a given declaration.
Definition: abg-ir.cc:8489
virtual ir::corpus_sptr read_corpus(status &status)
Read the ELF information associated to the current ELF file and construct an ABI representation from ...
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:10883
shared_ptr< translation_unit > translation_unit_sptr
Convenience typedef for a shared pointer on a translation_unit type.
Definition: abg-fwd.h:134
shared_ptr< typedef_decl > typedef_decl_sptr
Convenience typedef for a shared pointer on a typedef_decl.
Definition: abg-fwd.h:161
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:27619
var_decl * is_var_decl(const type_or_decl_base *tod)
Tests if a declaration is a variable declaration.
Definition: abg-ir.cc:11368
std::vector< enumerator > enumerators
Convenience typedef for a list of enumerator.
Definition: abg-ir.h:2699
type_base_sptr canonicalize(type_base_sptr t)
Compute the canonical type of a given type.
Definition: abg-ir.cc:15326
Toplevel namespace for libabigail.
shared_ptr< function_decl > function_decl_sptr
Convenience typedef for a shared pointer on a function_decl.
Definition: abg-fwd.h:263
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10409
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:10683
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3074
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3067
virtual void initialize(const std::string &elf_path, const vector< char ** > &debug_info_root_paths)
(re)Initialize) the resources used by the current reader.
origin
This abstracts where the corpus comes from. That is, either it has been read from the native xml form...
Definition: abg-corpus.h:44
This contains the private implementation of the suppression engine of libabigail. ...
Types of the main internal representation of libabigail.
const decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition: abg-ir.cc:10102
void initialize()
This function needs to be called before any libabigail function.
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:119
shared_ptr< type_decl > type_decl_sptr
Convenience typedef for a shared pointer on a type_decl.
Definition: abg-fwd.h:156
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition: abg-ir.h:872
#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:1659
function_decl * is_function_decl(const type_or_decl_base *d)
Test whether a declaration is a function_decl.
Definition: abg-ir.cc:10357
bool is_anonymous_type(const type_base *t)
Test whether a declaration is a type.
Definition: abg-ir.cc:10520
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
Definition: abg-fwd.h:169
void set_naming_typedef(const typedef_decl_sptr &)
Set the naming typedef of the current instance of decl_base.
Definition: abg-ir.cc:4882
This contains a set of ELF utilities used by the dwarf reader.
std::vector< subrange_sptr > subranges_type
Convenience typedef for a vector of subrange_sptr.
Definition: abg-ir.h:2476
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
This file contains the declarations of the front-end to analyze the BTF information contained in an E...
shared_ptr< subrange_type > subrange_sptr
Convenience typedef for a shared pointer on a function_decl::subrange.
Definition: abg-ir.h:2469
shared_ptr< array_type_def > array_type_def_sptr
Convenience typedef for a shared pointer on a array_type_def.
Definition: abg-fwd.h:234
shared_ptr< pointer_type_def > pointer_type_def_sptr
Convenience typedef for a shared pointer on a pointer_type_def.
Definition: abg-fwd.h:220
CV
Bit field values representing the cv qualifiers of the underlying type.
Definition: abg-ir.h:2231