]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/ctfread.c
CTF: handle forward reference type
[thirdparty/binutils-gdb.git] / gdb / ctfread.c
index 3e3bd89d5f1be742d30a7925beef51dc1452a93e..e2b65b622de20d6f5a0268931a64371264fba101 100644 (file)
@@ -1,6 +1,6 @@
 /* Compact ANSI-C Type Format (CTF) support in GDB.
 
-   Copyright (C) 2019 Free Software Foundation, Inc.
+   Copyright (C) 2019-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -45,7 +45,7 @@
    The file header stores a magic number and version information, encoding
    flags, and the byte offset of each of the sections relative to the end of the
    header itself.  If the CTF data has been uniquified against another set of
-   CTF data, a reference to that data also appears in the the header.  This
+   CTF data, a reference to that data also appears in the header.  This
    reference is the name of the label corresponding to the types uniquified
    against.
 
 #include "block.h"
 #include "ctfread.h"
 #include "psympriv.h"
+
+#if ENABLE_LIBCTF
+
 #include "ctf.h"
 #include "ctf-api.h"
 
 static const struct objfile_key<htab, htab_deleter> ctf_tid_key;
-static const struct objfile_data *ctf_file_key;
+
+struct ctf_fp_info
+{
+  explicit ctf_fp_info (ctf_dict_t *cfp) : fp (cfp) {}
+  ~ctf_fp_info ();
+  ctf_dict_t *fp;
+};
+
+/* Cleanup function for the ctf_dict_key data.  */
+ctf_fp_info::~ctf_fp_info ()
+{
+  if (fp == nullptr)
+    return;
+
+  ctf_archive_t *arc = ctf_get_arc (fp);
+  ctf_dict_close (fp);
+  ctf_close (arc);
+}
+
+static const objfile_key<ctf_fp_info> ctf_dict_key;
 
 /* A CTF context consists of a file pointer and an objfile pointer.  */
 
-typedef struct ctf_context
+struct ctf_context
 {
-  ctf_file_t *fp;
+  ctf_dict_t *fp;
   struct objfile *of;
+  psymtab_storage *partial_symtabs;
+  partial_symtab *pst;
   struct buildsym_compunit *builder;
-} ctf_context_t;
+};
+
+/* A partial symtab, specialized for this module.  */
+struct ctf_psymtab : public standard_psymtab
+{
+  ctf_psymtab (const char *filename,
+              psymtab_storage *partial_symtabs,
+              objfile_per_bfd_storage *objfile_per_bfd,
+              CORE_ADDR addr)
+    : standard_psymtab (filename, partial_symtabs, objfile_per_bfd, addr)
+  {
+  }
+
+  void read_symtab (struct objfile *) override;
+  void expand_psymtab (struct objfile *) override;
+
+  struct ctf_context *context;
+};
 
 /* The routines that read and process fields/members of a C struct, union,
    or enumeration, pass lists of data member fields in an instance of a
-   field_info structure. It is derived from dwarf2read.c.  */
+   ctf_field_info structure. It is derived from dwarf2read.c.  */
 
-struct nextfield
+struct ctf_nextfield
 {
   struct field field {};
 };
 
-struct field_info
+struct ctf_field_info
 {
   /* List of data member fields.  */
-  std::vector<struct nextfield> fields;
+  std::vector<struct ctf_nextfield> fields;
 
   /* Context.  */
-  ctf_context_t *cur_context;
+  struct ctf_context *cur_context;
 
   /* Parent type.  */
   struct type *ptype;
@@ -128,30 +169,30 @@ struct field_info
 
 /* Local function prototypes */
 
-static void psymtab_to_symtab (struct partial_symtab *);
-
 static int ctf_add_type_cb (ctf_id_t tid, void *arg);
 
-static struct type *read_array_type (ctf_context_t *ccp, ctf_id_t tid);
+static struct type *read_array_type (struct ctf_context *cp, ctf_id_t tid);
 
-static struct type *read_pointer_type (ctf_context_t *ccp, ctf_id_t tid,
+static struct type *read_pointer_type (struct ctf_context *cp, ctf_id_t tid,
                                       ctf_id_t btid);
 
-static struct type *read_structure_type (ctf_context_t *ccp, ctf_id_t tid);
+static struct type *read_structure_type (struct ctf_context *cp, ctf_id_t tid);
 
-static struct type *read_enum_type (ctf_context_t *ccp, ctf_id_t tid);
+static struct type *read_enum_type (struct ctf_context *cp, ctf_id_t tid);
 
-static struct type *read_typedef_type (ctf_context_t *ccp, ctf_id_t tid,
+static struct type *read_typedef_type (struct ctf_context *cp, ctf_id_t tid,
                                       ctf_id_t btid, const char *name);
 
-static struct type *read_type_record (ctf_context_t *ccp, ctf_id_t tid);
+static struct type *read_type_record (struct ctf_context *cp, ctf_id_t tid);
 
-static void process_structure_type (ctf_context_t *ccp, ctf_id_t tid);
+static void process_structure_type (struct ctf_context *cp, ctf_id_t tid);
 
-static void process_struct_members (ctf_context_t *ccp, ctf_id_t tid,
+static void process_struct_members (struct ctf_context *cp, ctf_id_t tid,
                                    struct type *type);
 
-static struct symbol *new_symbol (ctf_context_t *ccp, struct type *type,
+static struct type *read_forward_type (struct ctf_context *cp, ctf_id_t tid);
+
+static struct symbol *new_symbol (struct ctf_context *cp, struct type *type,
                                  ctf_id_t tid);
 
 struct ctf_tid_and_type
@@ -223,21 +264,40 @@ get_tid_type (struct objfile *of, ctf_id_t tid)
 
   htab = (htab_t) ctf_tid_key.get (of);
   if (htab == NULL)
-    return NULL;
+    return nullptr;
 
   ids.tid = tid;
-  ids.type = NULL;
+  ids.type = nullptr;
   slot = (struct ctf_tid_and_type *) htab_find (htab, &ids);
   if (slot)
     return slot->type;
   else
-    return NULL;
+    return nullptr;
+}
+
+/* Fetch the type for TID in CCP OF's tid_and_type hash, add the type to
+ *    context CCP if hash is empty or TID does not have a saved type.  */
+
+static struct type *
+fetch_tid_type (struct ctf_context *ccp, ctf_id_t tid)
+{
+  struct objfile *of = ccp->of;
+  struct type *typ;
+
+  typ = get_tid_type (of, tid);
+  if (typ == nullptr)
+    {
+      ctf_add_type_cb (tid, ccp);
+      typ = get_tid_type (of, tid);
+    }
+
+  return typ;
 }
 
 /* Return the size of storage in bits for INTEGER, FLOAT, or ENUM.  */
 
 static int
-get_bitsize (ctf_file_t *fp, ctf_id_t tid, uint32_t kind)
+get_bitsize (ctf_dict_t *fp, ctf_id_t tid, uint32_t kind)
 {
   ctf_encoding_t cet;
 
@@ -257,19 +317,19 @@ set_symbol_address (struct objfile *of, struct symbol *sym, const char *name)
 {
   struct bound_minimal_symbol msym;
 
-  msym = lookup_minimal_symbol (name, NULL, of);
+  msym = lookup_minimal_symbol (name, nullptr, of);
   if (msym.minsym != NULL)
     {
       SET_SYMBOL_VALUE_ADDRESS (sym, BMSYMBOL_VALUE_ADDRESS (msym));
       SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
-      SYMBOL_SECTION (sym) = MSYMBOL_SECTION (msym.minsym);
+      sym->set_section_index (msym.minsym->section_index ());
     }
 }
 
 /* Create the vector of fields, and attach it to TYPE.  */
 
 static void
-attach_fields_to_type (struct field_info *fip, struct type *type)
+attach_fields_to_type (struct ctf_field_info *fip, struct type *type)
 {
   int nfields = fip->fields.size ();
 
@@ -277,15 +337,15 @@ attach_fields_to_type (struct field_info *fip, struct type *type)
     return;
 
   /* Record the field count, allocate space for the array of fields.  */
-  TYPE_NFIELDS (type) = nfields;
-  TYPE_FIELDS (type)
-    = (struct field *) TYPE_ZALLOC (type, sizeof (struct field) * nfields);
+  type->set_num_fields (nfields);
+  type->set_fields
+    ((struct field *) TYPE_ZALLOC (type, sizeof (struct field) * nfields));
 
   /* Copy the saved-up fields into the field vector.  */
   for (int i = 0; i < nfields; ++i)
     {
-      struct nextfield &field = fip->fields[i];
-      TYPE_FIELD (type, i) = field.field;
+      struct ctf_nextfield &field = fip->fields[i];
+      type->field (i) = field.field;
     }
 }
 
@@ -299,12 +359,12 @@ ctf_init_float_type (struct objfile *objfile,
                     const char *name,
                     const char *name_hint)
 {
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   const struct floatformat **format;
   struct type *type;
 
   format = gdbarch_floatformat_for_type (gdbarch, name_hint, bits);
-  if (format != NULL)
+  if (format != nullptr)
     type = init_float_type (objfile, bits, name, format);
   else
     type = init_type (objfile, TYPE_CODE_ERROR, bits, name);
@@ -314,7 +374,7 @@ ctf_init_float_type (struct objfile *objfile,
 
 /* Callback to add member NAME to a struct/union type. TID is the type
    of struct/union member, OFFSET is the offset of member in bits,
-   and ARG contains the field_info.  */
+   and ARG contains the ctf_field_info.  */
 
 static int
 ctf_add_member_cb (const char *name,
@@ -322,9 +382,9 @@ ctf_add_member_cb (const char *name,
                   unsigned long offset,
                   void *arg)
 {
-  struct field_info *fip = (struct field_info *) arg;
-  ctf_context_t *ccp = fip->cur_context;
-  struct nextfield new_field;
+  struct ctf_field_info *fip = (struct ctf_field_info *) arg;
+  struct ctf_context *ccp = fip->cur_context;
+  struct ctf_nextfield new_field;
   struct field *fp;
   struct type *t;
   uint32_t kind;
@@ -333,11 +393,11 @@ ctf_add_member_cb (const char *name,
   FIELD_NAME (*fp) = name;
 
   kind = ctf_type_kind (ccp->fp, tid);
-  t = get_tid_type (ccp->of, tid);
-  if (t == NULL)
+  t = fetch_tid_type (ccp, tid);
+  if (t == nullptr)
     {
       t = read_type_record (ccp, tid);
-      if (t == NULL)
+      if (t == nullptr)
        {
          complaint (_("ctf_add_member_cb: %s has NO type (%ld)"), name, tid);
          t = objfile_type (ccp->of)->builtin_error;
@@ -348,7 +408,7 @@ ctf_add_member_cb (const char *name,
   if (kind == CTF_K_STRUCT || kind == CTF_K_UNION)
     process_struct_members (ccp, tid, t);
 
-  FIELD_TYPE (*fp) = t;
+  fp->set_type (t);
   SET_FIELD_BITPOS (*fp, offset / TARGET_CHAR_BIT);
   FIELD_BITSIZE (*fp) = get_bitsize (ccp->fp, tid, kind);
 
@@ -358,29 +418,29 @@ ctf_add_member_cb (const char *name,
 }
 
 /* Callback to add member NAME of EVAL to an enumeration type.
-   ARG contains the field_info.  */
+   ARG contains the ctf_field_info.  */
 
 static int
 ctf_add_enum_member_cb (const char *name, int enum_value, void *arg)
 {
-  struct field_info *fip = (struct field_info *) arg;
-  struct nextfield new_field;
+  struct ctf_field_info *fip = (struct ctf_field_info *) arg;
+  struct ctf_nextfield new_field;
   struct field *fp;
-  ctf_context_t *ccp = fip->cur_context;
+  struct ctf_context *ccp = fip->cur_context;
 
   fp = &new_field.field;
   FIELD_NAME (*fp) = name;
-  FIELD_TYPE (*fp) = NULL;
+  fp->set_type (nullptr);
   SET_FIELD_ENUMVAL (*fp, enum_value);
   FIELD_BITSIZE (*fp) = 0;
 
-  if (name != NULL)
+  if (name != nullptr)
     {
-      struct symbol *sym = allocate_symbol (ccp->of);
+      struct symbol *sym = new (&ccp->of->objfile_obstack) symbol;
       OBJSTAT (ccp->of, n_syms++);
 
-      SYMBOL_SET_LANGUAGE (sym, language_c, &ccp->of->objfile_obstack);
-      SYMBOL_SET_NAMES (sym, name, strlen (name), 0, ccp->of);
+      sym->set_language (language_c, &ccp->of->objfile_obstack);
+      sym->compute_and_set_names (name, false, ccp->of->per_bfd);
       SYMBOL_ACLASS_INDEX (sym) = LOC_CONST;
       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
       SYMBOL_TYPE (sym) = fip->ptype;
@@ -396,24 +456,24 @@ ctf_add_enum_member_cb (const char *name, int enum_value, void *arg)
    domain from TID's kind, and its type from TYPE.  */
 
 static struct symbol *
-new_symbol (ctf_context_t *ccp, struct type *type, ctf_id_t tid)
+new_symbol (struct ctf_context *ccp, struct type *type, ctf_id_t tid)
 {
   struct objfile *objfile = ccp->of;
-  ctf_file_t *fp = ccp->fp;
-  struct symbol *sym = NULL;
+  ctf_dict_t *fp = ccp->fp;
+  struct symbol *sym = nullptr;
 
   gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
-  if (name != NULL)
+  if (name != nullptr)
     {
-      sym = allocate_symbol (objfile);
+      sym = new (&objfile->objfile_obstack) symbol;
       OBJSTAT (objfile, n_syms++);
 
-      SYMBOL_SET_LANGUAGE (sym, language_c, &objfile->objfile_obstack);
-      SYMBOL_SET_NAMES (sym, name.get (), strlen (name.get ()), 1, objfile);
+      sym->set_language (language_c, &objfile->objfile_obstack);
+      sym->compute_and_set_names (name.get (), true, objfile->per_bfd);
       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
       SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
 
-      if (type != NULL)
+      if (type != nullptr)
        SYMBOL_TYPE (sym) = type;
 
       uint32_t kind = ctf_type_kind (fp, tid);
@@ -429,7 +489,7 @@ new_symbol (ctf_context_t *ccp, struct type *type, ctf_id_t tid)
            SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
            break;
          case CTF_K_CONST:
-           if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
+           if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_VOID)
              SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_int;
            break;
          case CTF_K_TYPEDEF:
@@ -459,12 +519,12 @@ new_symbol (ctf_context_t *ccp, struct type *type, ctf_id_t tid)
    and create the symbol for it.  */
 
 static struct type *
-read_base_type (ctf_context_t *ccp, ctf_id_t tid)
+read_base_type (struct ctf_context *ccp, ctf_id_t tid)
 {
   struct objfile *of = ccp->of;
-  ctf_file_t *fp = ccp->fp;
+  ctf_dict_t *fp = ccp->fp;
   ctf_encoding_t cet;
-  struct type *type = NULL;
+  struct type *type = nullptr;
   char *name;
   uint32_t kind;
 
@@ -472,14 +532,14 @@ read_base_type (ctf_context_t *ccp, ctf_id_t tid)
     {
       complaint (_("ctf_type_encoding read_base_type failed - %s"),
                 ctf_errmsg (ctf_errno (fp)));
-      return NULL;
+      return nullptr;
     }
 
   gdb::unique_xmalloc_ptr<char> copied_name (ctf_type_aname_raw (fp, tid));
-  if (copied_name == NULL || strlen (copied_name.get ()) == 0)
+  if (copied_name == nullptr || strlen (copied_name.get ()) == 0)
     {
       name = ctf_type_aname (fp, tid);
-      if (name == NULL)
+      if (name == nullptr)
        complaint (_("ctf_type_aname read_base_type failed - %s"),
                   ctf_errmsg (ctf_errno (fp)));
     }
@@ -490,7 +550,7 @@ read_base_type (ctf_context_t *ccp, ctf_id_t tid)
   if (kind == CTF_K_INTEGER)
     {
       uint32_t issigned, ischar, isbool;
-      struct gdbarch *gdbarch = get_objfile_arch (of);
+      struct gdbarch *gdbarch = of->arch ();
 
       issigned = cet.cte_format & CTF_INT_SIGNED;
       ischar = cet.cte_format & CTF_INT_CHAR;
@@ -522,7 +582,7 @@ read_base_type (ctf_context_t *ccp, ctf_id_t tid)
        {
          struct type *t
            = ctf_init_float_type (of, cet.cte_bits / 2, NULL, name);
-         type = init_complex_type (of, name, t);
+         type = init_complex_type (name, t);
        }
     }
   else
@@ -531,14 +591,14 @@ read_base_type (ctf_context_t *ccp, ctf_id_t tid)
       type = init_type (of, TYPE_CODE_ERROR, cet.cte_bits, name);
     }
 
-  if (name != NULL && strcmp (name, "char") == 0)
-    TYPE_NOSIGN (type) = 1;
+  if (name != nullptr && strcmp (name, "char") == 0)
+    type->set_has_no_signedness (true);
 
   return set_tid_type (of, tid, type);
 }
 
 static void
-process_base_type (ctf_context_t *ccp, ctf_id_t tid)
+process_base_type (struct ctf_context *ccp, ctf_id_t tid)
 {
   struct type *type;
 
@@ -554,24 +614,24 @@ process_base_type (ctf_context_t *ccp, ctf_id_t tid)
    (assuming the type has a name).  */
 
 static struct type *
-read_structure_type (ctf_context_t *ccp, ctf_id_t tid)
+read_structure_type (struct ctf_context *ccp, ctf_id_t tid)
 {
   struct objfile *of = ccp->of;
-  ctf_file_t *fp = ccp->fp;
+  ctf_dict_t *fp = ccp->fp;
   struct type *type;
   uint32_t kind;
 
   type = alloc_type (of);
 
   gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
-  if (name != NULL && strlen (name.get() ) != 0)
-    TYPE_NAME (type) = obstack_strdup (&of->objfile_obstack, name.get ());
+  if (name != nullptr && strlen (name.get ()) != 0)
+    type->set_name (obstack_strdup (&of->objfile_obstack, name.get ()));
 
   kind = ctf_type_kind (fp, tid);
   if (kind == CTF_K_UNION)
-    TYPE_CODE (type) = TYPE_CODE_UNION;
+    type->set_code (TYPE_CODE_UNION);
   else
-    TYPE_CODE (type) = TYPE_CODE_STRUCT;
+    type->set_code (TYPE_CODE_STRUCT);
 
   TYPE_LENGTH (type) = ctf_type_size (fp, tid);
   set_type_align (type, ctf_type_align (fp, tid));
@@ -583,11 +643,11 @@ read_structure_type (ctf_context_t *ccp, ctf_id_t tid)
    and create the symbol for it.  */
 
 static void
-process_struct_members (ctf_context_t *ccp,
+process_struct_members (struct ctf_context *ccp,
                        ctf_id_t tid,
                        struct type *type)
 {
-  struct field_info fi;
+  struct ctf_field_info fi;
 
   fi.cur_context = ccp;
   if (ctf_member_iter (ccp->fp, tid, ctf_add_member_cb, &fi) == CTF_ERR)
@@ -601,7 +661,7 @@ process_struct_members (ctf_context_t *ccp,
 }
 
 static void
-process_structure_type (ctf_context_t *ccp, ctf_id_t tid)
+process_structure_type (struct ctf_context *ccp, ctf_id_t tid)
 {
   struct type *type;
 
@@ -612,25 +672,52 @@ process_structure_type (ctf_context_t *ccp, ctf_id_t tid)
 /* Create a function type for TID and set its return type.  */
 
 static struct type *
-read_func_kind_type (ctf_context_t *ccp, ctf_id_t tid)
+read_func_kind_type (struct ctf_context *ccp, ctf_id_t tid)
 {
   struct objfile *of = ccp->of;
-  ctf_file_t *fp = ccp->fp;
-  struct type *type, *rettype;
+  ctf_dict_t *fp = ccp->fp;
+  struct type *type, *rettype, *atype;
   ctf_funcinfo_t cfi;
+  uint32_t argc;
 
   type = alloc_type (of);
 
   gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
-  if (name != NULL && strlen (name.get ()) != 0)
-    TYPE_NAME (type) = obstack_strdup (&of->objfile_obstack, name.get ());
+  if (name != nullptr && strlen (name.get ()) != 0)
+    type->set_name (obstack_strdup (&of->objfile_obstack, name.get ()));
 
-  TYPE_CODE (type) = TYPE_CODE_FUNC;
+  type->set_code (TYPE_CODE_FUNC);
   ctf_func_type_info (fp, tid, &cfi);
-  rettype = get_tid_type (of, cfi.ctc_return);
+  rettype = fetch_tid_type (ccp, cfi.ctc_return);
   TYPE_TARGET_TYPE (type) = rettype;
   set_type_align (type, ctf_type_align (fp, tid));
 
+  /* Set up function's arguments.  */
+  argc = cfi.ctc_argc;
+  type->set_num_fields (argc);
+  if ((cfi.ctc_flags & CTF_FUNC_VARARG) != 0)
+    type->set_has_varargs (true);
+
+  if (argc != 0)
+    {
+      std::vector<ctf_id_t> argv (argc);
+      if (ctf_func_type_args (fp, tid, argc, argv.data ()) == CTF_ERR)
+       return nullptr;
+
+      type->set_fields
+       ((struct field *) TYPE_ZALLOC (type, argc * sizeof (struct field)));
+      struct type *void_type = objfile_type (of)->builtin_void;
+      /* If failed to find the argument type, fill it with void_type.  */
+      for (int iparam = 0; iparam < argc; iparam++)
+       {
+         atype = get_tid_type (of, argv[iparam]);
+         if (atype != nullptr)
+           type->field (iparam).set_type (atype);
+         else
+           type->field (iparam).set_type (void_type);
+       }
+    }
+
   return set_tid_type (of, tid, type);
 }
 
@@ -638,20 +725,20 @@ read_func_kind_type (ctf_context_t *ccp, ctf_id_t tid)
    enumeration, and create the symbol for the enumeration type.  */
 
 static struct type *
-read_enum_type (ctf_context_t *ccp, ctf_id_t tid)
+read_enum_type (struct ctf_context *ccp, ctf_id_t tid)
 {
   struct objfile *of = ccp->of;
-  ctf_file_t *fp = ccp->fp;
+  ctf_dict_t *fp = ccp->fp;
   struct type *type, *target_type;
   ctf_funcinfo_t fi;
 
   type = alloc_type (of);
 
   gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
-  if (name != NULL && strlen (name.get ()) != 0)
-    TYPE_NAME (type) = obstack_strdup (&of->objfile_obstack, name.get ());
+  if (name != nullptr && strlen (name.get ()) != 0)
+    type->set_name (obstack_strdup (&of->objfile_obstack, name.get ()));
 
-  TYPE_CODE (type) = TYPE_CODE_ENUM;
+  type->set_code (TYPE_CODE_ENUM);
   TYPE_LENGTH (type) = ctf_type_size (fp, tid);
   ctf_func_type_info (fp, tid, &fi);
   target_type = get_tid_type (of, fi.ctc_return);
@@ -662,10 +749,10 @@ read_enum_type (ctf_context_t *ccp, ctf_id_t tid)
 }
 
 static void
-process_enum_type (ctf_context_t *ccp, ctf_id_t tid)
+process_enum_type (struct ctf_context *ccp, ctf_id_t tid)
 {
   struct type *type;
-  struct field_info fi;
+  struct ctf_field_info fi;
 
   type = read_enum_type (ccp, tid);
 
@@ -684,7 +771,7 @@ process_enum_type (ctf_context_t *ccp, ctf_id_t tid)
 /* Add given cv-qualifiers CNST+VOLTL to the BASE_TYPE of array TID.  */
 
 static struct type *
-add_array_cv_type (ctf_context_t *ccp,
+add_array_cv_type (struct ctf_context *ccp,
                   ctf_id_t tid,
                   struct type *base_type,
                   int cnst,
@@ -695,7 +782,7 @@ add_array_cv_type (ctf_context_t *ccp,
   base_type = copy_type (base_type);
   inner_array = base_type;
 
-  while (TYPE_CODE (TYPE_TARGET_TYPE (inner_array)) == TYPE_CODE_ARRAY)
+  while (TYPE_TARGET_TYPE (inner_array)->code () == TYPE_CODE_ARRAY)
     {
       TYPE_TARGET_TYPE (inner_array)
        = copy_type (TYPE_TARGET_TYPE (inner_array));
@@ -705,7 +792,7 @@ add_array_cv_type (ctf_context_t *ccp,
   el_type = TYPE_TARGET_TYPE (inner_array);
   cnst |= TYPE_CONST (el_type);
   voltl |= TYPE_VOLATILE (el_type);
-  TYPE_TARGET_TYPE (inner_array) = make_cv_type (cnst, voltl, el_type, NULL);
+  TYPE_TARGET_TYPE (inner_array) = make_cv_type (cnst, voltl, el_type, nullptr);
 
   return set_tid_type (ccp->of, tid, base_type);
 }
@@ -713,10 +800,10 @@ add_array_cv_type (ctf_context_t *ccp,
 /* Read all information from a TID of CTF_K_ARRAY.  */
 
 static struct type *
-read_array_type (ctf_context_t *ccp, ctf_id_t tid)
+read_array_type (struct ctf_context *ccp, ctf_id_t tid)
 {
   struct objfile *objfile = ccp->of;
-  ctf_file_t *fp = ccp->fp;
+  ctf_dict_t *fp = ccp->fp;
   struct type *element_type, *range_type, *idx_type;
   struct type *type;
   ctf_arinfo_t ar;
@@ -725,24 +812,24 @@ read_array_type (ctf_context_t *ccp, ctf_id_t tid)
     {
       complaint (_("ctf_array_info read_array_type failed - %s"),
                 ctf_errmsg (ctf_errno (fp)));
-      return NULL;
+      return nullptr;
     }
 
-  element_type = get_tid_type (objfile, ar.ctr_contents);
-  if (element_type == NULL)
-    return NULL;
+  element_type = fetch_tid_type (ccp, ar.ctr_contents);
+  if (element_type == nullptr)
+    return nullptr;
 
-  idx_type = get_tid_type (objfile, ar.ctr_index);
-  if (idx_type == NULL)
+  idx_type = fetch_tid_type (ccp, ar.ctr_index);
+  if (idx_type == nullptr)
     idx_type = objfile_type (objfile)->builtin_int;
 
   range_type = create_static_range_type (NULL, idx_type, 0, ar.ctr_nelems - 1);
   type = create_array_type (NULL, element_type, range_type);
   if (ar.ctr_nelems <= 1)      /* Check if undefined upper bound.  */
     {
-      TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
+      range_type->bounds ()->high.set_undefined ();
       TYPE_LENGTH (type) = 0;
-      TYPE_TARGET_STUB (type) = 1;
+      type->set_target_is_stub (true);
     }
   else
     TYPE_LENGTH (type) = ctf_type_size (fp, tid);
@@ -755,16 +842,16 @@ read_array_type (ctf_context_t *ccp, ctf_id_t tid)
 /* Read TID of kind CTF_K_CONST with base type BTID.  */
 
 static struct type *
-read_const_type (ctf_context_t *ccp, ctf_id_t tid, ctf_id_t btid)
+read_const_type (struct ctf_context *ccp, ctf_id_t tid, ctf_id_t btid)
 {
   struct objfile *objfile = ccp->of;
   struct type *base_type, *cv_type;
 
-  base_type = get_tid_type (objfile, btid);
-  if (base_type == NULL)
+  base_type = fetch_tid_type (ccp, btid);
+  if (base_type == nullptr)
     {
       base_type = read_type_record (ccp, btid);
-      if (base_type == NULL)
+      if (base_type == nullptr)
        {
          complaint (_("read_const_type: NULL base type (%ld)"), btid);
          base_type = objfile_type (objfile)->builtin_error;
@@ -778,17 +865,17 @@ read_const_type (ctf_context_t *ccp, ctf_id_t tid, ctf_id_t btid)
 /* Read TID of kind CTF_K_VOLATILE with base type BTID.  */
 
 static struct type *
-read_volatile_type (ctf_context_t *ccp, ctf_id_t tid, ctf_id_t btid)
+read_volatile_type (struct ctf_context *ccp, ctf_id_t tid, ctf_id_t btid)
 {
   struct objfile *objfile = ccp->of;
-  ctf_file_t *fp = ccp->fp;
+  ctf_dict_t *fp = ccp->fp;
   struct type *base_type, *cv_type;
 
-  base_type = get_tid_type (objfile, btid);
-  if (base_type == NULL)
+  base_type = fetch_tid_type (ccp, btid);
+  if (base_type == nullptr)
     {
       base_type = read_type_record (ccp, btid);
-      if (base_type == NULL)
+      if (base_type == nullptr)
        {
          complaint (_("read_volatile_type: NULL base type (%ld)"), btid);
          base_type = objfile_type (objfile)->builtin_error;
@@ -805,16 +892,16 @@ read_volatile_type (ctf_context_t *ccp, ctf_id_t tid, ctf_id_t btid)
 /* Read TID of kind CTF_K_RESTRICT with base type BTID.  */
 
 static struct type *
-read_restrict_type (ctf_context_t *ccp, ctf_id_t tid, ctf_id_t btid)
+read_restrict_type (struct ctf_context *ccp, ctf_id_t tid, ctf_id_t btid)
 {
   struct objfile *objfile = ccp->of;
   struct type *base_type, *cv_type;
 
-  base_type = get_tid_type (objfile, btid);
-  if (base_type == NULL)
+  base_type = fetch_tid_type (ccp, btid);
+  if (base_type == nullptr)
     {
       base_type = read_type_record (ccp, btid);
-      if (base_type == NULL)
+      if (base_type == nullptr)
        {
          complaint (_("read_restrict_type: NULL base type (%ld)"), btid);
          base_type = objfile_type (objfile)->builtin_error;
@@ -828,7 +915,7 @@ read_restrict_type (ctf_context_t *ccp, ctf_id_t tid, ctf_id_t btid)
 /* Read TID of kind CTF_K_TYPEDEF with its NAME and base type BTID.  */
 
 static struct type *
-read_typedef_type (ctf_context_t *ccp, ctf_id_t tid,
+read_typedef_type (struct ctf_context *ccp, ctf_id_t tid,
                   ctf_id_t btid, const char *name)
 {
   struct objfile *objfile = ccp->of;
@@ -837,12 +924,13 @@ read_typedef_type (ctf_context_t *ccp, ctf_id_t tid,
   char *aname = obstack_strdup (&objfile->objfile_obstack, name);
   this_type = init_type (objfile, TYPE_CODE_TYPEDEF, 0, aname);
   set_tid_type (objfile, tid, this_type);
-  target_type = get_tid_type (objfile, btid);
+  target_type = fetch_tid_type (ccp, btid);
   if (target_type != this_type)
     TYPE_TARGET_TYPE (this_type) = target_type;
   else
-    TYPE_TARGET_TYPE (this_type) = NULL;
-  TYPE_TARGET_STUB (this_type) = TYPE_TARGET_TYPE (this_type) ? 1 : 0;
+    TYPE_TARGET_TYPE (this_type) = nullptr;
+
+  this_type->set_target_is_stub (TYPE_TARGET_TYPE (this_type) != nullptr);
 
   return set_tid_type (objfile, tid, this_type);
 }
@@ -850,16 +938,16 @@ read_typedef_type (ctf_context_t *ccp, ctf_id_t tid,
 /* Read TID of kind CTF_K_POINTER with base type BTID.  */
 
 static struct type *
-read_pointer_type (ctf_context_t *ccp, ctf_id_t tid, ctf_id_t btid)
+read_pointer_type (struct ctf_context *ccp, ctf_id_t tid, ctf_id_t btid)
 {
   struct objfile *of = ccp->of;
   struct type *target_type, *type;
 
-  target_type = get_tid_type (of, btid);
-  if (target_type == NULL)
+  target_type = fetch_tid_type (ccp, btid);
+  if (target_type == nullptr)
     {
       target_type = read_type_record (ccp, btid);
-      if (target_type == NULL)
+      if (target_type == nullptr)
        {
          complaint (_("read_pointer_type: NULL target type (%ld)"), btid);
          target_type = objfile_type (ccp->of)->builtin_error;
@@ -872,14 +960,42 @@ read_pointer_type (ctf_context_t *ccp, ctf_id_t tid, ctf_id_t btid)
   return set_tid_type (of, tid, type);
 }
 
+/* Read information from a TID of CTF_K_FORWARD.  */
+
+static struct type *
+read_forward_type (struct ctf_context *ccp, ctf_id_t tid)
+{
+  struct objfile *of = ccp->of;
+  ctf_dict_t *fp = ccp->fp;
+  struct type *type;
+  uint32_t kind;
+
+  type = alloc_type (of);
+
+  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
+  if (name != NULL && strlen (name.get()) != 0)
+    type->set_name (obstack_strdup (&of->objfile_obstack, name.get ()));
+
+  kind = ctf_type_kind_forwarded (fp, tid);
+  if (kind == CTF_K_UNION)
+    type->set_code (TYPE_CODE_UNION);
+  else
+    type->set_code (TYPE_CODE_STRUCT);
+
+  TYPE_LENGTH (type) = 0;
+  type->set_is_stub (true);
+
+  return set_tid_type (of, tid, type);
+}
+
 /* Read information associated with type TID.  */
 
 static struct type *
-read_type_record (ctf_context_t *ccp, ctf_id_t tid)
+read_type_record (struct ctf_context *ccp, ctf_id_t tid)
 {
-  ctf_file_t *fp = ccp->fp;
+  ctf_dict_t *fp = ccp->fp;
   uint32_t kind;
-  struct type *type = NULL;
+  struct type *type = nullptr;
   ctf_id_t btid;
 
   kind = ctf_type_kind (fp, tid);
@@ -925,6 +1041,9 @@ read_type_record (ctf_context_t *ccp, ctf_id_t tid)
       case CTF_K_ARRAY:
        type = read_array_type (ccp, tid);
        break;
+      case CTF_K_FORWARD:
+       type = read_forward_type (ccp, tid);
+       break;
       case CTF_K_UNKNOWN:
        break;
       default:
@@ -939,13 +1058,13 @@ read_type_record (ctf_context_t *ccp, ctf_id_t tid)
 static int
 ctf_add_type_cb (ctf_id_t tid, void *arg)
 {
-  ctf_context_t *ccp = (ctf_context_t *) arg;
+  struct ctf_context *ccp = (struct ctf_context *) arg;
   struct type *type;
   uint32_t kind;
 
   /* Check if tid's type has already been defined.  */
   type = get_tid_type (ccp->of, tid);
-  if (type != NULL)
+  if (type != nullptr)
     return 0;
 
   ctf_id_t btid = ctf_type_reference (ccp->fp, tid);
@@ -1004,8 +1123,8 @@ ctf_add_type_cb (ctf_id_t tid, void *arg)
 static int
 ctf_add_var_cb (const char *name, ctf_id_t id, void *arg)
 {
-  ctf_context_t *ccp = (ctf_context_t *) arg;
-  struct symbol *sym = NULL;
+  struct ctf_context *ccp = (struct ctf_context *) arg;
+  struct symbol *sym = nullptr;
   struct type *type;
   uint32_t kind;
 
@@ -1015,7 +1134,7 @@ ctf_add_var_cb (const char *name, ctf_id_t id, void *arg)
   switch (kind)
     {
       case CTF_K_FUNCTION:
-       if (name && !strcmp(name, "main"))
+       if (name != nullptr && strcmp (name, "main") == 0)
          set_objfile_main_name (ccp->of, name, language_c);
        break;
       case CTF_K_INTEGER:
@@ -1029,23 +1148,23 @@ ctf_add_var_cb (const char *name, ctf_id_t id, void *arg)
        if (type)
          {
            sym = new_symbol (ccp, type, id);
-           SYMBOL_SET_NAMES (sym, name, strlen (name), 0, ccp->of);
+           sym->compute_and_set_names (name, false, ccp->of->per_bfd);
          }
        break;
       case CTF_K_STRUCT:
       case CTF_K_UNION:
       case CTF_K_ENUM:
-       if (type == NULL)
+       if (type == nullptr)
        {
          complaint (_("ctf_add_var_cb: %s has NO type (%ld)"), name, id);
          type = objfile_type (ccp->of)->builtin_error;
        }
-       sym = allocate_symbol (ccp->of);
+       sym = new (&ccp->of->objfile_obstack) symbol;
        OBJSTAT (ccp->of, n_syms++);
        SYMBOL_TYPE (sym) = type;
        SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
        SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
-       SYMBOL_SET_NAMES (sym, name, strlen (name), 0, ccp->of);
+       sym->compute_and_set_names (name, false, ccp->of->per_bfd);
        add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
        break;
       default:
@@ -1053,7 +1172,7 @@ ctf_add_var_cb (const char *name, ctf_id_t id, void *arg)
        break;
     }
 
-  if (sym)
+  if (sym != nullptr)
     set_symbol_address (ccp->of, sym, name);
 
   return 0;
@@ -1062,18 +1181,18 @@ ctf_add_var_cb (const char *name, ctf_id_t id, void *arg)
 /* Add an ELF STT_OBJ symbol with index IDX to the symbol table.  */
 
 static struct symbol *
-add_stt_obj (ctf_context_t *ccp, unsigned long idx)
+add_stt_obj (struct ctf_context *ccp, unsigned long idx)
 {
   struct symbol *sym;
   struct type *type;
   ctf_id_t tid;
 
   if ((tid = ctf_lookup_by_symbol (ccp->fp, idx)) == CTF_ERR)
-    return NULL;
+    return nullptr;
 
-  type = get_tid_type (ccp->of, tid);
-  if (type == NULL)
-    return NULL;
+  type = fetch_tid_type (ccp, tid);
+  if (type == nullptr)
+    return nullptr;
 
   sym = new_symbol (ccp, type, tid);
 
@@ -1083,7 +1202,7 @@ add_stt_obj (ctf_context_t *ccp, unsigned long idx)
 /* Add an ELF STT_FUNC symbol with index IDX to the symbol table.  */
 
 static struct symbol *
-add_stt_func (ctf_context_t *ccp, unsigned long idx)
+add_stt_func (struct ctf_context *ccp, unsigned long idx)
 {
   struct type *ftype, *atyp, *rettyp;
   struct symbol *sym;
@@ -1094,41 +1213,41 @@ add_stt_func (ctf_context_t *ccp, unsigned long idx)
   struct type *void_type = objfile_type (ccp->of)->builtin_void;
 
   if (ctf_func_info (ccp->fp, idx, &finfo) == CTF_ERR)
-    return NULL;
+    return nullptr;
 
   argc = finfo.ctc_argc;
   if (ctf_func_args (ccp->fp, idx, argc, argv) == CTF_ERR)
-    return NULL;
+    return nullptr;
 
   gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, idx));
-  if (name == NULL)
-    return NULL;
+  if (name == nullptr)
+    return nullptr;
 
   tid = ctf_lookup_by_symbol (ccp->fp, idx);
-  ftype = get_tid_type (ccp->of, tid);
-  if (finfo.ctc_flags & CTF_FUNC_VARARG)
-    TYPE_VARARGS (ftype) = 1;
-  TYPE_NFIELDS (ftype) = argc;
+  ftype = fetch_tid_type (ccp, tid);
+  if ((finfo.ctc_flags & CTF_FUNC_VARARG) != 0)
+    ftype->set_has_varargs (true);
+  ftype->set_num_fields (argc);
 
   /* If argc is 0, it has a "void" type.  */
   if (argc != 0)
-    TYPE_FIELDS (ftype)
-      = (struct field *) TYPE_ZALLOC (ftype, argc * sizeof (struct field));
+    ftype->set_fields
+      ((struct field *) TYPE_ZALLOC (ftype, argc * sizeof (struct field)));
 
   /* TYPE_FIELD_TYPE must never be NULL.  Fill it with void_type, if failed
      to find the argument type.  */
   for (int iparam = 0; iparam < argc; iparam++)
     {
-      atyp = get_tid_type (ccp->of, argv[iparam]);
+      atyp = fetch_tid_type (ccp, argv[iparam]);
       if (atyp)
-       TYPE_FIELD_TYPE (ftype, iparam) = atyp;
+       ftype->field (iparam).set_type (atyp);
       else
-       TYPE_FIELD_TYPE (ftype, iparam) = void_type;
+       ftype->field (iparam).set_type (void_type);
     }
 
   sym = new_symbol (ccp, ftype, tid);
-  rettyp = get_tid_type (ccp->of, finfo.ctc_return);
-  if (rettyp != NULL)
+  rettyp = fetch_tid_type (ccp, finfo.ctc_return);
+  if (rettyp != nullptr)
     SYMBOL_TYPE (sym) = rettyp;
   else
     SYMBOL_TYPE (sym) = void_type;
@@ -1141,36 +1260,25 @@ add_stt_func (ctf_context_t *ccp, unsigned long idx)
 static CORE_ADDR
 get_objfile_text_range (struct objfile *of, int *tsize)
 {
-  CORE_ADDR text_base;
   bfd *abfd = of->obfd;
   const asection *codes;
 
   codes = bfd_get_section_by_name (abfd, ".text");
-  if (codes == NULL)
-    {
-      text_base = 0;
-      *tsize = 0;
-    }
-  else
-    {
-      text_base = bfd_section_vma (codes);
-      *tsize = codes->size;
-    }
-
-  return text_base;
+  *tsize = codes ? bfd_section_size (codes) : 0;
+  return of->text_section_offset ();
 }
 
 /* Start a symtab for OBJFILE in CTF format.  */
 
 static void
-ctf_start_symtab (struct partial_symtab *pst,
+ctf_start_symtab (ctf_psymtab *pst,
                  struct objfile *of, CORE_ADDR text_offset)
 {
-  ctf_context_t *ccp;
+  struct ctf_context *ccp;
 
-  ccp = (ctf_context_t *) pst->read_symtab_private;
+  ccp = pst->context;
   ccp->builder = new buildsym_compunit
-                      (of, of->original_name, NULL,
+                      (of, of->original_name, nullptr,
                       language_c, text_offset);
   ccp->builder->record_debugformat ("ctf");
 }
@@ -1180,30 +1288,51 @@ ctf_start_symtab (struct partial_symtab *pst,
    the .text section number.  */
 
 static struct compunit_symtab *
-ctf_end_symtab (struct partial_symtab *pst,
+ctf_end_symtab (ctf_psymtab *pst,
                CORE_ADDR end_addr, int section)
 {
-  ctf_context_t *ccp;
+  struct ctf_context *ccp;
 
-  ccp = (ctf_context_t *) pst->read_symtab_private;
+  ccp = pst->context;
   struct compunit_symtab *result
     = ccp->builder->end_symtab (end_addr, section);
   delete ccp->builder;
-  ccp->builder = NULL;
+  ccp->builder = nullptr;
   return result;
 }
 
-/* Read in full symbols for PST, and anything it depends on.  */
+/* Add all members of an enum with type TID to partial symbol table.  */
 
 static void
-psymtab_to_symtab (struct partial_symtab *pst)
+ctf_psymtab_add_enums (struct ctf_context *ccp, ctf_id_t tid)
+{
+  int val;
+  const char *ename;
+  ctf_next_t *i = nullptr;
+
+  while ((ename = ctf_enum_next (ccp->fp, tid, &i, &val)) != nullptr)
+    {
+      ccp->pst->add_psymbol (ename, true,
+                            VAR_DOMAIN, LOC_CONST, -1,
+                            psymbol_placement::GLOBAL,
+                            0, language_c, ccp->partial_symtabs, ccp->of);
+    }
+  if (ctf_errno (ccp->fp) != ECTF_NEXT_END)
+    complaint (_("ctf_enum_next ctf_psymtab_add_enums failed - %s"),
+              ctf_errmsg (ctf_errno (ccp->fp)));
+}
+
+/* Read in full symbols for PST, and anything it depends on.  */
+
+void
+ctf_psymtab::expand_psymtab (struct objfile *objfile)
 {
   struct symbol *sym;
-  ctf_context_t *ccp;
+  struct ctf_context *ccp;
 
-  gdb_assert (!pst->readin);
+  gdb_assert (!readin);
 
-  ccp = (ctf_context_t *) pst->read_symtab_private;
+  ccp = context;
 
   /* Iterate over entries in data types section.  */
   if (ctf_type_iter (ccp->fp, ctf_add_type_cb, ccp) == CTF_ERR)
@@ -1220,50 +1349,50 @@ psymtab_to_symtab (struct partial_symtab *pst)
   for (unsigned long i = 0; ; i++)
     {
       sym = add_stt_obj (ccp, i);
-      if (sym == NULL)
+      if (sym == nullptr)
        {
          if (ctf_errno (ccp->fp) == EINVAL
              || ctf_errno (ccp->fp) == ECTF_NOSYMTAB)
            break;
          sym = add_stt_func (ccp, i);
        }
-      if (sym == NULL)
+      if (sym == nullptr)
        continue;
 
-      set_symbol_address (ccp->of, sym, SYMBOL_LINKAGE_NAME (sym));
+      set_symbol_address (ccp->of, sym, sym->linkage_name ());
     }
 
-  pst->readin = 1;
+  readin = true;
 }
 
 /* Expand partial symbol table PST into a full symbol table.
    PST is not NULL.  */
 
-static void
-ctf_read_symtab (struct partial_symtab *pst, struct objfile *objfile)
+void
+ctf_psymtab::read_symtab (struct objfile *objfile)
 {
-  if (pst->readin)
-    warning (_("bug: psymtab for %s is already read in."), pst->filename);
+  if (readin)
+    warning (_("bug: psymtab for %s is already read in."), filename);
   else
     {
       if (info_verbose)
        {
-         printf_filtered (_("Reading in CTF data for %s..."), pst->filename);
+         printf_filtered (_("Reading in CTF data for %s..."), filename);
          gdb_flush (gdb_stdout);
        }
 
       /* Start a symtab.  */
-      CORE_ADDR text_offset;        /* Start of text segment.  */
+      CORE_ADDR offset;        /* Start of text segment.  */
       int tsize;
 
-      text_offset = get_objfile_text_range (objfile, &tsize);
-      ctf_start_symtab (pst, objfile, text_offset);
-      psymtab_to_symtab (pst);
+      offset = get_objfile_text_range (objfile, &tsize);
+      ctf_start_symtab (this, objfile, offset);
+      expand_psymtab (objfile);
 
-      pst->set_text_low (text_offset);
-      pst->set_text_high (text_offset + tsize);
-      pst->compunit_symtab = ctf_end_symtab (pst, text_offset + tsize,
-                                            SECT_OFF_TEXT (objfile));
+      set_text_low (offset);
+      set_text_high (offset + tsize);
+      compunit_symtab = ctf_end_symtab (this, offset + tsize,
+                                       SECT_OFF_TEXT (objfile));
 
       /* Finish up the debug error message.  */
       if (info_verbose)
@@ -1271,17 +1400,6 @@ ctf_read_symtab (struct partial_symtab *pst, struct objfile *objfile)
     }
 }
 
-/* Cleanup function for the ctf_file_key data.  */
-
-static void
-ctf_close_objfile (struct objfile *of, void *datum)
-{
-  ctf_file_t *fp = static_cast<ctf_file_t *> (datum);
-  ctf_archive_t *arc = ctf_get_arc (fp);
-  ctf_file_close (fp);
-  ctf_close (arc);
-}
-
 /* Allocate a new partial_symtab NAME.
 
    Each source file that has not been fully read in is represented by
@@ -1294,21 +1412,24 @@ ctf_close_objfile (struct objfile *of, void *datum)
    partial_symtab remains around.  They are allocated on an obstack,
    objfile_obstack.  */
 
-static struct partial_symtab *
+static ctf_psymtab *
 create_partial_symtab (const char *name,
-                      ctf_file_t *cfp,
+                      ctf_dict_t *cfp,
+                      psymtab_storage *partial_symtabs,
                       struct objfile *objfile)
 {
-  struct partial_symtab *pst;
-  ctf_context_t *ccx;
+  ctf_psymtab *pst;
+  struct ctf_context *ccx;
 
-  pst = start_psymtab_common (objfile, name, 0);
+  pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);
 
-  ccx = XOBNEW (&objfile->objfile_obstack, ctf_context_t);
+  ccx = XOBNEW (&objfile->objfile_obstack, struct ctf_context);
   ccx->fp = cfp;
   ccx->of = objfile;
-  pst->read_symtab_private = (void *) ccx;
-  pst->read_symtab = ctf_read_symtab;
+  ccx->partial_symtabs = partial_symtabs;
+  ccx->pst = pst;
+  ccx->builder = nullptr;
+  pst->context = ccx;
 
   return pst;
 }
@@ -1318,23 +1439,23 @@ create_partial_symtab (const char *name,
 static int
 ctf_psymtab_type_cb (ctf_id_t tid, void *arg)
 {
-  ctf_context_t *ccp;
+  struct ctf_context *ccp;
   uint32_t kind;
   short section = -1;
 
-  ccp = (ctf_context_t *) arg;
+  ccp = (struct ctf_context *) arg;
   gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, tid));
-  if (name == NULL || strlen (name.get ()) == 0)
-    return 0;
 
   domain_enum domain = UNDEF_DOMAIN;
   enum address_class aclass = LOC_UNDEF;
   kind = ctf_type_kind (ccp->fp, tid);
   switch (kind)
     {
+      case CTF_K_ENUM:
+       ctf_psymtab_add_enums (ccp, tid);
+       /* FALL THROUGH */
       case CTF_K_STRUCT:
       case CTF_K_UNION:
-      case CTF_K_ENUM:
        domain = STRUCT_DOMAIN;
        aclass = LOC_TYPEDEF;
        break;
@@ -1365,10 +1486,13 @@ ctf_psymtab_type_cb (ctf_id_t tid, void *arg)
        return 0;
     }
 
-    add_psymbol_to_list (name.get (), strlen (name.get ()), true,
+  if (name == nullptr || strlen (name.get ()) == 0)
+    return 0;
+
+  ccp->pst->add_psymbol (name.get (), true,
                         domain, aclass, section,
                         psymbol_placement::GLOBAL,
-                        0, language_c, ccp->of);
+                        0, language_c, ccp->partial_symtabs, ccp->of);
 
   return 0;
 }
@@ -1378,12 +1502,12 @@ ctf_psymtab_type_cb (ctf_id_t tid, void *arg)
 static int
 ctf_psymtab_var_cb (const char *name, ctf_id_t id, void *arg)
 {
-  ctf_context_t *ccp = (ctf_context_t *) arg;
+  struct ctf_context *ccp = (struct ctf_context *) arg;
 
-  add_psymbol_to_list (name, strlen (name), true,
-                      VAR_DOMAIN, LOC_STATIC, -1,
-                      psymbol_placement::GLOBAL,
-                      0, language_c, ccp->of);
+  ccp->pst->add_psymbol (name, true,
+                        VAR_DOMAIN, LOC_STATIC, -1,
+                        psymbol_placement::GLOBAL,
+                        0, language_c, ccp->partial_symtabs, ccp->of);
   return 0;
 }
 
@@ -1391,21 +1515,20 @@ ctf_psymtab_var_cb (const char *name, ctf_id_t id, void *arg)
    debugging information is available.  */
 
 static void
-scan_partial_symbols (ctf_file_t *cfp, struct objfile *of)
+scan_partial_symbols (ctf_dict_t *cfp, psymtab_storage *partial_symtabs,
+                     struct objfile *of)
 {
-  ctf_context_t ccx;
   bfd *abfd = of->obfd;
   const char *name = bfd_get_filename (abfd);
-  struct partial_symtab *pst = create_partial_symtab (name, cfp, of);
+  ctf_psymtab *pst = create_partial_symtab (name, cfp, partial_symtabs, of);
 
-  ccx.fp = cfp;
-  ccx.of = of;
+  struct ctf_context *ccx = pst->context;
 
-  if (ctf_type_iter (cfp, ctf_psymtab_type_cb, &ccx) == CTF_ERR)
+  if (ctf_type_iter (cfp, ctf_psymtab_type_cb, ccx) == CTF_ERR)
     complaint (_("ctf_type_iter scan_partial_symbols failed - %s"),
               ctf_errmsg (ctf_errno (cfp)));
 
-  if (ctf_variable_iter (cfp, ctf_psymtab_var_cb, &ccx) == CTF_ERR)
+  if (ctf_variable_iter (cfp, ctf_psymtab_var_cb, ccx) == CTF_ERR)
     complaint (_("ctf_variable_iter scan_partial_symbols failed - %s"),
               ctf_errmsg (ctf_errno (cfp)));
 
@@ -1445,13 +1568,13 @@ scan_partial_symbols (ctf_file_t *cfp, struct objfile *of)
       else
        aclass = LOC_TYPEDEF;
 
-      add_psymbol_to_list (tname.get (), strlen (tname.get ()), true,
-                          tdomain, aclass, -1,
-                          psymbol_placement::STATIC,
-                          0, language_c, of);
+      pst->add_psymbol (tname.get (), true,
+                       tdomain, aclass, -1,
+                       psymbol_placement::STATIC,
+                       0, language_c, partial_symtabs, of);
     }
 
-  end_psymtab_common (of, pst);
+  pst->end ();
 }
 
 /* Read CTF debugging information from a BFD section.  This is
@@ -1465,22 +1588,28 @@ elfctf_build_psymtabs (struct objfile *of)
   int err;
 
   ctf_archive_t *arc = ctf_bfdopen (abfd, &err);
-  if (arc == NULL)
+  if (arc == nullptr)
     error (_("ctf_bfdopen failed on %s - %s"),
           bfd_get_filename (abfd), ctf_errmsg (err));
 
-  ctf_file_t *fp = ctf_arc_open_by_name (arc, NULL, &err);
-  if (fp == NULL)
-    error (_("ctf_arc_open_by_name failed on %s - %s"),
+  ctf_dict_t *fp = ctf_dict_open (arc, NULL, &err);
+  if (fp == nullptr)
+    error (_("ctf_dict_open failed on %s - %s"),
           bfd_get_filename (abfd), ctf_errmsg (err));
-  set_objfile_data (of, ctf_file_key, fp);
+  ctf_dict_key.emplace (of, fp);
 
-  scan_partial_symbols (fp, of);
+  psymbol_functions *psf = new psymbol_functions ();
+  psymtab_storage *partial_symtabs = psf->get_partial_symtabs ().get ();
+  of->qf.emplace_front (psf);
+  scan_partial_symbols (fp, partial_symtabs, of);
 }
 
+#else
+
 void
-_initialize_ctfread (void)
+elfctf_build_psymtabs (struct objfile *of)
 {
-  ctf_file_key
-    = register_objfile_data_with_cleanup (NULL, ctf_close_objfile);
+  /* Nothing to do if CTF is disabled.  */
 }
+
+#endif /* ENABLE_LIBCTF */