+2021-03-18 Nick Alcock <nick.alcock@oracle.com>
+
+ * ctf-impl.h (ctf_dtdef_t) <dtu_members>: Remove.
+ <dtd_u>: Likewise.
+ (ctf_dmdef_t): Remove.
+ (struct ctf_next) <u.ctn_dmd>: Remove.
+ * ctf-create.c (INITIAL_VLEN): New, more-or-less arbitrary initial
+ vlen size.
+ (ctf_add_enum): Use it.
+ (ctf_dtd_delete): Do not free the (removed) dmd; remove string
+ refs from the vlen on struct deletion.
+ (ctf_add_struct_sized): Populate the vlen: do it by hand if
+ promoting forwards. Always populate the full-size
+ lsizehi/lsizelo members.
+ (ctf_add_union_sized): Likewise.
+ (ctf_add_member_offset): Set up the vlen rather than the dmd.
+ Expand it as needed, repointing string refs via
+ ctf_str_move_pending. Add the member names as pending strings.
+ Always populate the full-size lsizehi/lsizelo members.
+ (membadd): Remove, folding back into...
+ (ctf_add_type_internal): ... here, adding via an ordinary
+ ctf_add_struct_sized and _next iteration rather than doing
+ everything by hand.
+ * ctf-serialize.c (ctf_copy_smembers): Remove this...
+ (ctf_copy_lmembers): ... and this...
+ (ctf_emit_type_sect): ... folding into here. Figure out if a
+ ctf_stype_t is needed here, not in ctf_add_*_sized.
+ (ctf_type_sect_size): Figure out the ctf_stype_t stuff the same
+ way here.
+ * ctf-types.c (ctf_member_next): Remove the dmd path and always
+ use the vlen. Force large-structure usage for dynamic types.
+ (ctf_type_align): Likewise.
+ (ctf_member_info): Likewise.
+ (ctf_type_rvisit): Likewise.
+ * testsuite/libctf-regression/type-add-unnamed-struct-ctf.c: Add a
+ self-referential type to this test.
+ * testsuite/libctf-regression/type-add-unnamed-struct.c: Adjusted
+ accordingly.
+ * testsuite/libctf-regression/type-add-unnamed-struct.lk: Likewise.
+
2021-03-18 Nick Alcock <nick.alcock@oracle.com>
* ctf-impl.h (ctf_dtdef_t) <dtd_vlen_alloc>: New.
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#endif
+/* The initial size of a dynamic type's vlen in members. Arbitrary: the bigger
+ this is, the less allocation needs to be done for small structure
+ initialization, and the more memory is wasted for small structures during CTF
+ construction. No effect on generated CTF or ctf_open()ed CTF. */
+#define INITIAL_VLEN 16
+
/* Make sure the ptrtab has enough space for at least one more type.
We start with 4KiB of ptrtab, enough for a thousand types, then grow it 25%
void
ctf_dtd_delete (ctf_dict_t *fp, ctf_dtdef_t *dtd)
{
- ctf_dmdef_t *dmd, *nmd;
int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
size_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
int name_kind = kind;
{
case CTF_K_STRUCT:
case CTF_K_UNION:
- for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
- dmd != NULL; dmd = nmd)
- {
- if (dmd->dmd_name != NULL)
- free (dmd->dmd_name);
- nmd = ctf_list_next (dmd);
- free (dmd);
- }
+ {
+ ctf_lmember_t *memb = (ctf_lmember_t *) dtd->dtd_vlen;
+ size_t i;
+
+ for (i = 0; i < vlen; i++)
+ ctf_str_remove_ref (fp, ctf_strraw (fp, memb[i].ctlm_name),
+ &memb[i].ctlm_name);
+ }
break;
case CTF_K_ENUM:
{
{
ctf_dtdef_t *dtd;
ctf_id_t type = 0;
+ size_t initial_vlen = sizeof (ctf_lmember_t) * INITIAL_VLEN;
/* Promote root-visible forwards to structs. */
if (name != NULL)
if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
dtd = ctf_dtd_lookup (fp, type);
else if ((type = ctf_add_generic (fp, flag, name, CTF_K_STRUCT,
- 0, &dtd)) == CTF_ERR)
+ initial_vlen, &dtd)) == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_STRUCT, flag, 0);
-
- if (size > CTF_MAX_SIZE)
+ /* Forwards won't have any vlen yet. */
+ if (dtd->dtd_vlen_alloc == 0)
{
- dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
- dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
- dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
+ if ((dtd->dtd_vlen = calloc (1, initial_vlen)) == NULL)
+ return (ctf_set_errno (fp, ENOMEM));
+ dtd->dtd_vlen_alloc = initial_vlen;
}
- else
- dtd->dtd_data.ctt_size = (uint32_t) size;
+
+ dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_STRUCT, flag, 0);
+ dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
+ dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
+ dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
return type;
}
{
ctf_dtdef_t *dtd;
ctf_id_t type = 0;
+ size_t initial_vlen = sizeof (ctf_lmember_t) * INITIAL_VLEN;
/* Promote root-visible forwards to unions. */
if (name != NULL)
if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
dtd = ctf_dtd_lookup (fp, type);
else if ((type = ctf_add_generic (fp, flag, name, CTF_K_UNION,
- 0, &dtd)) == CTF_ERR)
+ initial_vlen, &dtd)) == CTF_ERR)
return CTF_ERR; /* errno is set for us */
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_UNION, flag, 0);
-
- if (size > CTF_MAX_SIZE)
+ /* Forwards won't have any vlen yet. */
+ if (dtd->dtd_vlen_alloc == 0)
{
- dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
- dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
- dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
+ if ((dtd->dtd_vlen = calloc (1, initial_vlen)) == NULL)
+ return (ctf_set_errno (fp, ENOMEM));
+ dtd->dtd_vlen_alloc = initial_vlen;
}
- else
- dtd->dtd_data.ctt_size = (uint32_t) size;
+
+ dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_UNION, flag, 0);
+ dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
+ dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
+ dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
return type;
}
{
ctf_dtdef_t *dtd;
ctf_id_t type = 0;
- size_t initial_vlen = sizeof (ctf_enum_t) * 16;
+ size_t initial_vlen = sizeof (ctf_enum_t) * INITIAL_VLEN;
/* Promote root-visible forwards to enums. */
if (name != NULL)
ctf_id_t type, unsigned long bit_offset)
{
ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, souid);
- ctf_dmdef_t *dmd;
ssize_t msize, malign, ssize;
uint32_t kind, vlen, root;
- char *s = NULL;
+ size_t i;
int is_incomplete = 0;
+ unsigned char *old_vlen;
+ ctf_lmember_t *memb;
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
if (vlen == CTF_MAX_VLEN)
return (ctf_set_errno (fp, ECTF_DTFULL));
+ old_vlen = dtd->dtd_vlen;
+ if (ctf_grow_vlen (fp, dtd, sizeof (ctf_lmember_t) * (vlen + 1)) < 0)
+ return -1; /* errno is set for us. */
+ memb = (ctf_lmember_t *) dtd->dtd_vlen;
+
+ if (dtd->dtd_vlen != old_vlen)
+ {
+ ptrdiff_t move = (signed char *) dtd->dtd_vlen - (signed char *) old_vlen;
+
+ /* Remove pending refs in the old vlen region and reapply them. */
+
+ for (i = 0; i < vlen; i++)
+ ctf_str_move_pending (fp, &memb[i].ctlm_name, move);
+ }
+
if (name != NULL)
{
- for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
- dmd != NULL; dmd = ctf_list_next (dmd))
- {
- if (dmd->dmd_name != NULL && strcmp (dmd->dmd_name, name) == 0)
- return (ctf_set_errno (fp, ECTF_DUPLICATE));
- }
+ for (i = 0; i < vlen; i++)
+ if (strcmp (ctf_strptr (fp, memb[i].ctlm_name), name) == 0)
+ return (ctf_set_errno (fp, ECTF_DUPLICATE));
}
if ((msize = ctf_type_size (fp, type)) < 0 ||
return -1; /* errno is set for us. */
}
- if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL)
- return (ctf_set_errno (fp, EAGAIN));
-
- if (name != NULL && (s = strdup (name)) == NULL)
- {
- free (dmd);
- return (ctf_set_errno (fp, EAGAIN));
- }
-
- dmd->dmd_name = s;
- dmd->dmd_type = type;
- dmd->dmd_value = -1;
+ memb[vlen].ctlm_name = ctf_str_add_pending (fp, name, &memb[vlen].ctlm_name);
+ memb[vlen].ctlm_type = type;
+ if (memb[vlen].ctlm_name == 0 && name != NULL && name[0] != '\0')
+ return -1; /* errno is set for us. */
if (kind == CTF_K_STRUCT && vlen != 0)
{
{
/* Natural alignment. */
- ctf_dmdef_t *lmd = ctf_list_prev (&dtd->dtd_u.dtu_members);
- ctf_id_t ltype = ctf_type_resolve (fp, lmd->dmd_type);
- size_t off = lmd->dmd_offset;
+ ctf_id_t ltype = ctf_type_resolve (fp, memb[vlen - 1].ctlm_type);
+ size_t off = CTF_LMEM_OFFSET(&memb[vlen - 1]);
ctf_encoding_t linfo;
ssize_t lsize;
cannot insert right after such a member without explicit offset
specification, because its alignment and size is not known. */
if (ltype == CTF_ERR)
- {
- free (dmd);
- return -1; /* errno is set for us. */
- }
+ return -1; /* errno is set for us. */
if (is_incomplete)
{
off += lsize * CHAR_BIT;
else if (lsize == -1 && ctf_errno (fp) == ECTF_INCOMPLETE)
{
+ const char *lname = ctf_strraw (fp, memb[vlen - 1].ctlm_name);
+
ctf_err_warn (fp, 1, ECTF_INCOMPLETE,
_("ctf_add_member_offset: cannot add member %s of "
"type %lx to struct %lx without specifying "
"explicit offset after member %s of type %lx, "
"which is an incomplete type\n"),
name ? name : _("(unnamed member)"), type, souid,
- lmd->dmd_name ? lmd->dmd_name
- : _("(unnamed member)"), ltype);
+ lname ? lname : _("(unnamed member)"), ltype);
return -1; /* errno is set for us. */
}
off = roundup (off, CHAR_BIT) / CHAR_BIT;
off = roundup (off, MAX (malign, 1));
- dmd->dmd_offset = off * CHAR_BIT;
+ memb[vlen].ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (off * CHAR_BIT);
+ memb[vlen].ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (off * CHAR_BIT);
ssize = off + msize;
}
else
{
/* Specified offset in bits. */
- dmd->dmd_offset = bit_offset;
+ memb[vlen].ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (bit_offset);
+ memb[vlen].ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (bit_offset);
ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
ssize = MAX (ssize, ((signed) bit_offset / CHAR_BIT) + msize);
}
}
else
{
- dmd->dmd_offset = 0;
+ memb[vlen].ctlm_offsethi = 0;
+ memb[vlen].ctlm_offsetlo = 0;
ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
ssize = MAX (ssize, msize);
}
- if ((size_t) ssize > CTF_MAX_SIZE)
- {
- dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
- dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (ssize);
- dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (ssize);
- }
- else
- dtd->dtd_data.ctt_size = (uint32_t) ssize;
-
+ dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
+ dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (ssize);
+ dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (ssize);
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
- ctf_list_append (&dtd->dtd_u.dtu_members, dmd);
fp->ctf_flags |= LCTF_DIRTY;
return 0;
return 0;
}
-static int
-membadd (const char *name, ctf_id_t type, unsigned long offset, void *arg)
-{
- ctf_bundle_t *ctb = arg;
- ctf_dmdef_t *dmd;
- char *s = NULL;
-
- if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL)
- return (ctf_set_errno (ctb->ctb_dict, EAGAIN));
-
- /* Unnamed members in non-dynamic dicts have a name of "", while dynamic dicts
- use NULL. Adapt. */
-
- if (name[0] == 0)
- name = NULL;
-
- if (name != NULL && (s = strdup (name)) == NULL)
- {
- free (dmd);
- return (ctf_set_errno (ctb->ctb_dict, EAGAIN));
- }
-
- /* For now, dmd_type is copied as the src_fp's type; it is reset to an
- equivalent dst_fp type by a final loop in ctf_add_type(), below. */
- dmd->dmd_name = s;
- dmd->dmd_type = type;
- dmd->dmd_offset = offset;
- dmd->dmd_value = -1;
-
- ctf_list_append (&ctb->ctb_dtd->dtd_u.dtu_members, dmd);
-
- ctb->ctb_dict->ctf_flags |= LCTF_DIRTY;
- return 0;
-}
-
/* Record the correspondence between a source and ctf_add_type()-added
destination type: both types are translated into parent type IDs if need be,
so they relate to the actual dictionary they are in. Outside controlled
case CTF_K_STRUCT:
case CTF_K_UNION:
{
- ctf_dmdef_t *dmd;
- int errs = 0;
- size_t size;
- ssize_t ssize;
- ctf_dtdef_t *dtd;
+ ctf_next_t *i = NULL;
+ ssize_t offset;
+ const char *membname;
+ ctf_id_t src_membtype;
/* Technically to match a struct or union we need to check both
ways (src members vs. dst, dst members vs. src) but we make
break;
}
- /* Unlike the other cases, copying structs and unions is done
- manually so as to avoid repeated lookups in ctf_add_member
- and to ensure the exact same member offsets as in src_type. */
-
- dst_type = ctf_add_generic (dst_fp, flag, name, kind, 0, &dtd);
+ dst_type = ctf_add_struct_sized (dst_fp, flag, name,
+ ctf_type_size (src_fp, src_type));
if (dst_type == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
- dst.ctb_type = dst_type;
- dst.ctb_dtd = dtd;
-
/* Pre-emptively add this struct to the type mapping so that
structures that refer to themselves work. */
ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
- if (ctf_member_iter (src_fp, src_type, membadd, &dst) != 0)
- errs++; /* Increment errs and fail at bottom of case. */
-
- if ((ssize = ctf_type_size (src_fp, src_type)) < 0)
- return CTF_ERR; /* errno is set for us. */
-
- size = (size_t) ssize;
- if (size > CTF_MAX_SIZE)
- {
- dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
- dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
- dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
- }
- else
- dtd->dtd_data.ctt_size = (uint32_t) size;
-
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, vlen);
-
- /* Make a final pass through the members changing each dmd_type (a
- src_fp type) to an equivalent type in dst_fp. We pass through all
- members, leaving any that fail set to CTF_ERR, unless they fail
- because they are marking a member of type not representable in this
- version of CTF, in which case we just want to silently omit them:
- no consumer can do anything with them anyway. */
- for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
- dmd != NULL; dmd = ctf_list_next (dmd))
+ while ((offset = ctf_member_next (src_fp, src_type, &i, &membname,
+ &src_membtype, 0)) >= 0)
{
ctf_dict_t *dst = dst_fp;
- ctf_id_t memb_type;
+ ctf_id_t dst_membtype = ctf_type_mapping (src_fp, src_membtype, &dst);
- memb_type = ctf_type_mapping (src_fp, dmd->dmd_type, &dst);
- if (memb_type == 0)
+ if (dst_membtype == 0)
{
- if ((dmd->dmd_type =
- ctf_add_type_internal (dst_fp, src_fp, dmd->dmd_type,
- proc_tracking_fp)) == CTF_ERR)
+ dst_membtype = ctf_add_type_internal (dst_fp, src_fp,
+ src_membtype,
+ proc_tracking_fp);
+ if (dst_membtype == CTF_ERR)
{
if (ctf_errno (dst_fp) != ECTF_NONREPRESENTABLE)
- errs++;
+ {
+ ctf_next_destroy (i);
+ break;
+ }
}
}
- else
- dmd->dmd_type = memb_type;
- }
- if (errs)
+ if (ctf_add_member_offset (dst_fp, dst_type, membname,
+ dst_membtype, offset) < 0)
+ {
+ ctf_next_destroy (i);
+ break;
+ }
+ }
+ if (ctf_errno (src_fp) != ECTF_NEXT_END)
return CTF_ERR; /* errno is set for us. */
break;
}
int cd_enomem; /* Nonzero if OOM during printing. */
} ctf_decl_t;
-typedef struct ctf_dmdef
-{
- ctf_list_t dmd_list; /* List forward/back pointers. */
- char *dmd_name; /* Name of this member. */
- ctf_id_t dmd_type; /* Type of this member (for sou). */
- unsigned long dmd_offset; /* Offset of this member in bits (for sou). */
- int dmd_value; /* Value of this member (for enum). */
-} ctf_dmdef_t;
-
typedef struct ctf_dtdef
{
ctf_list_t dtd_list; /* List forward/back pointers. */
ctf_type_t dtd_data; /* Type node, including name. */
size_t dtd_vlen_alloc; /* Total vlen space allocated. */
unsigned char *dtd_vlen; /* Variable-length data for this type. */
- union
- {
- ctf_list_t dtu_members; /* struct, union, or enum */
- } dtd_u;
} ctf_dtdef_t;
typedef struct ctf_dvdef
{
const ctf_member_t *ctn_mp;
const ctf_lmember_t *ctn_lmp;
- const ctf_dmdef_t *ctn_dmd;
const ctf_enum_t *ctn_en;
const ctf_dvdef_t *ctn_dvd;
ctf_next_hkv_t *ctn_sorted_hkv;
/* Type section. */
-static unsigned char *
-ctf_copy_smembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
-{
- ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
- ctf_member_t ctm;
-
- for (; dmd != NULL; dmd = ctf_list_next (dmd))
- {
- ctf_member_t *copied;
-
- ctm.ctm_name = 0;
- ctm.ctm_type = (uint32_t) dmd->dmd_type;
- ctm.ctm_offset = (uint32_t) dmd->dmd_offset;
-
- memcpy (t, &ctm, sizeof (ctm));
- copied = (ctf_member_t *) t;
- if (dmd->dmd_name)
- ctf_str_add_ref (fp, dmd->dmd_name, &copied->ctm_name);
-
- t += sizeof (ctm);
- }
-
- return t;
-}
-
-static unsigned char *
-ctf_copy_lmembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
-{
- ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
- ctf_lmember_t ctlm;
-
- for (; dmd != NULL; dmd = ctf_list_next (dmd))
- {
- ctf_lmember_t *copied;
-
- ctlm.ctlm_name = 0;
- ctlm.ctlm_type = (uint32_t) dmd->dmd_type;
- ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (dmd->dmd_offset);
- ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (dmd->dmd_offset);
-
- memcpy (t, &ctlm, sizeof (ctlm));
- copied = (ctf_lmember_t *) t;
- if (dmd->dmd_name)
- ctf_str_add_ref (fp, dmd->dmd_name, &copied->ctlm_name);
-
- t += sizeof (ctlm);
- }
-
- return t;
-}
-
/* Iterate through the dynamic type definition list and compute the
size of the CTF type section. */
{
uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
+ size_t type_ctt_size = dtd->dtd_data.ctt_size;
+
+ /* Shrink ctf_type_t-using types from a ctf_type_t to a ctf_stype_t
+ if possible. */
+
+ if (kind == CTF_K_STRUCT || kind == CTF_K_UNION)
+ {
+ size_t lsize = CTF_TYPE_LSIZE (&dtd->dtd_data);
+
+ if (lsize <= CTF_MAX_SIZE)
+ type_ctt_size = lsize;
+ }
- if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
+ if (type_ctt_size != CTF_LSIZE_SENT)
type_size += sizeof (ctf_stype_t);
else
type_size += sizeof (ctf_type_t);
break;
case CTF_K_STRUCT:
case CTF_K_UNION:
- if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
+ if (type_ctt_size < CTF_LSTRUCT_THRESH)
type_size += sizeof (ctf_member_t) * vlen;
else
type_size += sizeof (ctf_lmember_t) * vlen;
{
uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
-
+ size_t type_ctt_size = dtd->dtd_data.ctt_size;
size_t len;
ctf_stype_t *copied;
const char *name;
size_t i;
- if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
+ /* Shrink ctf_type_t-using types from a ctf_type_t to a ctf_stype_t
+ if possible. */
+
+ if (kind == CTF_K_STRUCT || kind == CTF_K_UNION)
+ {
+ size_t lsize = CTF_TYPE_LSIZE (&dtd->dtd_data);
+
+ if (lsize <= CTF_MAX_SIZE)
+ type_ctt_size = lsize;
+ }
+
+ if (type_ctt_size != CTF_LSIZE_SENT)
len = sizeof (ctf_stype_t);
else
len = sizeof (ctf_type_t);
ctf_str_add_ref (fp, name, &copied->ctt_name);
ctf_str_add_ref (fp, name, &dtd->dtd_data.ctt_name);
}
+ copied->ctt_size = type_ctt_size;
t += len;
switch (kind)
t += sizeof (uint32_t) * (vlen + (vlen & 1));
break;
+ /* These need to be copied across element by element, depending on
+ their ctt_size. */
case CTF_K_STRUCT:
case CTF_K_UNION:
- if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
- t = ctf_copy_smembers (fp, dtd, t);
+ {
+ ctf_lmember_t *dtd_vlen = (ctf_lmember_t *) dtd->dtd_vlen;
+ ctf_lmember_t *t_lvlen = (ctf_lmember_t *) t;
+ ctf_member_t *t_vlen = (ctf_member_t *) t;
+
+ for (i = 0; i < vlen; i++)
+ {
+ const char *name = ctf_strraw (fp, dtd_vlen[i].ctlm_name);
+
+ ctf_str_add_ref (fp, name, &dtd_vlen[i].ctlm_name);
+
+ if (type_ctt_size < CTF_LSTRUCT_THRESH)
+ {
+ t_vlen[i].ctm_name = dtd_vlen[i].ctlm_name;
+ t_vlen[i].ctm_type = dtd_vlen[i].ctlm_type;
+ t_vlen[i].ctm_offset = CTF_LMEM_OFFSET (&dtd_vlen[i]);
+ ctf_str_add_ref (fp, name, &t_vlen[i].ctm_name);
+ }
+ else
+ {
+ t_lvlen[i] = dtd_vlen[i];
+ ctf_str_add_ref (fp, name, &t_lvlen[i].ctlm_name);
+ }
+ }
+ }
+
+ if (type_ctt_size < CTF_LSTRUCT_THRESH)
+ t += sizeof (ctf_member_t) * vlen;
else
- t = ctf_copy_lmembers (fp, dtd, t);
+ t += sizeof (ctf_lmember_t) * vlen;
break;
case CTF_K_ENUM:
dtd = ctf_dynamic_type (fp, type);
i->ctn_iter_fun = (void (*) (void)) ctf_member_next;
-
- /* We depend below on the RDWR state indicating whether the DTD-related
- fields or the DMD-related fields have been initialized. */
-
- assert ((dtd && (fp->ctf_flags & LCTF_RDWR))
- || (!dtd && (!(fp->ctf_flags & LCTF_RDWR))));
+ i->ctn_n = LCTF_INFO_VLEN (fp, tp->ctt_info);
if (dtd == NULL)
{
- i->ctn_n = LCTF_INFO_VLEN (fp, tp->ctt_info);
-
if (i->ctn_size < CTF_LSTRUCT_THRESH)
i->u.ctn_mp = (const ctf_member_t *) ((uintptr_t) tp + increment);
else
i->u.ctn_lmp = (const ctf_lmember_t *) ((uintptr_t) tp + increment);
}
else
- i->u.ctn_dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
+ i->u.ctn_lmp = (const ctf_lmember_t *) dtd->dtd_vlen;
*it = i;
}
retry:
if (!i->ctn_type)
{
- if (!(fp->ctf_flags & LCTF_RDWR))
- {
- if (i->ctn_n == 0)
- goto end_iter;
-
- if (i->ctn_size < CTF_LSTRUCT_THRESH)
- {
- const char *membname = ctf_strptr (fp, i->u.ctn_mp->ctm_name);
-
- if (name)
- *name = membname;
- if (membtype)
- *membtype = i->u.ctn_mp->ctm_type;
- offset = i->u.ctn_mp->ctm_offset;
-
- if (membname[0] == 0
- && (ctf_type_kind (fp, i->u.ctn_mp->ctm_type) == CTF_K_STRUCT
- || ctf_type_kind (fp, i->u.ctn_mp->ctm_type) == CTF_K_UNION))
- i->ctn_type = i->u.ctn_mp->ctm_type;
+ if (i->ctn_n == 0)
+ goto end_iter;
- i->u.ctn_mp++;
- }
- else
- {
- const char *membname = ctf_strptr (fp, i->u.ctn_lmp->ctlm_name);
+ /* Dynamic structures in read-write dicts always use lmembers. */
+ if (i->ctn_size < CTF_LSTRUCT_THRESH
+ && !(fp->ctf_flags & LCTF_RDWR))
+ {
+ const char *membname = ctf_strptr (fp, i->u.ctn_mp->ctm_name);
- if (name)
- *name = membname;
- if (membtype)
- *membtype = i->u.ctn_lmp->ctlm_type;
- offset = (unsigned long) CTF_LMEM_OFFSET (i->u.ctn_lmp);
+ if (name)
+ *name = membname;
+ if (membtype)
+ *membtype = i->u.ctn_mp->ctm_type;
+ offset = i->u.ctn_mp->ctm_offset;
- if (membname[0] == 0
- && (ctf_type_kind (fp, i->u.ctn_lmp->ctlm_type) == CTF_K_STRUCT
- || ctf_type_kind (fp, i->u.ctn_lmp->ctlm_type) == CTF_K_UNION))
- i->ctn_type = i->u.ctn_lmp->ctlm_type;
+ if (membname[0] == 0
+ && (ctf_type_kind (fp, i->u.ctn_mp->ctm_type) == CTF_K_STRUCT
+ || ctf_type_kind (fp, i->u.ctn_mp->ctm_type) == CTF_K_UNION))
+ i->ctn_type = i->u.ctn_mp->ctm_type;
- i->u.ctn_lmp++;
- }
- i->ctn_n--;
+ i->u.ctn_mp++;
}
else
{
- if (i->u.ctn_dmd == NULL)
- goto end_iter;
- /* The dmd contains a NULL for unnamed dynamic members. Don't inflict
- this on our callers. */
+ const char *membname = ctf_strptr (fp, i->u.ctn_lmp->ctlm_name);
+
if (name)
- {
- if (i->u.ctn_dmd->dmd_name)
- *name = i->u.ctn_dmd->dmd_name;
- else
- *name = "";
- }
+ *name = membname;
if (membtype)
- *membtype = i->u.ctn_dmd->dmd_type;
- offset = i->u.ctn_dmd->dmd_offset;
+ *membtype = i->u.ctn_lmp->ctlm_type;
+ offset = (unsigned long) CTF_LMEM_OFFSET (i->u.ctn_lmp);
- if (i->u.ctn_dmd->dmd_name == NULL
- && (ctf_type_kind (fp, i->u.ctn_dmd->dmd_type) == CTF_K_STRUCT
- || ctf_type_kind (fp, i->u.ctn_dmd->dmd_type) == CTF_K_UNION))
- i->ctn_type = i->u.ctn_dmd->dmd_type;
+ if (membname[0] == 0
+ && (ctf_type_kind (fp, i->u.ctn_lmp->ctlm_type) == CTF_K_STRUCT
+ || ctf_type_kind (fp, i->u.ctn_lmp->ctlm_type) == CTF_K_UNION))
+ i->ctn_type = i->u.ctn_lmp->ctlm_type;
- i->u.ctn_dmd = ctf_list_next (i->u.ctn_dmd);
+ i->u.ctn_lmp++;
}
+ i->ctn_n--;
/* The callers might want automatic recursive sub-struct traversal. */
if (!(flags & CTF_MN_RECURSE))
case CTF_K_UNION:
{
size_t align = 0;
+ int dynamic = 0;
ctf_dtdef_t *dtd;
- if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
- {
- uint32_t n = LCTF_INFO_VLEN (fp, tp->ctt_info);
- ssize_t size, increment;
- const void *vmp;
+ if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
+ dynamic = 1;
- (void) ctf_get_ctt_size (fp, tp, &size, &increment);
- vmp = (unsigned char *) tp + increment;
+ uint32_t n = LCTF_INFO_VLEN (fp, tp->ctt_info);
+ ssize_t size, increment;
+ const void *vmp;
- if (kind == CTF_K_STRUCT)
- n = MIN (n, 1); /* Only use first member for structs. */
+ (void) ctf_get_ctt_size (fp, tp, &size, &increment);
- if (size < CTF_LSTRUCT_THRESH)
- {
- const ctf_member_t *mp = vmp;
- for (; n != 0; n--, mp++)
- {
- ssize_t am = ctf_type_align (ofp, mp->ctm_type);
- align = MAX (align, (size_t) am);
- }
- }
- else
+ if (!dynamic)
+ vmp = (unsigned char *) tp + increment;
+ else
+ vmp = dtd->dtd_vlen;
+
+ if (kind == CTF_K_STRUCT)
+ n = MIN (n, 1); /* Only use first member for structs. */
+
+ if (size < CTF_LSTRUCT_THRESH && !dynamic)
+ {
+ const ctf_member_t *mp = vmp;
+ for (; n != 0; n--, mp++)
{
- const ctf_lmember_t *lmp = vmp;
- for (; n != 0; n--, lmp++)
- {
- ssize_t am = ctf_type_align (ofp, lmp->ctlm_type);
- align = MAX (align, (size_t) am);
- }
+ ssize_t am = ctf_type_align (ofp, mp->ctm_type);
+ align = MAX (align, (size_t) am);
}
}
else
{
- ctf_dmdef_t *dmd;
-
- for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
- dmd != NULL; dmd = ctf_list_next (dmd))
- {
- ssize_t am = ctf_type_align (ofp, dmd->dmd_type);
- align = MAX (align, (size_t) am);
- if (kind == CTF_K_STRUCT)
- break;
- }
+ const ctf_lmember_t *lmp = vmp;
+ for (; n != 0; n--, lmp++)
+ {
+ ssize_t am = ctf_type_align (ofp, lmp->ctlm_type);
+ align = MAX (align, (size_t) am);
+ }
}
-
return align;
}
ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
ctf_dtdef_t *dtd;
+ const void *vmp;
ssize_t size, increment;
uint32_t kind, n;
+ int dynamic = 0;
if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
return -1; /* errno is set for us. */
if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
return (ctf_set_errno (ofp, ECTF_NOTSOU));
- if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
- {
- if (size < CTF_LSTRUCT_THRESH)
- {
- const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
- increment);
+ if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
+ dynamic = 1;
- for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
- {
- const char *membname = ctf_strptr (fp, mp->ctm_name);
+ if (!dynamic)
+ vmp = (unsigned char *) tp + increment;
+ else
+ vmp = dtd->dtd_vlen;
- if (membname[0] == 0
- && (ctf_type_kind (fp, mp->ctm_type) == CTF_K_STRUCT
- || ctf_type_kind (fp, mp->ctm_type) == CTF_K_UNION)
- && (ctf_member_info (fp, mp->ctm_type, name, mip) == 0))
- return 0;
+ if (size < CTF_LSTRUCT_THRESH && !dynamic)
+ {
+ const ctf_member_t *mp = vmp;
- if (strcmp (membname, name) == 0)
- {
- mip->ctm_type = mp->ctm_type;
- mip->ctm_offset = mp->ctm_offset;
- return 0;
- }
- }
- }
- else
+ for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
{
- const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
- increment);
+ const char *membname = ctf_strptr (fp, mp->ctm_name);
- for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
- {
- const char *membname = ctf_strptr (fp, lmp->ctlm_name);
-
- if (membname[0] == 0
- && (ctf_type_kind (fp, lmp->ctlm_type) == CTF_K_STRUCT
- || ctf_type_kind (fp, lmp->ctlm_type) == CTF_K_UNION)
- && (ctf_member_info (fp, lmp->ctlm_type, name, mip) == 0))
- return 0;
+ if (membname[0] == 0
+ && (ctf_type_kind (fp, mp->ctm_type) == CTF_K_STRUCT
+ || ctf_type_kind (fp, mp->ctm_type) == CTF_K_UNION)
+ && (ctf_member_info (fp, mp->ctm_type, name, mip) == 0))
+ return 0;
- if (strcmp (membname, name) == 0)
- {
- mip->ctm_type = lmp->ctlm_type;
- mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (lmp);
- return 0;
- }
+ if (strcmp (membname, name) == 0)
+ {
+ mip->ctm_type = mp->ctm_type;
+ mip->ctm_offset = mp->ctm_offset;
+ return 0;
}
}
}
else
{
- ctf_dmdef_t *dmd;
+ const ctf_lmember_t *lmp = vmp;
- for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
- dmd != NULL; dmd = ctf_list_next (dmd))
+ for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
{
- if (dmd->dmd_name == NULL
- && (ctf_type_kind (fp, dmd->dmd_type) == CTF_K_STRUCT
- || ctf_type_kind (fp, dmd->dmd_type) == CTF_K_UNION)
- && (ctf_member_info (fp, dmd->dmd_type, name, mip) == 0))
+ const char *membname = ctf_strptr (fp, lmp->ctlm_name);
+
+ if (membname[0] == 0
+ && (ctf_type_kind (fp, lmp->ctlm_type) == CTF_K_STRUCT
+ || ctf_type_kind (fp, lmp->ctlm_type) == CTF_K_UNION)
+ && (ctf_member_info (fp, lmp->ctlm_type, name, mip) == 0))
return 0;
- if (dmd->dmd_name != NULL
- && strcmp (dmd->dmd_name, name) == 0)
+ if (strcmp (membname, name) == 0)
{
- mip->ctm_type = dmd->dmd_type;
- mip->ctm_offset = dmd->dmd_offset;
+ mip->ctm_type = lmp->ctlm_type;
+ mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (lmp);
return 0;
}
}
ctf_id_t otype = type;
const ctf_type_t *tp;
const ctf_dtdef_t *dtd;
+ const void *vmp;
ssize_t size, increment;
uint32_t kind, n;
+ int dynamic = 0;
int rc;
if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
(void) ctf_get_ctt_size (fp, tp, &size, &increment);
- if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
+ if ((dtd = ctf_dynamic_type (fp, type)) != NULL)
+ dynamic = 1;
+
+ if (!dynamic)
+ vmp = (unsigned char *) tp + increment;
+ else
+ vmp = dtd->dtd_vlen;
+
+ if (size < CTF_LSTRUCT_THRESH && !dynamic)
{
- if (size < CTF_LSTRUCT_THRESH)
- {
- const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
- increment);
+ const ctf_member_t *mp = vmp;
- for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
- {
- if ((rc = ctf_type_rvisit (fp, mp->ctm_type,
- func, arg, ctf_strptr (fp,
- mp->ctm_name),
- offset + mp->ctm_offset,
- depth + 1)) != 0)
- return rc;
- }
- }
- else
+ for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
{
- const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
- increment);
-
- for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
- {
- if ((rc = ctf_type_rvisit (fp, lmp->ctlm_type,
- func, arg, ctf_strptr (fp,
- lmp->ctlm_name),
- offset + (unsigned long) CTF_LMEM_OFFSET (lmp),
- depth + 1)) != 0)
- return rc;
- }
+ if ((rc = ctf_type_rvisit (fp, mp->ctm_type,
+ func, arg, ctf_strptr (fp,
+ mp->ctm_name),
+ offset + mp->ctm_offset,
+ depth + 1)) != 0)
+ return rc;
}
}
else
{
- ctf_dmdef_t *dmd;
+ const ctf_lmember_t *lmp = vmp;
- for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
- dmd != NULL; dmd = ctf_list_next (dmd))
+ for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
{
- if ((rc = ctf_type_rvisit (fp, dmd->dmd_type, func, arg,
- dmd->dmd_name, dmd->dmd_offset,
+ if ((rc = ctf_type_rvisit (fp, lmp->ctlm_type,
+ func, arg, ctf_strptr (fp,
+ lmp->ctlm_name),
+ offset + (unsigned long) CTF_LMEM_OFFSET (lmp),
depth + 1)) != 0)
return rc;
}
struct
{
int baz;
+ struct foo *foo;
};
};
};
ctf_id_t newtype;
const char *memb;
ctf_membinfo_t mi;
- const char *membs[] = { "bar", "baz", NULL };
+ const char *membs[] = { "bar", "baz", "foo", NULL };
const char **walk;
int err;
# source: type-add-unnamed-struct-ctf.c
Looked up bar, type [0-9a-f]*, offset [0-9a-f]*
Looked up baz, type [0-9a-f]*, offset [0-9a-f]*
+Looked up foo, type [0-9a-f]*, offset [0-9a-f]*