libctf: support getting strings from the ELF strtab
[deliverable/binutils-gdb.git] / libctf / ctf-create.c
index 5409ca4bb4d3eddb56b963e4861c64684d496f84..3e6a3197ff8149264c9f6c2c1bc303bfad4b526f 100644 (file)
 #include <string.h>
 #include <zlib.h>
 
+#ifndef roundup
+#define roundup(x, y)  ((((x) + ((y) - 1)) / (y)) * (y))
+#endif
+
 /* To create an empty CTF container, we just declare a zeroed header and call
    ctf_bufopen() on it.  If ctf_bufopen succeeds, we mark the new container r/w
-   and initialize the dynamic members.  We set dtvstrlen to 1 to reserve the
-   first byte of the string table for a \0 byte, and we start assigning type
-   IDs at 1 because type ID 0 is used as a sentinel and a not-found
-   indicator.  */
+   and initialize the dynamic members.  We start assigning type IDs at 1 because
+   type ID 0 is used as a sentinel and a not-found indicator.  */
 
 ctf_file_t *
 ctf_create (int *errp)
@@ -67,12 +69,9 @@ ctf_create (int *errp)
     }
 
   cts.cts_name = _CTF_SECTION;
-  cts.cts_type = SHT_PROGBITS;
-  cts.cts_flags = 0;
   cts.cts_data = &hdr;
   cts.cts_size = sizeof (hdr);
   cts.cts_entsize = 1;
-  cts.cts_offset = 0;
 
   if ((fp = ctf_bufopen (&cts, NULL, NULL, errp)) == NULL)
       goto err_dtbyname;
@@ -81,10 +80,9 @@ ctf_create (int *errp)
   fp->ctf_dtbyname = dtbyname;
   fp->ctf_dthash = dthash;
   fp->ctf_dvhash = dvhash;
-  fp->ctf_dtvstrlen = 1;
   fp->ctf_dtnextid = 1;
   fp->ctf_dtoldid = 0;
-  fp->ctf_snapshots = 0;
+  fp->ctf_snapshots = 1;
   fp->ctf_snapshot_lu = 0;
 
   return fp;
@@ -100,25 +98,24 @@ ctf_create (int *errp)
 }
 
 static unsigned char *
-ctf_copy_smembers (ctf_dtdef_t *dtd, uint32_t soff, unsigned char *t)
+ctf_copy_smembers (ctf_file_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))
     {
-      if (dmd->dmd_name)
-       {
-         ctm.ctm_name = soff;
-         soff += strlen (dmd->dmd_name) + 1;
-       }
-      else
-       ctm.ctm_name = 0;
+      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);
     }
 
@@ -126,26 +123,25 @@ ctf_copy_smembers (ctf_dtdef_t *dtd, uint32_t soff, unsigned char *t)
 }
 
 static unsigned char *
-ctf_copy_lmembers (ctf_dtdef_t *dtd, uint32_t soff, unsigned char *t)
+ctf_copy_lmembers (ctf_file_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))
     {
-      if (dmd->dmd_name)
-       {
-         ctlm.ctlm_name = soff;
-         soff += strlen (dmd->dmd_name) + 1;
-       }
-      else
-       ctlm.ctlm_name = 0;
+      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);
     }
 
@@ -153,81 +149,72 @@ ctf_copy_lmembers (ctf_dtdef_t *dtd, uint32_t soff, unsigned char *t)
 }
 
 static unsigned char *
-ctf_copy_emembers (ctf_dtdef_t *dtd, uint32_t soff, unsigned char *t)
+ctf_copy_emembers (ctf_file_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
 {
   ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
   ctf_enum_t cte;
 
   for (; dmd != NULL; dmd = ctf_list_next (dmd))
     {
-      cte.cte_name = soff;
+      ctf_enum_t *copied;
+
       cte.cte_value = dmd->dmd_value;
-      soff += strlen (dmd->dmd_name) + 1;
       memcpy (t, &cte, sizeof (cte));
+      copied = (ctf_enum_t *) t;
+      ctf_str_add_ref (fp, dmd->dmd_name, &copied->cte_name);
       t += sizeof (cte);
     }
 
   return t;
 }
 
-static unsigned char *
-ctf_copy_membnames (ctf_dtdef_t *dtd, unsigned char *s)
-{
-  ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
-  size_t len;
-
-  for (; dmd != NULL; dmd = ctf_list_next (dmd))
-    {
-      if (dmd->dmd_name == NULL)
-       continue;                       /* Skip anonymous members.  */
-      len = strlen (dmd->dmd_name) + 1;
-      memcpy (s, dmd->dmd_name, len);
-      s += len;
-    }
-
-  return s;
-}
-
 /* Sort a newly-constructed static variable array.  */
 
+typedef struct ctf_sort_var_arg_cb
+{
+  ctf_file_t *fp;
+  ctf_strs_t *strtab;
+} ctf_sort_var_arg_cb_t;
+
 static int
-ctf_sort_var (const void *one_, const void *two_, void *strtab_)
+ctf_sort_var (const void *one_, const void *two_, void *arg_)
 {
   const ctf_varent_t *one = one_;
   const ctf_varent_t *two = two_;
-  const char *strtab = strtab_;
-  const char *n1 = strtab + CTF_NAME_OFFSET (one->ctv_name);
-  const char *n2 = strtab + CTF_NAME_OFFSET (two->ctv_name);
+  ctf_sort_var_arg_cb_t *arg = arg_;
 
-  return (strcmp (n1, n2));
+  return (strcmp (ctf_strraw_explicit (arg->fp, one->ctv_name, arg->strtab),
+                 ctf_strraw_explicit (arg->fp, two->ctv_name, arg->strtab)));
 }
 
 /* If the specified CTF container is writable and has been modified, reload this
    container with the updated type definitions.  In order to make this code and
    the rest of libctf as simple as possible, we perform updates by taking the
    dynamic type definitions and creating an in-memory CTF file containing the
-   definitions, and then call ctf_simple_open() on it.  This not only leverages
-   ctf_simple_open(), but also avoids having to bifurcate the rest of the library
-   code with different lookup paths for static and dynamic type definitions.  We
-   are therefore optimizing greatly for lookup over update, which we assume will
-   be an uncommon operation.  We perform one extra trick here for the benefit of
-   callers and to keep our code simple: ctf_simple_open() will return a new
-   ctf_file_t, but we want to keep the fp constant for the caller, so after
-   ctf_simple_open() returns, we use memcpy to swap the interior of the old and
-   new ctf_file_t's, and then free the old.  */
+   definitions, and then call ctf_simple_open_internal() on it.  This not only
+   leverages ctf_simple_open(), but also avoids having to bifurcate the rest of
+   the library code with different lookup paths for static and dynamic type
+   definitions.  We are therefore optimizing greatly for lookup over update,
+   which we assume will be an uncommon operation.  We perform one extra trick
+   here for the benefit of callers and to keep our code simple:
+   ctf_simple_open_internal() will return a new ctf_file_t, but we want to keep
+   the fp constant for the caller, so after ctf_simple_open_internal() returns,
+   we use memcpy to swap the interior of the old and new ctf_file_t's, and then
+   free the old.  */
 int
 ctf_update (ctf_file_t *fp)
 {
   ctf_file_t ofp, *nfp;
-  ctf_header_t hdr;
+  ctf_header_t hdr, *hdrp;
   ctf_dtdef_t *dtd;
   ctf_dvdef_t *dvd;
   ctf_varent_t *dvarents;
+  ctf_strs_writable_t strtab;
 
-  unsigned char *s, *s0, *t;
+  unsigned char *t;
   unsigned long i;
   size_t buf_size, type_size, nvars;
-  void *buf;
+  unsigned char *buf, *newbuf;
   int err;
 
   if (!(fp->ctf_flags & LCTF_RDWR))
@@ -246,9 +233,6 @@ ctf_update (ctf_file_t *fp)
   hdr.cth_magic = CTF_MAGIC;
   hdr.cth_version = CTF_VERSION;
 
-  if (fp->ctf_flags & LCTF_CHILD)
-    hdr.cth_parname = 1;               /* parname added just below.  */
-
   /* Iterate through the dynamic type definition list and compute the
      size of the CTF type section we will need to generate.  */
 
@@ -297,80 +281,62 @@ ctf_update (ctf_file_t *fp)
   for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs);
        dvd != NULL; dvd = ctf_list_next (dvd), nvars++);
 
-  /* Fill in the string table and type offset and size, compute the size
-     of the entire CTF buffer we need, and then allocate a new buffer and
-     memcpy the finished header to the start of the buffer.  */
+  /* Compute the size of the CTF buffer we need, sans only the string table,
+     then allocate a new buffer and memcpy the finished header to the start of
+     the buffer.  (We will adjust this later with strtab length info.)  */
 
   hdr.cth_typeoff = hdr.cth_varoff + (nvars * sizeof (ctf_varent_t));
   hdr.cth_stroff = hdr.cth_typeoff + type_size;
-  hdr.cth_strlen = fp->ctf_dtvstrlen;
-  if (fp->ctf_parname != NULL)
-    hdr.cth_strlen += strlen (fp->ctf_parname) + 1;
+  hdr.cth_strlen = 0;
 
   buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;
 
-  if ((buf = ctf_data_alloc (buf_size)) == NULL)
+  if ((buf = malloc (buf_size)) == NULL)
     return (ctf_set_errno (fp, EAGAIN));
 
   memcpy (buf, &hdr, sizeof (ctf_header_t));
   t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_varoff;
-  s = s0 = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff;
 
-  s[0] = '\0';
-  s++;
+  hdrp = (ctf_header_t *) buf;
+  if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parname != NULL))
+    ctf_str_add_ref (fp, fp->ctf_parname, &hdrp->cth_parname);
+  if (fp->ctf_cuname != NULL)
+    ctf_str_add_ref (fp, fp->ctf_cuname, &hdrp->cth_cuname);
 
-  if (fp->ctf_parname != NULL)
-    {
-      memcpy (s, fp->ctf_parname, strlen (fp->ctf_parname) + 1);
-      s += strlen (fp->ctf_parname) + 1;
-    }
-
-  /* Work over the variable list, translating everything into
-     ctf_varent_t's and filling out the string table, then sort the buffer
-     of ctf_varent_t's.  */
+  /* Work over the variable list, translating everything into ctf_varent_t's and
+     prepping the string table.  */
 
   dvarents = (ctf_varent_t *) t;
   for (i = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL;
        dvd = ctf_list_next (dvd), i++)
     {
       ctf_varent_t *var = &dvarents[i];
-      size_t len = strlen (dvd->dvd_name) + 1;
 
-      var->ctv_name = (uint32_t) (s - s0);
+      ctf_str_add_ref (fp, dvd->dvd_name, &var->ctv_name);
       var->ctv_type = dvd->dvd_type;
-      memcpy (s, dvd->dvd_name, len);
-      s += len;
     }
   assert (i == nvars);
 
-  qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var, s0);
   t += sizeof (ctf_varent_t) * nvars;
 
   assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff);
 
-  /* We now take a final lap through the dynamic type definition list and
-     copy the appropriate type records and strings to the output buffer.  */
+  /* We now take a final lap through the dynamic type definition list and copy
+     the appropriate type records to the output buffer, noting down the
+     strings as we go.  */
 
   for (dtd = ctf_list_next (&fp->ctf_dtdefs);
        dtd != NULL; dtd = ctf_list_next (dtd))
     {
-
       uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
       uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
 
       ctf_array_t cta;
       uint32_t encoding;
       size_t len;
+      ctf_stype_t *copied;
 
-      if (dtd->dtd_name != NULL)
-       {
-         dtd->dtd_data.ctt_name = (uint32_t) (s - s0);
-         len = strlen (dtd->dtd_name) + 1;
-         memcpy (s, dtd->dtd_name, len);
-         s += len;
-       }
-      else
-       dtd->dtd_data.ctt_name = 0;
+      dtd->dtd_data.ctt_name = 0;
 
       if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
        len = sizeof (ctf_stype_t);
@@ -378,6 +344,9 @@ ctf_update (ctf_file_t *fp)
        len = sizeof (ctf_type_t);
 
       memcpy (t, &dtd->dtd_data, len);
+      copied = (ctf_stype_t *) t;  /* name is at the start: constant offset.  */
+      if (dtd->dtd_name)
+       ctf_str_add_ref (fp, dtd->dtd_name, &copied->ctt_name);
       t += len;
 
       switch (kind)
@@ -431,28 +400,57 @@ ctf_update (ctf_file_t *fp)
        case CTF_K_STRUCT:
        case CTF_K_UNION:
          if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
-           t = ctf_copy_smembers (dtd, (uint32_t) (s - s0), t);
+           t = ctf_copy_smembers (fp, dtd, t);
          else
-           t = ctf_copy_lmembers (dtd, (uint32_t) (s - s0), t);
-         s = ctf_copy_membnames (dtd, s);
+           t = ctf_copy_lmembers (fp, dtd, t);
          break;
 
        case CTF_K_ENUM:
-         t = ctf_copy_emembers (dtd, (uint32_t) (s - s0), t);
-         s = ctf_copy_membnames (dtd, s);
+         t = ctf_copy_emembers (fp, dtd, t);
          break;
        }
     }
   assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff);
 
+  /* Construct the final string table and fill out all the string refs with the
+     final offsets.  Then purge the refs list, because we're about to move this
+     strtab onto the end of the buf, invalidating all the offsets.  */
+  strtab = ctf_str_write_strtab (fp);
+  ctf_str_purge_refs (fp);
+
+  if (strtab.cts_strs == NULL)
+    {
+      ctf_free (buf);
+      return (ctf_set_errno (fp, EAGAIN));
+    }
+
+  /* Now the string table is constructed, we can sort the buffer of
+     ctf_varent_t's.  */
+  ctf_sort_var_arg_cb_t sort_var_arg = { fp, (ctf_strs_t *) &strtab };
+  ctf_qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var,
+              &sort_var_arg);
+
+  if ((newbuf = ctf_realloc (fp, buf, buf_size + strtab.cts_len)) == NULL)
+    {
+      ctf_free (buf);
+      ctf_free (strtab.cts_strs);
+      return (ctf_set_errno (fp, EAGAIN));
+    }
+  buf = newbuf;
+  memcpy (buf + buf_size, strtab.cts_strs, strtab.cts_len);
+  hdrp = (ctf_header_t *) buf;
+  hdrp->cth_strlen = strtab.cts_len;
+  buf_size += hdrp->cth_strlen;
+  ctf_free (strtab.cts_strs);
+
   /* Finally, we are ready to ctf_simple_open() the new container.  If this
      is successful, we then switch nfp and fp and free the old container.  */
 
-  ctf_data_protect (buf, buf_size);
-
-  if ((nfp = ctf_simple_open (buf, buf_size, NULL, 0, 0, NULL, 0, &err)) == NULL)
+  if ((nfp = ctf_simple_open_internal ((char *) buf, buf_size, NULL, 0,
+                                      0, NULL, 0, fp->ctf_syn_ext_strtab,
+                                      &err)) == NULL)
     {
-      ctf_data_free (buf, buf_size);
+      ctf_free (buf);
       return (ctf_set_errno (fp, err));
     }
 
@@ -461,23 +459,28 @@ ctf_update (ctf_file_t *fp)
 
   nfp->ctf_refcnt = fp->ctf_refcnt;
   nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY;
-  nfp->ctf_data.cts_data = NULL;       /* Force ctf_data_free() on close.  */
+  if (nfp->ctf_dynbase == NULL)
+    nfp->ctf_dynbase = buf;            /* Make sure buf is freed on close.  */
   nfp->ctf_dthash = fp->ctf_dthash;
   nfp->ctf_dtdefs = fp->ctf_dtdefs;
   nfp->ctf_dtbyname = fp->ctf_dtbyname;
   nfp->ctf_dvhash = fp->ctf_dvhash;
   nfp->ctf_dvdefs = fp->ctf_dvdefs;
-  nfp->ctf_dtvstrlen = fp->ctf_dtvstrlen;
   nfp->ctf_dtnextid = fp->ctf_dtnextid;
   nfp->ctf_dtoldid = fp->ctf_dtnextid - 1;
   nfp->ctf_snapshots = fp->ctf_snapshots + 1;
   nfp->ctf_specific = fp->ctf_specific;
+  nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab;
 
   nfp->ctf_snapshot_lu = fp->ctf_snapshots;
 
   fp->ctf_dtbyname = NULL;
   fp->ctf_dthash = NULL;
+  ctf_str_free_atoms (nfp);
+  nfp->ctf_str_atoms = fp->ctf_str_atoms;
+  fp->ctf_str_atoms = NULL;
   memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t));
+  fp->ctf_syn_ext_strtab = NULL;
 
   fp->ctf_dvhash = NULL;
   memset (&fp->ctf_dvdefs, 0, sizeof (ctf_list_t));
@@ -525,18 +528,22 @@ ctf_prefixed_name (int kind, const char *name)
   return prefixed;
 }
 
-void
+int
 ctf_dtd_insert (ctf_file_t *fp, ctf_dtdef_t *dtd)
 {
-  ctf_dynhash_insert (fp->ctf_dthash, (void *) dtd->dtd_type, dtd);
-  ctf_list_append (&fp->ctf_dtdefs, dtd);
+  if (ctf_dynhash_insert (fp->ctf_dthash, (void *) dtd->dtd_type, dtd) < 0)
+    return -1;
+
   if (dtd->dtd_name)
     {
       int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
-      ctf_dynhash_insert (fp->ctf_dtbyname, ctf_prefixed_name (kind,
-                                                              dtd->dtd_name),
-                         dtd);
+      if (ctf_dynhash_insert (fp->ctf_dtbyname,
+                             ctf_prefixed_name (kind, dtd->dtd_name),
+                             dtd) < 0)
+       return -1;
     }
+  ctf_list_append (&fp->ctf_dtdefs, dtd);
+  return 0;
 }
 
 void
@@ -556,10 +563,7 @@ ctf_dtd_delete (ctf_file_t *fp, ctf_dtdef_t *dtd)
           dmd != NULL; dmd = nmd)
        {
          if (dmd->dmd_name != NULL)
-           {
-             fp->ctf_dtvstrlen -= strlen (dmd->dmd_name) + 1;
              ctf_free (dmd->dmd_name);
-           }
          nmd = ctf_list_next (dmd);
          ctf_free (dmd);
        }
@@ -576,8 +580,6 @@ ctf_dtd_delete (ctf_file_t *fp, ctf_dtdef_t *dtd)
       name = ctf_prefixed_name (kind, dtd->dtd_name);
       ctf_dynhash_remove (fp->ctf_dtbyname, name);
       free (name);
-
-      fp->ctf_dtvstrlen -= strlen (dtd->dtd_name) + 1;
       ctf_free (dtd->dtd_name);
     }
 
@@ -622,19 +624,19 @@ ctf_dynamic_type (const ctf_file_t *fp, ctf_id_t id)
   return NULL;
 }
 
-void
+int
 ctf_dvd_insert (ctf_file_t *fp, ctf_dvdef_t *dvd)
 {
-  ctf_dynhash_insert (fp->ctf_dvhash, dvd->dvd_name, dvd);
+  if (ctf_dynhash_insert (fp->ctf_dvhash, dvd->dvd_name, dvd) < 0)
+    return -1;
   ctf_list_append (&fp->ctf_dvdefs, dvd);
+  return 0;
 }
 
 void
 ctf_dvd_delete (ctf_file_t *fp, ctf_dvdef_t *dvd)
 {
   ctf_dynhash_remove (fp->ctf_dvhash, dvd->dvd_name);
-
-  fp->ctf_dtvstrlen -= strlen (dvd->dvd_name) + 1;
   ctf_free (dvd->dvd_name);
 
   ctf_list_delete (&fp->ctf_dvdefs, dvd);
@@ -758,10 +760,11 @@ ctf_add_generic (ctf_file_t *fp, uint32_t flag, const char *name,
   dtd->dtd_name = s;
   dtd->dtd_type = type;
 
-  if (s != NULL)
-    fp->ctf_dtvstrlen += strlen (s) + 1;
-
-  ctf_dtd_insert (fp, dtd);
+  if (ctf_dtd_insert (fp, dtd) < 0)
+    {
+      ctf_free (dtd);
+      return CTF_ERR;                  /* errno is set for us.  */
+    }
   fp->ctf_flags |= LCTF_DIRTY;
 
   *rp = dtd;
@@ -799,7 +802,8 @@ ctf_add_encoded (ctf_file_t *fp, uint32_t flag,
     return CTF_ERR;            /* errno is set for us.  */
 
   dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, 0);
-  dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY);
+  dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, CHAR_BIT)
+                                / CHAR_BIT);
   dtd->dtd_u.dtu_enc = *ep;
 
   return type;
@@ -812,7 +816,7 @@ ctf_add_reftype (ctf_file_t *fp, uint32_t flag, ctf_id_t ref, uint32_t kind)
   ctf_id_t type;
   ctf_file_t *tmp = fp;
 
-  if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+  if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
     return (ctf_set_errno (fp, EINVAL));
 
   if (ctf_lookup_by_id (&tmp, ref) == NULL)
@@ -843,7 +847,7 @@ ctf_add_slice (ctf_file_t *fp, uint32_t flag, ctf_id_t ref,
   if ((ep->cte_bits > 255) || (ep->cte_offset > 255))
     return (ctf_set_errno (fp, ECTF_SLICEOVERFLOW));
 
-  if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+  if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
     return (ctf_set_errno (fp, EINVAL));
 
   if ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL)
@@ -858,7 +862,8 @@ ctf_add_slice (ctf_file_t *fp, uint32_t flag, ctf_id_t ref,
     return CTF_ERR;            /* errno is set for us.  */
 
   dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0);
-  dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY);
+  dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, CHAR_BIT)
+                                / CHAR_BIT);
   dtd->dtd_u.dtu_slice.cts_type = ref;
   dtd->dtd_u.dtu_slice.cts_bits = ep->cte_bits;
   dtd->dtd_u.dtu_slice.cts_offset = ep->cte_offset;
@@ -1175,7 +1180,7 @@ ctf_add_typedef (ctf_file_t *fp, uint32_t flag, const char *name,
   ctf_id_t type;
   ctf_file_t *tmp = fp;
 
-  if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+  if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
     return (ctf_set_errno (fp, EINVAL));
 
   if (ctf_lookup_by_id (&tmp, ref) == NULL)
@@ -1261,7 +1266,6 @@ ctf_add_enumerator (ctf_file_t *fp, ctf_id_t enid, const char *name,
   dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
   ctf_list_append (&dtd->dtd_u.dtu_members, dmd);
 
-  fp->ctf_dtvstrlen += strlen (s) + 1;
   fp->ctf_flags |= LCTF_DIRTY;
 
   return 0;
@@ -1304,9 +1308,9 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
        }
     }
 
-  if ((msize = ctf_type_size (fp, type)) == CTF_ERR ||
-      (malign = ctf_type_align (fp, type)) == CTF_ERR)
-    return CTF_ERR;            /* errno is set for us.  */
+  if ((msize = ctf_type_size (fp, type)) < 0 ||
+      (malign = ctf_type_align (fp, type)) < 0)
+    return -1;                 /* errno is set for us.  */
 
   if ((dmd = ctf_alloc (sizeof (ctf_dmdef_t))) == NULL)
     return (ctf_set_errno (fp, EAGAIN));
@@ -1334,10 +1338,10 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
          ctf_encoding_t linfo;
          ssize_t lsize;
 
-         if (ctf_type_encoding (fp, ltype, &linfo) != CTF_ERR)
+         if (ctf_type_encoding (fp, ltype, &linfo) == 0)
            off += linfo.cte_bits;
-         else if ((lsize = ctf_type_size (fp, ltype)) != CTF_ERR)
-           off += lsize * NBBY;
+         else if ((lsize = ctf_type_size (fp, ltype)) > 0)
+           off += lsize * CHAR_BIT;
 
          /* Round up the offset of the end of the last member to
             the next byte boundary, convert 'off' to bytes, and
@@ -1348,9 +1352,9 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
             packing if the new member is a bit-field, but we're
             the "compiler" and ANSI says we can do as we choose.  */
 
-         off = roundup (off, NBBY) / NBBY;
+         off = roundup (off, CHAR_BIT) / CHAR_BIT;
          off = roundup (off, MAX (malign, 1));
-         dmd->dmd_offset = off * NBBY;
+         dmd->dmd_offset = off * CHAR_BIT;
          ssize = off + msize;
        }
       else
@@ -1359,7 +1363,7 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
 
          dmd->dmd_offset = bit_offset;
          ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
-         ssize = MAX (ssize, (bit_offset / NBBY) + msize);
+         ssize = MAX (ssize, ((signed) bit_offset / CHAR_BIT) + msize);
        }
     }
   else
@@ -1369,7 +1373,7 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
       ssize = MAX (ssize, msize);
     }
 
-  if (ssize > CTF_MAX_SIZE)
+  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);
@@ -1381,9 +1385,6 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
   dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
   ctf_list_append (&dtd->dtd_u.dtu_members, dmd);
 
-  if (s != NULL)
-    fp->ctf_dtvstrlen += strlen (s) + 1;
-
   fp->ctf_flags |= LCTF_DIRTY;
   return 0;
 }
@@ -1401,7 +1402,7 @@ ctf_add_member_encoded (ctf_file_t *fp, ctf_id_t souid, const char *name,
     return (ctf_set_errno (fp, ECTF_NOTINTFP));
 
   if ((type = ctf_add_slice (fp, CTF_ADD_NONROOT, otype, &encoding)) == CTF_ERR)
-    return CTF_ERR;            /* errno is set for us.  */
+    return -1;                 /* errno is set for us.  */
 
   return ctf_add_member_offset (fp, souid, name, type, bit_offset);
 }
@@ -1426,7 +1427,7 @@ ctf_add_variable (ctf_file_t *fp, const char *name, ctf_id_t ref)
     return (ctf_set_errno (fp, ECTF_DUPLICATE));
 
   if (ctf_lookup_by_id (&tmp, ref) == NULL)
-    return CTF_ERR;            /* errno is set for us.  */
+    return -1;                 /* errno is set for us.  */
 
   if ((dvd = ctf_alloc (sizeof (ctf_dvdef_t))) == NULL)
     return (ctf_set_errno (fp, EAGAIN));
@@ -1439,9 +1440,12 @@ ctf_add_variable (ctf_file_t *fp, const char *name, ctf_id_t ref)
   dvd->dvd_type = ref;
   dvd->dvd_snapshots = fp->ctf_snapshots;
 
-  ctf_dvd_insert (fp, dvd);
+  if (ctf_dvd_insert (fp, dvd) < 0)
+    {
+      ctf_free (dvd);
+      return -1;                       /* errno is set for us.  */
+    }
 
-  fp->ctf_dtvstrlen += strlen (name) + 1;
   fp->ctf_flags |= LCTF_DIRTY;
   return 0;
 }
@@ -1452,7 +1456,7 @@ enumcmp (const char *name, int value, void *arg)
   ctf_bundle_t *ctb = arg;
   int bvalue;
 
-  if (ctf_enum_value (ctb->ctb_file, ctb->ctb_type, name, &bvalue) == CTF_ERR)
+  if (ctf_enum_value (ctb->ctb_file, ctb->ctb_type, name, &bvalue) < 0)
     {
       ctf_dprintf ("Conflict due to member %s iteration error.\n", name);
       return 1;
@@ -1472,7 +1476,7 @@ enumadd (const char *name, int value, void *arg)
   ctf_bundle_t *ctb = arg;
 
   return (ctf_add_enumerator (ctb->ctb_file, ctb->ctb_type,
-                             name, value) == CTF_ERR);
+                             name, value) < 0);
 }
 
 static int
@@ -1482,7 +1486,7 @@ membcmp (const char *name, ctf_id_t type _libctf_unused_, unsigned long offset,
   ctf_bundle_t *ctb = arg;
   ctf_membinfo_t ctm;
 
-  if (ctf_member_info (ctb->ctb_file, ctb->ctb_type, name, &ctm) == CTF_ERR)
+  if (ctf_member_info (ctb->ctb_file, ctb->ctb_type, name, &ctm) < 0)
     {
       ctf_dprintf ("Conflict due to member %s iteration error.\n", name);
       return 1;
@@ -1521,9 +1525,6 @@ membadd (const char *name, ctf_id_t type, unsigned long offset, void *arg)
 
   ctf_list_append (&ctb->ctb_dtd->dtd_u.dtu_members, dmd);
 
-  if (s != NULL)
-    ctb->ctb_file->ctf_dtvstrlen += strlen (s) + 1;
-
   ctb->ctb_file->ctf_flags |= LCTF_DIRTY;
   return 0;
 }
@@ -1550,7 +1551,6 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
 
   ctf_dtdef_t *dtd;
   ctf_funcinfo_t ctc;
-  ssize_t size;
 
   ctf_hash_t *hp;
 
@@ -1756,7 +1756,7 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
       break;
 
     case CTF_K_ARRAY:
-      if (ctf_array_info (src_fp, src_type, &src_ar) == CTF_ERR)
+      if (ctf_array_info (src_fp, src_type, &src_ar) != 0)
        return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
 
       src_ar.ctr_contents =
@@ -1803,6 +1803,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
       {
        ctf_dmdef_t *dmd;
        int errs = 0;
+       size_t size;
+       ssize_t ssize;
 
        /* Technically to match a struct or union we need to check both
           ways (src members vs. dst, dst members vs. src) but we make
@@ -1819,8 +1821,9 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
              {
                ctf_dprintf ("Conflict for type %s against ID %lx: "
                             "union size differs, old %li, new %li\n",
-                            name, dst_type, ctf_type_size (src_fp, src_type),
-                            ctf_type_size (dst_fp, dst_type));
+                            name, dst_type,
+                            (long) ctf_type_size (src_fp, src_type),
+                            (long) ctf_type_size (dst_fp, dst_type));
                return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
              }
 
@@ -1848,7 +1851,11 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
        if (ctf_member_iter (src_fp, src_type, membadd, &dst) != 0)
          errs++;              /* Increment errs and fail at bottom of case.  */
 
-       if ((size = ctf_type_size (src_fp, src_type)) > CTF_MAX_SIZE)
+       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);
@@ -1931,15 +1938,26 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
   return dst_type;
 }
 
-/* Write the compressed CTF data stream to the specified gzFile descriptor.
-   This is useful for saving the results of dynamic CTF containers.  */
+/* Write the compressed CTF data stream to the specified gzFile descriptor.  */
 int
 ctf_gzwrite (ctf_file_t *fp, gzFile fd)
 {
-  const unsigned char *buf = fp->ctf_base;
-  ssize_t resid = fp->ctf_size;
+  const unsigned char *buf;
+  ssize_t resid;
   ssize_t len;
 
+  resid = sizeof (ctf_header_t);
+  buf = (unsigned char *) fp->ctf_header;
+  while (resid != 0)
+    {
+      if ((len = gzwrite (fd, buf, resid)) <= 0)
+       return (ctf_set_errno (fp, errno));
+      resid -= len;
+      buf += len;
+    }
+
+  resid = fp->ctf_size;
+  buf = fp->ctf_buf;
   while (resid != 0)
     {
       if ((len = gzwrite (fd, buf, resid)) <= 0)
@@ -1962,24 +1980,24 @@ ctf_compress_write (ctf_file_t *fp, int fd)
   ctf_header_t *hp = &h;
   ssize_t header_len = sizeof (ctf_header_t);
   ssize_t compress_len;
-  size_t max_compress_len = compressBound (fp->ctf_size - header_len);
+  size_t max_compress_len = compressBound (fp->ctf_size);
   ssize_t len;
   int rc;
   int err = 0;
 
-  memcpy (hp, fp->ctf_base, header_len);
+  memcpy (hp, fp->ctf_header, header_len);
   hp->cth_flags |= CTF_F_COMPRESS;
 
-  if ((buf = ctf_data_alloc (max_compress_len)) == NULL)
+  if ((buf = ctf_alloc (max_compress_len)) == NULL)
     return (ctf_set_errno (fp, ECTF_ZALLOC));
 
   compress_len = max_compress_len;
-  if ((rc = compress (buf, (uLongf *) & compress_len,
-                     fp->ctf_base + header_len,
-                     fp->ctf_size - header_len)) != Z_OK)
+  if ((rc = compress (buf, (uLongf *) &compress_len,
+                     fp->ctf_buf, fp->ctf_size)) != Z_OK)
     {
       ctf_dprintf ("zlib deflate err: %s\n", zError (rc));
       err = ctf_set_errno (fp, ECTF_COMPRESS);
+      ctf_free (buf);
       goto ret;
     }
 
@@ -2007,22 +2025,33 @@ ctf_compress_write (ctf_file_t *fp, int fd)
     }
 
 ret:
-  ctf_data_free (buf, max_compress_len);
+  ctf_free (buf);
   return err;
 }
 
-/* Write the uncompressed CTF data stream to the specified file descriptor.
-   This is useful for saving the results of dynamic CTF containers.  */
+/* Write the uncompressed CTF data stream to the specified file descriptor.  */
 int
 ctf_write (ctf_file_t *fp, int fd)
 {
-  const unsigned char *buf = fp->ctf_base;
-  ssize_t resid = fp->ctf_size;
+  const unsigned char *buf;
+  ssize_t resid;
   ssize_t len;
 
+  resid = sizeof (ctf_header_t);
+  buf = (unsigned char *) fp->ctf_header;
+  while (resid != 0)
+    {
+      if ((len = write (fd, buf, resid)) <= 0)
+       return (ctf_set_errno (fp, errno));
+      resid -= len;
+      buf += len;
+    }
+
+  resid = fp->ctf_size;
+  buf = fp->ctf_buf;
   while (resid != 0)
     {
-      if ((len = write (fd, buf, resid)) < 0)
+      if ((len = write (fd, buf, resid)) <= 0)
        return (ctf_set_errno (fp, errno));
       resid -= len;
       buf += len;
This page took 0.042999 seconds and 4 git commands to generate.