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