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  corpus()->sort_functions();
401  corpus()->sort_variables();
402  return corpus();
403  }
404 
405  /// Build an abigail IR node for a given type described by a BTF
406  /// type ID. The node is added to the ABI corpus.
407  ///
408  /// @param type_id the ID of the type to build and IR node for.
409  ///
410  /// @return the IR node representing the type @p type_id.
412  build_ir_node_from_btf_type(int type_id)
413  {
414  type_or_decl_base_sptr result;
415  const btf_type *t = nullptr;
416 
417  if ((result = lookup_artifact_from_btf_id(type_id)))
418  return result;
419 
420  if (type_id == 0)
421  result = build_ir_node_for_void_type();
422  else
423  t = btf__type_by_id(btf_handle(), type_id);
424 
425  if (!result)
426  {
427  ABG_ASSERT(t);
428  int type_kind = btf_kind(t);
429 
430  switch(type_kind)
431  {
432  case BTF_KIND_INT/* Integer */:
433  result = build_int_type(type_id);
434  break;
435 
436  case BTF_KIND_FLOAT/* Floating point */:
437  result = build_float_type(type_id);
438  break;
439 
440  case BTF_KIND_TYPEDEF/* Typedef*/:
441  result = build_typedef_type(type_id);
442  break;
443 
444  case BTF_KIND_PTR/* Pointer */:
445  result = build_pointer_type(type_id);
446  break;
447 
448  case BTF_KIND_ARRAY/* Array */:
449  result = build_array_type(type_id);
450  break;
451 
452  case BTF_KIND_ENUM/* Enumeration up to 32-bit values */:
453 #ifdef WITH_BTF_ENUM64
454  case BTF_KIND_ENUM64/* Enumeration up to 64-bit values */:
455 #endif
456  result = build_enum_type(type_id);
457  break;
458 
459  case BTF_KIND_STRUCT/* Struct */:
460  case BTF_KIND_UNION/* Union */:
461  result = build_class_or_union_type(type_id);
462  break;
463 
464  case BTF_KIND_FWD/* Forward */:
465  result = build_class_or_union_type(type_id);
466  break;
467 
468  case BTF_KIND_CONST/* Const */:
469  case BTF_KIND_VOLATILE/* Volatile */:
470  case BTF_KIND_RESTRICT/* Restrict */:
471  result = build_qualified_type(type_id);
472  break;
473 
474  case BTF_KIND_FUNC/* Function */:
475  result = build_function_decl(type_id);
476  break;
477 
478  case BTF_KIND_FUNC_PROTO/* Function Proto */:
479  result = build_function_type(type_id);
480  break;
481 
482  case BTF_KIND_VAR/* Variable */:
483  result = build_variable_decl(type_id);
484  break;
485 
486 #ifdef WITH_BTF_KIND_TYPE_TAG
487  case BTF_KIND_TYPE_TAG/* Type Tag */:
488 #endif
489 #ifdef WITH_BTF_KIND_DECL_TAG
490  case BTF_KIND_DECL_TAG/* Decl Tag */:
491 #endif
492  case BTF_KIND_DATASEC/* Section */:
493  case BTF_KIND_UNKN/* Unknown */:
494  default:
496  break;
497  }
498  }
499 
500  add_decl_to_scope(is_decl(result), cur_tu()->get_global_scope());
501 
502  if (type_base_sptr type = is_type(result))
503  schedule_type_for_canonocalization(type);
504 
505  associate_artifact_to_btf_type_id(result, type_id);
506 
507  if (function_decl_sptr fn = is_function_decl(result))
508  add_fn_to_exported_or_undefined_decls(fn.get());
509  else if (var_decl_sptr var = is_var_decl(result))
510  add_var_to_exported_or_undefined_decls(var.get());
511 
512  return result;
513  }
514 
515  /// Build an IR node for the "void" type.
516  ///
517  /// @return the IR node for the void type.
518  type_base_sptr
519  build_ir_node_for_void_type()
520  {
521  type_base_sptr t = env().get_void_type();
522  add_decl_to_scope(is_decl(t), cur_tu()->get_global_scope());
523  canonicalize(t);
524  return t;
525  }
526 
527  /// Build an IR node for the "void" type.
528  ///
529  /// @return the IR node for the void type.
530  type_base_sptr
531  build_ir_node_for_void_pointer_type()
532  {
533  type_base_sptr t = env().get_void_pointer_type();
534  add_decl_to_scope(is_decl(t), cur_tu()->get_global_scope());
535  canonicalize(t);
536  return t;
537  }
538 
539  /// Build an IR node for the "variadic parameter" type.
540  ///
541  /// @return the IR node for the "variadic parameter" type.
542  type_base_sptr
543  build_ir_node_for_variadic_parameter_type()
544  {
545  type_base_sptr t = env().get_variadic_parameter_type();
546  add_decl_to_scope(is_decl(t), cur_tu()->get_global_scope());
547  decl_base_sptr t_decl = get_type_declaration(t);
548  canonicalize(t);
549  return t;
550  }
551 
552  /// Build an IR node for an integer type expressed in BTF.
553  ///
554  /// @param t a pointer a BTF type describing an integer.
555  ///
556  /// @return a pointer to @ref type_decl representing an integer
557  /// type.
559  build_int_type(int type_id)
560  {
561  type_decl_sptr result;
562 
563  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
564  ABG_ASSERT(btf_kind(t) == BTF_KIND_INT);
565 
566  uint32_t info = *reinterpret_cast<const uint32_t*>(t + 1);
567  uint64_t byte_size = 0, bit_size = 0;
568  string type_name;
569 
570  byte_size = t->size;
571  bit_size = byte_size * 8;
572 
573  if (BTF_INT_ENCODING(info) & BTF_INT_CHAR)
574  {
575  if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
576  type_name = "unsigned ";
577  type_name += "char";
578  }
579  else if (BTF_INT_ENCODING(info) & BTF_INT_BOOL)
580  type_name = "bool";
581  else if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
582  {
583  type_name = "unsigned ";
584  type_name += btf_offset_to_string(btf_handle(), t->name_off);
585  }
586  else
587  type_name = btf_offset_to_string(btf_handle(), t->name_off);
588 
589  location loc;
590  result.reset(new type_decl(env(), type_name,
591  bit_size, /*alignment=*/0,
592  loc, type_name));
593 
594  return result;
595  }
596 
597  /// Build an IR node for a float type expressed in BTF.
598  ///
599  /// @return a pointer to @ref type_decl representing a float type.
601  build_float_type(int type_id)
602  {
603  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
604  ABG_ASSERT(btf_kind(t) == BTF_KIND_FLOAT);
605 
606  string type_name = btf_offset_to_string(btf_handle(), t->name_off);;
607  uint64_t byte_size = t->size, bit_size = byte_size * 8;
608  location loc;
609  type_decl_sptr result(new type_decl(env(), type_name, bit_size,
610  /*alignment=*/0, loc, type_name));
611 
612  return result;
613  }
614 
615  /// Build an IR type that represents the underlying type of an enum type.
616  ///
617  /// This is a sub-routine of the build_enum_type() function.
618  ///
619  /// @param enum_name the name of the enum type this type is an
620  /// underlying type for.
621  ///
622  /// @param enum_size the size of the enum.
623  ///
624  /// @param is_anonymous if true, the enum type is anonymous.
625  ///
626  /// @return a pointer to type_decl that represents a integer type
627  /// that is the underlying type of an enum type.
629  build_enum_underlying_type(const string enum_name, uint64_t enum_size,
630  bool is_anonymous = true)
631  {
632  string underlying_type_name =
634  is_anonymous,
635  enum_size);
636  type_decl_sptr result(new type_decl(env(), underlying_type_name,
637  enum_size, enum_size, location()));
638  result->set_is_anonymous(is_anonymous);
639  result->set_is_artificial(true);
640  add_decl_to_scope(result, cur_tu()->get_global_scope());
641  canonicalize(result);
642  return result;
643  }
644 
645  /// Build an IR node that represents an enum type expressed in BTF.
646  ///
647  /// @param type_id the ID of the BTF representation of the enum.
648  ///
649  /// @return a pointer to @ref enum_type_decl representing @p t.
651  build_enum_type(int type_id)
652  {
653  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
654  int kind = btf_kind(t);
655 #ifdef WITH_BTF_ENUM64
656  ABG_ASSERT(kind == BTF_KIND_ENUM || kind == BTF_KIND_ENUM64);
657 #else
658  ABG_ASSERT(kind == BTF_KIND_ENUM);
659 #endif
660 
661  int byte_size = t->size, bit_size = byte_size * 8;
662 
663  string enum_name;
664  if (t->name_off)
665  enum_name = btf_offset_to_string(btf_handle(), t->name_off);
666  bool is_anonymous = enum_name.empty();
667 
668  int num_enms = btf_vlen(t);
670  string e_name;
671  if (kind == BTF_KIND_ENUM)
672  {
673  const struct btf_enum* e = btf_enum(t);
674  uint32_t e_value = 0;
675  for (int i = 0; i < num_enms; ++i, ++e)
676  {
677  e_name = btf_offset_to_string(btf_handle(), e->name_off);
678  e_value = e->val;
679  enms.push_back(enum_type_decl::enumerator(e_name, e_value));
680  }
681  }
682 #ifdef WITH_BTF_ENUM64
683  else if (kind == BTF_KIND_ENUM64)
684  {
685  const struct btf_enum64* e =
686  reinterpret_cast<const struct btf_enum64*>(t + 1);
687  uint64_t e_value = 0;
688  for (int i = 0; i < num_enms; ++i, ++e)
689  {
690  e_name = btf_offset_to_string(btf_handle(), e->name_off);
691  e_value = (static_cast<uint64_t>(e->val_hi32) << 32) | e->val_lo32;
692  enms.push_back(enum_type_decl::enumerator(e_name, e_value));
693  }
694  }
695 #endif
696  else
698 
699  type_decl_sptr underlying_type =
700  build_enum_underlying_type(enum_name, bit_size, is_anonymous);
701  enum_type_decl_sptr result(new enum_type_decl(enum_name,
702  location(),
703  underlying_type,
704  enms, enum_name));
705  result->set_is_anonymous(is_anonymous);
706  return result;
707  }
708 
709  /// Build an IR node for a typedef that is expressed in BTF.
710  ///
711  /// @param type_id the ID of the BTF representation of a typedef.
712  ///
713  /// @return a pointer to @ref typedef_decl representing @p t.
715  build_typedef_type(int type_id)
716  {
717  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
718  int kind = btf_kind(t);
719  ABG_ASSERT(kind == BTF_KIND_TYPEDEF);
720 
721  string type_name = btf_offset_to_string(btf_handle(), t->name_off);
722  type_base_sptr underlying_type =
723  is_type(build_ir_node_from_btf_type(t->type));
724  if (!underlying_type)
725  return type_or_decl_base_sptr();
726 
727  typedef_decl_sptr result(new typedef_decl(type_name, underlying_type,
728  location(),
729  /*linkage_name=*/type_name));
730  if ((is_class_or_union_type(underlying_type)
731  || is_enum_type(underlying_type))
732  && is_anonymous_type(underlying_type))
733  get_type_declaration(underlying_type)->set_naming_typedef(result);
734 
735  return result;
736  }
737 
738  /// Build an IR node representing a pointer described in BTF.
739  ///
740  /// @param type_id the ID of a BTF representation of a pointer type.
741  ///
742  /// @return a pointer to pointer_type_def that represents @p t.
744  build_pointer_type(int type_id)
745  {
746  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
747  int kind = btf_kind(t);
748  ABG_ASSERT(kind == BTF_KIND_PTR);
749 
750  type_base_sptr underlying_type =
751  is_type(build_ir_node_from_btf_type(t->type));
752  if (!underlying_type)
753  return type_or_decl_base_sptr();
754  if (env().is_void_type(underlying_type))
755  // Recognize a pointer to void and return a special unique IR
756  // for it.
757  return build_ir_node_for_void_pointer_type();
758 
759  int size = elf_helpers::get_architecture_word_size(elf_handle());
760  size *= 8;
761  pointer_type_def_sptr result(new pointer_type_def(underlying_type, size,
762  /*alignment=*/0,
763  location()));
764  return result;
765  }
766 
767  /// Build an IR node representing an array type described in BTF.
768  ///
769  /// @param type_id the ID of the BTF representation of an array
770  /// type.
771  ///
772  /// return a pointer to @ref array_type_def representing @p t.
774  build_array_type(int type_id)
775  {
776  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
777  int kind = btf_kind(t);
778  ABG_ASSERT(kind == BTF_KIND_ARRAY);
779 
780  const struct btf_array* arr = btf_array(t);
781 
782  type_base_sptr underlying_type =
783  is_type(build_ir_node_from_btf_type(arr->type));
784  if (!underlying_type)
785  return type_or_decl_base_sptr();
786 
787  uint64_t lower_bound = 0;
788  // Note that arr->nelems can be 0;
789  uint64_t upper_bound = arr->nelems ? arr->nelems - 1: 0;
790 
791  array_type_def::subrange_sptr subrange(new array_type_def::subrange_type
792  (env(), /*name=*/"",
793  lower_bound, upper_bound,
794  location()));
795  subrange->is_non_finite(!arr->nelems);
796  add_decl_to_scope(subrange, cur_tu()->get_global_scope());
797  canonicalize(subrange);
798  array_type_def::subranges_type subranges = {subrange};
799  array_type_def_sptr result(new array_type_def(underlying_type,
800  subranges, location()));
801 
802  return result;
803  }
804 
805  /// Build an IR node representing a qualified type described in BTF.
806  ///
807  /// @param type_id the ID of the BTF representation of an array
808  /// type.
809  ///
810  /// @return a pointer to a qualified_type_def representing @ t.
812  build_qualified_type(int type_id)
813  {
814  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
815  int kind = btf_kind(t);
816  ABG_ASSERT(kind == BTF_KIND_CONST
817  || kind == BTF_KIND_VOLATILE
818  || kind == BTF_KIND_RESTRICT);
819 
820  type_base_sptr underlying_type =
821  is_type(build_ir_node_from_btf_type(t->type));
822  if (!underlying_type)
823  return type_or_decl_base_sptr();
824 
825  qualified_type_def::CV qual = qualified_type_def::CV_NONE;
826  if (kind == BTF_KIND_CONST)
827  qual |= qualified_type_def::CV_CONST;
828  else if (kind == BTF_KIND_VOLATILE)
829  qual |= qualified_type_def::CV_VOLATILE;
830  else if (kind == BTF_KIND_RESTRICT)
831  qual |= qualified_type_def::CV_RESTRICT;
832  else
834 
835  qualified_type_def_sptr result(new qualified_type_def(underlying_type,
836  qual, location()));
837  return result;
838  }
839 
840  /// Build an IR node for a class or union type expressed in BTF.
841  ///
842  /// @param type_id the ID of a pointer to a BTF type describing a
843  /// class or union type.
844  ///
845  /// @return a pointer to either a @ref class_decl or a @ref
846  /// union_decl type representing the type expressed by @p t.
848  build_class_or_union_type(int type_id)
849  {
850  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
851 
852  int kind = btf_kind(t);
853  ABG_ASSERT(kind == BTF_KIND_STRUCT
854  || kind == BTF_KIND_UNION
855  || kind == BTF_KIND_FWD);
856 
857  string type_name;
858  if (t->name_off)
859  type_name = btf_offset_to_string(btf_handle(), t->name_off);
860 
861  bool is_anonymous = type_name.empty();
862  uint64_t size = t->size;
863  size *= 8;
864 
865  bool is_decl_only = (kind == BTF_KIND_FWD);
866 
867  class_or_union_sptr result;
868  if (kind == BTF_KIND_STRUCT
869  || (kind == BTF_KIND_FWD
870  && BTF_INFO_KFLAG(t->info) == 0 /*struct*/))
871  result.reset(new class_decl(env(), type_name, size,
872  /*alignment=*/0,
873  /*is_struct=*/true,
874  location(),
875  decl_base::VISIBILITY_DEFAULT,
876  is_anonymous));
877  else if (kind == BTF_KIND_UNION
878  || (kind == BTF_KIND_FWD
879  && BTF_INFO_KFLAG(t->info) == 1/*union*/))
880  result.reset(new union_decl(env(), type_name, size, location(),
881  decl_base::VISIBILITY_DEFAULT,
882  is_anonymous));
883  else
885 
886  if (is_decl_only)
887  result->set_is_declaration_only(is_decl_only);
888 
889  add_decl_to_scope(result, cur_tu()->get_global_scope());
890 
891  associate_artifact_to_btf_type_id(result, type_id);
892 
893  // For defined classes and unions, add data members to the type
894  // being built.
895  if (!is_decl_only)
896  {
897  const struct btf_member *m =
898  reinterpret_cast<const struct btf_member*>(t + 1);
899  uint64_t nb_members = btf_vlen(t);
900 
901  for (uint64_t i = 0; i < nb_members; ++i, ++m)
902  {
903  type_base_sptr member_type =
904  is_type(build_ir_node_from_btf_type(m->type));
905  if (!member_type)
906  continue;
907 
908  string member_name;
909  if (m->name_off)
910  member_name = btf_offset_to_string(btf_handle(), m->name_off);
911  var_decl_sptr data_member(new var_decl(member_name,
912  member_type,
913  location(),
914  /*linkage_name=*/""));
915  uint64_t offset_in_bits =
916  BTF_INFO_KFLAG(t->info)
917  ? BTF_MEMBER_BIT_OFFSET(m->offset)
918  : m->offset;
919 
920  result->add_data_member(data_member,
921  public_access,
922  /*is_laid_out=*/true,
923  /*is_static=*/false,
924  offset_in_bits);
925  }
926  }
927  return result;
928  }
929 
930  /// Build an IR node for a function type expressed in BTF.
931  ///
932  /// @param type_id the ID of a pointer to a BTF type describing a
933  /// function type.
934  ///
935  /// @return a pointer to a @ref function_type representing the
936  /// function type expressed by @p t.
938  build_function_type(int type_id)
939  {
940  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
941  int kind = btf_kind(t);
942  ABG_ASSERT(kind == BTF_KIND_FUNC_PROTO);
943 
944  type_base_sptr return_type = is_type(build_ir_node_from_btf_type(t->type));
945  if (return_type == nullptr)
946  return type_or_decl_base_sptr();
947 
948  int address_size = elf_helpers::get_architecture_word_size(elf_handle());
949  address_size *= 8;
950  function_type_sptr result(new function_type(env(), address_size,
951  /*alignment=*/0));
952  result->set_return_type(return_type);
953 
954  associate_artifact_to_btf_type_id(result, type_id);
955 
956  uint16_t nb_parms = btf_vlen(t);
957  const struct btf_param* parm =
958  reinterpret_cast<const struct btf_param*>(t + 1);
959 
960  function_decl::parameters function_parms;
961  for (uint16_t i = 0; i < nb_parms; ++i, ++parm)
962  {
963  type_base_sptr parm_type;
964  string parm_name;
965  bool is_variadic = false;
966 
967  if (parm->name_off == 0 && parm->type == 0)
968  {
969  is_variadic = true;
970  parm_type = build_ir_node_for_variadic_parameter_type();
971  }
972  else
973  {
974  parm_name = btf_offset_to_string(btf_handle(), parm->name_off);
975  parm_type = is_type(build_ir_node_from_btf_type(parm->type));
976  }
977 
978  if (!parm_type)
979  continue;
980 
982  (new function_decl::parameter(parm_type, parm_name,
983  location(), is_variadic));
984  function_parms.push_back(p);
985  }
986  result->set_parameters(function_parms);
987 
988  cur_tu()->bind_function_type_life_time(result);
989 
990  return result;
991  }
992 
993  /// Build an IR node for a function declaration expressed in BTF.
994  ///
995  /// @param type_id the ID of a pointer to a BTF "type" which realy
996  /// describes a function declaration.
997  ///
998  /// @return a pointer to a @ref function_decl representing the
999  /// function declaration expressed by @p t.
1001  build_function_decl(int type_id)
1002  {
1003  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1004  int kind = btf_kind(t);
1005  ABG_ASSERT(kind == BTF_KIND_FUNC);
1006 
1007  function_decl_sptr result;
1008 
1009  string fn_name = btf_offset_to_string(btf_handle(), t->name_off);
1010 
1011  type_base_sptr fn_type = is_type(build_ir_node_from_btf_type(t->type));
1012  if (!fn_type)
1013  return result;
1014 
1015  result.reset(new function_decl(fn_name, fn_type, /*is_inline=*/false,
1016  location(), /*linkage_name=*/fn_name));
1017 
1018  elf_symbol_sptr fn_sym;
1019  if ((fn_sym = function_symbol_is_exported(fn_name))
1020  || (fn_sym = function_symbol_is_undefined(fn_name)))
1021  {
1022  result->set_symbol(fn_sym);
1023  if (fn_sym->is_defined())
1024  result->set_is_in_public_symbol_table(true);
1025  }
1026  return result;
1027  }
1028 
1029  /// Build an IR node for a variable declaration expressed in BTF.
1030  ///
1031  /// @param t a pointer to a BTF "type" describing a variable
1032  /// declaration.
1033  ///
1034  /// @return a pointer to @ref var_decl representing the variable
1035  /// declaration expressed by @p t.
1037  build_variable_decl(int type_id)
1038  {
1039  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1040  int kind = btf_kind(t);
1041  ABG_ASSERT(kind == BTF_KIND_VAR);
1042 
1043  var_decl_sptr result;
1044 
1045  string var_name = btf_offset_to_string(btf_handle(), t->name_off);
1046 
1047  type_base_sptr var_type = is_type(build_ir_node_from_btf_type(t->type));
1048  if (!var_type)
1049  return result;
1050 
1051  result.reset(new var_decl(var_name, var_type, location(),
1052  /*linkage_name=*/var_name));
1053 
1054  elf_symbol_sptr var_sym;
1055  if ((var_sym = variable_symbol_is_exported(var_name))
1056  || (var_sym = variable_symbol_is_undefined(var_name)))
1057  {
1058  result->set_symbol(var_sym);
1059  if (var_sym->is_defined())
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:8625
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10665
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition: abg-fwd.h:209
#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:254
const global_scope * get_global_scope(const decl_base &decl)
return the global scope as seen by a given declaration.
Definition: abg-ir.cc:8717
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:11178
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:165
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:28453
var_decl * is_var_decl(const type_or_decl_base *tod)
Tests if a declaration is a variable declaration.
Definition: abg-ir.cc:11841
std::vector< enumerator > enumerators
Convenience typedef for a list of enumerator.
Definition: abg-ir.h:2763
type_base_sptr canonicalize(type_base_sptr t)
Compute the canonical type of a given type.
Definition: abg-ir.cc:15880
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:267
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10605
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:10897
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3138
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3131
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:50
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:10298
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:160
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition: abg-ir.h:886
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects...
Definition: abg-fwd.h:1714
function_decl * is_function_decl(const type_or_decl_base *d)
Test whether a declaration is a function_decl.
Definition: abg-ir.cc:10553
bool is_anonymous_type(const type_base *t)
Test whether a declaration is a type.
Definition: abg-ir.cc:10716
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
Definition: abg-fwd.h:173
void set_naming_typedef(const typedef_decl_sptr &)
Set the naming typedef of the current instance of decl_base.
Definition: abg-ir.cc:4973
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:2540
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:2533
shared_ptr< array_type_def > array_type_def_sptr
Convenience typedef for a shared pointer on a array_type_def.
Definition: abg-fwd.h:242
shared_ptr< pointer_type_def > pointer_type_def_sptr
Convenience typedef for a shared pointer on a pointer_type_def.
Definition: abg-fwd.h:224
CV
Bit field values representing the cv qualifiers of the underlying type.
Definition: abg-ir.h:2244