diff --git a/include/abg-ctf-reader.h b/include/abg-ctf-reader.h
index 3343f0d8..827d1bc2 100644
--- a/include/abg-ctf-reader.h
+++ b/include/abg-ctf-reader.h
@@ -19,6 +19,8 @@
 #include "abg-suppression.h"
 #include "abg-elf-reader-common.h"
 
+#include "ctf-api.h"
+
 namespace abigail
 {
 namespace ctf_reader
@@ -32,8 +34,25 @@ create_read_context(const std::string& elf_path,
                     ir::environment *env);
 corpus_sptr
 read_corpus(read_context *ctxt, elf_reader::status& status);
+
 corpus_sptr
 read_corpus(const read_context_sptr &ctxt, elf_reader::status &status);
+
+corpus_sptr
+read_and_add_corpus_to_group_from_elf(read_context*, corpus_group&, elf_reader::status&);
+
+void
+set_read_context_corpus_group(read_context& ctxt, corpus_group_sptr& group);
+
+void
+reset_read_context(read_context_sptr &ctxt,
+                   const std::string&	elf_path,
+                   ir::environment*	environment);
+void
+set_vmlinux_ctfa_path(read_context& ctxt,
+                      const string& filename);
+std::string
+dic_type_key(ctf_dict_t *dic, ctf_id_t ctf_type);
 } // end namespace ctf_reader
 } // end namespace abigail
 
diff --git a/include/abg-ir.h b/include/abg-ir.h
index a2f4e1a7..033e3708 100644
--- a/include/abg-ir.h
+++ b/include/abg-ir.h
@@ -136,7 +136,16 @@ class environment
 public:
   struct priv;
   std::unique_ptr<priv> priv_;
+  /// The possible debug format types. Default is DWARF_FORMAT_TYPE
+  enum debug_format_type
+  {
+    DWARF_FORMAT_TYPE,
+#ifdef WITH_CTF
+    CTF_FORMAT_TYPE,
+#endif
+  };
 
+  debug_format_type debug_format_;
   /// A convenience typedef for a map of canonical types.  The key is
   /// the pretty representation string of a particular type and the
   /// value is the vector of canonical types that have the same pretty
@@ -236,6 +245,11 @@ public:
   uintptr_t
   get_canonical_type_from_type_id(const char*);
 #endif
+  debug_format_type
+  get_debug_format_type() const;
+
+  void
+  set_debug_format_type(debug_format_type d);
 
   friend class class_or_union;
   friend class class_decl;
diff --git a/src/abg-ctf-reader.cc b/src/abg-ctf-reader.cc
index ec6a5c81..b9b3d939 100644
--- a/src/abg-ctf-reader.cc
+++ b/src/abg-ctf-reader.cc
@@ -16,6 +16,8 @@
 #include <fcntl.h> /* For open(3) */
 #include <iostream>
 #include <memory>
+#include <map>
+#include <algorithm>
 
 #include "ctf-api.h"
 
@@ -56,15 +58,25 @@ public:
   /// be read from the file then this is NULL.
   ctf_archive_t *ctfa;
 
+  /// The name of the vmlinux file from which the CTF archive got
+  /// extracted.
+  string vmlinux_ctfa_path_;
+
   /// A map associating CTF type ids with libabigail IR types.  This
   /// is used to reuse already generated types.
-  unordered_map<ctf_id_t,type_base_sptr> types_map;
+  std::map<std::string,type_base_sptr> types_map;
+
+  /// A set associating unknown CTF type ids
+  std::set<ctf_id_t> unknown_types_set;
 
   /// libelf handler for the ELF file from which we read the CTF data,
   /// and the corresponding file descriptor.
   Elf *elf_handler;
   int elf_fd;
 
+  /// set when ELF is ET_EXEC
+  bool is_elf_exec;
+
   /// The symtab read from the ELF file.
   symtab_reader::symtab_sptr symtab;
 
@@ -74,26 +86,109 @@ public:
   ctf_sect_t symtab_sect;
   ctf_sect_t strtab_sect;
 
+  corpus_sptr			cur_corpus_;
+  corpus_group_sptr		cur_corpus_group_;
+
+  /// Getter of the current corpus group being constructed.
+  ///
+  /// @return current the current corpus being constructed, if any, or
+  /// nil.
+  const corpus_group_sptr
+  current_corpus_group() const
+  {return cur_corpus_group_;}
+
+  /// Test if there is a corpus group being built.
+  ///
+  /// @return if there is a corpus group being built, false otherwise.
+  bool
+  has_corpus_group() const
+  {return bool(cur_corpus_group_);}
+
+  /// Return the main corpus from the current corpus group, if any.
+  ///
+  /// @return the main corpus of the current corpus group, if any, nil
+  /// if no corpus group is being constructed.
+  corpus_sptr
+  main_corpus_from_current_group()
+  {
+    if (cur_corpus_group_)
+      return cur_corpus_group_->get_main_corpus();
+    return corpus_sptr();
+  }
+
+  /// Test if the current corpus being built is the main corpus of the
+  /// current corpus group.
+  ///
+  /// @return return true iff the current corpus being built is the
+  /// main corpus of the current corpus group.
+  bool
+  current_corpus_is_main_corpus_from_current_group()
+  {
+    corpus_sptr main_corpus = main_corpus_from_current_group();
+
+    if (main_corpus && main_corpus.get() == cur_corpus_.get())
+      return true;
+
+    return false;
+  }
+
+  /// Return true if the current corpus is part of a corpus group
+  /// being built and if it's not the main corpus of the group.
+  ///
+  /// For instance, this would return true if we are loading a linux
+  /// kernel *module* that is part of the current corpus group that is
+  /// being built.  In this case, it means we should re-use types
+  /// coming from the "vmlinux" binary that is the main corpus of the
+  /// group.
+  ///
+  /// @return the corpus group the current corpus belongs to, if the
+  /// current corpus is part of a corpus group being built. Nil otherwise.
+  corpus_sptr
+  should_reuse_type_from_corpus_group()
+  {
+    if (has_corpus_group())
+      if (corpus_sptr main_corpus = main_corpus_from_current_group())
+	if (!current_corpus_is_main_corpus_from_current_group())
+	  return current_corpus_group();
+
+    return corpus_sptr();
+  }
+
   /// Associate a given CTF type ID with a given libabigail IR type.
-  void add_type(ctf_id_t ctf_type, type_base_sptr type)
+  void add_type(ctf_dict_t *dic, ctf_id_t ctf_type, type_base_sptr type)
   {
-    types_map.insert(std::make_pair(ctf_type, type));
+    string key = dic_type_key(dic, ctf_type);
+    types_map.insert(std::make_pair(key, type));
+  }
+
+  /// Insert a given CTF unknown type ID.
+  ///
+  /// @param ctf_type the unknown type ID to be added.
+  void add_unknown_type(ctf_id_t ctf_type)
+  {
+    unknown_types_set.insert(ctf_type);
   }
 
   /// Lookup a given CTF type ID in the types map.
   ///
   /// @param ctf_type the type ID of the type to lookup.
-  type_base_sptr lookup_type(ctf_id_t ctf_type)
+  type_base_sptr lookup_type(ctf_dict_t *dic, ctf_id_t ctf_type)
   {
     type_base_sptr result;
+    std::string key = dic_type_key(dic, ctf_type);
 
-    auto search = types_map.find(ctf_type);
+    auto search = types_map.find(key);
     if (search != types_map.end())
       result = search->second;
 
     return result;
   }
 
+  /// Lookup a given CTF unknown type ID in the unknown set.
+  /// @param ctf_type the unknown type ID to lookup.
+  bool lookup_unknown_type(ctf_id_t ctf_type)
+  { return unknown_types_set.find(ctf_type) != unknown_types_set.end(); }
+
   /// Canonicalize all the types stored in the types map.
   void canonicalize_all_types(void)
   {
@@ -105,19 +200,22 @@ public:
   ///
   /// @param elf_path the path to the ELF file.
   read_context(const string& elf_path, ir::environment *env)
+  {
+    initialize(elf_path, env);
+  }
+
+  void initialize(const string& elf_path, ir::environment *env)
   {
     types_map.clear();
     filename = elf_path;
     ir_env = env;
     elf_handler = NULL;
     elf_fd = -1;
+    is_elf_exec = false;
     ctfa = NULL;
-  }
-
-  /// Destructor of the @ref read_context type.
-  ~read_context()
-  {
-    ctf_close(ctfa);
+    vmlinux_ctfa_path_ = "";
+    symtab.reset();
+    cur_corpus_group_.reset();
   }
 }; // end class read_context.
 
@@ -153,13 +251,18 @@ process_ctf_typedef(read_context *ctxt,
     return result;
 
   const char *typedef_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
+  if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group())
+    if (result = lookup_typedef_type(typedef_name, *corp))
+      return result;
+
   type_base_sptr utype = lookup_type(ctxt, corp, tunit,
                                      ctf_dictionary, ctf_utype);
 
   if (!utype)
     return result;
 
-  result = dynamic_pointer_cast<typedef_decl>(ctxt->lookup_type(ctf_type));
+  result = dynamic_pointer_cast<typedef_decl>(ctxt->lookup_type(ctf_dictionary,
+                                                                ctf_type));
   if (result)
     return result;
 
@@ -180,7 +283,7 @@ process_ctf_typedef(read_context *ctxt,
   if (result)
     {
       add_decl_to_scope(result, tunit->get_global_scope());
-      ctxt->add_type(ctf_type, result);
+      ctxt->add_type(ctf_dictionary, ctf_type, result);
     }
 
   return result;
@@ -225,9 +328,20 @@ process_ctf_base_type(read_context *ctxt,
       type_base_sptr void_type = ctxt->ir_env->get_void_type();
       decl_base_sptr type_declaration = get_type_declaration(void_type);
       result = is_type_decl(type_declaration);
+      canonicalize(result);
     }
   else
     {
+      if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group())
+        {
+          string normalized_type_name = type_name;
+          integral_type int_type;
+          if (parse_integral_type(type_name, int_type))
+            normalized_type_name = int_type.to_string();
+          if (result = lookup_basic_type(normalized_type_name, *corp))
+            return result;
+        }
+
       result = lookup_basic_type(type_name, *corp);
       if (!result)
         result.reset(new type_decl(ctxt->ir_env,
@@ -242,7 +356,7 @@ process_ctf_base_type(read_context *ctxt,
   if (result)
     {
       add_decl_to_scope(result, tunit->get_global_scope());
-      ctxt->add_type(ctf_type, result);
+      ctxt->add_type(ctf_dictionary, ctf_type, result);
     }
 
   return result;
@@ -303,7 +417,8 @@ process_ctf_function_type(read_context *ctxt,
       function_parms.push_back(parm);
     }
 
-  result = dynamic_pointer_cast<function_type>(ctxt->lookup_type(ctf_type));
+  result = dynamic_pointer_cast<function_type>(ctxt->lookup_type(ctf_dictionary,
+                                                                 ctf_type));
   if (result)
     return result;
 
@@ -319,7 +434,7 @@ process_ctf_function_type(read_context *ctxt,
       result->set_is_artificial(true);
       decl_base_sptr function_type_decl = get_type_declaration(result);
       add_decl_to_scope(function_type_decl, tunit->get_global_scope());
-      ctxt->add_type(ctf_type, result);
+      ctxt->add_type(ctf_dictionary, ctf_type, result);
     }
 
   return result;
@@ -411,6 +526,11 @@ process_ctf_forward_type(read_context *ctxt,
     }
   else
     {
+      if (!type_is_anonymous)
+        if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group())
+          if (result = lookup_class_type(type_name, *corp))
+            return is_type(result);
+
       class_decl_sptr
        struct_fwd(new class_decl(ctxt->ir_env, type_name,
                                  /*alignment=*/0, /*size=*/0,
@@ -426,7 +546,7 @@ process_ctf_forward_type(read_context *ctxt,
     return is_type(result);
 
   add_decl_to_scope(result, tunit->get_global_scope());
-  ctxt->add_type(ctf_type, is_type(result));
+  ctxt->add_type(ctf_dictionary, ctf_type, is_type(result));
 
   return is_type(result);
 }
@@ -450,9 +570,14 @@ process_ctf_struct_type(read_context *ctxt,
 {
   class_decl_sptr result;
   std::string struct_type_name = ctf_type_name_raw(ctf_dictionary,
-                                                 ctf_type);
+                                                   ctf_type);
   bool struct_type_is_anonymous = (struct_type_name == "");
 
+  if (!struct_type_is_anonymous)
+    if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group())
+      if (result = lookup_class_type(struct_type_name, *corp))
+        return result;
+
   /* The libabigail IR encodes C struct types in `class' IR nodes.  */
   result.reset(new class_decl(ctxt->ir_env,
                               struct_type_name,
@@ -471,7 +596,7 @@ process_ctf_struct_type(read_context *ctxt,
      at this point even if the members haven't been added to the IR
      node yet.  */
   add_decl_to_scope(result, tunit->get_global_scope());
-  ctxt->add_type(ctf_type, result);
+  ctxt->add_type(ctf_dictionary, ctf_type, result);
 
   /* Now add the struct members as specified in the CTF type description.
      This is C, so named types can only be defined in the global
@@ -504,6 +629,11 @@ process_ctf_union_type(read_context *ctxt,
                                                    ctf_type);
   bool union_type_is_anonymous = (union_type_name == "");
 
+  if (!union_type_is_anonymous)
+    if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group())
+      if (result = lookup_union_type(union_type_name, *corp))
+        return result;
+
   /* Create the corresponding libabigail union IR node.  */
   result.reset(new union_decl(ctxt->ir_env,
                                 union_type_name,
@@ -520,7 +650,7 @@ process_ctf_union_type(read_context *ctxt,
      at this point even if the members haven't been added to the IR
      node yet.  */
   add_decl_to_scope(result, tunit->get_global_scope());
-  ctxt->add_type(ctf_type, result);
+  ctxt->add_type(ctf_dictionary, ctf_type, result);
 
   /* Now add the union members as specified in the CTF type description.
      This is C, so named types can only be defined in the global
@@ -576,7 +706,8 @@ process_ctf_array_type(read_context *ctxt,
   if (!index_type)
     return result;
 
-  result = dynamic_pointer_cast<array_type_def>(ctxt->lookup_type(ctf_type));
+  result = dynamic_pointer_cast<array_type_def>(ctxt->lookup_type(ctf_dictionary,
+                                                                  ctf_type));
   if (result)
     return result;
 
@@ -615,7 +746,7 @@ process_ctf_array_type(read_context *ctxt,
     {
       decl_base_sptr array_type_decl = get_type_declaration(result);
       add_decl_to_scope(array_type_decl, tunit->get_global_scope());
-      ctxt->add_type(ctf_type, result);
+      ctxt->add_type(ctf_dictionary, ctf_type, result);
     }
 
   return result;
@@ -644,6 +775,11 @@ process_ctf_qualified_type(read_context *ctxt,
   if (!utype)
     return result;
 
+  result = dynamic_pointer_cast<type_base>(ctxt->lookup_type(ctf_dictionary,
+                                                             ctf_type));
+  if (result)
+    return result;
+
   qualified_type_def::CV qualifiers = qualified_type_def::CV_NONE;
   if (type_kind == CTF_K_CONST)
     qualifiers |= qualified_type_def::CV_CONST;
@@ -660,7 +796,7 @@ process_ctf_qualified_type(read_context *ctxt,
     {
       decl_base_sptr qualified_type_decl = get_type_declaration(result);
       add_decl_to_scope(qualified_type_decl, tunit->get_global_scope());
-      ctxt->add_type(ctf_type, result);
+      ctxt->add_type(ctf_dictionary, ctf_type, result);
     }
 
   return result;
@@ -694,7 +830,8 @@ process_ctf_pointer_type(read_context *ctxt,
   if (!target_type)
     return result;
 
-  result = dynamic_pointer_cast<pointer_type_def>(ctxt->lookup_type(ctf_type));
+  result = dynamic_pointer_cast<pointer_type_def>(ctxt->lookup_type(ctf_dictionary,
+                                                                    ctf_type));
   if (result)
     return result;
 
@@ -705,7 +842,7 @@ process_ctf_pointer_type(read_context *ctxt,
   if (result)
     {
       add_decl_to_scope(result, tunit->get_global_scope());
-      ctxt->add_type(ctf_type, result);
+      ctxt->add_type(ctf_dictionary, ctf_type, result);
     }
 
   return result;
@@ -728,6 +865,12 @@ process_ctf_enum_type(read_context *ctxt,
                       ctf_id_t ctf_type)
 {
   enum_type_decl_sptr result;
+  std::string enum_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
+
+  if (!enum_name.empty())
+    if (corpus_sptr corp = ctxt->should_reuse_type_from_corpus_group())
+      if (result = lookup_enum_type(enum_name, *corp))
+        return result;
 
   /* Build a signed integral type for the type of the enumerators, aka
      the underlying type.  The size of the enumerators in bytes is
@@ -761,13 +904,12 @@ process_ctf_enum_type(read_context *ctxt,
       return result;
     }
 
-  const char *enum_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
-  result.reset(new enum_type_decl(enum_name, location(),
-                                  utype, enms, enum_name));
+  result.reset(new enum_type_decl(enum_name.c_str(), location(),
+                                  utype, enms, enum_name.c_str()));
   if (result)
     {
       add_decl_to_scope(result, tunit->get_global_scope());
-      ctxt->add_type(ctf_type, result);
+      ctxt->add_type(ctf_dictionary, ctf_type, result);
     }
 
   return result;
@@ -796,7 +938,10 @@ process_ctf_type(read_context *ctxt,
   int type_kind = ctf_type_kind(ctf_dictionary, ctf_type);
   type_base_sptr result;
 
-  if ((result = ctxt->lookup_type(ctf_type)))
+  if (ctxt->lookup_unknown_type(ctf_type))
+    return nullptr;
+
+  if ((result = ctxt->lookup_type(ctf_dictionary, ctf_type)))
     return result;
 
   switch (type_kind)
@@ -880,7 +1025,10 @@ process_ctf_type(read_context *ctxt,
     }
 
   if (!result)
-    fprintf(stderr, "NOT PROCESSED TYPE %lu\n", ctf_type);
+    {
+      fprintf(stderr, "NOT PROCESSED TYPE %lu\n", ctf_type);
+      ctxt->add_unknown_type(ctf_type);
+    }
 
   return result;
 }
@@ -904,7 +1052,7 @@ lookup_type(read_context *ctxt, corpus_sptr corp,
             translation_unit_sptr tunit, ctf_dict_t *ctf_dictionary,
             ctf_id_t ctf_type)
 {
-  type_base_sptr result = ctxt->lookup_type(ctf_type);
+  type_base_sptr result = ctxt->lookup_type(ctf_dictionary, ctf_type);
 
   if (!result)
     result = process_ctf_type(ctxt, corp, tunit, ctf_dictionary, ctf_type);
@@ -912,8 +1060,8 @@ lookup_type(read_context *ctxt, corpus_sptr corp,
 }
 
 /// Process a CTF archive and create libabigail IR for the types,
-/// variables and function declarations found in the archive.  The IR
-/// is added to the given corpus.
+/// variables and function declarations found in the archive, iterating
+/// over public symbols.  The IR is added to the given corpus.
 ///
 /// @param ctxt the read context containing the CTF archive to
 /// process.
@@ -928,43 +1076,49 @@ process_ctf_archive(read_context *ctxt, corpus_sptr corp)
   ir_translation_unit->set_language(translation_unit::LANG_C);
   corp->add(ir_translation_unit);
 
-  /* Iterate over the CTF dictionaries in the archive.  */
   int ctf_err;
   ctf_dict_t *ctf_dict;
-  ctf_next_t *dict_next = NULL;
-  const char *archive_name;
+  const auto symtab = ctxt->symtab;
+  symtab_reader::symtab_filter filter = symtab->make_filter();
+  filter.set_public_symbols();
+  std::string dict_name;
 
-  while ((ctf_dict = ctf_archive_next(ctxt->ctfa, &dict_next, &archive_name,
-                                      0 /* skip_parent */, &ctf_err)) != NULL)
+  if (corp->get_origin() == corpus::LINUX_KERNEL_BINARY_ORIGIN)
     {
-      /* Iterate over the CTF types stored in this archive.  */
-      ctf_id_t ctf_type;
-      int type_flag;
-      ctf_next_t *type_next = NULL;
+      tools_utils::base_name(ctxt->filename, dict_name);
 
-      while ((ctf_type = ctf_type_next(ctf_dict, &type_next, &type_flag,
-                                       1 /* want_hidden */)) != CTF_ERR)
-        {
-          process_ctf_type(ctxt, corp, ir_translation_unit,
-                            ctf_dict, ctf_type);
-        }
-      if (ctf_errno(ctf_dict) != ECTF_NEXT_END)
-        fprintf(stderr, "ERROR from ctf_type_next\n");
+      if (dict_name != "vmlinux")
+        // remove .ko suffix
+        dict_name.erase(dict_name.length() - 3, 3);
 
-      /* Canonicalize all the types generated above.  This must be
-         done "a posteriori" because the processing of types may
-         require other related types to not be already
-         canonicalized.  */
-      ctxt->canonicalize_all_types();
+      std::replace(dict_name.begin(), dict_name.end(), '-', '_');
+    }
 
-      /* Iterate over the CTF variables stored in this archive.  */
+  if ((ctf_dict = ctf_dict_open(ctxt->ctfa,
+                                dict_name.empty() ? NULL : dict_name.c_str(),
+                                &ctf_err)) == NULL)
+    {
+      fprintf(stderr, "ERROR dictionary not found\n");
+      abort();
+    }
+
+  for (const auto& symbol : symtab_reader::filtered_symtab(*symtab, filter))
+    {
+      std::string sym_name = symbol->get_name();
       ctf_id_t ctf_var_type;
-      ctf_next_t *var_next = NULL;
-      const char *var_name;
 
-      while ((ctf_var_type = ctf_variable_next(ctf_dict, &var_next, &var_name))
-             != CTF_ERR)
+      if (corp->get_origin() == corpus::LINUX_KERNEL_BINARY_ORIGIN
+          || ctxt->is_elf_exec)
+        ctf_var_type= ctf_lookup_variable (ctf_dict, sym_name.c_str());
+      else
+        ctf_var_type = ctf_lookup_by_symbol_name(ctf_dict, sym_name.c_str());
+
+      if (ctf_var_type == (ctf_id_t) -1)
+        continue;
+
+      if (ctf_type_kind (ctf_dict, ctf_var_type) != CTF_K_FUNCTION)
         {
+          const char *var_name = sym_name.c_str();
           type_base_sptr var_type = lookup_type(ctxt, corp, ir_translation_unit,
                                                 ctf_dict, ctf_var_type);
           if (!var_type)
@@ -977,50 +1131,38 @@ process_ctf_archive(read_context *ctxt, corpus_sptr corp)
                                              location(),
                                              var_name));
 
+          var_declaration->set_symbol(symbol);
           add_decl_to_scope(var_declaration,
-                             ir_translation_unit->get_global_scope());
+                            ir_translation_unit->get_global_scope());
         }
-      if (ctf_errno(ctf_dict) != ECTF_NEXT_END)
-        fprintf(stderr, "ERROR from ctf_variable_next\n");
-
-      /* Iterate over the CTF functions stored in this archive.  */
-      ctf_next_t *func_next = NULL;
-      const char *func_name = NULL;
-      ctf_id_t ctf_sym;
+      else
+        {
+          const char *func_name = sym_name.c_str();
+          ctf_id_t ctf_sym = ctf_var_type;
+          type_base_sptr func_type = lookup_type(ctxt, corp, ir_translation_unit,
+                                                 ctf_dict, ctf_sym);
+          if (!func_type)
+            /* Ignore function if its type can't be sorted out.  */
+            continue;
 
-      while ((ctf_sym = ctf_symbol_next(ctf_dict, &func_next, &func_name,
-                                        1 /* functions symbols only */) != CTF_ERR))
-      {
-        ctf_id_t ctf_func_type = ctf_lookup_by_name(ctf_dict, func_name);
-        type_base_sptr func_type = lookup_type(ctxt, corp, ir_translation_unit,
-                                               ctf_dict, ctf_func_type);
-        if (!func_type)
-          /* Ignore function if its type can't be sorted out.  */
-          continue;
-
-        elf_symbols func_elf_symbols = ctxt->symtab->lookup_symbol(func_name);
-        if (func_elf_symbols.size() == 0
-            || func_elf_symbols[0]->get_binding() == elf_symbol::LOCAL_BINDING)
-          /* Ignore local functions.  */
-          continue;
-
-        function_decl_sptr func_declaration;
-        func_declaration.reset(new function_decl(func_name,
-                                                 func_type,
-                                                 0 /* is_inline */,
-                                                 location()));
-
-        add_decl_to_scope(func_declaration,
-                           ir_translation_unit->get_global_scope());
-      }
-      if (ctf_errno(ctf_dict) != ECTF_NEXT_END)
-        fprintf(stderr, "ERROR from ctf_symbol_next\n");
+          function_decl_sptr func_declaration;
+          func_declaration.reset(new function_decl(func_name,
+                                                   func_type,
+                                                   0 /* is_inline */,
+                                                   location()));
 
-      ctf_dict_close(ctf_dict);
+          func_declaration->set_symbol(symbol);
+          add_decl_to_scope(func_declaration,
+                            ir_translation_unit->get_global_scope());
+        }
     }
-  if (ctf_err != ECTF_NEXT_END)
-    fprintf(stderr, "ERROR from ctf_archive_next\n");
 
+  ctf_dict_close(ctf_dict);
+  /* Canonicalize all the types generated above.  This must be
+     done "a posteriori" because the processing of types may
+     require other related types to not be already
+     canonicalized.  */
+  ctxt->canonicalize_all_types();
 }
 
 /// Open the ELF file described by the given read context.
@@ -1104,6 +1246,7 @@ slurp_elf_info(read_context *ctxt, corpus_sptr corp)
   /* Set the ELF architecture.  */
   GElf_Ehdr eh_mem;
   GElf_Ehdr *ehdr = gelf_getehdr(ctxt->elf_handler, &eh_mem);
+  ctxt->is_elf_exec = (ehdr->e_type == ET_EXEC);
   corp->set_architecture_name(elf_helpers::e_machine_to_string(ehdr->e_machine));
 
   /* Read the symtab from the ELF file and set it in the corpus.  */
@@ -1112,6 +1255,9 @@ slurp_elf_info(read_context *ctxt, corpus_sptr corp)
                                 0 /* No suppressions.  */);
   corp->set_symtab(ctxt->symtab);
 
+  if (corp->get_origin() == corpus::LINUX_KERNEL_BINARY_ORIGIN)
+    return 1;
+
   /* Get the raw ELF section contents for libctf.  */
   Elf_Scn *ctf_scn = elf_helpers::find_section(ctxt->elf_handler, ".ctf", SHT_PROGBITS);
   Elf_Scn *symtab_scn = elf_helpers::find_symbol_table_section(ctxt->elf_handler);
@@ -1158,6 +1304,7 @@ read_corpus(read_context *ctxt, elf_reader::status &status)
   corpus_sptr corp
     = std::make_shared<corpus>(ctxt->ir_env, ctxt->filename);
 
+  ctxt->cur_corpus_ = corp;
   /* Be optimist.  */
   status = elf_reader::STATUS_OK;
 
@@ -1168,27 +1315,45 @@ read_corpus(read_context *ctxt, elf_reader::status &status)
       return corp;
     }
 
+  bool is_linux_kernel = elf_helpers::is_linux_kernel(ctxt->elf_handler);
   /* Set some properties of the corpus first.  */
-  corp->set_origin(corpus::CTF_ORIGIN);
-  if (!slurp_elf_info(ctxt, corp))
+  if (is_linux_kernel)
+    corp->set_origin(corpus::LINUX_KERNEL_BINARY_ORIGIN);
+  else
+    corp->set_origin(corpus::CTF_ORIGIN);
+
+  if (ctxt->cur_corpus_group_)
+    ctxt->cur_corpus_group_->add_corpus(ctxt->cur_corpus_);
+
+  if (!slurp_elf_info(ctxt, corp) && !is_linux_kernel)
     {
       status = elf_reader::STATUS_NO_SYMBOLS_FOUND;
       return corp;
     }
 
-  /* Build the ctfa from the contents of the relevant ELF sections,
-     and process the CTF archive in the read context, if any.
-     Information about the types, variables, functions, etc contained
-     in the archive are added to the given corpus.  */
   int errp;
-  ctxt->ctfa = ctf_arc_bufopen(&ctxt->ctf_sect, &ctxt->symtab_sect,
-                               &ctxt->strtab_sect, &errp);
+  if (corp->get_origin() == corpus::LINUX_KERNEL_BINARY_ORIGIN)
+     ctxt->ctfa = ctf_arc_open(ctxt->vmlinux_ctfa_path_.c_str(), &errp);
+  else
+    /* Build the ctfa from the contents of the relevant ELF sections,
+       and process the CTF archive in the read context, if any.
+       Information about the types, variables, functions, etc contained
+       in the archive are added to the given corpus.  */
+    ctxt->ctfa = ctf_arc_bufopen(&ctxt->ctf_sect, &ctxt->symtab_sect,
+                                 &ctxt->strtab_sect, &errp);
+
+  ctxt->ir_env->canonicalization_is_done(false);
   if (ctxt->ctfa == NULL)
     status = elf_reader::STATUS_DEBUG_INFO_NOT_FOUND;
   else
     process_ctf_archive(ctxt, corp);
 
+  ctxt->ir_env->canonicalization_is_done(true);
+  ctxt->cur_corpus_->sort_functions();
+  ctxt->cur_corpus_->sort_variables();
+
   /* Cleanup and return.  */
+  ctf_close(ctxt->ctfa);
   close_elf_handler(ctxt);
   return corp;
 }
@@ -1207,5 +1372,93 @@ corpus_sptr
 read_corpus(const read_context_sptr &ctxt, elf_reader::status &status)
 {return read_corpus(ctxt.get(), status);}
 
+/// Set the @ref corpus_group being created to the current read context.
+///
+/// @param ctxt the read_context to consider.
+///
+/// @param group the @ref corpus_group to set.
+void
+set_read_context_corpus_group(read_context& ctxt,
+                              corpus_group_sptr& group)
+{
+  ctxt.cur_corpus_group_ = group;
+}
+//
+/// Read a corpus and add it to a given @ref corpus_group.
+///
+/// @param ctxt the reading context to consider.
+///
+/// @param group the @ref corpus_group to add the new corpus to.
+///
+/// @param status output parameter. The status of the read.  It is set
+/// by this function upon its completion.
+corpus_sptr
+read_and_add_corpus_to_group_from_elf(read_context* ctxt,
+                                      corpus_group& group,
+                                      elf_reader::status& status)
+{
+  corpus_sptr result;
+  corpus_sptr corp = read_corpus(ctxt, status);
+  if (status & elf_reader::STATUS_OK)
+    {
+      if (!corp->get_group())
+        group.add_corpus(corp);
+      result = corp;
+    }
+
+  return result;
+}
+
+/// Re-initialize a read_context so that it can re-used to read
+/// another binary.
+///
+/// @param ctxt the context to re-initialize.
+///
+/// @param elf_path the path to the elf file the context is to be used
+/// for.
+///
+/// @param environment the environment used by the current context.
+/// This environment contains resources needed by the reader and by
+/// the types and declarations that are to be created later.  Note
+/// that ABI artifacts that are to be compared all need to be created
+/// within the same environment.
+///
+/// Please also note that the life time of this environment object
+/// must be greater than the life time of the resulting @ref
+/// read_context the context uses resources that are allocated in the
+/// environment.
+void
+reset_read_context(read_context_sptr	&ctxt,
+                   const std::string&	 elf_path,
+                   ir::environment*	 environment)
+{
+  if (ctxt)
+    ctxt->initialize(elf_path, environment);
+}
+
+/// Set the @ref filename being assigned to the current read context.
+///
+/// @param ctxt the read_context to consider.
+///
+/// @param filename the @ref vmlinux CTFA filename to set.
+void
+set_vmlinux_ctfa_path(read_context& ctxt,
+                      const string& filename)
+{
+  ctxt.vmlinux_ctfa_path_ = filename;
+}
+
+std::string
+dic_type_key(ctf_dict_t *dic, ctf_id_t ctf_type)
+{
+  std::stringstream key;
+
+  if (ctf_type_isparent (dic, ctf_type))
+    key << std::hex << ctf_type;
+  else
+    key << std::hex << ctf_type << '-' << ctf_cuname(dic);
+  return key.str();
+}
+
 } // End of namespace ctf_reader
 } // End of namespace abigail
diff --git a/src/abg-ir.cc b/src/abg-ir.cc
index 0ef5e8b2..5eebcfa3 100644
--- a/src/abg-ir.cc
+++ b/src/abg-ir.cc
@@ -3165,7 +3165,8 @@ typedef unordered_map<interned_string,
 
 /// Default constructor of the @ref environment type.
 environment::environment()
-  :priv_(new priv)
+  :priv_(new priv),
+  debug_format_(DWARF_FORMAT_TYPE)
 {}
 
 /// Destructor for the @ref environment type.
@@ -3779,6 +3780,20 @@ environment::get_canonical_type_from_type_id(const char* type_id)
   return 0;
 }
 #endif
+
+/// Getter of the debug format of the source.
+///
+/// @return the debug format of the source.
+environment::debug_format_type
+environment::get_debug_format_type() const
+{return debug_format_;}
+
+/// Setter of the debug format of the source.
+///
+/// @param d the new debug format.
+void
+environment::set_debug_format_type(environment::debug_format_type d)
+{debug_format_ = d;}
 // </environment stuff>
 
 // <type_or_decl_base stuff>
diff --git a/src/abg-tools-utils.cc b/src/abg-tools-utils.cc
index e94c3003..b73786a8 100644
--- a/src/abg-tools-utils.cc
+++ b/src/abg-tools-utils.cc
@@ -44,6 +44,9 @@
 #include <sstream>
 
 #include "abg-dwarf-reader.h"
+#ifdef WITH_CTF
+#include "abg-ctf-reader.h"
+#endif
 #include "abg-internal.h"
 #include "abg-regex.h"
 
@@ -2234,9 +2237,11 @@ load_generate_apply_suppressions(dwarf_reader::read_context &read_ctxt,
 ///
 /// @param entry the FTSENT to consider.
 ///
+/// @param filename the name of file.
+///
 /// @return true iff @p entry is for a vmlinux binary.
 static bool
-is_vmlinux(const FTSENT *entry)
+is_vmlinux(const FTSENT *entry, const string &filename)
 {
   if (entry == NULL
       || (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
@@ -2246,7 +2251,7 @@ is_vmlinux(const FTSENT *entry)
 
   string fname = entry->fts_name;
 
-  if (fname == "vmlinux")
+  if (fname == filename)
     {
       string dirname;
       dir_name(entry->fts_path, dirname);
@@ -2317,7 +2322,7 @@ find_vmlinux_and_module_paths(const string&	from,
 	  continue;
 	}
 
-      if (!found_vmlinux && is_vmlinux(entry))
+      if (!found_vmlinux && is_vmlinux(entry, "vmlinux"))
 	{
 	  vmlinux_path = entry->fts_path;
 	  found_vmlinux = true;
@@ -2337,10 +2342,13 @@ find_vmlinux_and_module_paths(const string&	from,
 ///
 /// @param vmlinux_path output parameter
 ///
+/// @param vmlinux_name output parameter
+///
 /// return true iff the vmlinux binary was found
 static bool
 find_vmlinux_path(const string&	from,
-		  string		&vmlinux_path)
+		  string		&vmlinux_path,
+		  const string		&vmlinux_name)
 {
   char* path[] = {const_cast<char*>(from.c_str()), 0};
 
@@ -2359,7 +2367,7 @@ find_vmlinux_path(const string&	from,
 	  continue;
 	}
 
-      if (!found_vmlinux && is_vmlinux(entry))
+      if (!found_vmlinux && is_vmlinux(entry, vmlinux_name))
 	{
 	  vmlinux_path = entry->fts_path;
 	  found_vmlinux = true;
@@ -2456,12 +2464,37 @@ get_vmlinux_path_from_kernel_dist(const string&	from,
     dist_root += "/lib/modules";
 
   bool found = false;
-  if (find_vmlinux_path(dist_root, vmlinux_path))
+  if (find_vmlinux_path(dist_root, vmlinux_path, "vmlinux"))
     found = true;
 
   return found;
 }
 
+/// Get the paths of the CTF vmlinux archive under given directory.
+///
+/// @param from the directory under which to look for.
+///
+/// @param vmlinux_path output parameter.  The path of the CTF vmlinux
+/// binary that was found.
+///
+/// @return true if at least the path to the vmlinux.ctfa binary was found.
+#ifdef WITH_CTF
+bool
+get_vmlinux_ctfa_path_from_kernel_dist(const string& from,
+                                       string& vmlinux_ctfa_path)
+{
+  if (!dir_exists(from))
+    return false;
+
+  string dist_root = from;
+  bool found = false;
+  if (find_vmlinux_path(dist_root, vmlinux_ctfa_path, "vmlinux.ctfa"))
+    found = true;
+
+  return found;
+}
+#endif
+
 /// Get the paths of the vmlinux and kernel module binaries under
 /// given directory.
 ///
@@ -2543,12 +2576,21 @@ build_corpus_group_from_kernel_dist_under(const string&	root,
   t.start();
   bool got_binary_paths =
     get_binary_paths_from_kernel_dist(root, debug_info_root, vmlinux, modules);
+#ifdef WITH_CTF
+  string vmlinux_ctfa;
+  if (got_binary_paths &&
+      env->get_debug_format_type() == environment::CTF_FORMAT_TYPE)
+    {
+      got_binary_paths = get_vmlinux_ctfa_path_from_kernel_dist(root, vmlinux_ctfa);
+      ABG_ASSERT(!vmlinux_ctfa.empty());
+    }
+#endif
+
   t.stop();
 
   if (verbose)
     std::cerr << "DONE: " << t << "\n";
 
-  dwarf_reader::read_context_sptr ctxt;
   if (got_binary_paths)
     {
       shared_ptr<char> di_root =
@@ -2558,81 +2600,149 @@ build_corpus_group_from_kernel_dist_under(const string&	root,
       di_roots.push_back(&di_root_ptr);
       abigail::elf_reader::status status = abigail::elf_reader::STATUS_OK;
       corpus_group_sptr group;
-      if (!vmlinux.empty())
-	{
-	  ctxt =
-	    dwarf_reader::create_read_context(vmlinux, di_roots ,env.get(),
-					      /*read_all_types=*/false,
-					      /*linux_kernel_mode=*/true);
-	  dwarf_reader::set_do_log(*ctxt, verbose);
-
-	  t.start();
-	  load_generate_apply_suppressions(*ctxt, suppr_paths,
-					   kabi_wl_paths, supprs);
-	  t.stop();
-
-	  if (verbose)
-	    std::cerr << "loaded white list and generated suppr spec in: "
-		      << t
-		      << "\n";
-
-	  group.reset(new corpus_group(env.get(), root));
-
-	  set_read_context_corpus_group(*ctxt, group);
-
-	  if (verbose)
-	    std::cerr << "reading kernel binary '"
-		      << vmlinux << "' ...\n" << std::flush;
-
-	  // Read the vmlinux corpus and add it to the group.
-	  t.start();
-	  read_and_add_corpus_to_group_from_elf(*ctxt, *group, status);
-	  t.stop();
-
-	  if (verbose)
-	    std::cerr << vmlinux
-		      << " reading DONE:"
-		      << t << "\n";
-	}
 
-      if (!group->is_empty())
-	{
-	  // Now add the corpora of the modules to the corpus group.
-	  int total_nb_modules = modules.size();
-	  int cur_module_index = 1;
-	  for (vector<string>::const_iterator m = modules.begin();
-	       m != modules.end();
-	       ++m, ++cur_module_index)
-	    {
-	      if (verbose)
-		std::cerr << "reading module '"
-			  << *m << "' ("
-			  << cur_module_index
-			  << "/" << total_nb_modules
-			  << ") ... " << std::flush;
-
-	      reset_read_context(ctxt, *m, di_roots, env.get(),
-				 /*read_all_types=*/false,
-				 /*linux_kernel_mode=*/true);
-
-	      load_generate_apply_suppressions(*ctxt, suppr_paths,
-					       kabi_wl_paths, supprs);
-
-	      set_read_context_corpus_group(*ctxt, group);
-
-	      t.start();
-	      read_and_add_corpus_to_group_from_elf(*ctxt,
-						    *group, status);
-	      t.stop();
-	      if (verbose)
-		std::cerr << "module '"
-			  << *m
-			  << "' reading DONE: "
-			  << t << "\n";
-	    }
-
-	  result = group;
-	}
+      if (env->get_debug_format_type() == environment::DWARF_FORMAT_TYPE)
+        {
+          dwarf_reader::read_context_sptr ctxt;
+          if (!vmlinux.empty())
+            {
+              ctxt =
+               dwarf_reader::create_read_context(vmlinux, di_roots, env.get(),
+                                                 /*read_all_types=*/false,
+                                                 /*linux_kernel_mode=*/true);
+              dwarf_reader::set_do_log(*ctxt, verbose);
+
+              t.start();
+              load_generate_apply_suppressions(*ctxt, suppr_paths,
+                                               kabi_wl_paths, supprs);
+              t.stop();
+
+              if (verbose)
+                std::cerr << "loaded white list and generated suppr spec in: "
+                 << t
+                 << "\n";
+
+              group.reset(new corpus_group(env.get(), root));
+
+              set_read_context_corpus_group(*ctxt, group);
+
+              if (verbose)
+                std::cerr << "reading kernel binary '"
+                 << vmlinux << "' ...\n" << std::flush;
+
+              // Read the vmlinux corpus and add it to the group.
+              t.start();
+              read_and_add_corpus_to_group_from_elf(*ctxt, *group, status);
+              t.stop();
+
+              if (verbose)
+                std::cerr << vmlinux
+                 << " reading DONE:"
+                 << t << "\n";
+            }
+
+          if (!group->is_empty())
+            {
+              // Now add the corpora of the modules to the corpus group.
+              int total_nb_modules = modules.size();
+              int cur_module_index = 1;
+              for (vector<string>::const_iterator m = modules.begin();
+                   m != modules.end();
+                   ++m, ++cur_module_index)
+                {
+                  if (verbose)
+                    std::cerr << "reading module '"
+                     << *m << "' ("
+                     << cur_module_index
+                     << "/" << total_nb_modules
+                     << ") ... " << std::flush;
+
+                  reset_read_context(ctxt, *m, di_roots, env.get(),
+                                     /*read_all_types=*/false,
+                                     /*linux_kernel_mode=*/true);
+
+                  load_generate_apply_suppressions(*ctxt, suppr_paths,
+                                                   kabi_wl_paths, supprs);
+
+                  set_read_context_corpus_group(*ctxt, group);
+
+                  t.start();
+                  read_and_add_corpus_to_group_from_elf(*ctxt,
+                                                        *group, status);
+                  t.stop();
+                  if (verbose)
+                    std::cerr << "module '"
+                     << *m
+                     << "' reading DONE: "
+                     << t << "\n";
+                }
+
+              result = group;
+            }
+        }
+#ifdef WITH_CTF
+      else if (env->get_debug_format_type() == environment::CTF_FORMAT_TYPE)
+        {
+          ctf_reader::read_context_sptr ctxt;
+          if (!vmlinux.empty())
+            {
+              ctxt =
+               ctf_reader::create_read_context(vmlinux, env.get());
+              set_vmlinux_ctfa_path(*ctxt, vmlinux_ctfa);
+
+              group.reset(new corpus_group(env.get(), root));
+              set_read_context_corpus_group(*ctxt, group);
+
+              if (verbose)
+                std::cerr << "reading kernel binary '"
+                 << vmlinux << "' ...\n" << std::flush;
+
+              // Read the vmlinux corpus and add it to the group.
+              t.start();
+              read_and_add_corpus_to_group_from_elf(ctxt.get(), *group, status);
+              t.stop();
+
+              if (verbose)
+                std::cerr << vmlinux
+                 << " reading DONE:"
+                 << t << "\n";
+            }
+
+           if (!group->is_empty())
+             {
+               // Now add the corpora of the modules to the corpus group.
+               int total_nb_modules = modules.size();
+               int cur_module_index = 1;
+               for (vector<string>::const_iterator m = modules.begin();
+                    m != modules.end();
+                    ++m, ++cur_module_index)
+                 {
+                   if (verbose)
+                     std::cerr << "reading module '"
+                      << *m << "' ("
+                      << cur_module_index
+                      << "/" << total_nb_modules
+                      << ") ... " << std::flush;
+
+                   reset_read_context(ctxt, *m, env.get());
+                   set_vmlinux_ctfa_path(*ctxt, vmlinux_ctfa);
+                   set_read_context_corpus_group(*ctxt, group);
+
+                   t.start();
+                   read_and_add_corpus_to_group_from_elf(ctxt.get(),
+                                                         *group, status);
+                   t.stop();
+                   if (verbose)
+                     std::cerr << "module '"
+                      << *m
+                      << "' reading DONE: "
+                      << t << "\n";
+                 }
+
+               result = group;
+             }
+        }
+#endif
     }
 
   return result;
diff --git a/tests/data/test-read-common/test-PR26568-2.o b/tests/data/test-read-common/test-PR26568-2.o
index b192d52132766d4f95136e23f93de43a64d8cc2e..a6706e8cf508ab89927b0fccecd0268d27111ed9 100644
GIT binary patch
diff --git a/tests/data/test-read-ctf/PR27700/test-PR27700.abi b/tests/data/test-read-ctf/PR27700/test-PR27700.abi
index 62df1017..fe3a897d 100644
--- a/tests/data/test-read-ctf/PR27700/test-PR27700.abi
+++ b/tests/data/test-read-ctf/PR27700/test-PR27700.abi
@@ -11,9 +11,8 @@
       <enumerator name='foo_e2' value='2'/>
       <enumerator name='foo_e3' value='3'/>
     </enum-decl>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
     <pointer-type-def type-id='022218d8' size-in-bits='64' alignment-in-bits='64' id='8750e847'/>
-    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='foo'>
       <parameter type-id='8750e847'/>
       <return type-id='48b5725f'/>
     </function-decl>
diff --git a/tests/data/test-read-ctf/test-PR26568-1.o.abi b/tests/data/test-read-ctf/test-PR26568-1.o.abi
index d62474ec..cfb8a50c 100644
--- a/tests/data/test-read-ctf/test-PR26568-1.o.abi
+++ b/tests/data/test-read-ctf/test-PR26568-1.o.abi
@@ -20,14 +20,14 @@
         <var-decl name='y' type-id='type-id-6' visibility='default'/>
       </data-member>
     </class-decl>
-    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
+    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='x' type-id='type-id-4' visibility='default'/>
+        <var-decl name='y' type-id='type-id-6' visibility='default'/>
       </data-member>
     </class-decl>
-    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
+    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='y' type-id='type-id-6' visibility='default'/>
+        <var-decl name='x' type-id='type-id-4' visibility='default'/>
       </data-member>
     </class-decl>
     <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
@@ -47,7 +47,7 @@
       </data-member>
     </union-decl>
     <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
-    <function-decl name='fun' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='fun' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='fun'>
       <parameter type-id='type-id-7'/>
       <return type-id='type-id-8'/>
     </function-decl>
diff --git a/tests/data/test-read-ctf/test-PR26568-2.o.abi b/tests/data/test-read-ctf/test-PR26568-2.o.abi
index a934d15b..1163f085 100644
--- a/tests/data/test-read-ctf/test-PR26568-2.o.abi
+++ b/tests/data/test-read-ctf/test-PR26568-2.o.abi
@@ -3,34 +3,34 @@
     <elf-symbol name='fun' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
   <abi-instr address-size='64' language='LANG_C'>
-    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-1'>
+    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-1'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='x' type-id='type-id-2' visibility='default'/>
+        <var-decl name='y' type-id='type-id-2' visibility='default'/>
       </data-member>
     </class-decl>
-    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
+    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='y' type-id='type-id-4' visibility='default'/>
+        <var-decl name='x' type-id='type-id-4' visibility='default'/>
       </data-member>
     </class-decl>
-    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
-    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
     <union-decl name='A' size-in-bits='64' visibility='default' id='type-id-5'>
       <data-member access='public'>
-        <var-decl name='' type-id='type-id-1' visibility='default'/>
+        <var-decl name='' type-id='type-id-3' visibility='default'/>
       </data-member>
       <data-member access='public'>
-        <var-decl name='x' type-id='type-id-2' visibility='default'/>
+        <var-decl name='x' type-id='type-id-4' visibility='default'/>
       </data-member>
       <data-member access='public'>
-        <var-decl name='' type-id='type-id-3' visibility='default'/>
+        <var-decl name='' type-id='type-id-1' visibility='default'/>
       </data-member>
       <data-member access='public'>
-        <var-decl name='y' type-id='type-id-4' visibility='default'/>
+        <var-decl name='y' type-id='type-id-2' visibility='default'/>
       </data-member>
     </union-decl>
     <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
-    <function-decl name='fun' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='fun' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='fun'>
       <parameter type-id='type-id-6'/>
       <return type-id='type-id-7'/>
     </function-decl>
diff --git a/tests/data/test-read-ctf/test-PR27700.abi b/tests/data/test-read-ctf/test-PR27700.abi
new file mode 100644
index 00000000..fe3a897d
--- /dev/null
+++ b/tests/data/test-read-ctf/test-PR27700.abi
@@ -0,0 +1,21 @@
+<abi-corpus version='2.1' path='data/test-read-common/PR27700/test-PR27700.o'>
+  <elf-function-symbols>
+    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
+    <enum-decl name='foo' linkage-name='foo' id='022218d8'>
+      <underlying-type type-id='811c9dc5'/>
+      <enumerator name='foo_e0' value='0'/>
+      <enumerator name='foo_e1' value='1'/>
+      <enumerator name='foo_e2' value='2'/>
+      <enumerator name='foo_e3' value='3'/>
+    </enum-decl>
+    <pointer-type-def type-id='022218d8' size-in-bits='64' alignment-in-bits='64' id='8750e847'/>
+    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='foo'>
+      <parameter type-id='8750e847'/>
+      <return type-id='48b5725f'/>
+    </function-decl>
+    <type-decl name='void' id='48b5725f'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi b/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi
index 922a1daf..12050a5b 100644
--- a/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi
+++ b/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi
@@ -30,7 +30,6 @@
     <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='7359adad'/>
     <pointer-type-def type-id='3ed987a4' size-in-bits='64' alignment-in-bits='64' id='84d5ac12'/>
     <pointer-type-def type-id='1c12b755' size-in-bits='64' alignment-in-bits='64' id='55cd64e8'/>
-    <var-decl name='a' type-id='3ed987a4' mangled-name='a' visibility='default'/>
-    <var-decl name='foo' type-id='55cd64e8' mangled-name='foo' visibility='default'/>
+    <var-decl name='foo' type-id='55cd64e8' mangled-name='foo' visibility='default' elf-symbol-id='foo'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-B.c b/tests/data/test-read-ctf/test-ambiguous-struct-B.c
index 95a93469..e592529b 100644
--- a/tests/data/test-read-ctf/test-ambiguous-struct-B.c
+++ b/tests/data/test-read-ctf/test-ambiguous-struct-B.c
@@ -2,4 +2,4 @@ struct A;
 struct B { struct A *a; };
 struct A { struct B b; int foo; struct B b2; };
 
-static struct A a __attribute__((__used__));
+struct A a __attribute__((__used__));
diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-B.o b/tests/data/test-read-ctf/test-ambiguous-struct-B.o
index 06bd0f502a874ad4a10c4beb5788eaace44c2bf9..40a11fcbd4ae19b78a943812f69606cdc6c9fc15 100644
GIT binary patch
diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi b/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi
index 28291eb5..83d21919 100644
--- a/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi
+++ b/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi
@@ -1,4 +1,7 @@
 <abi-corpus version='2.1' path='data/test-read-ctf/test-ambiguous-struct-B.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='a' size='24' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
   <abi-instr address-size='64' language='LANG_C'>
     <class-decl name='A' size-in-bits='192' alignment-in-bits='64' is-struct='yes' visibility='default' id='3ed987a4'>
       <data-member access='public' layout-offset-in-bits='0'>
@@ -18,6 +21,6 @@
     </class-decl>
     <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
     <pointer-type-def type-id='3ed987a4' size-in-bits='64' alignment-in-bits='64' id='84d5ac12'/>
-    <var-decl name='a' type-id='3ed987a4' mangled-name='a' visibility='default'/>
+    <var-decl name='a' type-id='3ed987a4' mangled-name='a' visibility='default' elf-symbol-id='a'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-anonymous-fields.o.abi b/tests/data/test-read-ctf/test-anonymous-fields.o.abi
new file mode 100644
index 00000000..0419c29c
--- /dev/null
+++ b/tests/data/test-read-ctf/test-anonymous-fields.o.abi
@@ -0,0 +1,33 @@
+<abi-corpus version='2.1' path='data/test-read-ctf/test-anonymous-fields.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='t' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-1'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='vaddr' type-id='type-id-2' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='dup_xol_work' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='uprobe_task' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-5'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='' type-id='type-id-6' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
+    <union-decl name='' size-in-bits='64' is-anonymous='yes' visibility='default' id='type-id-6'>
+      <data-member access='public'>
+        <var-decl name='' type-id='type-id-1' visibility='default'/>
+      </data-member>
+      <data-member access='public'>
+        <var-decl name='' type-id='type-id-3' visibility='default'/>
+      </data-member>
+    </union-decl>
+    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
+    <var-decl name='t' type-id='type-id-5' mangled-name='t' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-array-of-pointers.abi b/tests/data/test-read-ctf/test-array-of-pointers.abi
index 920da28b..195361df 100644
--- a/tests/data/test-read-ctf/test-array-of-pointers.abi
+++ b/tests/data/test-read-ctf/test-array-of-pointers.abi
@@ -31,6 +31,6 @@
     <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
     <pointer-type-def type-id='type-id-4' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
     <pointer-type-def type-id='type-id-6' size-in-bits='64' alignment-in-bits='64' id='type-id-11'/>
-    <var-decl name='t' type-id='type-id-11' mangled-name='t' visibility='default'/>
+    <var-decl name='t' type-id='type-id-11' mangled-name='t' visibility='default' elf-symbol-id='t'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-callback.abi b/tests/data/test-read-ctf/test-callback.abi
index 704c4971..7f9b6c5f 100644
--- a/tests/data/test-read-ctf/test-callback.abi
+++ b/tests/data/test-read-ctf/test-callback.abi
@@ -4,28 +4,16 @@
     <elf-symbol name='f2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
   <abi-instr address-size='64' language='LANG_C'>
-    <class-decl name='test' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-1'>
-      <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='fn1' type-id='type-id-2' visibility='default'/>
-      </data-member>
-    </class-decl>
-    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
-    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
-    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
-    <pointer-type-def type-id='type-id-6' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
-    <function-decl name='assign' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
-      <return type-id='type-id-7'/>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
+    <function-decl name='assign' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='assign'>
+      <return type-id='type-id-3'/>
     </function-decl>
-    <function-decl name='f2' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
-      <parameter type-id='type-id-3'/>
-      <parameter type-id='type-id-4'/>
-      <return type-id='type-id-7'/>
+    <function-decl name='f2' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='f2'>
+      <parameter type-id='type-id-1'/>
+      <parameter type-id='type-id-2'/>
+      <return type-id='type-id-3'/>
     </function-decl>
-    <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-6'>
-      <parameter type-id='type-id-3'/>
-      <parameter type-id='type-id-4'/>
-      <return type-id='type-id-7'/>
-    </function-type>
-    <type-decl name='void' id='type-id-7'/>
+    <type-decl name='void' id='type-id-3'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-callback2.abi b/tests/data/test-read-ctf/test-callback2.abi
index bdd4ad33..ddc3e493 100644
--- a/tests/data/test-read-ctf/test-callback2.abi
+++ b/tests/data/test-read-ctf/test-callback2.abi
@@ -11,7 +11,7 @@
     <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
     <pointer-type-def type-id='type-id-4' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
     <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
-    <var-decl name='s0' type-id='type-id-5' mangled-name='s0' visibility='default'/>
+    <var-decl name='s0' type-id='type-id-5' mangled-name='s0' visibility='default' elf-symbol-id='s0'/>
     <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-4'>
       <parameter type-id='type-id-5'/>
       <return type-id='type-id-3'/>
diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi b/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi
index 03dd56b3..8d5c3e36 100644
--- a/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi
+++ b/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi
@@ -8,7 +8,7 @@
     <typedef-decl name='a_t' type-id='bd54fe1a' id='40acc204'/>
     <typedef-decl name='b_t' type-id='bd54fe1a' id='b3d2db81'/>
     <pointer-type-def type-id='40acc204' size-in-bits='64' alignment-in-bits='64' id='c6fd4117'/>
-    <var-decl name='a' type-id='c6fd4117' mangled-name='a' visibility='default'/>
-    <var-decl name='ignore2' type-id='b3d2db81' mangled-name='ignore2' visibility='default'/>
+    <var-decl name='a' type-id='c6fd4117' mangled-name='a' visibility='default' elf-symbol-id='a'/>
+    <var-decl name='ignore2' type-id='b3d2db81' mangled-name='ignore2' visibility='default' elf-symbol-id='ignore2'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi b/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi
index 35bcac7a..992b669d 100644
--- a/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi
+++ b/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi
@@ -7,7 +7,7 @@
     <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
     <typedef-decl name='a_t' type-id='bd54fe1a' id='40acc204'/>
     <typedef-decl name='b_t' type-id='bd54fe1a' id='b3d2db81'/>
-    <var-decl name='b' type-id='40acc204' mangled-name='b' visibility='default'/>
-    <var-decl name='ignore1' type-id='b3d2db81' mangled-name='ignore1' visibility='default'/>
+    <var-decl name='b' type-id='40acc204' mangled-name='b' visibility='default' elf-symbol-id='b'/>
+    <var-decl name='ignore1' type-id='b3d2db81' mangled-name='ignore1' visibility='default' elf-symbol-id='ignore1'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-dynamic-array.o.abi b/tests/data/test-read-ctf/test-dynamic-array.o.abi
index 02b22811..a9849d49 100644
--- a/tests/data/test-read-ctf/test-dynamic-array.o.abi
+++ b/tests/data/test-read-ctf/test-dynamic-array.o.abi
@@ -21,7 +21,7 @@
     <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-3'/>
     <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
     <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
-    <function-decl name='use_struct_s' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='use_struct_s' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='use_struct_s'>
       <parameter type-id='type-id-7'/>
       <return type-id='type-id-8'/>
     </function-decl>
diff --git a/tests/data/test-read-ctf/test-enum-ctf.o.abi b/tests/data/test-read-ctf/test-enum-ctf.o.abi
new file mode 100644
index 00000000..f36f3fad
--- /dev/null
+++ b/tests/data/test-read-ctf/test-enum-ctf.o.abi
@@ -0,0 +1,24 @@
+<abi-corpus version='2.1' path='data/test-read-ctf/test-enum-ctf.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='bar' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
+    <enum-decl name='e' linkage-name='e' id='type-id-2'>
+      <underlying-type type-id='type-id-1'/>
+      <enumerator name='ENUMSAMPLE_1' value='0'/>
+      <enumerator name='ENUMSAMPLE_2' value='1'/>
+    </enum-decl>
+    <enum-decl name='ie' linkage-name='ie' id='type-id-3'>
+      <underlying-type type-id='type-id-1'/>
+      <enumerator name='IENUMSAMPLE_1' value='-10'/>
+      <enumerator name='IENUMSAMPLE_2' value='-9'/>
+      <enumerator name='IENUMSAMPLE_3' value='-8'/>
+    </enum-decl>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-5'/>
+    <var-decl name='foo' type-id='type-id-2' mangled-name='foo' visibility='default'/>
+    <var-decl name='bar' type-id='type-id-3' mangled-name='bar' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi b/tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi
new file mode 100644
index 00000000..67a958a7
--- /dev/null
+++ b/tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi
@@ -0,0 +1,69 @@
+<abi-corpus version='2.1' path='data/test-read-ctf/test-enum-many-ctf.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='bar' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
+    <enum-decl name='e' linkage-name='e' id='a6c2eddf'>
+      <underlying-type type-id='811c9dc5'/>
+      <enumerator name='ENUMSAMPLE_1' value='0'/>
+      <enumerator name='ENUMSAMPLE_2' value='1'/>
+    </enum-decl>
+    <enum-decl name='ie' linkage-name='ie' id='1ee696ca'>
+      <underlying-type type-id='811c9dc5'/>
+      <enumerator name='IE_0' value='-10'/>
+      <enumerator name='IE_1' value='-9'/>
+      <enumerator name='IE_2' value='-8'/>
+      <enumerator name='IE_3' value='-7'/>
+      <enumerator name='IE_4' value='-6'/>
+      <enumerator name='IE_5' value='-5'/>
+      <enumerator name='IE_6' value='-4'/>
+      <enumerator name='IE_7' value='-3'/>
+      <enumerator name='IE_8' value='-2'/>
+      <enumerator name='IE_9' value='-1'/>
+      <enumerator name='IE_A' value='0'/>
+      <enumerator name='IE_B' value='1'/>
+      <enumerator name='IE_C' value='2'/>
+      <enumerator name='IE_D' value='3'/>
+      <enumerator name='IE_E' value='4'/>
+      <enumerator name='IE_F' value='5'/>
+      <enumerator name='IE_10' value='6'/>
+      <enumerator name='IE_11' value='7'/>
+      <enumerator name='IE_12' value='8'/>
+      <enumerator name='IE_13' value='9'/>
+      <enumerator name='IE_14' value='10'/>
+      <enumerator name='IE_15' value='11'/>
+      <enumerator name='IE_16' value='12'/>
+      <enumerator name='IE_17' value='13'/>
+      <enumerator name='IE_18' value='14'/>
+      <enumerator name='IE_19' value='15'/>
+      <enumerator name='IE_1A' value='16'/>
+      <enumerator name='IE_1B' value='17'/>
+      <enumerator name='IE_1C' value='18'/>
+      <enumerator name='IE_1D' value='19'/>
+      <enumerator name='IE_1E' value='20'/>
+      <enumerator name='IE_1F' value='21'/>
+      <enumerator name='IE_20' value='22'/>
+      <enumerator name='IE_21' value='23'/>
+      <enumerator name='IE_22' value='24'/>
+      <enumerator name='IE_23' value='25'/>
+      <enumerator name='IE_24' value='26'/>
+      <enumerator name='IE_25' value='27'/>
+      <enumerator name='IE_26' value='28'/>
+      <enumerator name='IE_27' value='29'/>
+      <enumerator name='IE_28' value='30'/>
+      <enumerator name='IE_29' value='31'/>
+      <enumerator name='IE_2A' value='32'/>
+      <enumerator name='IE_2B' value='33'/>
+      <enumerator name='IE_2C' value='34'/>
+      <enumerator name='IE_2D' value='35'/>
+      <enumerator name='IE_2E' value='36'/>
+      <enumerator name='IE_2F' value='37'/>
+    </enum-decl>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
+    <var-decl name='foo' type-id='a6c2eddf' mangled-name='foo' visibility='default'/>
+    <var-decl name='bar' type-id='1ee696ca' mangled-name='bar' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum-many.o.hash.abi b/tests/data/test-read-ctf/test-enum-many.o.hash.abi
index 26bc048c..116325f9 100644
--- a/tests/data/test-read-ctf/test-enum-many.o.hash.abi
+++ b/tests/data/test-read-ctf/test-enum-many.o.hash.abi
@@ -61,9 +61,7 @@
       <enumerator name='IE_2E' value='36'/>
       <enumerator name='IE_2F' value='37'/>
     </enum-decl>
-    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
-    <var-decl name='foo' type-id='a6c2eddf' mangled-name='foo' visibility='default'/>
-    <var-decl name='bar' type-id='1ee696ca' mangled-name='bar' visibility='default'/>
+    <var-decl name='foo' type-id='a6c2eddf' mangled-name='foo' visibility='default' elf-symbol-id='foo'/>
+    <var-decl name='bar' type-id='1ee696ca' mangled-name='bar' visibility='default' elf-symbol-id='bar'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi b/tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi
new file mode 100644
index 00000000..fea6eb8b
--- /dev/null
+++ b/tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi
@@ -0,0 +1,16 @@
+<abi-corpus version='2.1' path='data/test-read-ctf/test-enum-symbol-ctf.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='primary1' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
+    <enum-decl name='' is-anonymous='yes' id='08f5ca17'>
+      <underlying-type type-id='811c9dc5'/>
+      <enumerator name='red1' value='0'/>
+      <enumerator name='green1' value='1'/>
+      <enumerator name='blue1' value='2'/>
+    </enum-decl>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
+    <var-decl name='primary1' type-id='08f5ca17' mangled-name='primary1' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi b/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi
index d128b5b1..f4911bc4 100644
--- a/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi
+++ b/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi
@@ -10,7 +10,6 @@
       <enumerator name='green1' value='1'/>
       <enumerator name='blue1' value='2'/>
     </enum-decl>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
-    <var-decl name='primary1' type-id='08f5ca17' mangled-name='primary1' visibility='default'/>
+    <var-decl name='primary1' type-id='08f5ca17' mangled-name='primary1' visibility='default' elf-symbol-id='primary1'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum.o.abi b/tests/data/test-read-ctf/test-enum.o.abi
index 88e6ad61..bd3a55be 100644
--- a/tests/data/test-read-ctf/test-enum.o.abi
+++ b/tests/data/test-read-ctf/test-enum.o.abi
@@ -16,9 +16,7 @@
       <enumerator name='IENUMSAMPLE_2' value='-9'/>
       <enumerator name='IENUMSAMPLE_3' value='-8'/>
     </enum-decl>
-    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-5'/>
-    <var-decl name='foo' type-id='type-id-2' mangled-name='foo' visibility='default'/>
-    <var-decl name='bar' type-id='type-id-3' mangled-name='bar' visibility='default'/>
+    <var-decl name='foo' type-id='type-id-2' mangled-name='foo' visibility='default' elf-symbol-id='foo'/>
+    <var-decl name='bar' type-id='type-id-3' mangled-name='bar' visibility='default' elf-symbol-id='bar'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-forward-type-decl.abi b/tests/data/test-read-ctf/test-forward-type-decl.abi
index 21bb45c8..026e7d32 100644
--- a/tests/data/test-read-ctf/test-forward-type-decl.abi
+++ b/tests/data/test-read-ctf/test-forward-type-decl.abi
@@ -24,6 +24,6 @@
     <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
     <pointer-type-def type-id='type-id-4' size-in-bits='64' alignment-in-bits='64' id='type-id-3'/>
     <pointer-type-def type-id='type-id-6' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
-    <var-decl name='addr' type-id='type-id-5' mangled-name='addr' visibility='default'/>
+    <var-decl name='addr' type-id='type-id-5' mangled-name='addr' visibility='default' elf-symbol-id='addr'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-functions-declaration.abi b/tests/data/test-read-ctf/test-functions-declaration.abi
index 9ef05e44..7eb57d26 100644
--- a/tests/data/test-read-ctf/test-functions-declaration.abi
+++ b/tests/data/test-read-ctf/test-functions-declaration.abi
@@ -7,11 +7,11 @@
     <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
     <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
     <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
-    <function-decl name='attribute_container_add_device' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='attribute_container_add_device' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='attribute_container_add_device'>
       <parameter type-id='type-id-4'/>
       <return type-id='type-id-5'/>
     </function-decl>
-    <function-decl name='attribute_container_device_trigger' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='attribute_container_device_trigger' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='attribute_container_device_trigger'>
       <parameter type-id='type-id-4'/>
       <return type-id='type-id-5'/>
     </function-decl>
diff --git a/tests/data/test-read-ctf/test-list-struct.abi b/tests/data/test-read-ctf/test-list-struct.abi
index 196a79a1..deb6a4a1 100644
--- a/tests/data/test-read-ctf/test-list-struct.abi
+++ b/tests/data/test-read-ctf/test-list-struct.abi
@@ -14,7 +14,7 @@
     </class-decl>
     <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
     <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
-    <var-decl name='n1' type-id='type-id-1' mangled-name='n1' visibility='default'/>
-    <var-decl name='n2' type-id='type-id-1' mangled-name='n2' visibility='default'/>
+    <var-decl name='n1' type-id='type-id-1' mangled-name='n1' visibility='default' elf-symbol-id='n1'/>
+    <var-decl name='n2' type-id='type-id-1' mangled-name='n2' visibility='default' elf-symbol-id='n2'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test0 b/tests/data/test-read-ctf/test0
index aca7fbacdfff7ad2caf0142390710373a8da72a1..90aa8a39a2e1326a5cb5faaa9e854fc344caaa52 100755
GIT binary patch
diff --git a/tests/data/test-read-ctf/test0.abi b/tests/data/test-read-ctf/test0.abi
index 50ca26f4..fc61f2ac 100644
--- a/tests/data/test-read-ctf/test0.abi
+++ b/tests/data/test-read-ctf/test0.abi
@@ -39,16 +39,26 @@
     </array-type-def>
     <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-10'/>
     <type-decl name='short int' size-in-bits='16' alignment-in-bits='16' id='type-id-11'/>
-    <type-decl name='signed char' size-in-bits='8' alignment-in-bits='8' id='type-id-12'/>
-    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='type-id-13'/>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-14'/>
     <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
-    <type-decl name='unsigned short int' size-in-bits='16' alignment-in-bits='16' id='type-id-15'/>
-    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-16'/>
-    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-17'/>
-    <qualified-type-def type-id='type-id-3' const='yes' id='type-id-18'/>
-    <pointer-type-def type-id='type-id-10' size-in-bits='64' alignment-in-bits='64' id='type-id-19'/>
-    <qualified-type-def type-id='type-id-19' restrict='yes' id='type-id-20'/>
-    <qualified-type-def type-id='type-id-11' volatile='yes' id='type-id-21'/>
+    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-12'/>
+    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-13'/>
+    <qualified-type-def type-id='type-id-3' const='yes' id='type-id-14'/>
+    <pointer-type-def type-id='type-id-10' size-in-bits='64' alignment-in-bits='64' id='type-id-15'/>
+    <qualified-type-def type-id='type-id-15' restrict='yes' id='type-id-16'/>
+    <qualified-type-def type-id='type-id-11' volatile='yes' id='type-id-17'/>
+    <var-decl name='status' type-id='type-id-5' mangled-name='status' visibility='default' elf-symbol-id='status'/>
+    <var-decl name='test_pointer' type-id='type-id-13' mangled-name='test_pointer' visibility='default' elf-symbol-id='test_pointer'/>
+    <var-decl name='test_const' type-id='type-id-14' mangled-name='test_const' visibility='default' elf-symbol-id='test_const'/>
+    <var-decl name='test_float' type-id='type-id-6' mangled-name='test_float' visibility='default' elf-symbol-id='test_float'/>
+    <function-decl name='foo_1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='foo_1'>
+      <parameter type-id='type-id-12'/>
+      <return type-id='type-id-4'/>
+    </function-decl>
+    <function-decl name='main' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='main'>
+      <return type-id='type-id-4'/>
+    </function-decl>
+    <var-decl name='test_array' type-id='type-id-7' mangled-name='test_array' visibility='default' elf-symbol-id='test_array'/>
+    <var-decl name='test_restrict' type-id='type-id-16' mangled-name='test_restrict' visibility='default' elf-symbol-id='test_restrict'/>
+    <var-decl name='test_volatile' type-id='type-id-17' mangled-name='test_volatile' visibility='default' elf-symbol-id='test_volatile'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test0.c b/tests/data/test-read-ctf/test0.c
index eb702312..fdefd57c 100644
--- a/tests/data/test-read-ctf/test0.c
+++ b/tests/data/test-read-ctf/test0.c
@@ -1,3 +1,9 @@
+/*
+ * ELF EXEC files must use -Wl,--ctf-variables -Bdynimic options
+ * to export an ABI and store CTF symbols information.
+ *
+ * ctf-gcc -gctf -Wl,--ctf-variables -Bdynamic test0.c -o test0
+ */
 
 #include <stdio.h>
 
diff --git a/tests/data/test-read-ctf/test0.hash.abi b/tests/data/test-read-ctf/test0.hash.abi
index b58520ab..eff32228 100644
--- a/tests/data/test-read-ctf/test0.hash.abi
+++ b/tests/data/test-read-ctf/test0.hash.abi
@@ -39,16 +39,26 @@
     </array-type-def>
     <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
     <type-decl name='short int' size-in-bits='16' alignment-in-bits='16' id='a2185560'/>
-    <type-decl name='signed char' size-in-bits='8' alignment-in-bits='8' id='28577a57'/>
-    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='002ac4a6'/>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
     <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='7359adad'/>
-    <type-decl name='unsigned short int' size-in-bits='16' alignment-in-bits='16' id='8efea9e5'/>
     <pointer-type-def type-id='50d9a3fa' size-in-bits='64' alignment-in-bits='64' id='fd01f598'/>
     <pointer-type-def type-id='a84c031d' size-in-bits='64' alignment-in-bits='64' id='26a90f95'/>
     <qualified-type-def type-id='50d9a3fa' const='yes' id='0fb3b55d'/>
     <pointer-type-def type-id='bd54fe1a' size-in-bits='64' alignment-in-bits='64' id='3ccc2590'/>
     <qualified-type-def type-id='3ccc2590' restrict='yes' id='af4b1b38'/>
     <qualified-type-def type-id='a2185560' volatile='yes' id='ec67e496'/>
+    <var-decl name='status' type-id='e7f43f72' mangled-name='status' visibility='default' elf-symbol-id='status'/>
+    <var-decl name='test_pointer' type-id='26a90f95' mangled-name='test_pointer' visibility='default' elf-symbol-id='test_pointer'/>
+    <var-decl name='test_const' type-id='0fb3b55d' mangled-name='test_const' visibility='default' elf-symbol-id='test_const'/>
+    <var-decl name='test_float' type-id='a6c45d85' mangled-name='test_float' visibility='default' elf-symbol-id='test_float'/>
+    <function-decl name='foo_1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='foo_1'>
+      <parameter type-id='fd01f598'/>
+      <return type-id='95e97e5e'/>
+    </function-decl>
+    <function-decl name='main' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='main'>
+      <return type-id='95e97e5e'/>
+    </function-decl>
+    <var-decl name='test_array' type-id='b7bd1749' mangled-name='test_array' visibility='default' elf-symbol-id='test_array'/>
+    <var-decl name='test_restrict' type-id='af4b1b38' mangled-name='test_restrict' visibility='default' elf-symbol-id='test_restrict'/>
+    <var-decl name='test_volatile' type-id='ec67e496' mangled-name='test_volatile' visibility='default' elf-symbol-id='test_volatile'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test1.so.abi b/tests/data/test-read-ctf/test1.so.abi
index 5b3caf63..416bd39d 100644
--- a/tests/data/test-read-ctf/test1.so.abi
+++ b/tests/data/test-read-ctf/test1.so.abi
@@ -16,8 +16,13 @@
     </enum-decl>
     <typedef-decl name='opaque_enum' type-id='type-id-4' id='type-id-3'/>
     <typedef-decl name='opaque_struct' type-id='type-id-2' id='type-id-5'/>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-6'/>
-    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
-    <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
+    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
+    <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
+    <function-decl name='fn' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='fn'>
+      <parameter type-id='type-id-7'/>
+      <parameter type-id='type-id-6'/>
+      <return type-id='type-id-8'/>
+    </function-decl>
+    <type-decl name='void' id='type-id-8'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test1.so.hash.abi b/tests/data/test-read-ctf/test1.so.hash.abi
index 8019cb54..b3620e75 100644
--- a/tests/data/test-read-ctf/test1.so.hash.abi
+++ b/tests/data/test-read-ctf/test1.so.hash.abi
@@ -16,8 +16,13 @@
     </enum-decl>
     <typedef-decl name='opaque_enum' type-id='55763a91' id='99fcd3a5'/>
     <typedef-decl name='opaque_struct' type-id='6cde5052' id='dae69ca1'/>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
     <pointer-type-def type-id='99fcd3a5' size-in-bits='64' alignment-in-bits='64' id='0e0526e0'/>
     <pointer-type-def type-id='dae69ca1' size-in-bits='64' alignment-in-bits='64' id='3f6e71d0'/>
+    <function-decl name='fn' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='fn'>
+      <parameter type-id='3f6e71d0'/>
+      <parameter type-id='0e0526e0'/>
+      <return type-id='48b5725f'/>
+    </function-decl>
+    <type-decl name='void' id='48b5725f'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test2.so.abi b/tests/data/test-read-ctf/test2.so.abi
index eb6aff3e..67f802f9 100644
--- a/tests/data/test-read-ctf/test2.so.abi
+++ b/tests/data/test-read-ctf/test2.so.abi
@@ -20,6 +20,14 @@
     <qualified-type-def type-id='type-id-8' const='yes' id='type-id-9'/>
     <pointer-type-def type-id='type-id-9' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
     <pointer-type-def type-id='type-id-8' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
+    <function-decl name='bar' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='bar'>
+      <parameter type-id='type-id-7'/>
+      <return type-id='type-id-8'/>
+    </function-decl>
+    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='foo'>
+      <parameter type-id='type-id-6'/>
+      <return type-id='type-id-8'/>
+    </function-decl>
     <type-decl name='void' id='type-id-8'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test2.so.hash.abi b/tests/data/test-read-ctf/test2.so.hash.abi
index 6e57333b..6bbf347e 100644
--- a/tests/data/test-read-ctf/test2.so.hash.abi
+++ b/tests/data/test-read-ctf/test2.so.hash.abi
@@ -20,6 +20,14 @@
     <qualified-type-def type-id='48b5725f' const='yes' id='8581546e'/>
     <pointer-type-def type-id='8581546e' size-in-bits='64' alignment-in-bits='64' id='6e97a70c'/>
     <pointer-type-def type-id='48b5725f' size-in-bits='64' alignment-in-bits='64' id='eaa32e2f'/>
+    <function-decl name='bar' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='bar'>
+      <parameter type-id='5e30a4f9'/>
+      <return type-id='48b5725f'/>
+    </function-decl>
+    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='foo'>
+      <parameter type-id='842ea234'/>
+      <return type-id='48b5725f'/>
+    </function-decl>
     <type-decl name='void' id='48b5725f'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test3.so.abi b/tests/data/test-read-ctf/test3.so.abi
index 9d55fec5..3d2f6326 100644
--- a/tests/data/test-read-ctf/test3.so.abi
+++ b/tests/data/test-read-ctf/test3.so.abi
@@ -8,5 +8,9 @@
     <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
   <abi-instr address-size='64' language='LANG_C'>
+    <function-decl name='__foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='__foo'>
+      <return type-id='type-id-1'/>
+    </function-decl>
+    <type-decl name='void' id='type-id-1'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test3.so.hash.abi b/tests/data/test-read-ctf/test3.so.hash.abi
index 9d55fec5..1c69e2e1 100644
--- a/tests/data/test-read-ctf/test3.so.hash.abi
+++ b/tests/data/test-read-ctf/test3.so.hash.abi
@@ -8,5 +8,9 @@
     <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
   <abi-instr address-size='64' language='LANG_C'>
+    <function-decl name='__foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='__foo'>
+      <return type-id='48b5725f'/>
+    </function-decl>
+    <type-decl name='void' id='48b5725f'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test4.so.abi b/tests/data/test-read-ctf/test4.so.abi
index b8e0ead3..dc18e191 100644
--- a/tests/data/test-read-ctf/test4.so.abi
+++ b/tests/data/test-read-ctf/test4.so.abi
@@ -10,5 +10,11 @@
     <qualified-type-def type-id='type-id-1' const='yes' id='type-id-5'/>
     <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
     <qualified-type-def type-id='type-id-6' restrict='yes' id='type-id-7'/>
+    <function-decl name='cpy' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='cpy'>
+      <parameter type-id='type-id-4'/>
+      <parameter type-id='type-id-7'/>
+      <parameter type-id='type-id-2'/>
+      <return type-id='type-id-3'/>
+    </function-decl>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test4.so.hash.abi b/tests/data/test-read-ctf/test4.so.hash.abi
index dbe34d9c..dc428592 100644
--- a/tests/data/test-read-ctf/test4.so.hash.abi
+++ b/tests/data/test-read-ctf/test4.so.hash.abi
@@ -10,5 +10,11 @@
     <qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
     <pointer-type-def type-id='9b45d938' size-in-bits='64' alignment-in-bits='64' id='80f4b756'/>
     <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
+    <function-decl name='cpy' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='cpy'>
+      <parameter type-id='266fe297'/>
+      <parameter type-id='9d26089a'/>
+      <parameter type-id='f0981eeb'/>
+      <return type-id='26a90f95'/>
+    </function-decl>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test5.o.abi b/tests/data/test-read-ctf/test5.o.abi
index eb30cf6a..f7bcdeb1 100644
--- a/tests/data/test-read-ctf/test5.o.abi
+++ b/tests/data/test-read-ctf/test5.o.abi
@@ -17,34 +17,32 @@
     <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
     <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
     <type-decl name='long long int' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
-    <type-decl name='long long unsigned int' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
-    <typedef-decl name='long_long' type-id='type-id-6' id='type-id-8'/>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-9'/>
-    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-10'/>
-    <qualified-type-def type-id='type-id-4' const='yes' id='type-id-11'/>
-    <qualified-type-def type-id='type-id-5' const='yes' id='type-id-12'/>
-    <qualified-type-def type-id='type-id-12' volatile='yes' id='type-id-13'/>
-    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
-      <parameter type-id='type-id-10'/>
-      <parameter type-id='type-id-13'/>
+    <typedef-decl name='long_long' type-id='type-id-6' id='type-id-7'/>
+    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
+    <qualified-type-def type-id='type-id-4' const='yes' id='type-id-9'/>
+    <qualified-type-def type-id='type-id-5' const='yes' id='type-id-10'/>
+    <qualified-type-def type-id='type-id-10' volatile='yes' id='type-id-11'/>
+    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='foo'>
+      <parameter type-id='type-id-8'/>
+      <parameter type-id='type-id-11'/>
       <return type-id='type-id-5'/>
     </function-decl>
-    <function-decl name='baz2' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='baz2' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='baz2'>
       <parameter type-id='type-id-4'/>
-      <return type-id='type-id-8'/>
+      <return type-id='type-id-7'/>
     </function-decl>
-    <function-decl name='bar' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='bar' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='bar'>
       <parameter is-variadic='yes'/>
-      <return type-id='type-id-14'/>
+      <return type-id='type-id-12'/>
     </function-decl>
-    <function-decl name='bar2' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='bar2' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='bar2'>
       <parameter type-id='type-id-3'/>
-      <return type-id='type-id-14'/>
+      <return type-id='type-id-12'/>
     </function-decl>
-    <function-decl name='baz' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='baz' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='baz'>
       <parameter type-id='type-id-4'/>
-      <return type-id='type-id-14'/>
+      <return type-id='type-id-12'/>
     </function-decl>
-    <type-decl name='void' id='type-id-14'/>
+    <type-decl name='void' id='type-id-12'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test7.o.abi b/tests/data/test-read-ctf/test7.o.abi
index b744fac5..a13af174 100644
--- a/tests/data/test-read-ctf/test7.o.abi
+++ b/tests/data/test-read-ctf/test7.o.abi
@@ -3,40 +3,31 @@
     <elf-symbol name='first_type_constructor' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
   <abi-instr address-size='64' language='LANG_C'>
-    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-1'/>
-    <class-decl name='first_type' size-in-bits='128' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-2'>
+    <class-decl name='first_type' size-in-bits='128' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-1'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='member0' type-id='type-id-3' visibility='default'/>
+        <var-decl name='member0' type-id='type-id-2' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='32'>
-        <var-decl name='member1' type-id='type-id-4' visibility='default'/>
+        <var-decl name='member1' type-id='type-id-3' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='64'>
-        <var-decl name='ctor' type-id='type-id-5' visibility='default'/>
+        <var-decl name='ctor' type-id='type-id-4' visibility='default'/>
       </data-member>
     </class-decl>
-    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-6'/>
-    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
-    <type-decl name='long long int' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
-    <type-decl name='long long unsigned int' size-in-bits='64' alignment-in-bits='64' id='type-id-9'/>
-    <type-decl name='short int' size-in-bits='16' alignment-in-bits='16' id='type-id-10'/>
-    <type-decl name='signed char' size-in-bits='8' alignment-in-bits='8' id='type-id-11'/>
-    <typedef-decl name='character' type-id='type-id-12' id='type-id-4'/>
-    <typedef-decl name='constructor' type-id='type-id-13' id='type-id-5'/>
-    <typedef-decl name='integer' type-id='type-id-6' id='type-id-3'/>
-    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='type-id-12'/>
-    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-14'/>
-    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-15'/>
-    <type-decl name='unsigned short int' size-in-bits='16' alignment-in-bits='16' id='type-id-16'/>
-    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-17'/>
-    <pointer-type-def type-id='type-id-18' size-in-bits='64' alignment-in-bits='64' id='type-id-13'/>
-    <function-decl name='first_type_constructor' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
-      <parameter type-id='type-id-17'/>
-      <return type-id='type-id-19'/>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-5'/>
+    <typedef-decl name='character' type-id='type-id-6' id='type-id-3'/>
+    <typedef-decl name='constructor' type-id='type-id-7' id='type-id-4'/>
+    <typedef-decl name='integer' type-id='type-id-5' id='type-id-2'/>
+    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='type-id-6'/>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
+    <pointer-type-def type-id='type-id-9' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
+    <function-decl name='first_type_constructor' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='first_type_constructor'>
+      <parameter type-id='type-id-8'/>
+      <return type-id='type-id-10'/>
     </function-decl>
-    <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-18'>
-      <return type-id='type-id-19'/>
+    <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-9'>
+      <return type-id='type-id-10'/>
     </function-type>
-    <type-decl name='void' id='type-id-19'/>
+    <type-decl name='void' id='type-id-10'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test8.o.abi b/tests/data/test-read-ctf/test8.o.abi
index 68b3af06..b6996c29 100644
--- a/tests/data/test-read-ctf/test8.o.abi
+++ b/tests/data/test-read-ctf/test8.o.abi
@@ -4,7 +4,7 @@
   </elf-function-symbols>
   <abi-instr address-size='64' language='LANG_C'>
     <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
-    <function-decl name='bar' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='bar' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='bar'>
       <parameter type-id='type-id-2'/>
       <return type-id='type-id-1'/>
     </function-decl>
diff --git a/tests/data/test-read-ctf/test9.o.abi b/tests/data/test-read-ctf/test9.o.abi
index 746dd77b..08704d79 100644
--- a/tests/data/test-read-ctf/test9.o.abi
+++ b/tests/data/test-read-ctf/test9.o.abi
@@ -49,7 +49,7 @@
     <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
     <pointer-type-def type-id='type-id-16' size-in-bits='64' alignment-in-bits='64' id='type-id-17'/>
     <pointer-type-def type-id='type-id-18' size-in-bits='64' alignment-in-bits='64' id='type-id-20'/>
-    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='foo'>
       <parameter type-id='type-id-22'/>
       <return type-id='type-id-16'/>
     </function-decl>
diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
index 8ed8ac1a..7c9afa6d 100644
--- a/tests/test-read-ctf.cc
+++ b/tests/test-read-ctf.cc
@@ -261,20 +261,28 @@ static InOutSpec in_out_specs[] =
     "output/test-read-ctf/test-list-struct.abi",
   },
   {
-    "data/test-read-ctf/test-callback2.o",
+    "data/test-read-common/test-PR26568-1.o",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
-    "data/test-read-ctf/test-callback2.abi",
-    "output/test-read-ctf/test-callback2.abi",
+    "data/test-read-ctf/test-PR26568-1.o.abi",
+    "output/test-read-ctf/test-PR26568-1.o.abi",
   },
   {
-    "data/test-read-ctf/test-forward-undefine-type-decl.o",
+    "data/test-read-common/test-PR26568-2.o",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
-    "data/test-read-ctf/test-forward-undefine-type-decl.abi",
-    "output/test-read-ctf/test-forward-undefine-type-decl.abi",
+    "data/test-read-ctf/test-PR26568-2.o.abi",
+    "output/test-read-ctf/test-PR26568-2.o.abi",
+  },
+  {
+    "data/test-read-ctf/test-callback2.o",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-callback2.abi",
+    "output/test-read-ctf/test-callback2.abi",
   },
   // This should be the last entry.
   {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL}
diff --git a/tools/abidw.cc b/tools/abidw.cc
index f7a8937d..f9287b47 100644
--- a/tools/abidw.cc
+++ b/tools/abidw.cc
@@ -958,6 +958,11 @@ main(int argc, char* argv[])
   environment_sptr env(new environment);
   int exit_code = 0;
 
+#ifdef WITH_CTF
+  if (opts.use_ctf)
+    env->set_debug_format_type(environment::CTF_FORMAT_TYPE);
+#endif
+
   if (tools_utils::is_regular_file(opts.in_file_path))
     exit_code = load_corpus_and_write_abixml(argv, env, opts);
   else
