libabigail
abg-ctf-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) 2021-2023 Oracle, Inc.
5//
6// Author: Jose E. Marchesi
7
8/// @file
9///
10/// This file contains the definitions of the entry points to
11/// de-serialize an instance of @ref abigail::corpus from a file in
12/// ELF format, containing CTF information.
13
14#include "config.h"
15
16#include <fcntl.h> /* For open(3) */
17#include <sstream>
18#include <iostream>
19#include <memory>
20#include <map>
21#include <algorithm>
22
23#include "ctf-api.h"
24
25#include "abg-internal.h"
26#include "abg-ir-priv.h"
27#include "abg-symtab-reader.h"
28
29
30#include "abg-internal.h"
31// <headers defining libabigail's API go under here>
32ABG_BEGIN_EXPORT_DECLARATIONS
33
34#include "abg-ctf-reader.h"
36#include "abg-corpus.h"
37#include "abg-tools-utils.h"
38#include "abg-elf-helpers.h"
39
40ABG_END_EXPORT_DECLARATIONS
41// </headers defining libabigail's API>
42
43namespace abigail
44{
45namespace ctf
46{
47using std::dynamic_pointer_cast;
50
51class reader;
52
54process_ctf_typedef(reader *rdr,
55 ctf_dict_t *ctf_dictionary,
56 ctf_id_t ctf_type);
57
58static type_decl_sptr
59process_ctf_base_type(reader *rdr,
60 ctf_dict_t *ctf_dictionary,
61 ctf_id_t ctf_type);
62
63static decl_base_sptr
64build_ir_node_for_variadic_parameter_type(reader &rdr,
65 const translation_unit_sptr& tunit);
66
67static decl_base_sptr
68build_ir_node_for_void_type(reader& rdr,
69 const translation_unit_sptr& tunit);
70
72build_ir_node_for_void_pointer_type(reader& rdr,
73 const translation_unit_sptr& tunit);
74
76process_ctf_function_type(reader *rdr,
77 ctf_dict_t *ctf_dictionary,
78 ctf_id_t ctf_type);
79
80static void
81process_ctf_sou_members(reader *rdr,
82 ctf_dict_t *ctf_dictionary,
83 ctf_id_t ctf_type,
84 class_or_union_sptr sou);
85
86static type_base_sptr
87process_ctf_forward_type(reader *rdr,
88 ctf_dict_t *ctf_dictionary,
89 ctf_id_t ctf_type);
90
91static class_decl_sptr
92process_ctf_struct_type(reader *rdr,
93 ctf_dict_t *ctf_dictionary,
94 ctf_id_t ctf_type);
95
96static union_decl_sptr
97process_ctf_union_type(reader *rdr,
98 ctf_dict_t *ctf_dictionary,
99 ctf_id_t ctf_type);
100
102process_ctf_array_type(reader *rdr,
103 ctf_dict_t *ctf_dictionary,
104 ctf_id_t ctf_type);
105
106static type_base_sptr
107process_ctf_qualified_type(reader *rdr,
108 ctf_dict_t *ctf_dictionary,
109 ctf_id_t ctf_type);
110
112process_ctf_pointer_type(reader *rdr,
113 ctf_dict_t *ctf_dictionary,
114 ctf_id_t ctf_type);
115
117process_ctf_enum_type(reader *rdr,
118 ctf_dict_t *ctf_dictionary,
119 ctf_id_t ctf_type);
120
121static void
122fill_ctf_section(const Elf_Scn *elf_section, ctf_sect_t *ctf_section);
123
124static ctf_id_t
125lookup_symbol_in_ctf_archive(ctf_archive_t *ctfa, ctf_dict_t **ctf_dict,
126 const char *sym_name);
127
128static std::string
129dic_type_key(ctf_dict_t *dic, ctf_id_t ctf_type);
130
131/// The abstraction of a CTF reader.
132///
133/// It groks the type information contains the CTF-specific part of
134/// the ELF file and builds an ABI corpus out of it.
135class reader : public elf_based_reader
136{
137 /// The CTF archive read from FILENAME. If an archive couldn't
138 /// be read from the file then this is NULL.
139 ctf_archive_t *ctfa;
140
141 /// A map associating CTF type ids with libabigail IR types. This
142 /// is used to reuse already generated types.
144
145 /// A set associating unknown CTF type ids
146 std::set<ctf_id_t> unknown_types_set;
147
148 /// Raw contents of several sections from the ELF file. These are
149 /// used by libctf.
150 ctf_sect_t ctf_sect;
151 ctf_sect_t symtab_sect;
152 ctf_sect_t strtab_sect;
153 translation_unit_sptr cur_tu_;
154
155public:
156
157 /// Getter of the exported decls builder object.
158 ///
159 /// @return the exported decls builder.
160 corpus::exported_decls_builder*
161 exported_decls_builder()
162 {return corpus()->get_exported_decls_builder().get();}
163
164 /// Associate a given CTF type ID with a given libabigail IR type.
165 ///
166 /// @param dic the dictionnary the type belongs to.
167 ///
168 /// @param ctf_type the type ID.
169 ///
170 /// @param type the type to associate to the ID.
171 void
172 add_type(ctf_dict_t *dic, ctf_id_t ctf_type, type_base_sptr type)
173 {
174 string key = dic_type_key(dic, ctf_type);
175 types_map.insert(std::make_pair(key, type));
176 }
177
178 /// Insert a given CTF unknown type ID.
179 ///
180 /// @param ctf_type the unknown type ID to be added.
181 void
182 add_unknown_type(ctf_id_t ctf_type)
183 {
184 unknown_types_set.insert(ctf_type);
185 }
186
187 /// Lookup a given CTF type ID in the types map.
188 ///
189 /// @param dic the dictionnary the type belongs to.
190 ///
191 /// @param ctf_type the type ID of the type to lookup.
192 type_base_sptr
193 lookup_type(ctf_dict_t *dic, ctf_id_t ctf_type)
194 {
195 type_base_sptr result;
196 std::string key = dic_type_key(dic, ctf_type);
197
198 auto search = types_map.find(key);
199 if (search != types_map.end())
200 result = search->second;
201
202 return result;
203 }
204
205 /// Lookup a given CTF unknown type ID in the unknown set.
206 /// @param ctf_type the unknown type ID to lookup.
207 bool
208 lookup_unknown_type(ctf_id_t ctf_type)
209 { return unknown_types_set.find(ctf_type) != unknown_types_set.end(); }
210
211 /// Canonicalize all the types stored in the types map.
212 void
213 canonicalize_all_types(void)
214 {
216 (types_map.begin(), types_map.end(),
217 [](const string_type_base_sptr_map_type::const_iterator& i)
218 {return i->second;});
219 }
220
221 /// Constructor.
222 ///
223 /// @param elf_path the path to the ELF file.
224 ///
225 /// @param debug_info_root_paths vector with the paths
226 /// to directories where .debug file is located.
227 ///
228 /// @param env the environment used by the current context.
229 /// This environment contains resources needed by the reader and by
230 /// the types and declarations that are to be created later. Note
231 /// that ABI artifacts that are to be compared all need to be
232 /// created within the same environment.
233 reader(const string& elf_path,
234 const vector<char**>& debug_info_root_paths,
235 environment& env)
236 : elf_based_reader(elf_path, debug_info_root_paths, env)
237 {
238 initialize();
239 }
240
241 /// Initializer of the reader.
242 ///
243 /// This is useful to clear out the data used by the reader and get
244 /// it ready to be used again.
245 ///
246 /// Note that the reader eeps the same environment it has been
247 /// originally created with.
248 ///
249 /// Please also note that the life time of this environment object
250 /// must be greater than the life time of the resulting @ref
251 /// reader the context uses resources that are allocated in
252 /// the environment.
253 void
254 initialize()
255 {
256 ctfa = nullptr;
257 types_map.clear();
258 cur_tu_.reset();
259 corpus_group().reset();
260 }
261
262 /// Initializer of the reader.
263 ///
264 /// @param elf_path the new path to the new ELF file to use.
265 ///
266 /// @param debug_info_root_paths a vector of paths to use to look
267 /// for debug info that is split out into a separate file.
268 ///
269 /// @param load_all_types currently not used.
270 ///
271 /// @param linux_kernel_mode currently not used.
272 ///
273 /// This is useful to clear out the data used by the reader and get
274 /// it ready to be used again.
275 ///
276 /// Note that the reader eeps the same environment it has been
277 /// originally created with.
278 ///
279 /// Please also note that the life time of this environment object
280 /// must be greater than the life time of the resulting @ref
281 /// reader the context uses resources that are allocated in
282 /// the environment.
283 void
284 initialize(const string& elf_path,
285 const vector<char**>& debug_info_root_paths,
286 bool load_all_types = false,
287 bool linux_kernel_mode = false)
288 {
289 load_all_types = load_all_types;
290 linux_kernel_mode = linux_kernel_mode;
291 elf_based_reader::initialize(elf_path, debug_info_root_paths);
292 }
293
294 /// Setter of the current translation unit.
295 ///
296 /// @param tu the current translation unit being constructed.
297 void
298 cur_transl_unit(translation_unit_sptr tu)
299 {
300 if (tu)
301 cur_tu_ = tu;
302 }
303
304 /// Getter of the current translation unit.
305 ///
306 /// @return the current translation unit being constructed.
308 cur_transl_unit() const
309 {return cur_tu_;}
310
311 /// Getter of the environment of the current CTF reader.
312 ///
313 /// @return the environment of the current CTF reader.
314 const environment&
315 env() const
316 {return options().env;}
317
318 /// Getter of the environment of the current CTF reader.
319 ///
320 /// @return the environment of the current CTF reader.
321 environment&
322 env()
323 {return options().env;}
324
325 /// Look for vmlinux.ctfa file in default directory or in
326 /// directories provided by debug-info-dir command line option,
327 /// it stores location path in @ref ctfa_file.
328 ///
329 /// @param ctfa_file file name found.
330 /// @return true if file is found.
331 bool
332 find_ctfa_file(std::string& ctfa_file)
333 {
334 std::string ctfa_dirname;
335 dir_name(corpus_path(), ctfa_dirname, false);
336
337 // In corpus group we assume vmlinux as first file to
338 // be processed, so default location for vmlinux.cfa
339 // is vmlinux dirname.
340 ctfa_file = ctfa_dirname + "/vmlinux.ctfa";
341 if (file_exists(ctfa_file))
342 return true;
343
344 // If it's proccessing a module, then location directory
345 // for vmlinux.ctfa should be provided with --debug-info-dir
346 // option.
347 for (const auto& path : debug_info_root_paths())
348 if (tools_utils::find_file_under_dir(*path, "vmlinux.ctfa", ctfa_file))
349 return true;
350
351 return false;
352 }
353
354 /// Slurp certain information from the underlying ELF file, and
355 /// install it the current libabigail corpus associated to the
356 /// current CTF reader.
357 ///
358 /// @param status the resulting status flags.
359 void
360 slurp_elf_info(fe_iface::status& status)
361 {
362 // Read the ELF-specific parts of the corpus.
364
365 corpus_sptr corp = corpus();
366 if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN)
367 && corpus_group())
368 {
369 // Not finding any debug info so far is expected if we are
370 // building a kABI.
371 status &= static_cast<abigail::fe_iface::status>
372 (~STATUS_DEBUG_INFO_NOT_FOUND);
373 return;
374 }
375
376 if ((status & STATUS_NO_SYMBOLS_FOUND)
377 || !(status & STATUS_OK))
378 // Either we couldn't find ELF symbols or something went badly
379 // wrong. There is nothing we can do with this ELF file. Bail
380 // out.
381 return;
382
383 GElf_Ehdr *ehdr, eh_mem;
384 if (!(ehdr = gelf_getehdr(elf_handle(), &eh_mem)))
385 return;
386
387 // ET_{EXEC,DYN} needs .dyn{sym,str} in ctf_arc_bufopen
388 const char *symtab_name = ".dynsym";
389 const char *strtab_name = ".dynstr";
390
391 if (ehdr->e_type == ET_REL)
392 {
393 symtab_name = ".symtab";
394 strtab_name = ".strtab";
395 }
396
397 const Elf_Scn* ctf_scn = find_ctf_section();
398 fill_ctf_section(ctf_scn, &ctf_sect);
399
400 const Elf_Scn* symtab_scn =
401 elf_helpers::find_section_by_name(elf_handle(), symtab_name);
402 fill_ctf_section(symtab_scn, &symtab_sect);
403
404 const Elf_Scn* strtab_scn =
405 elf_helpers::find_section_by_name(elf_handle(), strtab_name);
406 fill_ctf_section(strtab_scn, &strtab_sect);
407
408 status |= fe_iface::STATUS_OK;
409 }
410
411 /// Process a CTF archive and create libabigail IR for the types,
412 /// variables and function declarations found in the archive, iterating
413 /// over public symbols. The IR is added to the given corpus.
414 void
415 process_ctf_archive()
416 {
417 corpus_sptr corp = corpus();
418 /* We only have a translation unit. */
419 translation_unit_sptr ir_translation_unit =
420 std::make_shared<translation_unit>(env(), "", 64);
421 ir_translation_unit->set_language(translation_unit::LANG_C);
422 corp->add(ir_translation_unit);
423 cur_transl_unit(ir_translation_unit);
424
425 int ctf_err;
426 ctf_dict_t *ctf_dict, *dict_tmp;
427 const auto symt = symtab();
428 symtab_reader::symtab_filter filter = symt->make_filter();
429 filter.set_public_symbols();
430 std::string dict_name;
431
432 if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN)
433 && corpus_group())
434 {
436 // remove .* suffix
437 std::size_t pos = dict_name.find(".");
438 if (pos != string::npos)
439 dict_name.erase(pos);
440
441 std::replace(dict_name.begin(), dict_name.end(), '-', '_');
442 }
443
444 if ((ctf_dict = ctf_dict_open(ctfa,
445 dict_name.empty() ? NULL : dict_name.c_str(),
446 &ctf_err)) == NULL)
447 {
448 fprintf(stderr, "ERROR dictionary not found\n");
449 abort();
450 }
451
452 dict_tmp = ctf_dict;
453
454 for (const auto& symbol : symtab_reader::filtered_symtab(*symt, filter))
455 {
456 std::string sym_name = symbol->get_name();
457 ctf_id_t ctf_sym_type;
458
459 ctf_sym_type = lookup_symbol_in_ctf_archive(ctfa, &ctf_dict,
460 sym_name.c_str());
461 if (ctf_sym_type == CTF_ERR)
462 continue;
463
464 if (ctf_type_kind(ctf_dict, ctf_sym_type) != CTF_K_FUNCTION)
465 {
466 const char *var_name = sym_name.c_str();
467 type_base_sptr var_type = build_type(ctf_dict, ctf_sym_type);
468 if (!var_type)
469 /* Ignore variable if its type can't be sorted out. */
470 continue;
471
472 var_decl_sptr var_declaration;
473 var_declaration.reset(new var_decl(var_name,
474 var_type,
475 location(),
476 var_name));
477
478 var_declaration->set_symbol(symbol);
479 add_decl_to_scope(var_declaration,
480 ir_translation_unit->get_global_scope());
481 var_declaration->set_is_in_public_symbol_table(true);
482 maybe_add_var_to_exported_decls(var_declaration.get());
483 }
484 else
485 {
486 const char *func_name = sym_name.c_str();
487 ctf_id_t ctf_sym = ctf_sym_type;
488 type_base_sptr func_type = build_type(ctf_dict, ctf_sym);
489 if (!func_type)
490 /* Ignore function if its type can't be sorted out. */
491 continue;
492
493 function_decl_sptr func_declaration;
494 func_declaration.reset(new function_decl(func_name,
495 func_type,
496 0 /* is_inline */,
497 location()));
498 func_declaration->set_symbol(symbol);
499 add_decl_to_scope(func_declaration,
500 ir_translation_unit->get_global_scope());
501 func_declaration->set_is_in_public_symbol_table(true);
502 maybe_add_fn_to_exported_decls(func_declaration.get());
503 }
504
505 ctf_dict = dict_tmp;
506 }
507
508 ctf_dict_close(ctf_dict);
509 /* Canonicalize all the types generated above. This must be
510 done "a posteriori" because the processing of types may
511 require other related types to not be already
512 canonicalized. */
513 canonicalize_all_types();
514 }
515
516 /// Add a new type declaration to the given libabigail IR corpus CORP.
517 ///
518 /// @param ctf_dictionary the CTF dictionary being read.
519 /// @param ctf_type the CTF type ID of the source type.
520 ///
521 /// Note that if @ref ctf_type can't reliably be translated to the IR
522 /// then it is simply ignored.
523 ///
524 /// @return a shared pointer to the IR node for the type.
525 type_base_sptr
526 process_ctf_type(ctf_dict_t *ctf_dictionary,
527 ctf_id_t ctf_type)
528 {
529 corpus_sptr corp = corpus();
530 translation_unit_sptr tunit = cur_transl_unit();
531 int type_kind = ctf_type_kind(ctf_dictionary, ctf_type);
532 type_base_sptr result;
533
534 if (lookup_unknown_type(ctf_type))
535 return nullptr;
536
537 if ((result = lookup_type(ctf_dictionary, ctf_type)))
538 return result;
539
540 switch (type_kind)
541 {
542 case CTF_K_INTEGER:
543 case CTF_K_FLOAT:
544 {
545 type_decl_sptr type_decl
546 = process_ctf_base_type(this, ctf_dictionary, ctf_type);
547 result = is_type(type_decl);
548 break;
549 }
550 case CTF_K_TYPEDEF:
551 {
552 typedef_decl_sptr typedef_decl
553 = process_ctf_typedef(this, ctf_dictionary, ctf_type);
554 result = is_type(typedef_decl);
555 break;
556 }
557 case CTF_K_POINTER:
558 {
559 pointer_type_def_sptr pointer_type
560 = process_ctf_pointer_type(this, ctf_dictionary, ctf_type);
561 result = pointer_type;
562 break;
563 }
564 case CTF_K_CONST:
565 case CTF_K_VOLATILE:
566 case CTF_K_RESTRICT:
567 {
568 type_base_sptr qualified_type
569 = process_ctf_qualified_type(this, ctf_dictionary, ctf_type);
570 result = qualified_type;
571 break;
572 }
573 case CTF_K_ARRAY:
574 {
575 array_type_def_sptr array_type
576 = process_ctf_array_type(this, ctf_dictionary, ctf_type);
577 result = array_type;
578 break;
579 }
580 case CTF_K_ENUM:
581 {
582 enum_type_decl_sptr enum_type
583 = process_ctf_enum_type(this, ctf_dictionary, ctf_type);
584 result = enum_type;
585 break;
586 }
587 case CTF_K_FUNCTION:
588 {
589 function_type_sptr function_type
590 = process_ctf_function_type(this, ctf_dictionary, ctf_type);
591 result = function_type;
592 break;
593 }
594 case CTF_K_STRUCT:
595 {
596 class_decl_sptr struct_decl
597 = process_ctf_struct_type(this, ctf_dictionary, ctf_type);
598 result = is_type(struct_decl);
599 break;
600 }
601 case CTF_K_FORWARD:
602 result = process_ctf_forward_type(this, ctf_dictionary, ctf_type);
603 break;
604 case CTF_K_UNION:
605 {
606 union_decl_sptr union_decl
607 = process_ctf_union_type(this, ctf_dictionary, ctf_type);
608 result = is_type(union_decl);
609 break;
610 }
611 case CTF_K_UNKNOWN:
612 /* Unknown types are simply ignored. */
613 default:
614 break;
615 }
616
617 if (!result)
618 {
619 fprintf(stderr, "NOT PROCESSED TYPE %lu\n", ctf_type);
620 add_unknown_type(ctf_type);
621 }
622
623 return result;
624 }
625
626 /// Given a CTF type id, build the corresponding libabigail IR type.
627 /// If the IR type has been generated it returns the corresponding
628 /// type.
629 ///
630 /// @param ctf_dictionary the CTF dictionary being read.
631 /// @param ctf_type the CTF type ID of the looked type.
632 ///
633 /// Note that if @ref ctf_type can't reliably be translated to the IR
634 /// then a NULL shared pointer is returned.
635 ///
636 /// @return a shared pointer to the IR node for the type.
637 type_base_sptr
638 build_type(ctf_dict_t *ctf_dictionary, ctf_id_t ctf_type)
639 {
640 type_base_sptr result = lookup_type(ctf_dictionary, ctf_type);
641
642 if (!result)
643 result = process_ctf_type(ctf_dictionary, ctf_type);
644 return result;
645 }
646
647 /// Read the CTF information in the binary and construct an ABI
648 /// corpus from it.
649 ///
650 /// @param status output parameter. Contains the status of the ABI
651 /// corpus construction.
652 ///
653 /// @return the corpus created as a result of processing the debug
654 /// information.
655 corpus_sptr
656 read_corpus(fe_iface::status &status)
657 {
658 corpus_sptr corp = corpus();
660
661 corpus::origin origin = corpus()->get_origin();
662 origin |= corpus::CTF_ORIGIN;
663 corp->set_origin(origin);
664
665 slurp_elf_info(status);
667 return corpus_sptr();
668
669 if (!(origin & corpus::LINUX_KERNEL_BINARY_ORIGIN)
671 return corp;
672
673 int errp;
674 if ((corp->get_origin() & corpus::LINUX_KERNEL_BINARY_ORIGIN)
675 && corpus_group())
676 {
677 if (ctfa == NULL)
678 {
679 std::string ctfa_filename;
680 if (find_ctfa_file(ctfa_filename))
681 ctfa = ctf_arc_open(ctfa_filename.c_str(), &errp);
682 }
683 }
684 else
685 /* Build the ctfa from the contents of the relevant ELF sections,
686 and process the CTF archive in the read context, if any.
687 Information about the types, variables, functions, etc contained
688 in the archive are added to the given corpus. */
689 ctfa = ctf_arc_bufopen(&ctf_sect, &symtab_sect,
690 &strtab_sect, &errp);
691
692 env().canonicalization_is_done(false);
693 if (ctfa == NULL)
695 else
696 {
697 process_ctf_archive();
698 corpus()->sort_functions();
699 corpus()->sort_variables();
700 }
701
702 env().canonicalization_is_done(true);
703
704 return corp;
705 }
706
707 /// Destructor of the CTF reader.
708 ~reader()
709 {
710 ctf_close(ctfa);
711 }
712}; // end class reader.
713
714typedef shared_ptr<reader> reader_sptr;
715
716/// Build and return a typedef libabigail IR.
717///
718/// @param rdr the read context.
719/// @param ctf_dictionary the CTF dictionary being read.
720/// @param ctf_type the CTF type ID of the source type.
721///
722/// @return a shared pointer to the IR node for the typedef.
723
725process_ctf_typedef(reader *rdr,
726 ctf_dict_t *ctf_dictionary,
727 ctf_id_t ctf_type)
728{
729 corpus_sptr corp = rdr->corpus();
730 translation_unit_sptr tunit = rdr->cur_transl_unit();
731 typedef_decl_sptr result;
732
733 ctf_id_t ctf_utype = ctf_type_reference(ctf_dictionary, ctf_type);
734 if (ctf_utype == CTF_ERR)
735 return result;
736
737 const char *typedef_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
738 if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group())
739 if ((result = lookup_typedef_type(typedef_name, *corp)))
740 return result;
741
742 type_base_sptr utype = rdr->build_type(ctf_dictionary, ctf_utype);
743
744 if (!utype)
745 return result;
746
747 result = dynamic_pointer_cast<typedef_decl>
748 (rdr->lookup_type(ctf_dictionary, ctf_type));
749 if (result)
750 return result;
751
752 result.reset(new typedef_decl(typedef_name, utype, location(),
753 typedef_name /* mangled_name */));
754
755 /* If this typedef "names" an anonymous type, reflect this fact in
756 the underlying type. In C enum, struct and union types can be
757 anonymous. */
758 if (is_anonymous_type(utype)
759 && (is_enum_type(utype) || is_class_or_union_type(utype)))
760 {
761 decl_base_sptr decl = is_decl(utype);
762 ABG_ASSERT(decl);
763 decl->set_naming_typedef(result);
764 }
765
766 if (result)
767 {
768 add_decl_to_scope(result, tunit->get_global_scope());
769 rdr->add_type(ctf_dictionary, ctf_type, result);
770 }
771
772 return result;
773}
774
775/// Build and return an integer or float type declaration libabigail
776/// IR.
777///
778/// @param rdr the read context.
779/// @param ctf_dictionary the CTF dictionary being read.
780/// @param ctf_type the CTF type ID of the source type.
781///
782/// @return a shared pointer to the IR node for the type.
783
784static type_decl_sptr
785process_ctf_base_type(reader *rdr,
786 ctf_dict_t *ctf_dictionary,
787 ctf_id_t ctf_type)
788{
789 corpus_sptr corp = rdr->corpus();
790 translation_unit_sptr tunit = rdr->cur_transl_unit();
791 type_decl_sptr result;
792
793 ctf_id_t ctf_ref = ctf_type_reference(ctf_dictionary, ctf_type);
794 const char *type_name = ctf_type_name_raw(ctf_dictionary,
795 (ctf_ref != CTF_ERR) ? ctf_ref : ctf_type);
796
797 /* Get the type encoding and extract some useful properties of
798 the type from it. In case of any error, just ignore the
799 type. */
800 ctf_encoding_t type_encoding;
801 if (ctf_type_encoding(ctf_dictionary,
802 (ctf_ref != CTF_ERR) ? ctf_ref : ctf_type,
803 &type_encoding))
804 return result;
805
806 /* Create the IR type corresponding to the CTF type. */
807 if (type_encoding.cte_bits == 0
808 && type_encoding.cte_format == CTF_INT_SIGNED)
809 {
810 /* This is the `void' type. */
811 decl_base_sptr type_declaration = build_ir_node_for_void_type(*rdr,
812 tunit);
813 type_base_sptr void_type = is_type(type_declaration);
814 result = is_type_decl(type_declaration);
815 canonicalize(result);
816 }
817 else
818 {
819 if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group())
820 {
821 string normalized_type_name = type_name;
822 integral_type int_type;
823 if (parse_integral_type(type_name, int_type))
824 normalized_type_name = int_type.to_string();
825 if ((result = lookup_basic_type(normalized_type_name, *corp)))
826 return result;
827 }
828
829 result = lookup_basic_type(type_name, *corp);
830 if (!result)
831 result.reset(new type_decl(rdr->env(),
832 type_name,
833 type_encoding.cte_bits,
834 /*alignment=*/0,
835 location(),
836 type_name /* mangled_name */));
837
838 }
839
840 if (result)
841 {
842 add_decl_to_scope(result, tunit->get_global_scope());
843 rdr->add_type(ctf_dictionary, ctf_type, result);
844 }
845
846 return result;
847}
848
849/// Build the IR node for a variadic parameter type.
850///
851/// @param rdr the read context to use.
852///
853/// @param tunit the translation unit it should belong to.
854///
855/// @return the variadic parameter type.
856static decl_base_sptr
857build_ir_node_for_variadic_parameter_type(reader &rdr,
858 const translation_unit_sptr& tunit)
859{
860
861 const ir::environment& env = rdr.env();
862 type_base_sptr t = env.get_variadic_parameter_type();
863 decl_base_sptr type_declaration = get_type_declaration(t);
864 add_decl_to_scope(type_declaration, tunit->get_global_scope());
865 canonicalize(t);
866 return type_declaration;
867}
868
869/// Build the IR node for a void type.
870///
871/// Note that this returns the unique pointer
872/// environment::get_void_type(), which is added to the current
873/// translation unit if it's the first it's being used.
874///
875/// @param rdr the read context to use.
876///
877/// @param tunit the translation unit it should belong to.
878///
879/// @return the void type type.
880static decl_base_sptr
881build_ir_node_for_void_type(reader& rdr, const translation_unit_sptr& tunit)
882{
883 const environment& env = rdr.env();
884 type_base_sptr t = env.get_void_type();
885 add_decl_to_scope(is_decl(t), tunit->get_global_scope());
886 canonicalize(t);
887 return is_decl(t);
888}
889
890/// Build the IR node for a void pointer type.
891///
892/// Note that this returns the unique pointer
893/// environment::get_void_pointer_type(), which is added to the
894/// current translation unit if it's the first it's being used.
895///
896/// @param rdr the read context to use.
897///
898/// @param tunit the translation unit it should belong to.
899///
900/// @return the void pointer type.
902build_ir_node_for_void_pointer_type(reader& rdr,
903 const translation_unit_sptr& tunit)
904{
905 const environment& env = rdr.env();
906 type_base_sptr t = env.get_void_pointer_type();
907 add_decl_to_scope(is_decl(t), tunit->get_global_scope());
908 canonicalize(t);
909 return is_decl(t);
910}
911
912/// Build and return a function type libabigail IR.
913///
914/// @param rdr the read context.
915/// @param ctf_dictionary the CTF dictionary being read.
916/// @param ctf_type the CTF type ID of the source type.
917///
918/// @return a shared pointer to the IR node for the function type.
919
921process_ctf_function_type(reader *rdr,
922 ctf_dict_t *ctf_dictionary,
923 ctf_id_t ctf_type)
924{
925 corpus_sptr corp = rdr->corpus();
926 translation_unit_sptr tunit = rdr->cur_transl_unit();
927 function_type_sptr result;
928
929 /* Fetch the function type info from the CTF type. */
930 ctf_funcinfo_t funcinfo;
931 ctf_func_type_info(ctf_dictionary, ctf_type, &funcinfo);
932 int vararg_p = funcinfo.ctc_flags & CTF_FUNC_VARARG;
933
934 /* Take care first of the result type. */
935 ctf_id_t ctf_ret_type = funcinfo.ctc_return;
936 type_base_sptr ret_type = rdr->build_type(ctf_dictionary, ctf_ret_type);
937 if (!ret_type)
938 return result;
939
940 /* Now process the argument types. */
941 int argc = funcinfo.ctc_argc;
942 std::vector<ctf_id_t> argv(argc);
943 if (static_cast<ctf_id_t>(ctf_func_type_args(ctf_dictionary, ctf_type,
944 argc, argv.data())) == CTF_ERR)
945 return result;
946
947 function_decl::parameters function_parms;
948 for (int i = 0; i < argc; i++)
949 {
950 ctf_id_t ctf_arg_type = argv[i];
951 type_base_sptr arg_type = rdr->build_type(ctf_dictionary, ctf_arg_type);
952 if (!arg_type)
953 return result;
954
956 (new function_decl::parameter(arg_type, "",
957 location(),
958 false,
959 false /* is_artificial */));
960 function_parms.push_back(parm);
961 }
962
963 if (vararg_p)
964 {
965 type_base_sptr arg_type =
966 is_type(build_ir_node_for_variadic_parameter_type(*rdr, tunit));
967
969 (new function_decl::parameter(arg_type, "",
970 location(),
971 true,
972 false /* is_artificial */));
973 function_parms.push_back(parm);
974 }
975
976 result = dynamic_pointer_cast<function_type>
977 (rdr->lookup_type(ctf_dictionary, ctf_type));
978 if (result)
979 return result;
980
981 /* Ok now the function type itself. */
982 result.reset(new function_type(ret_type,
983 function_parms,
984 tunit->get_address_size(),
985 /*alignment=*/0));
986
987 if (result)
988 {
989 tunit->bind_function_type_life_time(result);
990 result->set_is_artificial(true);
991 decl_base_sptr function_type_decl = get_type_declaration(result);
992 add_decl_to_scope(function_type_decl, tunit->get_global_scope());
993 rdr->add_type(ctf_dictionary, ctf_type, result);
994 }
995
996 return result;
997}
998
999/// Add member information to a IR struct or union type.
1000///
1001/// @param rdr the read context.
1002/// @param ctf_dictionary the CTF dictionary being read.
1003/// @param ctf_type the CTF type ID of the source type.
1004/// @param sou the IR struct or union type to which add the members.
1005
1006static void
1007process_ctf_sou_members(reader *rdr,
1008 ctf_dict_t *ctf_dictionary,
1009 ctf_id_t ctf_type,
1010 class_or_union_sptr sou)
1011{
1012 corpus_sptr corp = rdr->corpus();
1013 translation_unit_sptr tunit = rdr->cur_transl_unit();
1014 ssize_t member_size;
1015 ctf_next_t *member_next = NULL;
1016 const char *member_name = NULL;
1017 ctf_id_t member_ctf_type;
1018
1019 while ((member_size = ctf_member_next(ctf_dictionary, ctf_type,
1020 &member_next, &member_name,
1021 &member_ctf_type,
1022 0 /* flags */)) >= 0)
1023 {
1024 ctf_membinfo_t membinfo;
1025
1026 if (static_cast<ctf_id_t>(ctf_member_info(ctf_dictionary,
1027 ctf_type,
1028 member_name,
1029 &membinfo)) == CTF_ERR)
1030 return;
1031
1032 /* Build the IR for the member's type. */
1033 type_base_sptr member_type = rdr->build_type(ctf_dictionary,
1034 member_ctf_type);
1035 if (!member_type)
1036 /* Ignore this member. */
1037 continue;
1038
1039 /* Create a declaration IR node for the member and add it to the
1040 struct type. */
1041 var_decl_sptr data_member_decl(new var_decl(member_name,
1042 member_type,
1043 location(),
1044 member_name));
1045 sou->add_data_member(data_member_decl,
1046 public_access,
1047 true /* is_laid_out */,
1048 false /* is_static */,
1049 membinfo.ctm_offset);
1050 }
1051 if (ctf_errno(ctf_dictionary) != ECTF_NEXT_END)
1052 fprintf(stderr, "ERROR from ctf_member_next\n");
1053}
1054
1055/// Create a declaration-only union or struct type and add it to the
1056/// IR.
1057///
1058/// @param rdr the read context.
1059/// @param ctf_dictionary the CTF dictionary being read.
1060/// @param ctf_type the CTF type ID of the source type.
1061/// @return the resulting IR node created.
1062
1063static type_base_sptr
1064process_ctf_forward_type(reader *rdr,
1065 ctf_dict_t *ctf_dictionary,
1066 ctf_id_t ctf_type)
1067{
1068 translation_unit_sptr tunit = rdr->cur_transl_unit();
1069 decl_base_sptr result;
1070 std::string type_name = ctf_type_name_raw(ctf_dictionary,
1071 ctf_type);
1072 bool type_is_anonymous = (type_name == "");
1073 uint32_t kind = ctf_type_kind_forwarded (ctf_dictionary, ctf_type);
1074
1075 if (kind == CTF_K_UNION)
1076 {
1077 union_decl_sptr
1078 union_fwd(new union_decl(rdr->env(),
1079 type_name,
1080 /*alignment=*/0,
1081 location(),
1082 decl_base::VISIBILITY_DEFAULT,
1083 type_is_anonymous));
1084 union_fwd->set_is_declaration_only(true);
1085 result = union_fwd;
1086 }
1087 else
1088 {
1089 if (!type_is_anonymous)
1090 if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group())
1091 if ((result = lookup_class_type(type_name, *corp)))
1092 return is_type(result);
1093
1095 struct_fwd(new class_decl(rdr->env(), type_name,
1096 /*alignment=*/0, /*size=*/0,
1097 true /* is_struct */,
1098 location(),
1099 decl_base::VISIBILITY_DEFAULT,
1100 type_is_anonymous));
1101 struct_fwd->set_is_declaration_only(true);
1102 result = struct_fwd;
1103 }
1104
1105 if (!result)
1106 return is_type(result);
1107
1108 add_decl_to_scope(result, tunit->get_global_scope());
1109 rdr->add_type(ctf_dictionary, ctf_type, is_type(result));
1110
1111 return is_type(result);
1112}
1113
1114/// Build and return a struct type libabigail IR.
1115///
1116/// @param rdr the read context.
1117/// @param ctf_dictionary the CTF dictionary being read.
1118/// @param ctf_type the CTF type ID of the source type.
1119///
1120/// @return a shared pointer to the IR node for the struct type.
1121
1122static class_decl_sptr
1123process_ctf_struct_type(reader *rdr,
1124 ctf_dict_t *ctf_dictionary,
1125 ctf_id_t ctf_type)
1126{
1127 corpus_sptr corp = rdr->corpus();
1128 translation_unit_sptr tunit = rdr->cur_transl_unit();
1129 class_decl_sptr result;
1130 std::string struct_type_name = ctf_type_name_raw(ctf_dictionary,
1131 ctf_type);
1132 bool struct_type_is_anonymous = (struct_type_name == "");
1133
1134 if (!struct_type_is_anonymous)
1135 if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group())
1136 if ((result = lookup_class_type(struct_type_name, *corp)))
1137 return result;
1138
1139 /* The libabigail IR encodes C struct types in `class' IR nodes. */
1140 result.reset(new class_decl(rdr->env(),
1141 struct_type_name,
1142 ctf_type_size(ctf_dictionary, ctf_type) * 8,
1143 /*alignment=*/0,
1144 true /* is_struct */,
1145 location(),
1146 decl_base::VISIBILITY_DEFAULT,
1147 struct_type_is_anonymous));
1148 if (!result)
1149 return result;
1150
1151 /* The C type system indirectly supports loops by the mean of
1152 pointers to structs or unions. Since some contained type can
1153 refer to this struct, we have to make it available in the cache
1154 at this point even if the members haven't been added to the IR
1155 node yet. */
1156 add_decl_to_scope(result, tunit->get_global_scope());
1157 rdr->add_type(ctf_dictionary, ctf_type, result);
1158
1159 /* Now add the struct members as specified in the CTF type description.
1160 This is C, so named types can only be defined in the global
1161 scope. */
1162 process_ctf_sou_members(rdr, ctf_dictionary, ctf_type, result);
1163
1164 return result;
1165}
1166
1167/// Build and return an union type libabigail IR.
1168///
1169/// @param rdr the read context.
1170/// @param ctf_dictionary the CTF dictionary being read.
1171/// @param ctf_type the CTF type ID of the source type.
1172///
1173/// @return a shared pointer to the IR node for the union type.
1174
1175static union_decl_sptr
1176process_ctf_union_type(reader *rdr,
1177 ctf_dict_t *ctf_dictionary,
1178 ctf_id_t ctf_type)
1179{
1180 corpus_sptr corp = rdr->corpus();
1181 translation_unit_sptr tunit = rdr->cur_transl_unit();
1182 union_decl_sptr result;
1183 std::string union_type_name = ctf_type_name_raw(ctf_dictionary,
1184 ctf_type);
1185 bool union_type_is_anonymous = (union_type_name == "");
1186
1187 if (!union_type_is_anonymous)
1188 if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group())
1189 if ((result = lookup_union_type(union_type_name, *corp)))
1190 return result;
1191
1192 /* Create the corresponding libabigail union IR node. */
1193 result.reset(new union_decl(rdr->env(),
1194 union_type_name,
1195 ctf_type_size(ctf_dictionary, ctf_type) * 8,
1196 location(),
1197 decl_base::VISIBILITY_DEFAULT,
1198 union_type_is_anonymous));
1199 if (!result)
1200 return result;
1201
1202 /* The C type system indirectly supports loops by the mean of
1203 pointers to structs or unions. Since some contained type can
1204 refer to this union, we have to make it available in the cache
1205 at this point even if the members haven't been added to the IR
1206 node yet. */
1207 add_decl_to_scope(result, tunit->get_global_scope());
1208 rdr->add_type(ctf_dictionary, ctf_type, result);
1209
1210 /* Now add the union members as specified in the CTF type description.
1211 This is C, so named types can only be defined in the global
1212 scope. */
1213 process_ctf_sou_members(rdr, ctf_dictionary, ctf_type, result);
1214
1215 return result;
1216}
1217
1218/// Build and return an array subrange.
1219///
1220/// @param rdr the read context.
1221///
1222/// @param ctf_dictionary the CTF dictionary where @ref index
1223/// will be found.
1224///
1225/// @param index the CTF type ID for the array index.
1226///
1227/// @param nelems the elements number of the array.
1228///
1229/// @return a shared pointer to subrange built.
1231build_array_ctf_range(reader *rdr, ctf_dict_t *dic,
1232 ctf_id_t index, uint64_t nelems)
1233{
1234 bool is_non_finite = false;
1235 corpus_sptr corp = rdr->corpus();
1236 translation_unit_sptr tunit = rdr->cur_transl_unit();
1238 array_type_def::subrange_type::bound_value lower_bound;
1239 array_type_def::subrange_type::bound_value upper_bound;
1240
1241 type_base_sptr index_type = rdr->build_type(dic, index);
1242 if (!index_type)
1243 return nullptr;
1244
1245 lower_bound.set_unsigned(0); /* CTF supports C only. */
1246 upper_bound.set_unsigned(nelems > 0 ? nelems - 1 : 0U);
1247
1248 /* for VLAs number of array elements is 0 */
1249 if (upper_bound.get_unsigned_value() == 0 && nelems == 0)
1250 is_non_finite = true;
1251
1252 subrange.reset(new array_type_def::subrange_type(rdr->env(),
1253 "",
1254 lower_bound,
1255 upper_bound,
1256 index_type,
1257 location(),
1258 translation_unit::LANG_C));
1259 if (!subrange)
1260 return nullptr;
1261
1262 subrange->is_non_finite(is_non_finite);
1263 add_decl_to_scope(subrange, tunit->get_global_scope());
1264 canonicalize(subrange);
1265
1266 return subrange;
1267}
1268
1269/// Build and return an array type libabigail IR.
1270///
1271/// @param rdr the read context.
1272///
1273/// @param ctf_dictionary the CTF dictionary being read.
1274///
1275/// @param ctf_type the CTF type ID of the source type.
1276///
1277/// @return a shared pointer to the IR node for the array type.
1279process_ctf_array_type(reader *rdr,
1280 ctf_dict_t *ctf_dictionary,
1281 ctf_id_t ctf_type)
1282{
1283 corpus_sptr corp = rdr->corpus();
1284 translation_unit_sptr tunit = rdr->cur_transl_unit();
1285 array_type_def_sptr result;
1286 ctf_arinfo_t ctf_ainfo;
1287
1288 /* First, get the information about the CTF array. */
1289 if (static_cast<ctf_id_t>(ctf_array_info(ctf_dictionary,
1290 ctf_type,
1291 &ctf_ainfo)) == CTF_ERR)
1292 return result;
1293
1294 ctf_id_t ctf_element_type = ctf_ainfo.ctr_contents;
1295 ctf_id_t ctf_index_type = ctf_ainfo.ctr_index;
1296 uint64_t nelems = ctf_ainfo.ctr_nelems;
1299
1300 int type_array_kind = ctf_type_kind(ctf_dictionary, ctf_element_type);
1301 while (type_array_kind == CTF_K_ARRAY)
1302 {
1303 if (static_cast<ctf_id_t>(ctf_array_info(ctf_dictionary,
1304 ctf_element_type,
1305 &ctf_ainfo)) == CTF_ERR)
1306 return result;
1307
1308 subrange = build_array_ctf_range(rdr, ctf_dictionary,
1309 ctf_ainfo.ctr_index,
1310 ctf_ainfo.ctr_nelems);
1311 subranges.push_back(subrange);
1312 ctf_element_type = ctf_ainfo.ctr_contents;
1313 type_array_kind = ctf_type_kind(ctf_dictionary, ctf_element_type);
1314 }
1315
1316 std::reverse(subranges.begin(), subranges.end());
1317
1318 /* Make sure the element type is generated. */
1319 type_base_sptr element_type = rdr->build_type(ctf_dictionary,
1320 ctf_element_type);
1321 if (!element_type)
1322 return result;
1323
1324 /* Ditto for the index type. */
1325 type_base_sptr index_type = rdr->build_type(ctf_dictionary,
1326 ctf_index_type);
1327 if (!index_type)
1328 return result;
1329
1330 result = dynamic_pointer_cast<array_type_def>
1331 (rdr->lookup_type(ctf_dictionary, ctf_type));
1332 if (result)
1333 return result;
1334
1335 subrange = build_array_ctf_range(rdr, ctf_dictionary,
1336 ctf_index_type, nelems);
1337 subranges.push_back(subrange);
1338
1339 /* Finally build the IR for the array type and return it. */
1340 result.reset(new array_type_def(element_type, subranges, location()));
1341 if (result)
1342 {
1343 decl_base_sptr array_type_decl = get_type_declaration(result);
1344 add_decl_to_scope(array_type_decl, tunit->get_global_scope());
1345 rdr->add_type(ctf_dictionary, ctf_type, result);
1346 }
1347
1348 return result;
1349}
1350
1351/// Strip qualification from a qualified type, when it makes sense.
1352///
1353/// The C language specification says in [6.7.3]/8:
1354///
1355/// [If the specification of an array type includes any type
1356/// qualifiers, the element type is so- qualified, not the
1357/// array type.]
1358///
1359/// In more mundane words, a const array of int is the same as an
1360/// array of const int.
1361///
1362/// This function thus removes the qualifiers of the array and applies
1363/// them to the array element. The function then pretends that the
1364/// array itself it not qualified.
1365///
1366/// It might contain code to strip other cases like this in the
1367/// future.
1368///
1369/// @param t the type to strip const qualification from.
1370///
1371/// @return the stripped type or just return @p t.
1372static decl_base_sptr
1373maybe_strip_qualification(const qualified_type_def_sptr t)
1374{
1375 if (!t)
1376 return t;
1377
1378 decl_base_sptr result = t;
1379 type_base_sptr u = t->get_underlying_type();
1380
1381 if (is_array_type(u))
1382 {
1383 // Let's apply the qualifiers of the array to the array element
1384 // and pretend that the array itself is not qualified, as per
1385 // section [6.7.3]/8 of the C specification.
1386
1388 ABG_ASSERT(array);
1389 // We should not be editing types that are already canonicalized.
1390 ABG_ASSERT(!array->get_canonical_type());
1391 type_base_sptr element_type = array->get_element_type();
1392
1393 if (qualified_type_def_sptr qualified = is_qualified_type(element_type))
1394 {
1395 qualified_type_def::CV quals = qualified->get_cv_quals();
1396 quals |= t->get_cv_quals();
1397 // So we apply the qualifiers of the array to the array
1398 // element.
1399 qualified->set_cv_quals(quals);
1400 // Let's pretend that the array is no more qualified.
1401 result = is_decl(u);
1402 }
1403 }
1404
1405 return result;
1406}
1407
1408/// Build and return a qualified type libabigail IR.
1409///
1410/// @param rdr the read context.
1411/// @param ctf_dictionary the CTF dictionary being read.
1412/// @param ctf_type the CTF type ID of the source type.
1413
1414static type_base_sptr
1415process_ctf_qualified_type(reader *rdr,
1416 ctf_dict_t *ctf_dictionary,
1417 ctf_id_t ctf_type)
1418{
1419 corpus_sptr corp = rdr->corpus();
1420 translation_unit_sptr tunit = rdr->cur_transl_unit();
1421 type_base_sptr result;
1422 int type_kind = ctf_type_kind(ctf_dictionary, ctf_type);
1423 ctf_id_t ctf_utype = ctf_type_reference(ctf_dictionary, ctf_type);
1424 type_base_sptr utype = rdr->build_type(ctf_dictionary, ctf_utype);
1425 if (!utype)
1426 return result;
1427
1428 result = dynamic_pointer_cast<type_base>
1429 (rdr->lookup_type(ctf_dictionary, ctf_type));
1430 if (result)
1431 return result;
1432
1433 qualified_type_def::CV qualifiers = qualified_type_def::CV_NONE;
1434 if (type_kind == CTF_K_CONST)
1435 qualifiers |= qualified_type_def::CV_CONST;
1436 else if (type_kind == CTF_K_VOLATILE)
1437 qualifiers |= qualified_type_def::CV_VOLATILE;
1438 else if (type_kind == CTF_K_RESTRICT)
1439 qualifiers |= qualified_type_def::CV_RESTRICT;
1440 else
1442
1443 // qualifiers are not be use in functions
1444 if (is_function_type(utype))
1445 return result;
1446
1447 result.reset(new qualified_type_def(utype, qualifiers, location()));
1448 if (result)
1449 {
1450 // Strip some potentially redundant type qualifiers from
1451 // the qualified type we just built.
1452 decl_base_sptr d = maybe_strip_qualification(is_qualified_type(result));
1453 if (!d)
1454 d = get_type_declaration(result);
1455 ABG_ASSERT(d);
1456
1457 add_decl_to_scope(d, tunit->get_global_scope());
1458 result = is_type(d);
1459 rdr->add_type(ctf_dictionary, ctf_type, result);
1460 }
1461
1462 return result;
1463}
1464
1465/// Build and return a pointer type libabigail IR.
1466///
1467/// @param rdr the read context.
1468/// @param ctf_dictionary the CTF dictionary being read.
1469/// @param ctf_type the CTF type ID of the source type.
1470///
1471/// @return a shared pointer to the IR node for the pointer type.
1472
1474process_ctf_pointer_type(reader *rdr,
1475 ctf_dict_t *ctf_dictionary,
1476 ctf_id_t ctf_type)
1477{
1478 corpus_sptr corp = rdr->corpus();
1479 translation_unit_sptr tunit = rdr->cur_transl_unit();
1480 pointer_type_def_sptr result;
1481 ctf_id_t ctf_target_type = ctf_type_reference(ctf_dictionary, ctf_type);
1482 if (ctf_target_type == CTF_ERR)
1483 return result;
1484
1485 type_base_sptr target_type = rdr->build_type(ctf_dictionary,
1486 ctf_target_type);
1487 if (!target_type)
1488 return result;
1489
1490 result = dynamic_pointer_cast<pointer_type_def>
1491 (rdr->lookup_type(ctf_dictionary, ctf_type));
1492 if (result)
1493 return result;
1494
1495 if (rdr->env().is_void_type(target_type))
1496 result = is_pointer_type(build_ir_node_for_void_pointer_type(*rdr, tunit));
1497 else
1498 result.reset(new pointer_type_def(target_type,
1499 ctf_type_size(ctf_dictionary,
1500 ctf_type) * 8,
1501 ctf_type_align(ctf_dictionary,
1502 ctf_type) * 8,
1503 location()));
1504 if (result)
1505 {
1506 add_decl_to_scope(result, tunit->get_global_scope());
1507 rdr->add_type(ctf_dictionary, ctf_type, result);
1508 }
1509
1510 return result;
1511}
1512
1513/// Build and return an enum type libabigail IR.
1514///
1515/// @param rdr the read context.
1516/// @param ctf_dictionary the CTF dictionary being read.
1517/// @param ctf_type the CTF type ID of the source type.
1518///
1519/// @return a shared pointer to the IR node for the enum type.
1520
1522process_ctf_enum_type(reader *rdr,
1523 ctf_dict_t *ctf_dictionary,
1524 ctf_id_t ctf_type)
1525{
1526 translation_unit_sptr tunit = rdr->cur_transl_unit();
1527 enum_type_decl_sptr result;
1528 ctf_id_t ctf_ref = ctf_type_reference(ctf_dictionary, ctf_type);
1529 std::string enum_name = ctf_type_name_raw(ctf_dictionary,
1530 (ctf_ref != CTF_ERR)
1531 ? ctf_ref : ctf_type);
1532
1533 if (!enum_name.empty())
1534 if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group())
1535 if ((result = lookup_enum_type(enum_name, *corp)))
1536 return result;
1537
1538 /* Build a signed integral type for the type of the enumerators, aka
1539 the underlying type. The size of the enumerators in bytes is
1540 specified in the CTF enumeration type. */
1541 size_t utype_size_in_bits = ctf_type_size(ctf_dictionary,
1542 (ctf_ref != CTF_ERR)
1543 ? ctf_ref : ctf_type) * 8;
1544 string underlying_type_name =
1546 utype_size_in_bits);
1547
1548 type_decl_sptr utype;
1549 utype.reset(new type_decl(rdr->env(),
1550 underlying_type_name,
1551 utype_size_in_bits,
1552 utype_size_in_bits,
1553 location()));
1554 utype->set_is_anonymous(true);
1555 utype->set_is_artificial(true);
1556 if (!utype)
1557 return result;
1558
1559 add_decl_to_scope(utype, tunit->get_global_scope());
1560 canonicalize(utype);
1561
1562 /* Iterate over the enum entries. */
1564 ctf_next_t *enum_next = NULL;
1565 const char *ename;
1566 int evalue;
1567
1568 while ((ename = ctf_enum_next(ctf_dictionary, ctf_type, &enum_next, &evalue)))
1569 enms.push_back(enum_type_decl::enumerator(ename, evalue));
1570
1571 if (ctf_errno(ctf_dictionary) != ECTF_NEXT_END)
1572 {
1573 fprintf(stderr, "ERROR from ctf_enum_next\n");
1574 return result;
1575 }
1576
1577 result.reset(new enum_type_decl(enum_name.c_str(), location(),
1578 utype, enms, enum_name.c_str()));
1579 if (result)
1580 {
1581 add_decl_to_scope(result, tunit->get_global_scope());
1582 rdr->add_type(ctf_dictionary, ctf_type, result);
1583 }
1584
1585 return result;
1586}
1587
1588/// Given a symbol name, lookup the corresponding CTF information in
1589/// the default dictionary (CTF archive member provided by the caller)
1590/// If the search is not success, the looks for the symbol name
1591/// in _all_ archive members.
1592///
1593/// @param ctfa the CTF archive.
1594/// @param dict the default dictionary to looks for.
1595/// @param sym_name the symbol name.
1596/// @param corp the IR corpus.
1597///
1598/// Note that if @ref sym_name is found in other than its default dictionary
1599/// @ref ctf_dict will be updated and it must be explicitly closed by its
1600/// caller.
1601///
1602/// @return a valid CTF type id, if @ref sym_name was found, CTF_ERR otherwise.
1603
1604static ctf_id_t
1605lookup_symbol_in_ctf_archive(ctf_archive_t *ctfa, ctf_dict_t **ctf_dict,
1606 const char *sym_name)
1607{
1608 int ctf_err;
1609 ctf_dict_t *dict = *ctf_dict;
1610 ctf_id_t ctf_type = ctf_lookup_by_symbol_name(dict, sym_name);
1611
1612 if (ctf_type != CTF_ERR)
1613 return ctf_type;
1614
1615 /* Probably --ctf-variables option was used by ld, so symbol type
1616 definition must be found in the CTF Variable section. */
1617 ctf_type = ctf_lookup_variable(dict, sym_name);
1618
1619 /* Not lucky, then, search in whole archive */
1620 if (ctf_type == CTF_ERR)
1621 {
1622 ctf_dict_t *fp;
1623 ctf_next_t *i = NULL;
1624 const char *arcname;
1625
1626 while ((fp = ctf_archive_next(ctfa, &i, &arcname, 1, &ctf_err)) != NULL)
1627 {
1628 if ((ctf_type = ctf_lookup_by_symbol_name (fp, sym_name)) == CTF_ERR)
1629 ctf_type = ctf_lookup_variable(fp, sym_name);
1630
1631 if (ctf_type != CTF_ERR)
1632 {
1633 *ctf_dict = fp;
1634 break;
1635 }
1636 ctf_dict_close(fp);
1637 }
1638 }
1639
1640 return ctf_type;
1641}
1642
1643/// Fill a CTF section description with the information in a given ELF
1644/// section.
1645///
1646/// @param elf_section the ELF section from which to get.
1647/// @param ctf_section the CTF section to fill with the raw data.
1648
1649static void
1650fill_ctf_section(const Elf_Scn *elf_section, ctf_sect_t *ctf_section)
1651{
1652 GElf_Shdr section_header_mem, *section_header;
1653 Elf_Data *section_data;
1654
1655 section_header = gelf_getshdr(const_cast<Elf_Scn*>(elf_section),
1656 &section_header_mem);
1657 section_data = elf_getdata(const_cast<Elf_Scn*>(elf_section), 0);
1658
1659 ABG_ASSERT (section_header != NULL);
1660 ABG_ASSERT (section_data != NULL);
1661
1662 ctf_section->cts_name = ""; /* This is not actually used by libctf. */
1663 ctf_section->cts_data = (char *) section_data->d_buf;
1664 ctf_section->cts_size = section_data->d_size;
1665 ctf_section->cts_entsize = section_header->sh_entsize;
1666}
1667
1668/// Create and return a new read context to process CTF information
1669/// from a given ELF file.
1670///
1671/// @param elf_path the patch of some ELF file.
1672/// @param env a libabigail IR environment.
1673
1674elf_based_reader_sptr
1675create_reader(const std::string& elf_path,
1676 const vector<char**>& debug_info_root_paths,
1677 environment& env)
1678{
1679 reader_sptr result(new reader(elf_path,
1680 debug_info_root_paths,
1681 env));
1682 return result;
1683}
1684
1685/// Re-initialize a reader so that it can re-used to read
1686/// another binary.
1687///
1688/// @param rdr the context to re-initialize.
1689///
1690/// @param elf_path the path to the elf file the context is to be used
1691/// for.
1692///
1693/// @param environment the environment used by the current context.
1694/// This environment contains resources needed by the reader and by
1695/// the types and declarations that are to be created later. Note
1696/// that ABI artifacts that are to be compared all need to be created
1697/// within the same environment.
1698///
1699/// Please also note that the life time of this environment object
1700/// must be greater than the life time of the resulting @ref
1701/// reader the context uses resources that are allocated in the
1702/// environment.
1703void
1705 const std::string& elf_path,
1706 const vector<char**>& debug_info_root_path)
1707{
1708 ctf::reader& r = dynamic_cast<reader&>(rdr);
1709 r.initialize(elf_path, debug_info_root_path);
1710}
1711
1712/// Returns a key to be use in types_map dict conformed by
1713/// dictionary id and the CTF type id for a given type.
1714///
1715/// CTF id types are unique by child dictionary, but CTF id
1716/// types in parent dictionary are unique across the all
1717/// dictionaries in the CTF archive, to differentiate
1718/// one each other this member function relies in
1719/// ctf_type_isparent function.
1720///
1721/// @param dic the pointer to CTF dictionary where the @p type
1722/// was found.
1723///
1724/// @param type the id for given CTF type.
1725static std::string
1726dic_type_key(ctf_dict_t *dic, ctf_id_t ctf_type)
1727{
1728 std::stringstream key;
1729
1730 if (ctf_type_isparent (dic, ctf_type))
1731 key << std::hex << ctf_type;
1732 else
1733 key << std::hex << ctf_type << '-' << ctf_cuname(dic);
1734 return key.str();
1735}
1736
1737} // End of namespace ctf
1738} // End of namespace abigail
void reset_reader(elf_based_reader &rdr, const std::string &elf_path, const vector< char ** > &debug_info_root_path)
Re-initialize a reader so that it can re-used to read another binary.
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 file contains the declarations of the entry points to de-serialize an instance of abigail::corpu...
This file contains the declarations for an elf-based. DWARF and CTF readers can inherit this one.
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:1695
This contains the private implementation of the suppression engine of libabigail.
This contains the declarations for the symtab reader.
#define ABG_ASSERT_NOT_REACHED
A macro that expands to aborting the program when executed.
Elf * elf_handle() const
Getter of the handle used to access ELF information from the current ELF file.
const Elf_Scn * find_ctf_section() const
Find and return a pointer to the the CTF section.
virtual ir::corpus_sptr read_corpus(status &status)
Read the ELF information associated to the current ELF file and construct an ABI representation from ...
const vector< char ** > & debug_info_root_paths() const
Getter of the vector of directory paths to look into for split debug information files.
symtab_reader::symtab_sptr & symtab() const
Getter of an abstract representation of the symbol table of the underlying ELF file.
The common interface of readers based on ELF.
elf_based_reader(const std::string &elf_path, const vector< char ** > &debug_info_root_paths, environment &env)
Readers that implement this interface must provide a factory method to create a reader instance as th...
virtual void initialize(const std::string &elf_path, const vector< char ** > &debug_info_root_paths)
(re)Initialize) the resources used by the current reader.
status
The status of the fe_iface::read_corpus call.
Definition: abg-fe-iface.h:38
@ STATUS_NO_SYMBOLS_FOUND
This status is for when the symbols of the ELF binaries could not be read.
Definition: abg-fe-iface.h:54
@ STATUS_DEBUG_INFO_NOT_FOUND
This status is for when the debug info could not be read.
Definition: abg-fe-iface.h:46
@ STATUS_OK
This status is for when the call went OK.
Definition: abg-fe-iface.h:43
@ STATUS_UNKNOWN
The status is in an unknown state.
Definition: abg-fe-iface.h:40
const options_type & options() const
Getter of the the options of the current Front End Interface.
Definition: abg-fe-iface.cc:92
void maybe_add_fn_to_exported_decls(const function_decl *fn)
Try and add the representation of the ABI of a function to the set of exported declarations of the cu...
corpus_sptr corpus()
Getter for the ABI corpus being built by the current front-end.
void maybe_add_var_to_exported_decls(const var_decl *var)
Try and add the representation of the ABI of a variable to the set of exported declarations of the cu...
corpus_group_sptr & corpus_group()
Getter for the ABI corpus group being built by the current front-end.
const std::string & corpus_path() const
Getter of the path to the file which an ABI corpus is to be created for.
shared_ptr< subrange_type > subrange_sptr
Convenience typedef for a shared pointer on a function_decl::subrange.
Definition: abg-ir.h:2537
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:45
std::vector< enumerator > enumerators
Convenience typedef for a list of enumerator.
Definition: abg-ir.h:2766
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition: abg-ir.h:140
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3135
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
type_decl_sptr lookup_basic_type(const interned_string &type_name, const translation_unit &tu)
Lookup a basic type from a translation unit.
Definition: abg-ir.cc:12103
unordered_map< string, type_base_sptr > string_type_base_sptr_map_type
A convenience typedef for a map which key is a string and which value is a type_base_sptr.
Definition: abg-ir.h:563
shared_ptr< function_decl > function_decl_sptr
Convenience typedef for a shared pointer on a function_decl.
Definition: abg-fwd.h:266
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10541
shared_ptr< array_type_def > array_type_def_sptr
Convenience typedef for a shared pointer on a array_type_def.
Definition: abg-fwd.h:241
bool is_anonymous_type(const type_base *t)
Test whether a declaration is a type.
Definition: abg-ir.cc:10592
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:11054
shared_ptr< class_decl > class_decl_sptr
Convenience typedef for a shared pointer on a class_decl.
Definition: abg-fwd.h:190
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
const type_decl * is_type_decl(const type_or_decl_base *t)
Test whether a type is a type_decl (a builtin type).
Definition: abg-ir.cc:10643
function_type_sptr is_function_type(const type_or_decl_base_sptr &t)
Test whether a type is a function_type.
Definition: abg-ir.cc:11516
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition: abg-fwd.h:207
shared_ptr< typedef_decl > typedef_decl_sptr
Convenience typedef for a shared pointer on a typedef_decl.
Definition: abg-fwd.h:164
class_decl_sptr lookup_class_type(const string &fqn, const translation_unit &tu)
Lookup a class type from a translation unit.
Definition: abg-ir.cc:12143
bool parse_integral_type(const string &type_name, integral_type &type)
Parse an integral type from a string.
Definition: abg-ir.cc:16261
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:10773
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:253
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:121
shared_ptr< translation_unit > translation_unit_sptr
Convenience typedef for a shared pointer on a translation_unit type.
Definition: abg-fwd.h:137
const type_base_sptr lookup_type(const interned_string &fqn, const translation_unit &tu)
Lookup a type in a translation unit.
Definition: abg-ir.cc:12549
union_decl_sptr lookup_union_type(const interned_string &type_name, const translation_unit &tu)
Lookup a union type from a translation unit.
Definition: abg-ir.cc:12180
type_base_sptr canonicalize(type_base_sptr t)
Compute the canonical type of a given type.
Definition: abg-ir.cc:15752
shared_ptr< pointer_type_def > pointer_type_def_sptr
Convenience typedef for a shared pointer on a pointer_type_def.
Definition: abg-fwd.h:223
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10481
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:8501
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:28314
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
Definition: abg-fwd.h:172
const pointer_type_def * is_pointer_type(const type_or_decl_base *t, bool look_through_qualifiers)
Test whether a type is a pointer_type_def.
Definition: abg-ir.cc:11137
enum_type_decl_sptr lookup_enum_type(const interned_string &type_name, const translation_unit &tu)
Lookup an enum type from a translation unit.
Definition: abg-ir.cc:12248
const decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition: abg-ir.cc:10174
array_type_def * is_array_type(const type_or_decl_base *type, bool look_through_qualifiers)
Test if a type is an array_type_def.
Definition: abg-ir.cc:11781
shared_ptr< type_decl > type_decl_sptr
Convenience typedef for a shared pointer on a type_decl.
Definition: abg-fwd.h:158
qualified_type_def * is_qualified_type(const type_or_decl_base *t)
Test whether a type is a reference_type_def.
Definition: abg-ir.cc:11496
typedef_decl_sptr lookup_typedef_type(const interned_string &type_name, const translation_unit &tu)
Lookup a typedef type from a translation unit.
Definition: abg-ir.cc:12286
bool find_file_under_dir(const string &root_dir, const string &file_path_to_look_for, string &result)
Find a given file under a root directory and return its absolute path.
bool dir_name(string const &path, string &dir_name, bool keep_separator_at_end)
Return the directory part of a file path.
bool base_name(string const &path, string &file_name)
Return the file name part of a file part.
void initialize()
This function needs to be called before any libabigail function.
bool file_exists(const string &path)
Tests whether a path exists;.
Toplevel namespace for libabigail.