/* Compact ANSI-C Type Format (CTF) support in GDB.
- Copyright (C) 2019-2020 Free Software Foundation, Inc.
+ Copyright (C) 2019-2022 Free Software Foundation, Inc.
This file is part of GDB.
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"
struct ctf_fp_info
{
- explicit ctf_fp_info (ctf_file_t *cfp) : fp (cfp) {}
+ explicit ctf_fp_info (ctf_dict_t *cfp) : fp (cfp) {}
~ctf_fp_info ();
- ctf_file_t *fp;
+ ctf_dict_t *fp;
};
-/* Cleanup function for the ctf_file_key data. */
+/* Cleanup function for the ctf_dict_key data. */
ctf_fp_info::~ctf_fp_info ()
{
- if (!fp)
+ if (fp == nullptr)
return;
ctf_archive_t *arc = ctf_get_arc (fp);
- ctf_file_close (fp);
+ ctf_dict_close (fp);
ctf_close (arc);
}
-static const objfile_key<ctf_fp_info> ctf_file_key;
+static const objfile_key<ctf_fp_info> ctf_dict_key;
/* A CTF context consists of a file pointer and an objfile pointer. */
struct ctf_context
{
- ctf_file_t *fp;
+ ctf_dict_t *fp;
struct objfile *of;
+ psymtab_storage *partial_symtabs;
+ partial_symtab *pst;
+ ctf_archive_t *arc;
struct buildsym_compunit *builder;
};
/* A partial symtab, specialized for this module. */
struct ctf_psymtab : public standard_psymtab
{
- ctf_psymtab (const char *filename, struct objfile *objfile, CORE_ADDR addr)
- : standard_psymtab (filename, objfile, addr)
+ 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;
+ struct ctf_context context;
};
/* The routines that read and process fields/members of a C struct, union,
std::vector<struct decl_field> nested_types_list;
};
+/* Data held for a translation unit. */
+
+struct ctf_per_tu_data
+{
+ ctf_dict_t *fp;
+ struct objfile *of;
+ ctf_archive_t *arc;
+ psymtab_storage *pss;
+ psymbol_functions *psf;
+};
/* Local function prototypes */
static void process_struct_members (struct ctf_context *cp, ctf_id_t tid,
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);
ids.tid = tid;
ids.type = typ;
slot = (struct ctf_tid_and_type **) htab_find_slot (htab, &ids, INSERT);
- if (*slot)
- complaint (_("An internal GDB problem: ctf_ id_t %ld type already set"),
- (tid));
- *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
+ if (*slot == nullptr)
+ *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
**slot = ids;
return typ;
}
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;
{
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 ());
}
}
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 ctf_nextfield &field = fip->fields[i];
- TYPE_FIELD (type, i) = field.field;
+ type->field (i) = field.field;
}
}
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);
uint32_t kind;
fp = &new_field.field;
- FIELD_NAME (*fp) = name;
+ fp->set_name (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;
if (kind == CTF_K_STRUCT || kind == CTF_K_UNION)
process_struct_members (ccp, tid, t);
- FIELD_TYPE (*fp) = t;
- SET_FIELD_BITPOS (*fp, offset / TARGET_CHAR_BIT);
+ fp->set_type (t);
+ fp->set_loc_bitpos (offset / TARGET_CHAR_BIT);
FIELD_BITSIZE (*fp) = get_bitsize (ccp->fp, tid, kind);
fip->fields.emplace_back (new_field);
struct ctf_context *ccp = fip->cur_context;
fp = &new_field.field;
- FIELD_NAME (*fp) = name;
- FIELD_TYPE (*fp) = NULL;
- SET_FIELD_ENUMVAL (*fp, enum_value);
+ fp->set_name (name);
+ fp->set_type (nullptr);
+ fp->set_loc_enumval (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++);
sym->set_language (language_c, &ccp->of->objfile_obstack);
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)
+ const char *name = ctf_type_name_raw (fp, tid);
+ if (name != nullptr)
{
- sym = allocate_symbol (objfile);
+ sym = new (&objfile->objfile_obstack) symbol;
OBJSTAT (objfile, n_syms++);
sym->set_language (language_c, &objfile->objfile_obstack);
- sym->compute_and_set_names (name.get (), true, objfile->per_bfd);
+ sym->compute_and_set_names (name, false, 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);
break;
case CTF_K_FUNCTION:
SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
+ set_symbol_address (objfile, sym, sym->linkage_name ());
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:
break;
}
- add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
+ add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
}
return sym;
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;
- char *name;
+ struct type *type = nullptr;
+ const char *name;
uint32_t kind;
if (ctf_type_encoding (fp, tid, &cet))
{
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)
+ name = ctf_type_name_raw (fp, tid);
+ if (name == nullptr || strlen (name) == 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)));
}
- else
- name = obstack_strdup (&of->objfile_obstack, copied_name.get ());
kind = ctf_type_kind (fp, 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;
{
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
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);
}
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 ());
+ const char *name = ctf_type_name_raw (fp, tid);
+ if (name != nullptr && strlen (name) != 0)
+ type->set_name (name);
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));
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 ());
-
- TYPE_CODE (type) = TYPE_CODE_FUNC;
- ctf_func_type_info (fp, tid, &cfi);
- rettype = get_tid_type (of, cfi.ctc_return);
+ type->set_code (TYPE_CODE_FUNC);
+ if (ctf_func_type_info (fp, tid, &cfi) < 0)
+ {
+ const char *fname = ctf_type_name_raw (fp, tid);
+ error (_("Error getting function type info: %s"),
+ fname == nullptr ? "noname" : fname);
+ }
+ 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 = fetch_tid_type (ccp, 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);
}
read_enum_type (struct ctf_context *ccp, ctf_id_t tid)
{
struct objfile *of = ccp->of;
- ctf_file_t *fp = ccp->fp;
- struct type *type, *target_type;
- ctf_funcinfo_t fi;
+ ctf_dict_t *fp = ccp->fp;
+ struct type *type;
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 ());
+ const char *name = ctf_type_name_raw (fp, tid);
+ if (name != nullptr && strlen (name) != 0)
+ type->set_name (name);
- 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);
- TYPE_TARGET_TYPE (type) = target_type;
+ /* Set the underlying type based on its ctf_type_size bits. */
+ TYPE_TARGET_TYPE (type) = objfile_int_type (of, TYPE_LENGTH (type), false);
set_type_align (type, ctf_type_align (fp, tid));
return set_tid_type (of, tid, type);
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));
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);
}
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;
{
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);
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;
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;
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;
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);
}
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;
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);
+
+ const char *name = ctf_type_name_raw (fp, tid);
+ if (name != nullptr && strlen (name) != 0)
+ type->set_name (name);
+
+ 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 (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);
break;
case CTF_K_TYPEDEF:
{
- gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
+ const char *name = ctf_type_name_raw (fp, tid);
btid = ctf_type_reference (fp, tid);
- type = read_typedef_type (ccp, tid, btid, name.get ());
+ type = read_typedef_type (ccp, tid, btid, name);
}
break;
case CTF_K_VOLATILE:
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:
/* 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);
ctf_add_var_cb (const char *name, ctf_id_t id, void *arg)
{
struct ctf_context *ccp = (struct ctf_context *) arg;
- struct symbol *sym = NULL;
+ struct symbol *sym = nullptr;
struct type *type;
uint32_t kind;
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:
case CTF_K_CONST:
case CTF_K_POINTER:
case CTF_K_ARRAY:
- if (type)
+ if (type != nullptr)
{
sym = new_symbol (ccp, type, id);
- sym->compute_and_set_names (name, false, ccp->of->per_bfd);
+ if (sym != nullptr)
+ 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)
- {
- complaint (_("ctf_add_var_cb: %s has NO type (%ld)"), name, id);
- type = objfile_type (ccp->of)->builtin_error;
- }
- sym = allocate_symbol (ccp->of);
+ if (type == nullptr)
+ {
+ complaint (_("ctf_add_var_cb: %s has NO type (%ld)"), name, id);
+ type = objfile_type (ccp->of)->builtin_error;
+ }
+ 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;
sym->compute_and_set_names (name, false, ccp->of->per_bfd);
- add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
+ add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
break;
default:
complaint (_("ctf_add_var_cb: kind unsupported (%d)"), kind);
break;
}
- if (sym)
+ if (sym != nullptr)
set_symbol_address (ccp->of, sym, name);
return 0;
}
-/* Add an ELF STT_OBJ symbol with index IDX to the symbol table. */
+/* Add entries in either data objects or function info section, controlled
+ by FUNCTIONS. */
-static struct symbol *
-add_stt_obj (struct ctf_context *ccp, unsigned long idx)
+static void
+add_stt_entries (struct ctf_context *ccp, int functions)
{
- struct symbol *sym;
- struct type *type;
+ ctf_next_t *i = nullptr;
+ const char *tname;
ctf_id_t tid;
+ struct symbol *sym = nullptr;
+ struct type *type;
- if ((tid = ctf_lookup_by_symbol (ccp->fp, idx)) == CTF_ERR)
- return NULL;
-
- type = get_tid_type (ccp->of, tid);
- if (type == NULL)
- return NULL;
-
- sym = new_symbol (ccp, type, tid);
-
- return sym;
+ while ((tid = ctf_symbol_next (ccp->fp, &i, &tname, functions)) != CTF_ERR)
+ {
+ type = get_tid_type (ccp->of, tid);
+ if (type == nullptr)
+ continue;
+ 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_STATIC;
+ sym->compute_and_set_names (tname, false, ccp->of->per_bfd);
+ add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
+ set_symbol_address (ccp->of, sym, tname);
+ }
}
-/* Add an ELF STT_FUNC symbol with index IDX to the symbol table. */
+/* Add entries in data objects section. */
-static struct symbol *
-add_stt_func (struct ctf_context *ccp, unsigned long idx)
+static void
+add_stt_obj (struct ctf_context *ccp)
{
- struct type *ftype, *atyp, *rettyp;
- struct symbol *sym;
- ctf_funcinfo_t finfo;
- ctf_id_t argv[32];
- uint32_t argc;
- ctf_id_t tid;
- struct type *void_type = objfile_type (ccp->of)->builtin_void;
-
- if (ctf_func_info (ccp->fp, idx, &finfo) == CTF_ERR)
- return NULL;
-
- argc = finfo.ctc_argc;
- if (ctf_func_args (ccp->fp, idx, argc, argv) == CTF_ERR)
- return NULL;
-
- gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, idx));
- if (name == NULL)
- return NULL;
-
- 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;
-
- /* If argc is 0, it has a "void" type. */
- if (argc != 0)
- TYPE_FIELDS (ftype)
- = (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]);
- if (atyp)
- TYPE_FIELD_TYPE (ftype, iparam) = atyp;
- else
- TYPE_FIELD_TYPE (ftype, iparam) = void_type;
- }
+ add_stt_entries (ccp, 0);
+}
- sym = new_symbol (ccp, ftype, tid);
- rettyp = get_tid_type (ccp->of, finfo.ctc_return);
- if (rettyp != NULL)
- SYMBOL_TYPE (sym) = rettyp;
- else
- SYMBOL_TYPE (sym) = void_type;
+/* Add entries in function info section. */
- return sym;
+static void
+add_stt_func (struct ctf_context *ccp)
+{
+ add_stt_entries (ccp, 1);
}
/* Get text segment base for OBJFILE, TSIZE contains the segment size. */
{
struct ctf_context *ccp;
- ccp = pst->context;
+ 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");
}
{
struct ctf_context *ccp;
- ccp = pst->context;
+ 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;
}
+/* Add all members of an enum with type TID to partial symbol table. */
+
+static void
+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)));
+}
+
+/* Add entries in either data objects or function info section, controlled
+ by FUNCTIONS, to psymtab. */
+
+static void
+ctf_psymtab_add_stt_entries (ctf_dict_t *cfp, ctf_psymtab *pst,
+ struct objfile *of, int functions)
+{
+ ctf_next_t *i = nullptr;
+ ctf_id_t tid;
+ const char *tname;
+
+ while ((tid = ctf_symbol_next (cfp, &i, &tname, functions)) != CTF_ERR)
+ {
+ uint32_t kind = ctf_type_kind (cfp, tid);
+ address_class aclass;
+ domain_enum tdomain;
+ switch (kind)
+ {
+ case CTF_K_STRUCT:
+ case CTF_K_UNION:
+ case CTF_K_ENUM:
+ tdomain = STRUCT_DOMAIN;
+ break;
+ default:
+ tdomain = VAR_DOMAIN;
+ break;
+ }
+
+ if (kind == CTF_K_FUNCTION)
+ aclass = LOC_STATIC;
+ else if (kind == CTF_K_CONST)
+ aclass = LOC_CONST;
+ else
+ aclass = LOC_TYPEDEF;
+
+ pst->add_psymbol (tname, true,
+ tdomain, aclass, -1,
+ psymbol_placement::GLOBAL,
+ 0, language_c, pst->context.partial_symtabs, of);
+ }
+}
+
+/* Add entries in data objects section to psymtab. */
+
+static void
+ctf_psymtab_add_stt_obj (ctf_dict_t *cfp, ctf_psymtab *pst,
+ struct objfile *of)
+{
+ ctf_psymtab_add_stt_entries (cfp, pst, of, 0);
+}
+
+/* Add entries in function info section to psymtab. */
+
+static void
+ctf_psymtab_add_stt_func (ctf_dict_t *cfp, ctf_psymtab *pst,
+ struct objfile *of)
+{
+ ctf_psymtab_add_stt_entries (cfp, pst, of, 1);
+}
+
/* Read in full symbols for PST, and anything it depends on. */
void
ctf_psymtab::expand_psymtab (struct objfile *objfile)
{
- struct symbol *sym;
struct ctf_context *ccp;
gdb_assert (!readin);
- ccp = context;
+ ccp = &context;
/* Iterate over entries in data types section. */
if (ctf_type_iter (ccp->fp, ctf_add_type_cb, ccp) == CTF_ERR)
ctf_errmsg (ctf_errno (ccp->fp)));
/* Add entries in data objects and function info sections. */
- for (unsigned long i = 0; ; i++)
- {
- sym = add_stt_obj (ccp, i);
- if (sym == NULL)
- {
- if (ctf_errno (ccp->fp) == EINVAL
- || ctf_errno (ccp->fp) == ECTF_NOSYMTAB)
- break;
- sym = add_stt_func (ccp, i);
- }
- if (sym == NULL)
- continue;
-
- set_symbol_address (ccp->of, sym, sym->linkage_name ());
- }
+ add_stt_obj (ccp);
+ add_stt_func (ccp);
readin = true;
}
static ctf_psymtab *
create_partial_symtab (const char *name,
- ctf_file_t *cfp,
+ ctf_archive_t *arc,
+ ctf_dict_t *cfp,
+ psymtab_storage *partial_symtabs,
struct objfile *objfile)
{
ctf_psymtab *pst;
- struct ctf_context *ccx;
- pst = new ctf_psymtab (name, objfile, 0);
+ pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);
- ccx = XOBNEW (&objfile->objfile_obstack, struct ctf_context);
- ccx->fp = cfp;
- ccx->of = objfile;
- pst->context = ccx;
+ pst->context.arc = arc;
+ pst->context.fp = cfp;
+ pst->context.of = objfile;
+ pst->context.partial_symtabs = partial_symtabs;
+ pst->context.pst = pst;
return pst;
}
short section = -1;
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;
return 0;
}
- add_psymbol_to_list (name.get (), true,
+ const char *name = ctf_type_name_raw (ccp->fp, tid);
+ if (name == nullptr || strlen (name) == 0)
+ return 0;
+
+ ccp->pst->add_psymbol (name, false,
domain, aclass, section,
- psymbol_placement::GLOBAL,
- 0, language_c, ccp->of);
+ psymbol_placement::STATIC,
+ 0, language_c, ccp->partial_symtabs, ccp->of);
return 0;
}
{
struct ctf_context *ccp = (struct ctf_context *) arg;
- add_psymbol_to_list (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;
}
+/* Start a subfile for CTF. FNAME is the name of the archive. */
+
+static void
+ctf_start_archive (struct ctf_context *ccx, struct objfile *of,
+ const char *fname)
+{
+ if (ccx->builder == nullptr)
+ {
+ ccx->builder = new buildsym_compunit (of,
+ of->original_name, nullptr, language_c, 0);
+ ccx->builder->record_debugformat ("ctf");
+ }
+ ccx->builder->start_subfile (fname);
+}
+
/* Setup partial_symtab's describing each source file for which
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 ctf_per_tu_data *tup, const char *fname)
{
- struct ctf_context ccx;
- bfd *abfd = of->obfd;
- const char *name = bfd_get_filename (abfd);
- ctf_psymtab *pst = create_partial_symtab (name, cfp, of);
+ struct objfile *of = tup->of;
+ bool isparent = false;
+
+ if (strcmp (fname, ".ctf") == 0)
+ {
+ fname = bfd_get_filename (of->obfd);
+ isparent = true;
+ }
+
+ ctf_psymtab *pst = create_partial_symtab (fname, tup->arc, cfp,
+ partial_symtabs, of);
- ccx.fp = cfp;
- ccx.of = of;
+ struct ctf_context *ccx = &pst->context;
+ if (isparent == false)
+ {
+ ctf_start_archive (ccx, of, fname);
+ ccx->pst = pst;
+ }
- 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)));
/* Scan CTF object and function sections which correspond to each
STT_FUNC or STT_OBJECT entry in the symbol table,
pick up what init_symtab has done. */
- for (unsigned long idx = 0; ; idx++)
- {
- ctf_id_t tid;
- if ((tid = ctf_lookup_by_symbol (cfp, idx)) == CTF_ERR)
- {
- if (ctf_errno (cfp) == EINVAL || ctf_errno (cfp) == ECTF_NOSYMTAB)
- break; // Done, reach end of the section.
- else
- continue;
- }
- gdb::unique_xmalloc_ptr<char> tname (ctf_type_aname_raw (cfp, tid));
- uint32_t kind = ctf_type_kind (cfp, tid);
- address_class aclass;
- domain_enum tdomain;
- switch (kind)
- {
- case CTF_K_STRUCT:
- case CTF_K_UNION:
- case CTF_K_ENUM:
- tdomain = STRUCT_DOMAIN;
- break;
- default:
- tdomain = VAR_DOMAIN;
- break;
- }
+ ctf_psymtab_add_stt_obj (cfp, pst, of);
+ ctf_psymtab_add_stt_func (cfp, pst, of);
- if (kind == CTF_K_FUNCTION)
- aclass = LOC_STATIC;
- else if (kind == CTF_K_CONST)
- aclass = LOC_CONST;
- else
- aclass = LOC_TYPEDEF;
+ pst->end ();
+}
+
+/* Callback to build the psymtab for archive member NAME. */
+
+static int
+build_ctf_archive_member (ctf_dict_t *ctf, const char *name, void *arg)
+{
+ struct ctf_per_tu_data *tup = (struct ctf_per_tu_data *) arg;
+ ctf_dict_t *parent = tup->fp;
+
+ if (strcmp (name, ".ctf") != 0)
+ ctf_import (ctf, parent);
- add_psymbol_to_list (tname.get (), true,
- tdomain, aclass, -1,
- psymbol_placement::STATIC,
- 0, language_c, of);
+ if (info_verbose)
+ {
+ printf_filtered (_("Scanning archive member %s..."), name);
+ gdb_flush (gdb_stdout);
}
- end_psymtab_common (of, pst);
+ psymtab_storage *pss = tup->psf->get_partial_symtabs ().get ();
+ scan_partial_symbols (ctf, pss, tup, name);
+
+ return 0;
}
/* Read CTF debugging information from a BFD section. This is
void
elfctf_build_psymtabs (struct objfile *of)
{
+ struct ctf_per_tu_data pcu;
bfd *abfd = of->obfd;
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));
- ctf_file_key.emplace (of, fp);
+ ctf_dict_key.emplace (of, fp);
+
+ pcu.fp = fp;
+ pcu.of = of;
+ pcu.arc = arc;
- scan_partial_symbols (fp, of);
+ psymbol_functions *psf = new psymbol_functions ();
+ of->qf.emplace_front (psf);
+ pcu.psf = psf;
+
+ if (ctf_archive_iter (arc, build_ctf_archive_member, &pcu) < 0)
+ error (_("ctf_archive_iter failed in input file %s: - %s"),
+ bfd_get_filename (abfd), ctf_errmsg (err));
}
+
+#else
+
+void
+elfctf_build_psymtabs (struct objfile *of)
+{
+ /* Nothing to do if CTF is disabled. */
+}
+
+#endif /* ENABLE_LIBCTF */