libctf: map from old to corresponding newly-added types in ctf_add_type
[deliverable/binutils-gdb.git] / libctf / ctf-create.c
index 24ea114f294426b08273adc43065dfff5d22702d..90e45f340b16b30e105c612e0f3205bb1bab0084 100644 (file)
@@ -170,31 +170,37 @@ ctf_copy_emembers (ctf_file_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
 
 /* 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)
 {
@@ -294,6 +300,8 @@ ctf_update (ctf_file_t *fp)
   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);
 
   /* Work over the variable list, translating everything into ctf_varent_t's and
      prepping the string table.  */
@@ -410,10 +418,17 @@ ctf_update (ctf_file_t *fp)
   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,
-              strtab.cts_strs);
+              &sort_var_arg);
 
   if ((newbuf = ctf_realloc (fp, buf, buf_size + strtab.cts_len)) == NULL)
     {
@@ -431,8 +446,9 @@ ctf_update (ctf_file_t *fp)
   /* 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.  */
 
-  if ((nfp = ctf_simple_open ((char *) 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_free (buf);
       return (ctf_set_errno (fp, err));
@@ -443,7 +459,8 @@ 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_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;
@@ -453,6 +470,10 @@ ctf_update (ctf_file_t *fp)
   nfp->ctf_dtoldid = fp->ctf_dtnextid - 1;
   nfp->ctf_snapshots = fp->ctf_snapshots + 1;
   nfp->ctf_specific = fp->ctf_specific;
+  nfp->ctf_link_inputs = fp->ctf_link_inputs;
+  nfp->ctf_link_outputs = fp->ctf_link_outputs;
+  nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab;
+  nfp->ctf_link_type_mapping = fp->ctf_link_type_mapping;
 
   nfp->ctf_snapshot_lu = fp->ctf_snapshots;
 
@@ -462,6 +483,10 @@ ctf_update (ctf_file_t *fp)
   nfp->ctf_str_atoms = fp->ctf_str_atoms;
   fp->ctf_str_atoms = NULL;
   memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t));
+  fp->ctf_link_inputs = NULL;
+  fp->ctf_link_outputs = NULL;
+  fp->ctf_syn_ext_strtab = NULL;
+  fp->ctf_link_type_mapping = NULL;
 
   fp->ctf_dvhash = NULL;
   memset (&fp->ctf_dvdefs, 0, sizeof (ctf_list_t));
@@ -1534,6 +1559,7 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
   ctf_funcinfo_t ctc;
 
   ctf_hash_t *hp;
+  ctf_id_t orig_src_type = src_type;
 
   if (!(dst_fp->ctf_flags & LCTF_RDWR))
     return (ctf_set_errno (dst_fp, ECTF_RDONLY));
@@ -1617,7 +1643,10 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
              if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
                {
                  if (kind != CTF_K_SLICE)
-                   return dst_type;
+                   {
+                     ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
+                     return dst_type;
+                   }
                }
              else
                  {
@@ -1656,7 +1685,10 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
              int match;        /* Do the encodings match?  */
 
              if (kind != CTF_K_INTEGER && kind != CTF_K_FLOAT && kind != CTF_K_SLICE)
-               return dtd->dtd_type;
+               {
+                 ctf_add_type_mapping (src_fp, src_type, dst_fp, dtd->dtd_type);
+                 return dtd->dtd_type;
+               }
 
              sroot = (flag & CTF_ADD_ROOT);
              droot = (LCTF_INFO_ISROOT (dst_fp,
@@ -1675,7 +1707,10 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
              if (match && sroot == droot)
                {
                  if (kind != CTF_K_SLICE)
-                   return dtd->dtd_type;
+                   {
+                     ctf_add_type_mapping (src_fp, src_type, dst_fp, dtd->dtd_type);
+                     return dtd->dtd_type;
+                   }
                }
              else if (!match && sroot && droot)
                {
@@ -1916,18 +1951,31 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
       return (ctf_set_errno (dst_fp, ECTF_CORRUPT));
     }
 
+  if (dst_type != CTF_ERR)
+    ctf_add_type_mapping (src_fp, orig_src_type, dst_fp, dst_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)
@@ -1950,12 +1998,12 @@ 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_alloc (max_compress_len)) == NULL)
@@ -1963,12 +2011,10 @@ ctf_compress_write (ctf_file_t *fp, int fd)
 
   compress_len = max_compress_len;
   if ((rc = compress (buf, (uLongf *) &compress_len,
-                     fp->ctf_base + header_len,
-                     fp->ctf_size - header_len)) != Z_OK)
+                     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;
     }
 
@@ -2000,18 +2046,80 @@ ret:
   return err;
 }
 
-/* Write the uncompressed CTF data stream to the specified file descriptor.
-   This is useful for saving the results of dynamic CTF containers.  */
+/* Optionally compress the specified CTF data stream and return it as a new
+   dynamically-allocated string.  */
+unsigned char *
+ctf_write_mem (ctf_file_t *fp, size_t *size, size_t threshold)
+{
+  unsigned char *buf;
+  unsigned char *bp;
+  ctf_header_t *hp;
+  ssize_t header_len = sizeof (ctf_header_t);
+  ssize_t compress_len;
+  size_t max_compress_len = compressBound (fp->ctf_size);
+  int rc;
+
+  if (fp->ctf_size < threshold)
+    max_compress_len = fp->ctf_size;
+  if ((buf = malloc (max_compress_len
+                    + sizeof (struct ctf_header))) == NULL)
+    {
+      ctf_set_errno (fp, ENOMEM);
+      return NULL;
+    }
+
+  hp = (ctf_header_t *) buf;
+  memcpy (hp, fp->ctf_header, header_len);
+  bp = buf + sizeof (struct ctf_header);
+  *size = sizeof (struct ctf_header);
+
+  compress_len = max_compress_len;
+
+  if (fp->ctf_size < threshold)
+    {
+      hp->cth_flags &= ~CTF_F_COMPRESS;
+      memcpy (bp, fp->ctf_buf, fp->ctf_size);
+      *size += fp->ctf_size;
+    }
+  else
+    {
+      hp->cth_flags |= CTF_F_COMPRESS;
+      if ((rc = compress (bp, (uLongf *) &compress_len,
+                         fp->ctf_buf, fp->ctf_size)) != Z_OK)
+       {
+         ctf_dprintf ("zlib deflate err: %s\n", zError (rc));
+         ctf_set_errno (fp, ECTF_COMPRESS);
+         ctf_free (buf);
+         return NULL;
+       }
+      *size += compress_len;
+    }
+  return buf;
+}
+
+/* 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.028368 seconds and 4 git commands to generate.