• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2022-2023 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 /// @file
9 ///
10 /// This file contains the definitions of the front-end to analyze the
11 /// BTF information contained in an ELF file.
12 
13 #include "abg-internal.h"
14 
15 #ifdef WITH_BTF
16 
17 #include <bpf/btf.h>
18 #include <iostream>
19 #include <unordered_map>
20 
21 #include "abg-elf-helpers.h"
22 #include "abg-ir-priv.h"
23 
24 // <headers defining libabigail's API go under here>
25 ABG_BEGIN_EXPORT_DECLARATIONS
26 
27 #include "abg-btf-reader.h"
28 #include "abg-ir.h"
29 #include "abg-tools-utils.h"
30 
31 ABG_END_EXPORT_DECLARATIONS
32 // </headers defining libabigail's API>
33 
34 namespace abigail
35 {
36 using namespace ir;
37 
38 namespace btf
39 {
40 
41 class reader;
42 
43 /// A convenience typedef for a shared pointer to
44 /// abigail::btf::reader.
45 typedef shared_ptr<reader> reader_sptr;
46 
47 static const char*
btf_offset_to_string(const::btf * btf,uint32_t offset)48 btf_offset_to_string(const ::btf* btf, uint32_t offset)
49 {
50   if (!offset)
51     return "__anonymous__";
52   return btf__name_by_offset(btf, offset) ?: "(invalid string offset)";
53 }
54 
55 /// A convenience typedef of a map that associates a btf type id to a
56 /// libabigail ABI artifact.
57 typedef std::unordered_map<int, type_or_decl_base_sptr>
58 btf_type_id_to_abi_artifact_map_type;
59 
60 /// The BTF front-end abstraction type.
61 class reader : public elf_based_reader
62 {
63   ::btf*				btf_handle_ = nullptr;
64   translation_unit_sptr		cur_tu_;
65   vector<type_base_sptr>		types_to_canonicalize_;
66   btf_type_id_to_abi_artifact_map_type	btf_type_id_to_artifacts_;
67 
68   /// Getter of the handle to the BTF data as returned by libbpf.
69   ///
70   /// @return the handle to the BTF data as returned by libbpf.
71   ::btf*
btf_handle()72   btf_handle()
73   {
74     if (btf_handle_ == nullptr)
75       {
76 	btf_handle_ = btf__parse(corpus_path().c_str(), nullptr);
77 	if (!btf_handle_)
78 	  std::cerr << "Could not parse BTF information from file '"
79 		    << corpus_path().c_str() << "'" << std::endl;
80       }
81     return btf_handle_;
82   }
83 
84   /// Getter of the environment of the current front-end.
85   ///
86   /// @return The environment of the current front-end.
87   environment&
env()88   env()
89   {return options().env;}
90 
91   /// Getter of the environment of the current front-end.
92   ///
93   /// @return The environment of the current front-end.
94   const environment&
env() const95   env() const
96   {return const_cast<reader*>(this)->env();}
97 
98   /// Getter of the current translation unit being built.
99   ///
100   /// Actually, BTF doesn't keep track of the translation unit each
101   /// ABI artifact originates from.  So an "artificial" translation
102   /// unit is built.  It contains all the ABI artifacts of the binary.
103   ///
104   /// @return The current translation unit being built.
105   translation_unit_sptr&
cur_tu()106   cur_tu()
107   {return cur_tu_;}
108 
109   /// Getter of the current translation unit being built.
110   ///
111   /// Actually, BTF doesn't keep track of the translation unit each
112   /// ABI artifact originates from.  So an "artificial" translation
113   /// unit is built.  It contains all the ABI artifacts of the binary.
114   ///
115   /// @return The current translation unit being built.
116   const translation_unit_sptr&
cur_tu() const117   cur_tu() const
118   {return cur_tu_;}
119 
120   /// Getter of the current translation unit being built.
121   ///
122   /// Actually, BTF doesn't keep track of the translation unit each
123   /// ABI artifact originates from.  So an "artificial" translation
124   /// unit is built.  It contains all the ABI artifacts of the binary.
125   ///
126   /// @return The current translation unit being built.
127   void
cur_tu(const translation_unit_sptr & tu)128   cur_tu(const translation_unit_sptr& tu)
129   {cur_tu_ = tu;}
130 
131   /// Getter of the map that associates a BTF type ID to an ABI
132   /// artifact.
133   ///
134   /// @return The map that associates a BTF type ID to an ABI
135   /// artifact.
136   btf_type_id_to_abi_artifact_map_type&
btf_type_id_to_artifacts()137   btf_type_id_to_artifacts()
138   {return btf_type_id_to_artifacts_;}
139 
140   /// Getter of the map that associates a BTF type ID to an ABI
141   /// artifact.
142   ///
143   /// @return The map that associates a BTF type ID to an ABI
144   /// artifact.
145   const btf_type_id_to_abi_artifact_map_type&
btf_type_id_to_artifacts() const146   btf_type_id_to_artifacts() const
147   {return btf_type_id_to_artifacts_;}
148 
149   /// Get the ABI artifact that is associated to a given BTF type ID.
150   ///
151   /// If no ABI artifact is associated to the BTF type id, then return
152   /// nil.
153   ///
154   /// @return the ABI artifact that is associated to a given BTF type
155   /// id.
156   type_or_decl_base_sptr
lookup_artifact_from_btf_id(int btf_id)157   lookup_artifact_from_btf_id(int btf_id)
158   {
159     auto i = btf_type_id_to_artifacts().find(btf_id);
160     if (i != btf_type_id_to_artifacts().end())
161       return i->second;
162     return type_or_decl_base_sptr();
163   }
164 
165   /// Associate an ABI artifact to a given BTF type ID.
166   ///
167   /// @param artifact the ABI artifact to consider.
168   ///
169   /// @param btf_type_id the BTF type ID to associate to @p artifact.
170   void
associate_artifact_to_btf_type_id(const type_or_decl_base_sptr & artifact,int btf_type_id)171   associate_artifact_to_btf_type_id(const type_or_decl_base_sptr& artifact,
172 				    int btf_type_id)
173   {btf_type_id_to_artifacts()[btf_type_id] = artifact;}
174 
175   /// Schecule a type for canonicalization at the end of the debug
176   /// info loading.
177   ///
178   /// @param t the type to schedule.
179   void
schedule_type_for_canonocalization(const type_base_sptr & t)180   schedule_type_for_canonocalization(const type_base_sptr& t)
181   {types_to_canonicalize_.push_back(t);}
182 
183   /// Canonicalize all the types scheduled for canonicalization using
184   /// abigail::ir::canonicalize_types() which performs some sanity
185   /// checking around type canonicalization if necessary.
186   void
canonicalize_types()187   canonicalize_types()
188   {
189     ir::canonicalize_types(types_to_canonicalize_.begin(),
190 			   types_to_canonicalize_.end(),
191 			   [](const vector<type_base_sptr>::const_iterator& i)
192 			   {return *i;});
193   }
194 
195   uint64_t
nr_btf_types() const196   nr_btf_types() const
197   {
198 #ifdef WITH_BTF__GET_NR_TYPES
199 #define GET_NB_TYPES btf__get_nr_types
200 #endif
201 
202 #ifdef WITH_BTF__TYPE_CNT
203 #undef GET_NB_TYPES
204 #define GET_NB_TYPES btf__type_cnt
205 #endif
206 
207 #ifndef GET_NB_TYPES
208     ABG_ASSERT_NOT_REACHED;
209     return 0;
210 #endif
211 
212     return GET_NB_TYPES(const_cast<reader*>(this)->btf_handle());
213   }
214 
215 protected:
216   reader() = delete;
217 
218   /// Initializer of the current instance of @ref btf::reader.
219   ///
220   /// This frees the resources used by the current instance of @ref
221   /// btf::reader and gets it ready to analyze another ELF
222   /// file.
223   ///
224   /// @param elf_path the path to the ELF file to read from.
225   ///
226   /// @param debug_info_root_paths the paths where to look for
227   /// seperate debug info.
228   ///
229   /// @param load_all_types if true, then load all the types described
230   /// in the binary, rather than loading only the types reachable from
231   /// the exported decls.
232   ///
233   /// @param linux_kernel_mode
234   void
initialize(const string & elf_path,const vector<char ** > & debug_info_root_paths,bool load_all_types,bool linux_kernel_mode)235   initialize(const string&		elf_path,
236 	     const vector<char**>&	debug_info_root_paths,
237 	     bool			load_all_types,
238 	     bool			linux_kernel_mode)
239   {
240     elf_based_reader::initialize(elf_path, debug_info_root_paths);
241     btf__free(btf_handle_);
242     options().load_all_types = load_all_types;
243     options().load_in_linux_kernel_mode = linux_kernel_mode;
244   }
245 
246   /// Constructor of the btf::reader type.
247   ///
248   /// @param elf_path the path to the ELF file to analyze.
249   ///
250   /// @param debug_info_root_paths the set of directory where to look
251   /// debug info from, for cases where the debug is split.
252   ///
253   /// @param environment the environment of the current front-end.
254   ///
255   /// @param load_all_types if true load all the types described by
256   /// the BTF debug info, as opposed to loading only the types
257   /// reachable from the decls that are defined and exported.
258   ///
259   /// @param linux_kernel_mode if true, then consider the binary being
260   /// analyzed as a linux kernel binary.
reader(const string & elf_path,const vector<char ** > & debug_info_root_paths,environment & environment,bool load_all_types,bool linux_kernel_mode)261   reader(const string&		elf_path,
262 	 const vector<char**>&	debug_info_root_paths,
263 	 environment&		environment,
264 	 bool			load_all_types,
265 	 bool			linux_kernel_mode)
266     : elf_based_reader(elf_path,
267 		       debug_info_root_paths,
268 		       environment)
269   {
270     initialize(elf_path, debug_info_root_paths,
271 	       load_all_types, linux_kernel_mode);
272   }
273 
274 public:
275 
276   /// Constructor of the btf::reader type.
277   ///
278   /// @param elf_path the path to the ELF file to analyze.
279   ///
280   /// @param debug_info_root_paths the set of directory where to look
281   /// debug info from, for cases where the debug is split.
282   ///
283   /// @param environment the environment of the current front-end.
284   ///
285   /// @param load_all_types if true load all the types described by
286   /// the BTF debug info, as opposed to loading only the types
287   /// reachable from the decls that are defined and exported.
288   ///
289   /// @param linux_kernel_mode if true, then consider the binary being
290   /// analyzed as a linux kernel binary.
291   static btf::reader_sptr
create(const string & elf_path,const vector<char ** > & debug_info_root_paths,environment & environment,bool load_all_types,bool linux_kernel_mode)292   create(const string&		elf_path,
293 	 const vector<char**>&	debug_info_root_paths,
294 	 environment&		environment,
295 	 bool			load_all_types,
296 	 bool			linux_kernel_mode)
297   {
298     reader_sptr result(new reader(elf_path, debug_info_root_paths, environment,
299 				  load_all_types, linux_kernel_mode));
300     return result;
301   }
302 
303   /// Destructor of the btf::reader type.
~reader()304   ~reader()
305   {
306     btf__free(btf_handle_);
307   }
308 
309   /// Read the ELF information as well as the BTF type information to
310   /// build an ABI corpus.
311   ///
312   /// @param status output parameter.  The status of the analysis.
313   ///
314   /// @return the resulting ABI corpus.
315   corpus_sptr
read_corpus(status & status)316   read_corpus(status& status)
317   {
318     // Read the properties of the ELF file.
319     elf::reader::read_corpus(status);
320 
321     corpus::origin origin = corpus()->get_origin();
322     origin |= corpus::BTF_ORIGIN;
323     corpus()->set_origin(origin);
324 
325     if ((status & STATUS_NO_SYMBOLS_FOUND)
326 	|| !(status & STATUS_OK))
327       // Either we couldn't find ELF symbols or something went badly
328       // wrong.  There is nothing we can do with this ELF file.  Bail
329       // out.
330       return corpus_sptr();
331 
332     if (find_btf_section() == nullptr)
333       status |= STATUS_DEBUG_INFO_NOT_FOUND;
334 
335     read_debug_info_into_corpus();
336 
337     status |= STATUS_OK;
338 
339     return corpus();
340   }
341 
342   /// Read the BTF debug info to construct the ABI corpus.
343   ///
344   /// @return the resulting ABI corpus.
345   corpus_sptr
read_debug_info_into_corpus()346   read_debug_info_into_corpus()
347   {
348     btf_handle();
349 
350     translation_unit_sptr artificial_tu
351       (new translation_unit(env(), "", /*address_size=*/64));
352     corpus()->add(artificial_tu);
353     cur_tu(artificial_tu);
354 
355     int number_of_types = nr_btf_types();
356     int first_type_id = 1;
357 
358     // Let's cycle through whatever is described in the BTF section
359     // and emit libabigail IR for it.
360     for (int type_id = first_type_id;
361 	 type_id < number_of_types;
362 	 ++type_id)
363       {
364 	// Build IR nodes only for decls (functions and variables)
365 	// that have associated ELF symbols that are publicly defined
366 	// and exported, unless the user asked to load all types.
367 
368 	bool do_construct_ir_node = false;
369 
370 	const btf_type* t = btf__type_by_id(btf_handle(), type_id);
371 	string name;
372 	if (t->name_off)
373 	  name = btf_offset_to_string(btf_handle(), t->name_off);
374 
375 	int kind = btf_kind(t);
376 	if (kind == BTF_KIND_FUNC)
377 	  {
378 	    ABG_ASSERT(!name.empty());
379 	    if (btf_vlen(t) == BTF_FUNC_GLOBAL
380 		|| btf_vlen(t) == BTF_FUNC_EXTERN
381 		|| function_symbol_is_exported(name))
382 	      do_construct_ir_node = true;
383 	  }
384 	else if (kind == BTF_KIND_VAR)
385 	  {
386 	    ABG_ASSERT(!name.empty());
387 	    if (btf_vlen(t) == BTF_VAR_GLOBAL_ALLOCATED
388 		|| btf_vlen(t) == BTF_VAR_GLOBAL_EXTERN
389 		|| variable_symbol_is_exported(name))
390 	      do_construct_ir_node = true;
391 	  }
392 	else if (options().load_all_types)
393 	  do_construct_ir_node = true;
394 
395 	if (do_construct_ir_node)
396 	  build_ir_node_from_btf_type(type_id);
397       }
398 
399     canonicalize_types();
400 
401     return corpus();
402   }
403 
404   /// Build an abigail IR node for a given type described by a BTF
405   /// type ID.  The node is added to the ABI corpus.
406   ///
407   /// @param type_id the ID of the type to build and IR node for.
408   ///
409   /// @return the IR node representing the type @p type_id.
410   type_or_decl_base_sptr
build_ir_node_from_btf_type(int type_id)411   build_ir_node_from_btf_type(int type_id)
412   {
413     type_or_decl_base_sptr result;
414     const btf_type *t = nullptr;
415 
416     if ((result = lookup_artifact_from_btf_id(type_id)))
417       return result;
418 
419     if (type_id == 0)
420       result = build_ir_node_for_void_type();
421     else
422       t = btf__type_by_id(btf_handle(), type_id);
423 
424     if (!result)
425       {
426 	ABG_ASSERT(t);
427 	int type_kind = btf_kind(t);
428 
429 	switch(type_kind)
430 	  {
431 	  case BTF_KIND_INT/* Integer */:
432 	    result = build_int_type(type_id);
433 	    break;
434 
435 	  case BTF_KIND_FLOAT/* Floating point */:
436 	    result = build_float_type(type_id);
437 	    break;
438 
439 	  case BTF_KIND_TYPEDEF/* Typedef*/:
440 	    result = build_typedef_type(type_id);
441 	    break;
442 
443 	  case BTF_KIND_PTR/* Pointer */:
444 	    result = build_pointer_type(type_id);
445 	    break;
446 
447 	  case BTF_KIND_ARRAY/* Array */:
448 	    result = build_array_type(type_id);
449 	    break;
450 
451 	  case BTF_KIND_ENUM/* Enumeration up to 32-bit values */:
452 #ifdef WITH_BTF_ENUM64
453 	  case BTF_KIND_ENUM64/* Enumeration up to 64-bit values */:
454 #endif
455 	    result = build_enum_type(type_id);
456 	    break;
457 
458 	  case BTF_KIND_STRUCT/* Struct */:
459 	  case BTF_KIND_UNION/* Union */:
460 	    result = build_class_or_union_type(type_id);
461 	    break;
462 
463 	  case BTF_KIND_FWD/* Forward */:
464 	    result = build_class_or_union_type(type_id);
465 	    break;
466 
467 	  case BTF_KIND_CONST/* Const	*/:
468 	  case BTF_KIND_VOLATILE/* Volatile */:
469 	  case BTF_KIND_RESTRICT/* Restrict */:
470 	    result = build_qualified_type(type_id);
471 	    break;
472 
473 	  case BTF_KIND_FUNC/* Function */:
474 	    result = build_function_decl(type_id);
475 	    break;
476 
477 	  case BTF_KIND_FUNC_PROTO/* Function Proto */:
478 	    result = build_function_type(type_id);
479 	    break;
480 
481 	  case BTF_KIND_VAR/* Variable */:
482 	    result = build_variable_decl(type_id);
483 	    break;
484 
485 #ifdef WITH_BTF_KIND_TYPE_TAG
486 	  case BTF_KIND_TYPE_TAG/* Type Tag */:
487 #endif
488 #ifdef WITH_BTF_KIND_DECL_TAG
489 	  case BTF_KIND_DECL_TAG/* Decl Tag */:
490 #endif
491 	  case BTF_KIND_DATASEC/* Section */:
492 	  case BTF_KIND_UNKN/* Unknown	*/:
493 	  default:
494 	    ABG_ASSERT_NOT_REACHED;
495 	    break;
496 	  }
497       }
498 
499     add_decl_to_scope(is_decl(result), cur_tu()->get_global_scope());
500 
501     if (type_base_sptr type = is_type(result))
502       schedule_type_for_canonocalization(type);
503 
504     associate_artifact_to_btf_type_id(result, type_id);
505 
506     if (function_decl_sptr fn = is_function_decl(result))
507       {
508 	if (fn->get_is_in_public_symbol_table())
509 	  maybe_add_fn_to_exported_decls(fn.get());
510       }
511     else if (var_decl_sptr var = is_var_decl(result))
512       {
513 	if (var->get_is_in_public_symbol_table())
514 	  maybe_add_var_to_exported_decls(var.get());
515       }
516 
517     return result;
518   }
519 
520   /// Build an IR node for the "void" type.
521   ///
522   /// @return the IR node for the void type.
523   type_base_sptr
build_ir_node_for_void_type()524   build_ir_node_for_void_type()
525   {
526     type_base_sptr t = env().get_void_type();
527     add_decl_to_scope(is_decl(t), cur_tu()->get_global_scope());
528     canonicalize(t);
529     return t;
530   }
531 
532   /// Build an IR node for the "void" type.
533   ///
534   /// @return the IR node for the void type.
535   type_base_sptr
build_ir_node_for_void_pointer_type()536   build_ir_node_for_void_pointer_type()
537   {
538     type_base_sptr t = env().get_void_pointer_type();
539     add_decl_to_scope(is_decl(t), cur_tu()->get_global_scope());
540     canonicalize(t);
541     return t;
542   }
543 
544   /// Build an IR node for the "variadic parameter" type.
545   ///
546   /// @return the IR node for the "variadic parameter" type.
547   type_base_sptr
build_ir_node_for_variadic_parameter_type()548   build_ir_node_for_variadic_parameter_type()
549   {
550     type_base_sptr t = env().get_variadic_parameter_type();
551     add_decl_to_scope(is_decl(t), cur_tu()->get_global_scope());
552     decl_base_sptr t_decl = get_type_declaration(t);
553     canonicalize(t);
554     return t;
555   }
556 
557   /// Build an IR node for an integer type expressed in BTF.
558   ///
559   /// @param t a pointer a BTF type describing an integer.
560   ///
561   /// @return a pointer to @ref type_decl representing an integer
562   /// type.
563   type_or_decl_base_sptr
build_int_type(int type_id)564   build_int_type(int type_id)
565   {
566     type_decl_sptr result;
567 
568     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
569     ABG_ASSERT(btf_kind(t) == BTF_KIND_INT);
570 
571     uint32_t info = *reinterpret_cast<const uint32_t*>(t + 1);
572     uint64_t byte_size = 0, bit_size = 0;
573     string type_name;
574 
575     byte_size = t->size;
576     bit_size = byte_size * 8;
577 
578     if (BTF_INT_ENCODING(info) & BTF_INT_CHAR)
579       {
580 	if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
581 	  type_name = "unsigned ";
582 	type_name += "char";
583       }
584     else if (BTF_INT_ENCODING(info) & BTF_INT_BOOL)
585       type_name = "bool";
586     else if (!(BTF_INT_ENCODING(info) & BTF_INT_SIGNED))
587       {
588 	type_name = "unsigned ";
589 	type_name += btf_offset_to_string(btf_handle(), t->name_off);
590       }
591     else
592       type_name = btf_offset_to_string(btf_handle(), t->name_off);
593 
594     location loc;
595     result.reset(new type_decl(env(), type_name,
596 			       bit_size, /*alignment=*/0,
597 			       loc, type_name));
598 
599     return result;
600   }
601 
602   /// Build an IR node for a float type expressed in BTF.
603   ///
604   /// @return a pointer to @ref type_decl representing a float type.
605   type_or_decl_base_sptr
build_float_type(int type_id)606   build_float_type(int type_id)
607   {
608     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
609     ABG_ASSERT(btf_kind(t) == BTF_KIND_FLOAT);
610 
611     string type_name = btf_offset_to_string(btf_handle(), t->name_off);;
612     uint64_t byte_size = t->size, bit_size = byte_size * 8;
613     location loc;
614     type_decl_sptr result(new type_decl(env(), type_name, bit_size,
615 					/*alignment=*/0, loc, type_name));
616 
617     return result;
618   }
619 
620   /// Build an IR type that represents the underlying type of an enum type.
621   ///
622   /// This is a sub-routine of the build_enum_type() function.
623   ///
624   /// @param enum_name the name of the enum type this type is an
625   /// underlying type for.
626   ///
627   /// @param enum_size the size of the enum.
628   ///
629   /// @param is_anonymous if true, the enum type is anonymous.
630   ///
631   /// @return a pointer to type_decl that represents a integer type
632   /// that is the underlying type of an enum type.
633   type_decl_sptr
build_enum_underlying_type(const string enum_name,uint64_t enum_size,bool is_anonymous=true)634   build_enum_underlying_type(const string enum_name, uint64_t enum_size,
635 			     bool is_anonymous = true)
636   {
637     string underlying_type_name =
638       build_internal_underlying_enum_type_name(enum_name,
639 					       is_anonymous,
640 					       enum_size);
641     type_decl_sptr result(new type_decl(env(), underlying_type_name,
642 					enum_size, enum_size, location()));
643     result->set_is_anonymous(is_anonymous);
644     result->set_is_artificial(true);
645     add_decl_to_scope(result, cur_tu()->get_global_scope());
646     canonicalize(result);
647     return result;
648   }
649 
650   /// Build an IR node that represents an enum type expressed in BTF.
651   ///
652   /// @param type_id the ID of the BTF representation of the enum.
653   ///
654   /// @return a pointer to @ref enum_type_decl representing @p t.
655   type_or_decl_base_sptr
build_enum_type(int type_id)656   build_enum_type(int type_id)
657   {
658     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
659     int kind = btf_kind(t);
660 #ifdef WITH_BTF_ENUM64
661     ABG_ASSERT(kind == BTF_KIND_ENUM || kind == BTF_KIND_ENUM64);
662 #else
663     ABG_ASSERT(kind == BTF_KIND_ENUM);
664 #endif
665 
666     int byte_size = t->size, bit_size = byte_size * 8;
667 
668     string enum_name;
669     if (t->name_off)
670       enum_name = btf_offset_to_string(btf_handle(), t->name_off);
671     bool is_anonymous = enum_name.empty();
672 
673     int num_enms = btf_vlen(t);
674     enum_type_decl::enumerators enms;
675     string e_name;
676     if (kind == BTF_KIND_ENUM)
677       {
678 	const struct btf_enum* e = btf_enum(t);
679 	uint32_t e_value = 0;
680 	for (int i = 0; i < num_enms; ++i, ++e)
681 	  {
682 	    e_name = btf_offset_to_string(btf_handle(), e->name_off);
683 	    e_value = e->val;
684 	    enms.push_back(enum_type_decl::enumerator(e_name, e_value));
685 	  }
686       }
687 #ifdef WITH_BTF_ENUM64
688     else if (kind == BTF_KIND_ENUM64)
689       {
690 	const struct btf_enum64* e =
691 	  reinterpret_cast<const struct btf_enum64*>(t + 1);
692 	uint64_t e_value = 0;
693 	for (int i = 0; i < num_enms; ++i, ++e)
694 	  {
695 	    e_name = btf_offset_to_string(btf_handle(), e->name_off);
696 	    e_value = (static_cast<uint64_t>(e->val_hi32) << 32) | e->val_lo32;
697 	    enms.push_back(enum_type_decl::enumerator(e_name, e_value));
698 	  }
699       }
700 #endif
701     else
702       ABG_ASSERT_NOT_REACHED;
703 
704     type_decl_sptr underlying_type =
705       build_enum_underlying_type(enum_name, bit_size, is_anonymous);
706     enum_type_decl_sptr result(new enum_type_decl(enum_name,
707 						  location(),
708 						  underlying_type,
709 						  enms, enum_name));
710     result->set_is_anonymous(is_anonymous);
711     return result;
712   }
713 
714   /// Build an IR node for a typedef that is expressed in BTF.
715   ///
716   /// @param type_id the ID of the BTF representation of a typedef.
717   ///
718   /// @return a pointer to @ref typedef_decl representing @p t.
719   type_or_decl_base_sptr
build_typedef_type(int type_id)720   build_typedef_type(int type_id)
721   {
722     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
723     int kind = btf_kind(t);
724     ABG_ASSERT(kind == BTF_KIND_TYPEDEF);
725 
726     string type_name = btf_offset_to_string(btf_handle(), t->name_off);
727     type_base_sptr underlying_type =
728       is_type(build_ir_node_from_btf_type(t->type));
729     if (!underlying_type)
730       return type_or_decl_base_sptr();
731 
732     typedef_decl_sptr result(new typedef_decl(type_name, underlying_type,
733 					      location(),
734 					      /*linkage_name=*/type_name));
735     if ((is_class_or_union_type(underlying_type)
736 	 || is_enum_type(underlying_type))
737 	&& is_anonymous_type(underlying_type))
738       get_type_declaration(underlying_type)->set_naming_typedef(result);
739 
740     return result;
741   }
742 
743   /// Build an IR node representing a pointer described in BTF.
744   ///
745   /// @param type_id the ID of a BTF representation of a pointer type.
746   ///
747   /// @return a pointer to pointer_type_def that represents @p t.
748   type_or_decl_base_sptr
build_pointer_type(int type_id)749   build_pointer_type(int type_id)
750   {
751     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
752     int kind = btf_kind(t);
753     ABG_ASSERT(kind == BTF_KIND_PTR);
754 
755     type_base_sptr underlying_type =
756       is_type(build_ir_node_from_btf_type(t->type));
757     if (!underlying_type)
758       return type_or_decl_base_sptr();
759     if (env().is_void_type(underlying_type))
760       // Recognize a pointer to void and return a special unique IR
761       // for it.
762       return build_ir_node_for_void_pointer_type();
763 
764     int size = elf_helpers::get_architecture_word_size(elf_handle());
765     size *= 8;
766     pointer_type_def_sptr result(new pointer_type_def(underlying_type, size,
767 						      /*alignment=*/0,
768 						      location()));
769     return result;
770   }
771 
772   /// Build an IR node representing an array type described in BTF.
773   ///
774   /// @param type_id the ID of the BTF representation of an array
775   /// type.
776   ///
777   /// return a pointer to @ref array_type_def representing @p t.
778   type_or_decl_base_sptr
build_array_type(int type_id)779   build_array_type(int type_id)
780   {
781     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
782     int kind = btf_kind(t);
783     ABG_ASSERT(kind == BTF_KIND_ARRAY);
784 
785     const struct btf_array* arr = btf_array(t);
786 
787     type_base_sptr underlying_type =
788       is_type(build_ir_node_from_btf_type(arr->type));
789     if (!underlying_type)
790       return type_or_decl_base_sptr();
791 
792     uint64_t lower_boud = 0;
793     // Note that arr->nelems can be 0;
794     uint64_t upper_bound = arr->nelems ? arr->nelems - 1: 0;
795 
796     array_type_def::subrange_sptr subrange(new array_type_def::subrange_type
797 					   (env(), /*name=*/"",
798 					    lower_boud, upper_bound,
799 					    location()));
800     add_decl_to_scope(subrange, cur_tu()->get_global_scope());
801     canonicalize(subrange);
802     array_type_def::subranges_type subranges = {subrange};
803     array_type_def_sptr result(new array_type_def(underlying_type,
804 						  subranges, location()));
805 
806     return result;
807   }
808 
809   /// Build an IR node representing a qualified type described in BTF.
810   ///
811   /// @param type_id the ID of the BTF representation of an array
812   /// type.
813   ///
814   /// @return a pointer to a qualified_type_def representing @ t.
815   type_or_decl_base_sptr
build_qualified_type(int type_id)816   build_qualified_type(int type_id)
817   {
818     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
819     int kind = btf_kind(t);
820     ABG_ASSERT(kind == BTF_KIND_CONST
821 	       || kind == BTF_KIND_VOLATILE
822 	       || kind == BTF_KIND_RESTRICT);
823 
824     type_base_sptr underlying_type =
825       is_type(build_ir_node_from_btf_type(t->type));
826     if (!underlying_type)
827       return type_or_decl_base_sptr();
828 
829     qualified_type_def::CV qual = qualified_type_def::CV_NONE;
830     if (kind == BTF_KIND_CONST)
831       qual |= qualified_type_def::CV_CONST;
832     else if (kind == BTF_KIND_VOLATILE)
833       qual |= qualified_type_def::CV_VOLATILE;
834     else if (kind == BTF_KIND_RESTRICT)
835       qual |= qualified_type_def::CV_RESTRICT;
836     else
837       ABG_ASSERT_NOT_REACHED;
838 
839     qualified_type_def_sptr result(new qualified_type_def(underlying_type,
840 							  qual, location()));
841     return result;
842   }
843 
844   /// Build an IR node for a class or union type expressed in BTF.
845   ///
846   /// @param type_id the ID of a pointer to a BTF type describing a
847   /// class or union type.
848   ///
849   /// @return a pointer to either a @ref class_decl or a @ref
850   /// union_decl type representing the type expressed by @p t.
851   type_or_decl_base_sptr
build_class_or_union_type(int type_id)852   build_class_or_union_type(int type_id)
853   {
854     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
855 
856     int kind = btf_kind(t);
857     ABG_ASSERT(kind == BTF_KIND_STRUCT
858 	       || kind == BTF_KIND_UNION
859 	       || kind == BTF_KIND_FWD);
860 
861     string type_name;
862     if (t->name_off)
863       type_name = btf_offset_to_string(btf_handle(), t->name_off);
864 
865     bool is_anonymous = type_name.empty();
866     uint64_t size = t->size;
867     size *= 8;
868 
869     bool is_decl_only = (kind == BTF_KIND_FWD);
870 
871     class_or_union_sptr result;
872     if (kind == BTF_KIND_STRUCT
873 	|| (kind == BTF_KIND_FWD
874 	    && BTF_INFO_KFLAG(t->info) == 0 /*struct*/))
875     result.reset(new class_decl(env(), type_name, size,
876 				/*alignment=*/0,
877 				/*is_struct=*/true,
878 				location(),
879 				decl_base::VISIBILITY_DEFAULT,
880 				is_anonymous));
881     else if (kind == BTF_KIND_UNION
882 	     || (kind == BTF_KIND_FWD
883 		 && BTF_INFO_KFLAG(t->info) == 1/*union*/))
884       result.reset(new union_decl(env(), type_name, size, location(),
885 				  decl_base::VISIBILITY_DEFAULT,
886 				  is_anonymous));
887     else
888       ABG_ASSERT_NOT_REACHED;
889 
890     if (is_decl_only)
891       result->set_is_declaration_only(is_decl_only);
892 
893     add_decl_to_scope(result, cur_tu()->get_global_scope());
894 
895     associate_artifact_to_btf_type_id(result, type_id);
896 
897     // For defined classes and unions, add data members to the type
898     // being built.
899     if (!is_decl_only)
900       {
901 	const struct btf_member *m =
902 	  reinterpret_cast<const struct btf_member*>(t + 1);
903 	uint64_t nb_members = btf_vlen(t);
904 
905 	for (uint64_t i = 0; i < nb_members; ++i, ++m)
906 	  {
907 	    type_base_sptr member_type =
908 	      is_type(build_ir_node_from_btf_type(m->type));
909 	    if (!member_type)
910 	      continue;
911 
912 	    string member_name;
913 	    if (m->name_off)
914 	      member_name = btf_offset_to_string(btf_handle(), m->name_off);
915 	    var_decl_sptr data_member(new var_decl(member_name,
916 						   member_type,
917 						   location(),
918 						   /*linkage_name=*/""));
919 	    uint64_t offset_in_bits =
920 	      BTF_INFO_KFLAG(t->info)
921 	      ? BTF_MEMBER_BIT_OFFSET(m->offset)
922 	      : m->offset;
923 
924 	    result->add_data_member(data_member,
925 				    public_access,
926 				    /*is_laid_out=*/true,
927 				    /*is_static=*/false,
928 				    offset_in_bits);
929 	  }
930       }
931     return result;
932   }
933 
934   /// Build an IR node for a function type expressed in BTF.
935   ///
936   /// @param type_id the ID of a pointer to a BTF type describing a
937   /// function type.
938   ///
939   /// @return a pointer to a @ref function_type representing the
940   /// function type expressed by @p t.
941   type_or_decl_base_sptr
build_function_type(int type_id)942   build_function_type(int type_id)
943   {
944     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
945     int kind = btf_kind(t);
946     ABG_ASSERT(kind == BTF_KIND_FUNC_PROTO);
947 
948     type_base_sptr return_type = is_type(build_ir_node_from_btf_type(t->type));
949     if (return_type == nullptr)
950       return type_or_decl_base_sptr();
951 
952     int address_size = elf_helpers::get_architecture_word_size(elf_handle());
953     address_size *= 8;
954     function_type_sptr result(new function_type(env(), address_size,
955 						/*alignment=*/0));
956     result->set_return_type(return_type);
957 
958     associate_artifact_to_btf_type_id(result, type_id);
959 
960     uint16_t nb_parms = btf_vlen(t);
961     const struct btf_param* parm =
962       reinterpret_cast<const struct btf_param*>(t + 1);
963 
964     function_decl::parameters function_parms;
965     for (uint16_t i = 0; i < nb_parms; ++i, ++parm)
966       {
967 	type_base_sptr parm_type;
968 	string parm_name;
969 	bool is_variadic = false;
970 
971 	if (parm->name_off == 0 && parm->type == 0)
972 	  {
973 	    is_variadic = true;
974 	    parm_type = build_ir_node_for_variadic_parameter_type();
975 	  }
976 	else
977 	  {
978 	    parm_name = btf_offset_to_string(btf_handle(), parm->name_off);
979 	    parm_type = is_type(build_ir_node_from_btf_type(parm->type));
980 	  }
981 
982 	if (!parm_type)
983 	  continue;
984 
985 	function_decl::parameter_sptr p
986 	  (new function_decl::parameter(parm_type, parm_name,
987 					location(), is_variadic));
988 	function_parms.push_back(p);
989       }
990     result->set_parameters(function_parms);
991 
992     cur_tu()->bind_function_type_life_time(result);
993 
994     return result;
995   }
996 
997   /// Build an IR node for a function declaration expressed in BTF.
998   ///
999   /// @param type_id the ID of a pointer to a BTF "type" which realy
1000   /// describes a function declaration.
1001   ///
1002   /// @return a pointer to a @ref function_decl representing the
1003   /// function declaration expressed by @p t.
1004   type_or_decl_base_sptr
build_function_decl(int type_id)1005   build_function_decl(int type_id)
1006   {
1007     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1008     int kind = btf_kind(t);
1009     ABG_ASSERT(kind == BTF_KIND_FUNC);
1010 
1011     function_decl_sptr result;
1012 
1013     string fn_name = btf_offset_to_string(btf_handle(), t->name_off);
1014 
1015     type_base_sptr fn_type = is_type(build_ir_node_from_btf_type(t->type));
1016     if (!fn_type)
1017       return result;
1018 
1019     result.reset(new function_decl(fn_name, fn_type, /*is_inline=*/false,
1020 				   location(), /*linkage_name=*/fn_name));
1021 
1022     elf_symbol_sptr fn_sym;
1023     if ((fn_sym = function_symbol_is_exported(fn_name)))
1024       {
1025 	result->set_symbol(fn_sym);
1026 	result->set_is_in_public_symbol_table(true);
1027       }
1028     return result;
1029   }
1030 
1031   /// Build an IR node for a variable declaration expressed in BTF.
1032   ///
1033   /// @param t a pointer to a BTF "type" describing a variable
1034   /// declaration.
1035   ///
1036   /// @return a pointer to @ref var_decl representing the variable
1037   /// declaration expressed by @p t.
1038   type_or_decl_base_sptr
build_variable_decl(int type_id)1039   build_variable_decl(int type_id)
1040   {
1041     const btf_type *t = btf__type_by_id(btf_handle(), type_id);
1042     int kind = btf_kind(t);
1043     ABG_ASSERT(kind == BTF_KIND_VAR);
1044 
1045     var_decl_sptr result;
1046 
1047     string var_name = btf_offset_to_string(btf_handle(), t->name_off);
1048 
1049     type_base_sptr var_type = is_type(build_ir_node_from_btf_type(t->type));
1050     if (!var_type)
1051       return result;
1052 
1053     result.reset(new var_decl(var_name, var_type, location(),
1054 			      /*linkage_name=*/var_name));
1055 
1056     elf_symbol_sptr var_sym;
1057     if ((var_sym = variable_symbol_is_exported(var_name)))
1058       {
1059 	result->set_symbol(var_sym);
1060 	result->set_is_in_public_symbol_table(true);
1061       }
1062     return result;
1063   }
1064 
1065 }; // end class reader.
1066 
1067 /// Create and return a BTF reader (or front-end) which is an instance
1068 /// of @ref btf::reader.
1069 ///
1070 /// @param elf_path the path to the path to the elf file the reader is
1071 /// to be used for.
1072 ///
1073 /// @param debug_info_root_paths a vector to the paths to the
1074 /// directories under which the debug info is to be found for @p
1075 /// elf_path.  Pass an empty vector if th debug info is not in a split
1076 /// file.
1077 ///
1078 /// @param environment the environment used by the current context.
1079 /// This environment contains resources needed by the BTF reader and
1080 /// by the types and declarations that are to be created later.  Note
1081 /// that ABI artifacts that are to be compared all need to be created
1082 /// within the same environment.
1083 ///
1084 /// Please also note that the life time of this environment object
1085 /// must be greater than the life time of the resulting @ref
1086 /// reader the context uses resources that are allocated in the
1087 /// environment.
1088 ///
1089 /// @param load_all_types if set to false only the types that are
1090 /// reachable from publicly exported declarations (of functions and
1091 /// variables) are read.  If set to true then all types found in the
1092 /// debug information are loaded.
1093 ///
1094 /// @param linux_kernel_mode if set to true, then consider the special
1095 /// linux kernel symbol tables when determining if a symbol is
1096 /// exported or not.
1097 ///
1098 /// @return a smart pointer to the resulting btf::reader.
1099 elf_based_reader_sptr
create_reader(const std::string & elf_path,const vector<char ** > & debug_info_root_paths,environment & env,bool load_all_types,bool linux_kernel_mode)1100 create_reader(const std::string&	elf_path,
1101 	      const vector<char**>&	debug_info_root_paths,
1102 	      environment&		env,
1103 	      bool			load_all_types,
1104 	      bool			linux_kernel_mode)
1105 {
1106   reader_sptr rdr = reader::create(elf_path, debug_info_root_paths, env,
1107 				   load_all_types, linux_kernel_mode);
1108   return rdr;
1109 }
1110 
1111 } // end namespace btf
1112 } // end namespace abigail
1113 
1114 #endif //WITH_BTF
1115