_CTF_ITEM (ECTF_NONAME, "Type name must not be empty.") \
_CTF_ITEM (ECTF_BADFLAG, "Invalid CTF dict flag specified.") \
_CTF_ITEM (ECTF_CTFVERS_NO_SERIALIZE, "CTFv1 dicts are too old to serialize.") \
- _CTF_ITEM (ECTF_UNSTABLE, "Attempt to write unstable file format version: set I_KNOW_LIBCTF_IS_UNSTABLE in the environment.")
+ _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.")
#define ECTF_BASE 1000 /* Base value for libctf errnos. */
#undef _CTF_FIRST
};
-#define ECTF_NERR (ECTF_UNSTABLE - ECTF_BASE + 1) /* Count of CTF errors. */
+#define ECTF_NERR (ECTF_WRONGPARENT - ECTF_BASE + 1) /* Count of CTF errors. */
/* The CTF data model is inferred to be the caller's data model or the data
model of the given object, unless ctf_setmodel is explicitly called. */
contain the name of their originating compilation unit and the name of
their parent. Dicts opened from CTF archives have this relationship set
up already, but if opening via raw low-level calls, you need to figure
- out which dict is the parent and set it on the child via ctf_import(). */
+ out which dict is the parent and set it on the child via ctf_import().
+
+ Almost all operations other than ctf_import and ctf_close do not work on
+ child dicts that have not yet had ctf_import called on them; in particular,
+ name lookups and type lookup in general are broken, as is type addition. */
extern const char *ctf_cuname (ctf_dict_t *);
extern ctf_dict_t *ctf_parent_dict (ctf_dict_t *);
ctf_dtdef_t *dtd, *ntd;
ctf_dvdef_t *dvd, *nvd;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
if (id.snapshot_id < fp->ctf_stypes)
return (ctf_set_errno (fp, ECTF_RDONLY));
if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_typemax, 1) == (CTF_MAX_PTYPE - 1))
return (ctf_set_typed_errno (fp, ECTF_FULL));
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
/* Prohibit addition of a root-visible type that is already present
in the non-dynamic portion. */
ctf_id_t type = 0;
size_t initial_vlen = 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 structs. */
if (name != NULL)
type = ctf_lookup_by_rawname (fp, CTF_K_STRUCT, name);
ctf_id_t type = 0;
size_t initial_vlen = 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);
ctf_id_t type = 0;
size_t initial_vlen = sizeof (ctf_enum_t) * INITIAL_VLEN;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
/* Promote root-visible forwards to enums. */
if (name != NULL)
type = ctf_lookup_by_rawname (fp, CTF_K_ENUM, name);
if (name == NULL || name[0] == '\0')
return (ctf_set_typed_errno (fp, ECTF_NONAME));
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
/* If the type is already defined or exists as a forward tag, just return
the ctf_id_t of the existing definition. Since this changes nothing,
it's safe to do even on the read-only portion of the dict. */
ctf_dtdef_t *dtd;
ctf_id_t type = 0;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
/* If a type is already defined with this name, error (if not CTF_K_UNKNOWN)
or just return it. */
if (enid < fp->ctf_stypes)
return (ctf_set_errno (ofp, ECTF_RDONLY));
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
if (dtd == NULL)
return (ctf_set_errno (ofp, ECTF_BADID));
unsigned char *old_vlen;
ctf_lmember_t *memb;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, souid))
{
/* Adding a child type to a parent, even via the child, is prohibited.
int
ctf_add_variable (ctf_dict_t *fp, const char *name, ctf_id_t ref)
{
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
if (ctf_lookup_variable_here (fp, name) != CTF_ERR)
return (ctf_set_errno (fp, ECTF_DUPLICATE));
char *dupname;
ctf_dynhash_t *h = is_function ? fp->ctf_funchash : fp->ctf_objthash;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
if (ctf_lookup_by_id (&tmp, id) == NULL)
return -1; /* errno is set for us. */
{
ctf_id_t id;
+ if ((src_fp->ctf_flags & LCTF_NO_STR) || (dst_fp->ctf_flags & LCTF_NO_STR))
+ return (ctf_set_errno (dst_fp, ECTF_NOPARENT));
+
if (!src_fp->ctf_add_processing)
src_fp->ctf_add_processing = ctf_dynhash_create (ctf_hash_integer,
ctf_hash_eq_integer,
char *line;
ctf_dump_state_t *state = NULL;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ {
+ ctf_set_errno (fp, ECTF_NOPARENT);
+ return NULL;
+ }
+
if (*statep == NULL)
{
/* Data collection. Transforming a call-at-a-time iterator into a
#define LCTF_VBYTES(fp, kind, size, vlen) \
((fp)->ctf_dictops->ctfo_get_vbytes(fp, kind, size, vlen))
-#define LCTF_CHILD 0x0001 /* CTF dict is a child. */
+#define LCTF_CHILD 0x0001 /* CTF dict is a child. */
+#define LCTF_LINKING 0x0002 /* CTF link is underway: respect ctf_link_flags. */
#define LCTF_STRICT_NO_DUP_ENUMERATORS 0x0004 /* Duplicate enums prohibited. */
+#define LCTF_NO_STR 0x0008 /* No string lookup possible yet. */
#define LCTF_NO_SERIALIZE 0x0010 /* Serialization of this dict prohibited. */
extern ctf_dynhash_t *ctf_name_table (ctf_dict_t *, int);
ctf_id_t
ctf_lookup_by_name (ctf_dict_t *fp, const char *name)
{
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
+
return ctf_lookup_by_name_internal (fp, NULL, name);
}
{
ctf_id_t type;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
+
if ((type = ctf_lookup_variable_here (fp, name)) == CTF_ERR)
{
if (ctf_errno (fp) == ECTF_NOTYPEDAT && fp->ctf_parent != NULL)
ctf_id_t type;
int enum_int_value;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
+
if (ctf_dynset_lookup (fp->ctf_conflicting_enums, name))
return (ctf_set_typed_errno (fp, ECTF_DUPLICATE));
ctf_next_t *i = *it;
int found = 0;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
+
/* We use ctf_type_next() to iterate across all types, but then traverse each
enumerator found by hand: traversing enumerators is very easy, and it would
probably be more confusing to use two nested iterators than to do it this
ctf_next_t *i = *it;
int err;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
+
if (!i)
{
if ((i = ctf_next_create ()) == NULL)
if (symname == NULL && symidx >= fp->ctf_nsyms)
goto try_parent;
- /* Try an indexed lookup. */
+ /* Try an indexed lookup. We can only do indexed lookups if we have a string
+ table. */
if (fp->ctf_objtidx_names && is_function != 1)
{
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
+
if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 0)) == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
}
if (type == 0 && fp->ctf_funcidx_names && is_function != 0)
{
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
+
if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 1)) == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
}
uint32_t max_vlen;
ctf_next_t *i = *it;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
if (!i)
{
const ctf_type_t *tp;
const char *name;
ctf_next_t *i = *it;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ {
+ ctf_set_errno (fp, ECTF_NOPARENT);
+ return NULL;
+ }
+
if (!i)
{
const ctf_type_t *tp;
ctf_next_t *i = *it;
ctf_id_t id;
+ /* (No need for a LCTF_NO_STR check: checking for a missing parent covers more
+ cases, and we need to do that anyway.) */
+
if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent == NULL))
return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
if (fp == NULL && type == CTF_ERR)
return NULL; /* Simplify caller code by permitting CTF_ERR. */
+ if (fp->ctf_flags & LCTF_NO_STR)
+ {
+ ctf_set_errno (fp, ECTF_NOPARENT);
+ return NULL;
+ }
+
ctf_decl_init (&cd);
ctf_decl_push (&cd, fp, type);
{
const ctf_type_t *tp;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ {
+ ctf_set_errno (fp, ECTF_NOPARENT);
+ return NULL;
+ }
+
if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
return NULL; /* errno is set for us. */
uint32_t lkind, rkind;
int same_names = 0;
+ if (lfp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (lfp, ECTF_NOPARENT));
+
+ if (rfp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (rfp, ECTF_NOPARENT));
+
if (ctf_type_cmp (lfp, ltype, rfp, rtype) == 0)
return 1;
ssize_t size, increment, vbytes;
uint32_t kind, n, i = 0;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
return -1; /* errno is set for us. */
ssize_t increment;
uint32_t n;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ {
+ ctf_set_errno (fp, ECTF_NOPARENT);
+ return NULL;
+ }
+
if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
return NULL; /* errno is set for us. */
ssize_t increment;
uint32_t n;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
return -1; /* errno is set for us. */
int nonrepresentable = 0;
int rc;
+ if (fp->ctf_flags & LCTF_NO_STR)
+ return (ctf_set_errno (fp, ECTF_NOPARENT));
+
if ((type = ctf_type_resolve (fp, type)) == CTF_ERR) {
if (ctf_errno (fp) != ECTF_NONREPRESENTABLE)
return -1; /* errno is set for us. */