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