aboutsummaryrefslogtreecommitdiff
path: root/libctf/ctf-create.c
diff options
context:
space:
mode:
Diffstat (limited to 'libctf/ctf-create.c')
-rw-r--r--libctf/ctf-create.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 073006b..d674603 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -1048,7 +1048,6 @@ ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name,
ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, enid);
unsigned char *old_vlen;
ctf_enum_t *en;
- size_t i;
uint32_t kind, vlen, root;
@@ -1068,6 +1067,12 @@ ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name,
root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
+ /* Enumeration constant names are only added, and only checked for duplicates,
+ if the enum they are part of is a root-visible type. */
+
+ if (root == CTF_ADD_ROOT && ctf_dynhash_lookup (fp->ctf_names, name))
+ return (ctf_set_errno (ofp, ECTF_DUPLICATE));
+
if (kind != CTF_K_ENUM)
return (ctf_set_errno (ofp, ECTF_NOTENUM));
@@ -1075,24 +1080,46 @@ ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name,
return (ctf_set_errno (ofp, ECTF_DTFULL));
old_vlen = dtd->dtd_vlen;
+
if (ctf_grow_vlen (fp, dtd, sizeof (ctf_enum_t) * (vlen + 1)) < 0)
return -1; /* errno is set for us. */
+
en = (ctf_enum_t *) dtd->dtd_vlen;
/* Remove refs in the old vlen region and reapply them. */
ctf_str_move_refs (fp, old_vlen, sizeof (ctf_enum_t) * vlen, dtd->dtd_vlen);
- for (i = 0; i < vlen; i++)
- if (strcmp (ctf_strptr (fp, en[i].cte_name), name) == 0)
- return (ctf_set_errno (ofp, ECTF_DUPLICATE));
+ /* Check for constant duplication within any given enum: only needed for
+ non-root-visible types, since the duplicate detection above does the job
+ for root-visible types just fine. */
- en[i].cte_name = ctf_str_add_movable_ref (fp, name, &en[i].cte_name);
- en[i].cte_value = value;
+ if (root == CTF_ADD_NONROOT)
+ {
+ size_t i;
- if (en[i].cte_name == 0 && name != NULL && name[0] != '\0')
+ for (i = 0; i < vlen; i++)
+ if (strcmp (ctf_strptr (fp, en[i].cte_name), name) == 0)
+ return (ctf_set_errno (ofp, ECTF_DUPLICATE));
+ }
+
+ en[vlen].cte_name = ctf_str_add_movable_ref (fp, name, &en[vlen].cte_name);
+ en[vlen].cte_value = value;
+
+ if (en[vlen].cte_name == 0 && name != NULL && name[0] != '\0')
return (ctf_set_errno (ofp, ctf_errno (fp)));
+ /* Put the newly-added enumerator name into the name table if this type is
+ root-visible. */
+
+ if (root == CTF_ADD_ROOT)
+ {
+ if (ctf_dynhash_insert (fp->ctf_names,
+ (char *) ctf_strptr (fp, en[vlen].cte_name),
+ (void *) (uintptr_t) enid) < 0)
+ return ctf_set_errno (fp, ENOMEM);
+ }
+
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
return 0;