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 
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*
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  reset(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  decl_base_sptr type_declaration = get_type_declaration(t);
528  if (!has_scope(type_declaration))
529  {
530  add_decl_to_scope(type_declaration, cur_tu()->get_global_scope());
531  canonicalize(t);
532  }
533 
534  return t;
535  }
536 
537  /// Build an IR node for the "variadic parameter" type.
538  ///
539  /// @return the IR node for the "variadic parameter" type.
540  type_base_sptr
541  build_ir_node_for_variadic_parameter_type()
542  {
543  type_base_sptr t = env().get_variadic_parameter_type();
544  decl_base_sptr t_decl = get_type_declaration(t);
545  if (!has_scope(t_decl))
546  {
547  add_decl_to_scope(t_decl, cur_tu()->get_global_scope());
548  canonicalize(t);
549  }
550  return t;
551  }
552 
553  /// Build an IR node for an integer type expressed in BTF.
554  ///
555  /// @param t a pointer a BTF type describing an integer.
556  ///
557  /// @return a pointer to @ref type_decl representing an integer
558  /// type.
560  build_int_type(int type_id)
561  {
562  type_decl_sptr result;
563 
564  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
565  ABG_ASSERT(btf_kind(t) == BTF_KIND_INT);
566 
567  uint32_t info = *reinterpret_cast<const uint32_t*>(t + 1);
568  uint64_t byte_size = 0, bit_size = 0;
569  string type_name;
570 
571  byte_size = t->size;
572  bit_size = byte_size * 8;
573 
574  if (BTF_INT_ENCODING(info) & BTF_INT_CHAR)
575  {
576  if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
577  type_name = "unsigned ";
578  type_name += "char";
579  }
580  else if (BTF_INT_ENCODING(info) & BTF_INT_BOOL)
581  type_name = "bool";
582  else if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
583  {
584  type_name = "unsigned ";
585  type_name += btf_offset_to_string(btf_handle(), t->name_off);
586  }
587  else
588  type_name = btf_offset_to_string(btf_handle(), t->name_off);
589 
590  location loc;
591  result.reset(new type_decl(env(), type_name,
592  bit_size, /*alignment=*/0,
593  loc, type_name));
594 
595  return result;
596  }
597 
598  /// Build an IR node for a float type expressed in BTF.
599  ///
600  /// @return a pointer to @ref type_decl representing a float type.
602  build_float_type(int type_id)
603  {
604  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
605  ABG_ASSERT(btf_kind(t) == BTF_KIND_FLOAT);
606 
607  string type_name = btf_offset_to_string(btf_handle(), t->name_off);;
608  uint64_t byte_size = t->size, bit_size = byte_size * 8;
609  location loc;
610  type_decl_sptr result(new type_decl(env(), type_name, bit_size,
611  /*alignment=*/0, loc, type_name));
612 
613  return result;
614  }
615 
616  /// Build an IR type that represents the underlying type of an enum type.
617  ///
618  /// This is a sub-routine of the build_enum_type() function.
619  ///
620  /// @param enum_name the name of the enum type this type is an
621  /// underlying type for.
622  ///
623  /// @param enum_size the size of the enum.
624  ///
625  /// @param is_anonymous if true, the enum type is anonymous.
626  ///
627  /// @return a pointer to type_decl that represents a integer type
628  /// that is the underlying type of an enum type.
630  build_enum_underlying_type(const string enum_name, uint64_t enum_size,
631  bool is_anonymous = true)
632  {
633  string underlying_type_name =
635  is_anonymous,
636  enum_size);
637  type_decl_sptr result(new type_decl(env(), underlying_type_name,
638  enum_size, enum_size, location()));
639  result->set_is_anonymous(is_anonymous);
640  result->set_is_artificial(true);
641  add_decl_to_scope(result, cur_tu()->get_global_scope());
642  canonicalize(result);
643  return result;
644  }
645 
646  /// Build an IR node that represents an enum type expressed in BTF.
647  ///
648  /// @param type_id the ID of the BTF representation of the enum.
649  ///
650  /// @return a pointer to @ref enum_type_decl representing @p t.
652  build_enum_type(int type_id)
653  {
654  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
655  int kind = btf_kind(t);
656 #ifdef WITH_BTF_ENUM64
657  ABG_ASSERT(kind == BTF_KIND_ENUM || kind == BTF_KIND_ENUM64);
658 #else
659  ABG_ASSERT(kind == BTF_KIND_ENUM);
660 #endif
661 
662  int byte_size = t->size, bit_size = byte_size * 8;
663 
664  string enum_name;
665  if (t->name_off)
666  enum_name = btf_offset_to_string(btf_handle(), t->name_off);
667  bool is_anonymous = enum_name.empty();
668 
669  int num_enms = btf_vlen(t);
671  string e_name;
672  if (kind == BTF_KIND_ENUM)
673  {
674  const struct btf_enum* e = btf_enum(t);
675  uint32_t e_value = 0;
676  for (int i = 0; i < num_enms; ++i, ++e)
677  {
678  e_name = btf_offset_to_string(btf_handle(), e->name_off);
679  e_value = e->val;
680  enms.push_back(enum_type_decl::enumerator(e_name, e_value));
681  }
682  }
683 #ifdef WITH_BTF_ENUM64
684  else if (kind == BTF_KIND_ENUM64)
685  {
686  const struct btf_enum64* e =
687  reinterpret_cast<const struct btf_enum64*>(t + 1);
688  uint64_t e_value = 0;
689  for (int i = 0; i < num_enms; ++i, ++e)
690  {
691  e_name = btf_offset_to_string(btf_handle(), e->name_off);
692  e_value = (static_cast<uint64_t>(e->val_hi32) << 32) | e->val_lo32;
693  enms.push_back(enum_type_decl::enumerator(e_name, e_value));
694  }
695  }
696 #endif
697  else
699 
700  type_decl_sptr underlying_type =
701  build_enum_underlying_type(enum_name, bit_size, is_anonymous);
702  enum_type_decl_sptr result(new enum_type_decl(enum_name,
703  location(),
704  underlying_type,
705  enms, enum_name));
706  result->set_is_anonymous(is_anonymous);
707  return result;
708  }
709 
710  /// Build an IR node for a typedef that is expressed in BTF.
711  ///
712  /// @param type_id the ID of the BTF representation of a typedef.
713  ///
714  /// @return a pointer to @ref typedef_decl representing @p t.
716  build_typedef_type(int type_id)
717  {
718  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
719  int kind = btf_kind(t);
720  ABG_ASSERT(kind == BTF_KIND_TYPEDEF);
721 
722  string type_name = btf_offset_to_string(btf_handle(), t->name_off);
723  type_base_sptr underlying_type =
724  is_type(build_ir_node_from_btf_type(t->type));
725  if (!underlying_type)
726  return type_or_decl_base_sptr();
727 
728  typedef_decl_sptr result(new typedef_decl(type_name, underlying_type,
729  location(),
730  /*linkage_name=*/type_name));
731  if ((is_class_or_union_type(underlying_type)
732  || is_enum_type(underlying_type))
733  && is_anonymous_type(underlying_type))
734  get_type_declaration(underlying_type)->set_naming_typedef(result);
735 
736  return result;
737  }
738 
739  /// Build an IR node representing a pointer described in BTF.
740  ///
741  /// @param type_id the ID of a BTF representation of a pointer type.
742  ///
743  /// @return a pointer to pointer_type_def that represents @p t.
745  build_pointer_type(int type_id)
746  {
747  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
748  int kind = btf_kind(t);
749  ABG_ASSERT(kind == BTF_KIND_PTR);
750 
751  type_base_sptr underlying_type =
752  is_type(build_ir_node_from_btf_type(t->type));
753  if (!underlying_type)
754  return type_or_decl_base_sptr();
755 
756  int size = elf_helpers::get_architecture_word_size(elf_handle());
757  size *= 8;
758  pointer_type_def_sptr result(new pointer_type_def(underlying_type, size,
759  /*alignment=*/0,
760  location()));
761  return result;
762  }
763 
764  /// Build an IR node representing an array type described in BTF.
765  ///
766  /// @param type_id the ID of the BTF representation of an array
767  /// type.
768  ///
769  /// return a pointer to @ref array_type_def representing @p t.
771  build_array_type(int type_id)
772  {
773  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
774  int kind = btf_kind(t);
775  ABG_ASSERT(kind == BTF_KIND_ARRAY);
776 
777  const struct btf_array* arr = btf_array(t);
778 
779  type_base_sptr underlying_type =
780  is_type(build_ir_node_from_btf_type(arr->type));
781  if (!underlying_type)
782  return type_or_decl_base_sptr();
783 
784  uint64_t lower_boud = 0;
785  // Note that arr->nelems can be 0;
786  uint64_t upper_bound = arr->nelems ? arr->nelems - 1: 0;
787 
788  array_type_def::subrange_sptr subrange(new array_type_def::subrange_type
789  (env(), /*name=*/"",
790  lower_boud, upper_bound,
791  location()));
792  add_decl_to_scope(subrange, cur_tu()->get_global_scope());
793  canonicalize(subrange);
794  array_type_def::subranges_type subranges = {subrange};
795  array_type_def_sptr result(new array_type_def(underlying_type,
796  subranges, location()));
797 
798  return result;
799  }
800 
801  /// Build an IR node representing a qualified type described in BTF.
802  ///
803  /// @param type_id the ID of the BTF representation of an array
804  /// type.
805  ///
806  /// @return a pointer to a qualified_type_def representing @ t.
808  build_qualified_type(int type_id)
809  {
810  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
811  int kind = btf_kind(t);
812  ABG_ASSERT(kind == BTF_KIND_CONST
813  || kind == BTF_KIND_VOLATILE
814  || kind == BTF_KIND_RESTRICT);
815 
816  type_base_sptr underlying_type =
817  is_type(build_ir_node_from_btf_type(t->type));
818  if (!underlying_type)
819  return type_or_decl_base_sptr();
820 
821  qualified_type_def::CV qual = qualified_type_def::CV_NONE;
822  if (kind == BTF_KIND_CONST)
823  qual |= qualified_type_def::CV_CONST;
824  else if (kind == BTF_KIND_VOLATILE)
825  qual |= qualified_type_def::CV_VOLATILE;
826  else if (kind == BTF_KIND_RESTRICT)
827  qual |= qualified_type_def::CV_RESTRICT;
828  else
830 
831  qualified_type_def_sptr result(new qualified_type_def(underlying_type,
832  qual, location()));
833  return result;
834  }
835 
836  /// Build an IR node for a class or union type expressed in BTF.
837  ///
838  /// @param type_id the ID of a pointer to a BTF type describing a
839  /// class or union type.
840  ///
841  /// @return a pointer to either a @ref class_decl or a @ref
842  /// union_decl type representing the type expressed by @p t.
844  build_class_or_union_type(int type_id)
845  {
846  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
847 
848  int kind = btf_kind(t);
849  ABG_ASSERT(kind == BTF_KIND_STRUCT
850  || kind == BTF_KIND_UNION
851  || kind == BTF_KIND_FWD);
852 
853  string type_name;
854  if (t->name_off)
855  type_name = btf_offset_to_string(btf_handle(), t->name_off);
856 
857  bool is_anonymous = type_name.empty();
858  uint64_t size = t->size;
859  size *= 8;
860 
861  bool is_decl_only = (kind == BTF_KIND_FWD);
862 
863  class_or_union_sptr result;
864  if (kind == BTF_KIND_STRUCT
865  || (kind == BTF_KIND_FWD
866  && BTF_INFO_KFLAG(t->info) == 0 /*struct*/))
867  result.reset(new class_decl(env(), type_name, size,
868  /*alignment=*/0,
869  /*is_struct=*/true,
870  location(),
871  decl_base::VISIBILITY_DEFAULT,
872  is_anonymous));
873  else if (kind == BTF_KIND_UNION
874  || (kind == BTF_KIND_FWD
875  && BTF_INFO_KFLAG(t->info) == 1/*union*/))
876  result.reset(new union_decl(env(), type_name, size, location(),
877  decl_base::VISIBILITY_DEFAULT,
878  is_anonymous));
879  else
881 
882  if (is_decl_only)
883  result->set_is_declaration_only(is_decl_only);
884 
885  add_decl_to_scope(result, cur_tu()->get_global_scope());
886 
887  associate_artifact_to_btf_type_id(result, type_id);
888 
889  // For defined classes and unions, add data members to the type
890  // being built.
891  if (!is_decl_only)
892  {
893  const struct btf_member *m =
894  reinterpret_cast<const struct btf_member*>(t + 1);
895  uint64_t nb_members = btf_vlen(t);
896 
897  for (uint64_t i = 0; i < nb_members; ++i, ++m)
898  {
899  type_base_sptr member_type =
900  is_type(build_ir_node_from_btf_type(m->type));
901  if (!member_type)
902  continue;
903 
904  string member_name;
905  if (m->name_off)
906  member_name = btf_offset_to_string(btf_handle(), m->name_off);
907  var_decl_sptr data_member(new var_decl(member_name,
908  member_type,
909  location(),
910  /*linkage_name=*/""));
911  uint64_t offset_in_bits =
912  BTF_INFO_KFLAG(t->info)
913  ? BTF_MEMBER_BIT_OFFSET(m->offset)
914  : m->offset;
915 
916  result->add_data_member(data_member,
917  public_access,
918  /*is_laid_out=*/true,
919  /*is_static=*/false,
920  offset_in_bits);
921  }
922  }
923  return result;
924  }
925 
926  /// Build an IR node for a function type expressed in BTF.
927  ///
928  /// @param type_id the ID of a pointer to a BTF type describing a
929  /// function type.
930  ///
931  /// @return a pointer to a @ref function_type representing the
932  /// function type expressed by @p t.
934  build_function_type(int type_id)
935  {
936  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
937  int kind = btf_kind(t);
938  ABG_ASSERT(kind == BTF_KIND_FUNC_PROTO);
939 
940  type_base_sptr return_type = is_type(build_ir_node_from_btf_type(t->type));
941  if (return_type == nullptr)
942  return type_or_decl_base_sptr();
943 
944  int address_size = elf_helpers::get_architecture_word_size(elf_handle());
945  address_size *= 8;
946  function_type_sptr result(new function_type(env(), address_size,
947  /*alignment=*/0));
948  result->set_return_type(return_type);
949 
950  associate_artifact_to_btf_type_id(result, type_id);
951 
952  uint16_t nb_parms = btf_vlen(t);
953  const struct btf_param* parm =
954  reinterpret_cast<const struct btf_param*>(t + 1);
955 
956  function_decl::parameters function_parms;
957  for (uint16_t i = 0; i < nb_parms; ++i, ++parm)
958  {
959  type_base_sptr parm_type;
960  string parm_name;
961  bool is_variadic = false;
962 
963  if (parm->name_off == 0 && parm->type == 0)
964  {
965  is_variadic = true;
966  parm_type = build_ir_node_for_variadic_parameter_type();
967  }
968  else
969  {
970  parm_name = btf_offset_to_string(btf_handle(), parm->name_off);
971  parm_type = is_type(build_ir_node_from_btf_type(parm->type));
972  }
973 
974  if (!parm_type)
975  continue;
976 
978  (new function_decl::parameter(parm_type, parm_name,
979  location(), is_variadic));
980  function_parms.push_back(p);
981  }
982  result->set_parameters(function_parms);
983 
984  cur_tu()->bind_function_type_life_time(result);
985 
986  return result;
987  }
988 
989  /// Build an IR node for a function declaration expressed in BTF.
990  ///
991  /// @param type_id the ID of a pointer to a BTF "type" which realy
992  /// describes a function declaration.
993  ///
994  /// @return a pointer to a @ref function_decl representing the
995  /// function declaration expressed by @p t.
997  build_function_decl(int type_id)
998  {
999  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1000  int kind = btf_kind(t);
1001  ABG_ASSERT(kind == BTF_KIND_FUNC);
1002 
1003  function_decl_sptr result;
1004 
1005  string fn_name = btf_offset_to_string(btf_handle(), t->name_off);
1006 
1007  type_base_sptr fn_type = is_type(build_ir_node_from_btf_type(t->type));
1008  if (!fn_type)
1009  return result;
1010 
1011  result.reset(new function_decl(fn_name, fn_type, /*is_inline=*/false,
1012  location(), /*linkage_name=*/fn_name));
1013 
1014  elf_symbol_sptr fn_sym;
1015  if ((fn_sym = function_symbol_is_exported(fn_name)))
1016  {
1017  result->set_symbol(fn_sym);
1018  result->set_is_in_public_symbol_table(true);
1019  }
1020  return result;
1021  }
1022 
1023  /// Build an IR node for a variable declaration expressed in BTF.
1024  ///
1025  /// @param t a pointer to a BTF "type" describing a variable
1026  /// declaration.
1027  ///
1028  /// @return a pointer to @ref var_decl representing the variable
1029  /// declaration expressed by @p t.
1031  build_variable_decl(int type_id)
1032  {
1033  const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1034  int kind = btf_kind(t);
1035  ABG_ASSERT(kind == BTF_KIND_VAR);
1036 
1037  var_decl_sptr result;
1038 
1039  string var_name = btf_offset_to_string(btf_handle(), t->name_off);
1040 
1041  type_base_sptr var_type = is_type(build_ir_node_from_btf_type(t->type));
1042  if (!var_type)
1043  return result;
1044 
1045  result.reset(new var_decl(var_name, var_type, location(),
1046  /*linkage_name=*/var_name));
1047 
1048  elf_symbol_sptr var_sym;
1049  if ((var_sym = variable_symbol_is_exported(var_name)))
1050  {
1051  result->set_symbol(var_sym);
1052  result->set_is_in_public_symbol_table(true);
1053  }
1054  return result;
1055  }
1056 
1057 }; // end class reader.
1058 
1059 /// Create and return a BTF reader (or front-end) which is an instance
1060 /// of @ref btf::reader.
1061 ///
1062 /// @param elf_path the path to the path to the elf file the reader is
1063 /// to be used for.
1064 ///
1065 /// @param debug_info_root_paths a vector to the paths to the
1066 /// directories under which the debug info is to be found for @p
1067 /// elf_path. Pass an empty vector if th debug info is not in a split
1068 /// file.
1069 ///
1070 /// @param environment the environment used by the current context.
1071 /// This environment contains resources needed by the BTF reader and
1072 /// by the types and declarations that are to be created later. Note
1073 /// that ABI artifacts that are to be compared all need to be created
1074 /// within the same environment.
1075 ///
1076 /// Please also note that the life time of this environment object
1077 /// must be greater than the life time of the resulting @ref
1078 /// reader the context uses resources that are allocated in the
1079 /// environment.
1080 ///
1081 /// @param load_all_types if set to false only the types that are
1082 /// reachable from publicly exported declarations (of functions and
1083 /// variables) are read. If set to true then all types found in the
1084 /// debug information are loaded.
1085 ///
1086 /// @param linux_kernel_mode if set to true, then consider the special
1087 /// linux kernel symbol tables when determining if a symbol is
1088 /// exported or not.
1089 ///
1090 /// @return a smart pointer to the resulting btf::reader.
1091 elf_based_reader_sptr
1092 create_reader(const std::string& elf_path,
1093  const vector<char**>& debug_info_root_paths,
1094  environment& env,
1095  bool load_all_types,
1096  bool linux_kernel_mode)
1097 {
1098  reader_sptr rdr = reader::create(elf_path, debug_info_root_paths, env,
1099  load_all_types, linux_kernel_mode);
1100  return rdr;
1101 }
1102 
1103 } // end namespace btf
1104 } // end namespace abigail
1105 
1106 #endif //WITH_BTF
This file contains the declarations of the front-end to analyze the BTF information contained in an E...
elf_based_reader_sptr create_reader(const std::string &elf_path, const vector< char ** > &debug_info_root_paths, environment &env)
Create and return a new read context to process CTF information from a given ELF file.
This contains a set of ELF utilities used by the dwarf reader.
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects,...
Definition: abg-fwd.h:1589
This contains the private implementation of the suppression engine of libabigail.
Types of the main internal representation of libabigail.
#define ABG_ASSERT_NOT_REACHED
A macro that expands to aborting the program when executed.
virtual ir::corpus_sptr read_corpus(status &status)
Read the ELF information associated to the current ELF file and construct an ABI representation from ...
shared_ptr< subrange_type > subrange_sptr
Convenience typedef for a shared pointer on a function_decl::subrange.
Definition: abg-ir.h:2460
std::vector< subrange_sptr > subranges_type
Convenience typedef for a vector of subrange_sptr.
Definition: abg-ir.h:2467
origin
This abstracts where the corpus comes from. That is, either it has been read from the native xml form...
Definition: abg-corpus.h:45
void set_naming_typedef(const typedef_decl_sptr &)
Set the naming typedef of the current instance of decl_base.
Definition: abg-ir.cc:4806
std::vector< enumerator > enumerators
Convenience typedef for a list of enumerator.
Definition: abg-ir.h:2690
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3044
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3051
CV
Bit field values representing the cv qualifiers of the underlying type.
Definition: abg-ir.h:2223
shared_ptr< function_decl > function_decl_sptr
Convenience typedef for a shared pointer on a function_decl.
Definition: abg-fwd.h:263
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10194
bool has_scope(const decl_base &d)
Tests if a declaration has got a scope.
Definition: abg-ir.cc:5472
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition: abg-ir.h:863
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
bool is_anonymous_type(const type_base *t)
Test whether a declaration is a type.
Definition: abg-ir.cc:10245
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:10509
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:1314
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition: abg-fwd.h:205
shared_ptr< typedef_decl > typedef_decl_sptr
Convenience typedef for a shared pointer on a typedef_decl.
Definition: abg-fwd.h:161
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:10399
const global_scope * get_global_scope(const decl_base &decl)
return the global scope as seen by a given declaration.
Definition: abg-ir.cc:8386
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:246
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< translation_unit > translation_unit_sptr
Convenience typedef for a shared pointer on a translation_unit type.
Definition: abg-fwd.h:134
type_base_sptr canonicalize(type_base_sptr t)
Compute the canonical type of a given type.
Definition: abg-ir.cc:14839
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
var_decl * is_var_decl(const type_or_decl_base *tod)
Tests if a declaration is a variable declaration.
Definition: abg-ir.cc:10890
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10134
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.
Definition: abg-ir.cc:8293
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:26874
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
Definition: abg-fwd.h:169
const decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition: abg-ir.cc:9827
shared_ptr< type_decl > type_decl_sptr
Convenience typedef for a shared pointer on a type_decl.
Definition: abg-fwd.h:156
function_decl * is_function_decl(const type_or_decl_base *d)
Test whether a declaration is a function_decl.
Definition: abg-ir.cc:10082
Toplevel namespace for libabigail.