_CTF_ITEM (ECTF_UNSTABLE, "Attempt to write unstable file format version: set I_KNOW_LIBCTF_IS_UNSTABLE in the environment.") \
_CTF_ITEM (ECTF_HASPARENT, "Cannot ctf_import: dict already has a parent.") \
_CTF_ITEM (ECTF_WRONGPARENT, "Cannot ctf_import: incorrect parent provided.") \
- _CTF_ITEM (ECTF_NOTSERIALIZED, "CTF dict must be serialized first.")
+ _CTF_ITEM (ECTF_NOTSERIALIZED, "CTF dict must be serialized first.") \
+ _CTF_ITEM (ECTF_NOTBITSOU, "Type is not a bitfield-capable struct or union.") \
+ _CTF_ITEM (ECTF_DESCENDING, "Structure offsets may not descend.") \
#define ECTF_BASE 1000 /* Base value for libctf errnos. */
#define CTF_ADD_NONROOT 0 /* Type only visible in nested scope. */
#define CTF_ADD_ROOT 1 /* Type visible at top-level scope. */
+#define CTF_ADD_STRUCT_BITFIELDS 2 /* Struct/union field-level bitfields */
/* Flags for ctf_member_next. */
/* Struct and union addition. Straight addition uses possibly-confusing rules
to guess the final size of the struct/union given its members: to explicitly
state the size of the struct or union (to report compiler-generated padding,
- etc) use the _sized variants. */
+ etc) use the _sized variants. The FLAG parameter can take the value
+ CTF_ADD_STRUCT_BITFIELDS, indicating that bitfields can be directly added
+ to this struct via ctf_add_member_bitfield. */
-extern ctf_id_t ctf_add_struct (ctf_dict_t *, uint32_t, const char *);
-extern ctf_id_t ctf_add_union (ctf_dict_t *, uint32_t, const char *);
-extern ctf_id_t ctf_add_struct_sized (ctf_dict_t *, uint32_t, const char *,
+extern ctf_id_t ctf_add_struct (ctf_dict_t *, uint32_t flag, const char *);
+extern ctf_id_t ctf_add_union (ctf_dict_t *, uint32_t flag, const char *);
+extern ctf_id_t ctf_add_struct_sized (ctf_dict_t *, uint32_t flag, const char *,
size_t);
-extern ctf_id_t ctf_add_union_sized (ctf_dict_t *, uint32_t, const char *,
+extern ctf_id_t ctf_add_union_sized (ctf_dict_t *, uint32_t flag, const char *,
size_t);
/* Note that CTF cannot encode a given type. This usually returns an
if (ctc->ctc_flags & CTF_FUNC_VARARG)
vdat[vlen - 1] = 0; /* Add trailing zero to indicate varargs. */
- return type;
+ return dtd->dtd_type;
}
-ctf_id_t
-ctf_add_struct_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
- size_t size)
+static ctf_id_t
+ctf_add_sou_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
+ size_t size, int kind)
{
ctf_dtdef_t *dtd;
+ ctf_type_t *prefix;
ctf_id_t type = 0;
- size_t initial_vbytes = sizeof (ctf_lmember_t) * INITIAL_VLEN;
+ uint32_t idx;
+ size_t initial_vbytes = sizeof (ctf_member_t) * INITIAL_VLEN;
+ int root_flag = flag & (~CTF_ADD_STRUCT_BITFIELDS);
if (fp->ctf_flags & LCTF_NO_STR)
return (ctf_set_errno (fp, ECTF_NOPARENT));
- /* Promote root-visible forwards to structs. */
+ /* Promote root-visible forwards to structs/unions. */
if (name != NULL)
- type = ctf_lookup_by_rawname (fp, CTF_K_STRUCT, name);
+ type = ctf_lookup_by_rawname (fp, kind, name);
+
+ if (type > 0)
+ idx = ctf_type_to_index (fp, type);
/* Prohibit promotion if this type was ctf_open()ed. */
- if (type > 0 && type < fp->ctf_stypes)
+ if (type > 0 && idx < fp->ctf_stypes)
return (ctf_set_errno (fp, ECTF_RDONLY));
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,
- initial_vbytes, &dtd)) == CTF_ERR)
- return CTF_ERR; /* errno is set for us. */
-
- /* Forwards won't have any vlen yet. */
- if (dtd->dtd_vlen_alloc == 0)
{
- if ((dtd->dtd_vlen = calloc (1, initial_vbytes)) == NULL)
- return (ctf_set_typed_errno (fp, ENOMEM));
- dtd->dtd_vlen_alloc = initial_vbytes;
+ dtd = ctf_dtd_lookup (fp, type);
+
+ if ((prefix = ctf_add_prefix (fp, dtd, initial_vbytes)) == NULL)
+ return CTF_ERR; /* errno is set for us. */
}
+ else if ((dtd = ctf_add_generic (fp, root_flag, name, kind, 1, 0,
+ initial_vbytes, &prefix)) == NULL)
+ return CTF_ERR; /* errno is set for us. */
- 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);
+ prefix->ctt_info = CTF_TYPE_INFO (CTF_K_BIG, 0, 0);
+ dtd->dtd_data->ctt_info = CTF_TYPE_INFO (kind, !!(flag & CTF_ADD_STRUCT_BITFIELDS), 0);
+ prefix->ctt_size = CTF_SIZE_TO_LSIZE_HI (size);
+ dtd->dtd_data->ctt_size = CTF_SIZE_TO_LSIZE_LO (size);
- return type;
+ return dtd->dtd_type;
+}
+
+ctf_id_t
+ctf_add_struct_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
+ size_t size)
+{
+ return ctf_add_sou_sized (fp, flag, name, size, CTF_K_STRUCT);
}
ctf_id_t
ctf_add_union_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
size_t size)
{
- ctf_dtdef_t *dtd;
- ctf_id_t type = 0;
- size_t initial_vbytes = sizeof (ctf_lmember_t) * INITIAL_VLEN;
-
- if (fp->ctf_flags & LCTF_NO_STR)
- return (ctf_set_errno (fp, ECTF_NOPARENT));
-
- /* Promote root-visible forwards to unions. */
- if (name != NULL)
- type = ctf_lookup_by_rawname (fp, CTF_K_UNION, name);
-
- /* Prohibit promotion if this type was ctf_open()ed. */
- if (type > 0 && type < fp->ctf_stypes)
- return (ctf_set_errno (fp, ECTF_RDONLY));
-
- 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,
- initial_vbytes, &dtd)) == CTF_ERR)
- return CTF_ERR; /* errno is set for us. */
-
- /* Forwards won't have any vlen yet. */
- if (dtd->dtd_vlen_alloc == 0)
- {
- if ((dtd->dtd_vlen = calloc (1, initial_vbytes)) == NULL)
- return (ctf_set_typed_errno (fp, ENOMEM));
- dtd->dtd_vlen_alloc = initial_vbytes;
- }
-
- 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;
+ return ctf_add_sou_sized (fp, flag, name, size, CTF_K_UNION);
}
ctf_id_t