break;
case STT_FUNC:
- if (funcoff >= hp->cth_typeoff)
+ if (funcoff >= hp->cth_objtidxoff)
{
*xp = -1u;
break;
hp->cth_stroff = oldhp->cth_stroff;
hp->cth_typeoff = oldhp->cth_typeoff;
hp->cth_varoff = oldhp->cth_varoff;
+ hp->cth_funcidxoff = hp->cth_varoff; /* No index sections. */
+ hp->cth_objtidxoff = hp->cth_funcidxoff;
hp->cth_funcoff = oldhp->cth_funcoff;
hp->cth_objtoff = oldhp->cth_objtoff;
hp->cth_lbloff = oldhp->cth_lbloff;
The upgrade is not done in-place: the ctf_base is moved. ctf_strptr() must
not be called before reallocation is complete.
+ Sections not checked here due to nonexistence or nonpopulated state in older
+ formats: objtidx, funcidx.
+
Type kinds not checked here due to nonexistence in older formats:
CTF_K_SLICE. */
static int
number unchanged, so that LCTF_INFO_* still works on the
as-yet-untranslated type info. */
- if ((ctf_base = ctf_alloc (fp->ctf_size + increase)) == NULL)
+ if ((ctf_base = malloc (fp->ctf_size + increase)) == NULL)
return ECTF_ZALLOC;
/* Start at ctf_buf, not ctf_base, to squeeze out the original header: we
assert ((size_t) t2p - (size_t) fp->ctf_buf == cth->cth_stroff);
ctf_set_version (fp, cth, CTF_VERSION_1_UPGRADED_3);
- ctf_free (old_ctf_base);
+ free (old_ctf_base);
return 0;
}
unsigned long pop[CTF_K_MAX + 1] = { 0 };
const ctf_type_t *tp;
- ctf_hash_t *hp;
uint32_t id, dst;
uint32_t *xp;
int nlstructs = 0, nlunions = 0;
int err;
+ assert (!(fp->ctf_flags & LCTF_RDWR));
+
if (_libctf_unlikely_ (fp->ctf_version == CTF_VERSION_1))
{
int err;
/* Now that we've counted up the number of each type, we can allocate
the hash tables, type translation table, and pointer table. */
- if ((fp->ctf_structs = ctf_hash_create (pop[CTF_K_STRUCT], ctf_hash_string,
- ctf_hash_eq_string)) == NULL)
+ if ((fp->ctf_structs.ctn_readonly
+ = ctf_hash_create (pop[CTF_K_STRUCT], ctf_hash_string,
+ ctf_hash_eq_string)) == NULL)
return ENOMEM;
- if ((fp->ctf_unions = ctf_hash_create (pop[CTF_K_UNION], ctf_hash_string,
- ctf_hash_eq_string)) == NULL)
+ if ((fp->ctf_unions.ctn_readonly
+ = ctf_hash_create (pop[CTF_K_UNION], ctf_hash_string,
+ ctf_hash_eq_string)) == NULL)
return ENOMEM;
- if ((fp->ctf_enums = ctf_hash_create (pop[CTF_K_ENUM], ctf_hash_string,
- ctf_hash_eq_string)) == NULL)
+ if ((fp->ctf_enums.ctn_readonly
+ = ctf_hash_create (pop[CTF_K_ENUM], ctf_hash_string,
+ ctf_hash_eq_string)) == NULL)
return ENOMEM;
- if ((fp->ctf_names = ctf_hash_create (pop[CTF_K_INTEGER] +
- pop[CTF_K_FLOAT] +
- pop[CTF_K_FUNCTION] +
- pop[CTF_K_TYPEDEF] +
- pop[CTF_K_POINTER] +
- pop[CTF_K_VOLATILE] +
- pop[CTF_K_CONST] +
- pop[CTF_K_RESTRICT],
- ctf_hash_string,
- ctf_hash_eq_string)) == NULL)
+ if ((fp->ctf_names.ctn_readonly
+ = ctf_hash_create (pop[CTF_K_INTEGER] +
+ pop[CTF_K_FLOAT] +
+ pop[CTF_K_FUNCTION] +
+ pop[CTF_K_TYPEDEF] +
+ pop[CTF_K_POINTER] +
+ pop[CTF_K_VOLATILE] +
+ pop[CTF_K_CONST] +
+ pop[CTF_K_RESTRICT],
+ ctf_hash_string,
+ ctf_hash_eq_string)) == NULL)
return ENOMEM;
- fp->ctf_txlate = ctf_alloc (sizeof (uint32_t) * (fp->ctf_typemax + 1));
- fp->ctf_ptrtab = ctf_alloc (sizeof (uint32_t) * (fp->ctf_typemax + 1));
+ fp->ctf_txlate = malloc (sizeof (uint32_t) * (fp->ctf_typemax + 1));
+ fp->ctf_ptrtab_len = fp->ctf_typemax + 1;
+ fp->ctf_ptrtab = malloc (sizeof (uint32_t) * fp->ctf_ptrtab_len);
if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL)
return ENOMEM; /* Memory allocation failed. */
root-visible version so that we can be sure to find it when
checking for conflicting definitions in ctf_add_type(). */
- if (((ctf_hash_lookup_type (fp->ctf_names, fp, name)) == 0)
+ if (((ctf_hash_lookup_type (fp->ctf_names.ctn_readonly,
+ fp, name)) == 0)
|| (flag & CTF_ADD_ROOT))
{
- err = ctf_hash_define_type (fp->ctf_names, fp,
+ err = ctf_hash_define_type (fp->ctf_names.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name);
- if (err != 0 && err != ECTF_STRTAB)
+ if (err != 0)
return err;
}
break;
break;
case CTF_K_FUNCTION:
- err = ctf_hash_insert_type (fp->ctf_names, fp,
+ err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name);
- if (err != 0 && err != ECTF_STRTAB)
+ if (err != 0)
return err;
break;
case CTF_K_STRUCT:
- err = ctf_hash_define_type (fp->ctf_structs, fp,
+ err = ctf_hash_define_type (fp->ctf_structs.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name);
- if (err != 0 && err != ECTF_STRTAB)
+ if (err != 0)
return err;
if (size >= CTF_LSTRUCT_THRESH)
break;
case CTF_K_UNION:
- err = ctf_hash_define_type (fp->ctf_unions, fp,
+ err = ctf_hash_define_type (fp->ctf_unions.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name);
- if (err != 0 && err != ECTF_STRTAB)
+ if (err != 0)
return err;
if (size >= CTF_LSTRUCT_THRESH)
break;
case CTF_K_ENUM:
- err = ctf_hash_define_type (fp->ctf_enums, fp,
+ err = ctf_hash_define_type (fp->ctf_enums.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name);
- if (err != 0 && err != ECTF_STRTAB)
+ if (err != 0)
return err;
break;
case CTF_K_TYPEDEF:
- err = ctf_hash_insert_type (fp->ctf_names, fp,
+ err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name);
- if (err != 0 && err != ECTF_STRTAB)
+ if (err != 0)
return err;
break;
case CTF_K_FORWARD:
- /* Only insert forward tags into the given hash if the type or tag
- name is not already present. */
- switch (tp->ctt_type)
- {
- case CTF_K_STRUCT:
- hp = fp->ctf_structs;
- break;
- case CTF_K_UNION:
- hp = fp->ctf_unions;
- break;
- case CTF_K_ENUM:
- hp = fp->ctf_enums;
- break;
- default:
- hp = fp->ctf_structs;
- }
-
- if (ctf_hash_lookup_type (hp, fp, name) == 0)
- {
- err = ctf_hash_insert_type (hp, fp,
- LCTF_INDEX_TO_TYPE (fp, id, child),
- tp->ctt_name);
- if (err != 0 && err != ECTF_STRTAB)
- return err;
- }
- break;
+ {
+ ctf_names_t *np = ctf_name_table (fp, tp->ctt_type);
+ /* Only insert forward tags into the given hash if the type or tag
+ name is not already present. */
+ if (ctf_hash_lookup_type (np->ctn_readonly, fp, name) == 0)
+ {
+ err = ctf_hash_insert_type (np->ctn_readonly, fp,
+ LCTF_INDEX_TO_TYPE (fp, id, child),
+ tp->ctt_name);
+ if (err != 0)
+ return err;
+ }
+ break;
+ }
case CTF_K_POINTER:
/* If the type referenced by the pointer is in this CTF container,
case CTF_K_VOLATILE:
case CTF_K_CONST:
case CTF_K_RESTRICT:
- err = ctf_hash_insert_type (fp->ctf_names, fp,
+ err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name);
- if (err != 0 && err != ECTF_STRTAB)
+ if (err != 0)
return err;
break;
default:
}
ctf_dprintf ("%lu total types processed\n", fp->ctf_typemax);
- ctf_dprintf ("%u enum names hashed\n", ctf_hash_size (fp->ctf_enums));
+ ctf_dprintf ("%u enum names hashed\n",
+ ctf_hash_size (fp->ctf_enums.ctn_readonly));
ctf_dprintf ("%u struct names hashed (%d long)\n",
- ctf_hash_size (fp->ctf_structs), nlstructs);
+ ctf_hash_size (fp->ctf_structs.ctn_readonly), nlstructs);
ctf_dprintf ("%u union names hashed (%d long)\n",
- ctf_hash_size (fp->ctf_unions), nlunions);
- ctf_dprintf ("%u base type names hashed\n", ctf_hash_size (fp->ctf_names));
+ ctf_hash_size (fp->ctf_unions.ctn_readonly), nlunions);
+ ctf_dprintf ("%u base type names hashed\n",
+ ctf_hash_size (fp->ctf_names.ctn_readonly));
/* Make an additional pass through the pointer table to find pointers that
point to anonymous typedef nodes. If we find one, modify the pointer table
{
tp = LCTF_INDEX_TO_TYPEPTR (fp, id);
- if (LCTF_INFO_KIND (fp, tp->ctt_info) == CTF_K_TYPEDEF &&
- strcmp (ctf_strptr (fp, tp->ctt_name), "") == 0 &&
- LCTF_TYPE_ISCHILD (fp, tp->ctt_type) == child &&
- LCTF_TYPE_TO_INDEX (fp, tp->ctt_type) <= fp->ctf_typemax)
- fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, tp->ctt_type)] = dst;
+ if (LCTF_INFO_KIND (fp, tp->ctt_info) == CTF_K_TYPEDEF
+ && strcmp (ctf_strptr (fp, tp->ctt_name), "") == 0
+ && LCTF_TYPE_ISCHILD (fp, tp->ctt_type) == child
+ && LCTF_TYPE_TO_INDEX (fp, tp->ctt_type) <= fp->ctf_typemax)
+ fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, tp->ctt_type)] = dst;
}
}
swap_thing (cth->cth_cuname);
swap_thing (cth->cth_objtoff);
swap_thing (cth->cth_funcoff);
+ swap_thing (cth->cth_objtidxoff);
+ swap_thing (cth->cth_funcidxoff);
swap_thing (cth->cth_varoff);
swap_thing (cth->cth_typeoff);
swap_thing (cth->cth_stroff);
flip_lbls (void *start, size_t len)
{
ctf_lblent_t *lbl = start;
+ ssize_t i;
- for (ssize_t i = len / sizeof (struct ctf_lblent); i > 0; lbl++, i--)
+ for (i = len / sizeof (struct ctf_lblent); i > 0; lbl++, i--)
{
swap_thing (lbl->ctl_label);
swap_thing (lbl->ctl_type);
}
}
-/* Flip the endianness of the data-object or function sections, an array of
- uint32_t. (The function section has more internal structure, but that
- structure is an array of uint32_t, so can be treated as one big array for
- byte-swapping.) */
+/* Flip the endianness of the data-object or function sections or their indexes,
+ all arrays of uint32_t. (The function section has more internal structure,
+ but that structure is an array of uint32_t, so can be treated as one big
+ array for byte-swapping.) */
static void
flip_objts (void *start, size_t len)
{
uint32_t *obj = start;
+ ssize_t i;
- for (ssize_t i = len / sizeof (uint32_t); i > 0; obj++, i--)
+ for (i = len / sizeof (uint32_t); i > 0; obj++, i--)
swap_thing (*obj);
}
flip_vars (void *start, size_t len)
{
ctf_varent_t *var = start;
+ ssize_t i;
- for (ssize_t i = len / sizeof (struct ctf_varent); i > 0; var++, i--)
+ for (i = len / sizeof (struct ctf_varent); i > 0; var++, i--)
{
swap_thing (var->ctv_name);
swap_thing (var->ctv_type);
/* This type has a bunch of uint32_ts. */
uint32_t *item = (uint32_t *) t;
+ ssize_t i;
- for (ssize_t i = vlen; i > 0; item++, i--)
+ for (i = vlen; i > 0; item++, i--)
swap_thing (*item);
break;
}
if (_libctf_unlikely_ (size >= CTF_LSTRUCT_THRESH))
{
ctf_lmember_t *lm = (ctf_lmember_t *) t;
- for (ssize_t i = vlen; i > 0; i--, lm++)
+ ssize_t i;
+ for (i = vlen; i > 0; i--, lm++)
{
swap_thing (lm->ctlm_name);
swap_thing (lm->ctlm_offsethi);
else
{
ctf_member_t *m = (ctf_member_t *) t;
- for (ssize_t i = vlen; i > 0; i--, m++)
+ ssize_t i;
+ for (i = vlen; i > 0; i--, m++)
{
swap_thing (m->ctm_name);
swap_thing (m->ctm_offset);
/* This has an array of ctf_enum_t. */
ctf_enum_t *item = (ctf_enum_t *) t;
+ ssize_t i;
- for (ssize_t i = vlen; i > 0; item++, i--)
+ for (i = vlen; i > 0; item++, i--)
{
swap_thing (item->cte_name);
swap_thing (item->cte_value);
{
flip_lbls (buf + cth->cth_lbloff, cth->cth_objtoff - cth->cth_lbloff);
flip_objts (buf + cth->cth_objtoff, cth->cth_funcoff - cth->cth_objtoff);
- flip_objts (buf + cth->cth_funcoff, cth->cth_varoff - cth->cth_funcoff);
+ flip_objts (buf + cth->cth_funcoff, cth->cth_objtidxoff - cth->cth_funcoff);
+ flip_objts (buf + cth->cth_objtidxoff, cth->cth_funcidxoff - cth->cth_objtidxoff);
+ flip_objts (buf + cth->cth_funcidxoff, cth->cth_varoff - cth->cth_funcidxoff);
flip_vars (buf + cth->cth_varoff, cth->cth_typeoff - cth->cth_varoff);
return flip_types (buf + cth->cth_typeoff, cth->cth_stroff - cth->cth_typeoff);
}
+/* Set up the ctl hashes in a ctf_file_t. Called by both writable and
+ non-writable dictionary initialization. */
+void ctf_set_ctl_hashes (ctf_file_t *fp)
+{
+ /* Initialize the ctf_lookup_by_name top-level dictionary. We keep an
+ array of type name prefixes and the corresponding ctf_hash to use. */
+ fp->ctf_lookups[0].ctl_prefix = "struct";
+ fp->ctf_lookups[0].ctl_len = strlen (fp->ctf_lookups[0].ctl_prefix);
+ fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs;
+ fp->ctf_lookups[1].ctl_prefix = "union";
+ fp->ctf_lookups[1].ctl_len = strlen (fp->ctf_lookups[1].ctl_prefix);
+ fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions;
+ fp->ctf_lookups[2].ctl_prefix = "enum";
+ fp->ctf_lookups[2].ctl_len = strlen (fp->ctf_lookups[2].ctl_prefix);
+ fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums;
+ fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR;
+ fp->ctf_lookups[3].ctl_len = strlen (fp->ctf_lookups[3].ctl_prefix);
+ fp->ctf_lookups[3].ctl_hash = &fp->ctf_names;
+ fp->ctf_lookups[4].ctl_prefix = NULL;
+ fp->ctf_lookups[4].ctl_len = 0;
+ fp->ctf_lookups[4].ctl_hash = NULL;
+}
+
/* Open a CTF file, mocking up a suitable ctf_sect. */
+
ctf_file_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size,
const char *symsect, size_t symsect_size,
size_t symsect_entsize,
const char *strsect, size_t strsect_size,
int *errp)
+{
+ return ctf_simple_open_internal (ctfsect, ctfsect_size, symsect, symsect_size,
+ symsect_entsize, strsect, strsect_size, NULL,
+ 0, errp);
+}
+
+/* Open a CTF file, mocking up a suitable ctf_sect and overriding the external
+ strtab with a synthetic one. */
+
+ctf_file_t *ctf_simple_open_internal (const char *ctfsect, size_t ctfsect_size,
+ const char *symsect, size_t symsect_size,
+ size_t symsect_entsize,
+ const char *strsect, size_t strsect_size,
+ ctf_dynhash_t *syn_strtab, int writable,
+ int *errp)
{
ctf_sect_t skeleton;
strsectp = &str_sect;
}
- return ctf_bufopen (ctfsectp, symsectp, strsectp, errp);
+ return ctf_bufopen_internal (ctfsectp, symsectp, strsectp, syn_strtab,
+ writable, errp);
}
/* Decode the specified CTF buffer and optional symbol table, and create a new
ctf_file_t *
ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
const ctf_sect_t *strsect, int *errp)
+{
+ return ctf_bufopen_internal (ctfsect, symsect, strsect, NULL, 0, errp);
+}
+
+/* Like ctf_bufopen, but overriding the external strtab with a synthetic one. */
+
+ctf_file_t *
+ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
+ const ctf_sect_t *strsect, ctf_dynhash_t *syn_strtab,
+ int writable, int *errp)
{
const ctf_preamble_t *pp;
size_t hdrsz = sizeof (ctf_header_t);
libctf_init_debug();
- if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL)))
+ if ((ctfsect == NULL) || ((symsect != NULL) &&
+ ((strsect == NULL) && syn_strtab == NULL)))
return (ctf_set_open_errno (errp, EINVAL));
if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) &&
if (ctfsect->cts_size < hdrsz)
return (ctf_set_open_errno (errp, ECTF_NOCTFBUF));
- if ((fp = ctf_alloc (sizeof (ctf_file_t))) == NULL)
+ if ((fp = malloc (sizeof (ctf_file_t))) == NULL)
return (ctf_set_open_errno (errp, ENOMEM));
memset (fp, 0, sizeof (ctf_file_t));
- if ((fp->ctf_header = ctf_alloc (sizeof (struct ctf_header))) == NULL)
+ if (writable)
+ fp->ctf_flags |= LCTF_RDWR;
+
+ if ((fp->ctf_header = malloc (sizeof (struct ctf_header))) == NULL)
{
- ctf_free (fp);
+ free (fp);
return (ctf_set_open_errno (errp, ENOMEM));
}
hp = fp->ctf_header;
(unsigned long) fp->ctf_size);
if (hp->cth_lbloff > fp->ctf_size || hp->cth_objtoff > fp->ctf_size
- || hp->cth_funcoff > fp->ctf_size || hp->cth_typeoff > fp->ctf_size
+ || hp->cth_funcoff > fp->ctf_size || hp->cth_objtidxoff > fp->ctf_size
+ || hp->cth_funcidxoff > fp->ctf_size || hp->cth_typeoff > fp->ctf_size
|| hp->cth_stroff > fp->ctf_size)
return (ctf_set_open_errno (errp, ECTF_CORRUPT));
if (hp->cth_lbloff > hp->cth_objtoff
|| hp->cth_objtoff > hp->cth_funcoff
|| hp->cth_funcoff > hp->cth_typeoff
- || hp->cth_funcoff > hp->cth_varoff
+ || hp->cth_funcoff > hp->cth_objtidxoff
+ || hp->cth_objtidxoff > hp->cth_funcidxoff
+ || hp->cth_funcidxoff > hp->cth_varoff
|| hp->cth_varoff > hp->cth_typeoff || hp->cth_typeoff > hp->cth_stroff)
return (ctf_set_open_errno (errp, ECTF_CORRUPT));
if ((hp->cth_lbloff & 3) || (hp->cth_objtoff & 2)
- || (hp->cth_funcoff & 2) || (hp->cth_varoff & 3)
+ || (hp->cth_funcoff & 2) || (hp->cth_objtidxoff & 2)
+ || (hp->cth_funcidxoff & 2) || (hp->cth_varoff & 3)
|| (hp->cth_typeoff & 3))
return (ctf_set_open_errno (errp, ECTF_CORRUPT));
/* We are allocating this ourselves, so we can drop the ctf header
copy in favour of ctf->ctf_header. */
- if ((fp->ctf_base = ctf_alloc (fp->ctf_size)) == NULL)
+ if ((fp->ctf_base = malloc (fp->ctf_size)) == NULL)
{
err = ECTF_ZALLOC;
goto bad;
}
else if (foreign_endian)
{
- if ((fp->ctf_base = ctf_alloc (fp->ctf_size)) == NULL)
+ if ((fp->ctf_base = malloc (fp->ctf_size)) == NULL)
{
err = ECTF_ZALLOC;
goto bad;
}
if (fp->ctf_data.cts_name != NULL)
- fp->ctf_data.cts_name = ctf_strdup (fp->ctf_data.cts_name);
+ if ((fp->ctf_data.cts_name = strdup (fp->ctf_data.cts_name)) == NULL)
+ {
+ err = ENOMEM;
+ goto bad;
+ }
if (fp->ctf_symtab.cts_name != NULL)
- fp->ctf_symtab.cts_name = ctf_strdup (fp->ctf_symtab.cts_name);
+ if ((fp->ctf_symtab.cts_name = strdup (fp->ctf_symtab.cts_name)) == NULL)
+ {
+ err = ENOMEM;
+ goto bad;
+ }
if (fp->ctf_strtab.cts_name != NULL)
- fp->ctf_strtab.cts_name = ctf_strdup (fp->ctf_strtab.cts_name);
+ if ((fp->ctf_strtab.cts_name = strdup (fp->ctf_strtab.cts_name)) == NULL)
+ {
+ err = ENOMEM;
+ goto bad;
+ }
if (fp->ctf_data.cts_name == NULL)
fp->ctf_data.cts_name = _CTF_NULLSTR;
fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data;
fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size;
}
+ fp->ctf_syn_ext_strtab = syn_strtab;
if (foreign_endian &&
(err = flip_ctf (hp, fp->ctf_buf)) != 0)
{
/* We can be certain that flip_ctf() will have endian-flipped everything
- other than the types table when we return. In particular the header
- is fine, so set it, to allow freeing to use the usual code path. */
+ other than the types table when we return. In particular the header
+ is fine, so set it, to allow freeing to use the usual code path. */
ctf_set_base (fp, hp, fp->ctf_base);
goto bad;
ctf_set_base (fp, hp, fp->ctf_base);
+ /* No need to do anything else for dynamic containers: they do not support
+ symbol lookups, and the type table is maintained in the dthashes. */
+ if (fp->ctf_flags & LCTF_RDWR)
+ {
+ fp->ctf_refcnt = 1;
+ return fp;
+ }
+
if ((err = init_types (fp, hp)) != 0)
goto bad;
if (symsect != NULL)
{
fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize;
- fp->ctf_sxlate = ctf_alloc (fp->ctf_nsyms * sizeof (uint32_t));
+ fp->ctf_sxlate = malloc (fp->ctf_nsyms * sizeof (uint32_t));
if (fp->ctf_sxlate == NULL)
{
goto bad;
}
- /* Initialize the ctf_lookup_by_name top-level dictionary. We keep an
- array of type name prefixes and the corresponding ctf_hash to use.
- NOTE: This code must be kept in sync with the code in ctf_update(). */
- fp->ctf_lookups[0].ctl_prefix = "struct";
- fp->ctf_lookups[0].ctl_len = strlen (fp->ctf_lookups[0].ctl_prefix);
- fp->ctf_lookups[0].ctl_hash = fp->ctf_structs;
- fp->ctf_lookups[1].ctl_prefix = "union";
- fp->ctf_lookups[1].ctl_len = strlen (fp->ctf_lookups[1].ctl_prefix);
- fp->ctf_lookups[1].ctl_hash = fp->ctf_unions;
- fp->ctf_lookups[2].ctl_prefix = "enum";
- fp->ctf_lookups[2].ctl_len = strlen (fp->ctf_lookups[2].ctl_prefix);
- fp->ctf_lookups[2].ctl_hash = fp->ctf_enums;
- fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR;
- fp->ctf_lookups[3].ctl_len = strlen (fp->ctf_lookups[3].ctl_prefix);
- fp->ctf_lookups[3].ctl_hash = fp->ctf_names;
- fp->ctf_lookups[4].ctl_prefix = NULL;
- fp->ctf_lookups[4].ctl_len = 0;
- fp->ctf_lookups[4].ctl_hash = NULL;
+ ctf_set_ctl_hashes (fp);
if (symsect != NULL)
{
return;
}
- ctf_free (fp->ctf_dyncuname);
- ctf_free (fp->ctf_dynparname);
+ free (fp->ctf_dyncuname);
+ free (fp->ctf_dynparname);
ctf_file_close (fp->ctf_parent);
for (dtd = ctf_list_next (&fp->ctf_dtdefs); dtd != NULL; dtd = ntd)
ctf_dtd_delete (fp, dtd);
}
ctf_dynhash_destroy (fp->ctf_dthash);
- ctf_dynhash_destroy (fp->ctf_dtbyname);
+ if (fp->ctf_flags & LCTF_RDWR)
+ {
+ ctf_dynhash_destroy (fp->ctf_structs.ctn_writable);
+ ctf_dynhash_destroy (fp->ctf_unions.ctn_writable);
+ ctf_dynhash_destroy (fp->ctf_enums.ctn_writable);
+ ctf_dynhash_destroy (fp->ctf_names.ctn_writable);
+ }
+ else
+ {
+ ctf_hash_destroy (fp->ctf_structs.ctn_readonly);
+ ctf_hash_destroy (fp->ctf_unions.ctn_readonly);
+ ctf_hash_destroy (fp->ctf_enums.ctn_readonly);
+ ctf_hash_destroy (fp->ctf_names.ctn_readonly);
+ }
for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
{
}
ctf_dynhash_destroy (fp->ctf_dvhash);
ctf_str_free_atoms (fp);
- ctf_free (fp->ctf_tmp_typeslice);
+ free (fp->ctf_tmp_typeslice);
if (fp->ctf_data.cts_name != _CTF_NULLSTR)
- ctf_free ((char *) fp->ctf_data.cts_name);
+ free ((char *) fp->ctf_data.cts_name);
if (fp->ctf_symtab.cts_name != _CTF_NULLSTR)
- ctf_free ((char *) fp->ctf_symtab.cts_name);
+ free ((char *) fp->ctf_symtab.cts_name);
if (fp->ctf_strtab.cts_name != _CTF_NULLSTR)
- ctf_free ((char *) fp->ctf_strtab.cts_name);
-
+ free ((char *) fp->ctf_strtab.cts_name);
else if (fp->ctf_data_mmapped)
ctf_munmap (fp->ctf_data_mmapped, fp->ctf_data_mmapped_len);
- ctf_free (fp->ctf_dynbase);
+ free (fp->ctf_dynbase);
- ctf_free (fp->ctf_sxlate);
- ctf_free (fp->ctf_txlate);
- ctf_free (fp->ctf_ptrtab);
+ ctf_dynhash_destroy (fp->ctf_syn_ext_strtab);
+ ctf_dynhash_destroy (fp->ctf_link_inputs);
+ ctf_dynhash_destroy (fp->ctf_link_outputs);
+ ctf_dynhash_destroy (fp->ctf_link_type_mapping);
+ ctf_dynhash_destroy (fp->ctf_link_cu_mapping);
+ ctf_dynhash_destroy (fp->ctf_add_processing);
- ctf_hash_destroy (fp->ctf_structs);
- ctf_hash_destroy (fp->ctf_unions);
- ctf_hash_destroy (fp->ctf_enums);
- ctf_hash_destroy (fp->ctf_names);
+ free (fp->ctf_sxlate);
+ free (fp->ctf_txlate);
+ free (fp->ctf_ptrtab);
- ctf_free (fp->ctf_header);
- ctf_free (fp);
+ free (fp->ctf_header);
+ free (fp);
}
/* The converse of ctf_open(). ctf_open() disguises whatever it opens as an
structure, not a pointer to it, since that is likely to become a pointer to
freed data before the return value is used under the expected use case of
ctf_getsect()/ ctf_file_close()/free(). */
-extern ctf_sect_t
+ctf_sect_t
ctf_getdatasect (const ctf_file_t *fp)
{
return fp->ctf_data;
/* Set the parent name. It is an error to call this routine without calling
ctf_import() at some point. */
-void
+int
ctf_parent_name_set (ctf_file_t *fp, const char *name)
{
if (fp->ctf_dynparname != NULL)
- ctf_free (fp->ctf_dynparname);
+ free (fp->ctf_dynparname);
- fp->ctf_dynparname = ctf_strdup (name);
+ if ((fp->ctf_dynparname = strdup (name)) == NULL)
+ return (ctf_set_errno (fp, ENOMEM));
fp->ctf_parname = fp->ctf_dynparname;
+ return 0;
}
/* Return the name of the compilation unit this CTF file applies to. Usually
}
/* Set the compilation unit name. */
-void
+int
ctf_cuname_set (ctf_file_t *fp, const char *name)
{
if (fp->ctf_dyncuname != NULL)
- ctf_free (fp->ctf_dyncuname);
+ free (fp->ctf_dyncuname);
- fp->ctf_dyncuname = ctf_strdup (name);
+ if ((fp->ctf_dyncuname = strdup (name)) == NULL)
+ return (ctf_set_errno (fp, ENOMEM));
fp->ctf_cuname = fp->ctf_dyncuname;
+ return 0;
}
/* Import the types from the specified parent container by storing a pointer
return (ctf_set_errno (fp, ECTF_DMODEL));
if (fp->ctf_parent != NULL)
- ctf_file_close (fp->ctf_parent);
+ {
+ fp->ctf_parent->ctf_refcnt--;
+ ctf_file_close (fp->ctf_parent);
+ fp->ctf_parent = NULL;
+ }
if (pfp != NULL)
{
- fp->ctf_flags |= LCTF_CHILD;
- pfp->ctf_refcnt++;
+ int err;
if (fp->ctf_parname == NULL)
- ctf_parent_name_set (fp, "PARENT");
+ if ((err = ctf_parent_name_set (fp, "PARENT")) < 0)
+ return err;
+
+ fp->ctf_flags |= LCTF_CHILD;
+ pfp->ctf_refcnt++;
}
+
fp->ctf_parent = pfp;
return 0;
}