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