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