Documentation for the new mtag commands
[deliverable/binutils-gdb.git] / libctf / ctf-serialize.c
index d8e78f361f40f536de64c0e45b27d07a093f4bbd..0811b7b6efed4e2d3f1ae4fa4ca9dacb1c19ce26 100644 (file)
@@ -719,77 +719,6 @@ symerr:
 
 /* Type section.  */
 
-static unsigned char *
-ctf_copy_smembers (ctf_dict_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))
-    {
-      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);
-    }
-
-  return t;
-}
-
-static unsigned char *
-ctf_copy_lmembers (ctf_dict_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))
-    {
-      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);
-    }
-
-  return t;
-}
-
-static unsigned char *
-ctf_copy_emembers (ctf_dict_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))
-    {
-      ctf_enum_t *copied;
-
-      cte.cte_value = dmd->dmd_value;
-      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;
-}
-
 /* Iterate through the dynamic type definition list and compute the
    size of the CTF type section.  */
 
@@ -804,8 +733,20 @@ ctf_type_sect_size (ctf_dict_t *fp)
     {
       uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
       uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
+      size_t type_ctt_size = dtd->dtd_data.ctt_size;
+
+      /* Shrink ctf_type_t-using types from a ctf_type_t to a ctf_stype_t
+        if possible.  */
+
+      if (kind == CTF_K_STRUCT || kind == CTF_K_UNION)
+       {
+         size_t lsize = CTF_TYPE_LSIZE (&dtd->dtd_data);
 
-      if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
+         if (lsize <= CTF_MAX_SIZE)
+           type_ctt_size = lsize;
+       }
+
+      if (type_ctt_size != CTF_LSIZE_SENT)
        type_size += sizeof (ctf_stype_t);
       else
        type_size += sizeof (ctf_type_t);
@@ -827,7 +768,7 @@ ctf_type_sect_size (ctf_dict_t *fp)
          break;
        case CTF_K_STRUCT:
        case CTF_K_UNION:
-         if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
+         if (type_ctt_size < CTF_LSTRUCT_THRESH)
            type_size += sizeof (ctf_member_t) * vlen;
          else
            type_size += sizeof (ctf_lmember_t) * vlen;
@@ -856,12 +797,24 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr)
     {
       uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
       uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
-
+      size_t type_ctt_size = dtd->dtd_data.ctt_size;
       size_t len;
       ctf_stype_t *copied;
       const char *name;
+      size_t i;
+
+      /* Shrink ctf_type_t-using types from a ctf_type_t to a ctf_stype_t
+        if possible.  */
+
+      if (kind == CTF_K_STRUCT || kind == CTF_K_UNION)
+       {
+         size_t lsize = CTF_TYPE_LSIZE (&dtd->dtd_data);
+
+         if (lsize <= CTF_MAX_SIZE)
+           type_ctt_size = lsize;
+       }
 
-      if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
+      if (type_ctt_size != CTF_LSIZE_SENT)
        len = sizeof (ctf_stype_t);
       else
        len = sizeof (ctf_type_t);
@@ -870,7 +823,11 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr)
       copied = (ctf_stype_t *) t;  /* name is at the start: constant offset.  */
       if (copied->ctt_name
          && (name = ctf_strraw (fp, copied->ctt_name)) != NULL)
-       ctf_str_add_ref (fp, name, &copied->ctt_name);
+       {
+         ctf_str_add_ref (fp, name, &copied->ctt_name);
+         ctf_str_add_ref (fp, name, &dtd->dtd_data.ctt_name);
+       }
+      copied->ctt_size = type_ctt_size;
       t += len;
 
       switch (kind)
@@ -892,31 +849,63 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr)
          break;
 
        case CTF_K_FUNCTION:
-         {
-           uint32_t *argv = (uint32_t *) (uintptr_t) t;
-           uint32_t argc;
-
-           for (argc = 0; argc < vlen; argc++)
-             *argv++ = dtd->dtd_u.dtu_argv[argc];
-
-           if (vlen & 1)
-             *argv++ = 0;      /* Pad to 4-byte boundary.  */
-
-           t = (unsigned char *) argv;
-           break;
-         }
+         memcpy (t, dtd->dtd_vlen, sizeof (uint32_t) * (vlen + (vlen & 1)));
+         t += sizeof (uint32_t) * (vlen + (vlen & 1));
+         break;
 
+         /* These need to be copied across element by element, depending on
+            their ctt_size.  */
        case CTF_K_STRUCT:
        case CTF_K_UNION:
-         if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
-           t = ctf_copy_smembers (fp, dtd, t);
+         {
+           ctf_lmember_t *dtd_vlen = (ctf_lmember_t *) dtd->dtd_vlen;
+           ctf_lmember_t *t_lvlen = (ctf_lmember_t *) t;
+           ctf_member_t *t_vlen = (ctf_member_t *) t;
+
+           for (i = 0; i < vlen; i++)
+             {
+               const char *name = ctf_strraw (fp, dtd_vlen[i].ctlm_name);
+
+               ctf_str_add_ref (fp, name, &dtd_vlen[i].ctlm_name);
+
+               if (type_ctt_size < CTF_LSTRUCT_THRESH)
+                 {
+                   t_vlen[i].ctm_name = dtd_vlen[i].ctlm_name;
+                   t_vlen[i].ctm_type = dtd_vlen[i].ctlm_type;
+                   t_vlen[i].ctm_offset = CTF_LMEM_OFFSET (&dtd_vlen[i]);
+                   ctf_str_add_ref (fp, name, &t_vlen[i].ctm_name);
+                 }
+               else
+                 {
+                   t_lvlen[i] = dtd_vlen[i];
+                   ctf_str_add_ref (fp, name, &t_lvlen[i].ctlm_name);
+                 }
+             }
+         }
+
+         if (type_ctt_size < CTF_LSTRUCT_THRESH)
+           t += sizeof (ctf_member_t) * vlen;
          else
-           t = ctf_copy_lmembers (fp, dtd, t);
+           t += sizeof (ctf_lmember_t) * vlen;
          break;
 
        case CTF_K_ENUM:
-         t = ctf_copy_emembers (fp, dtd, t);
-         break;
+         {
+           ctf_enum_t *dtd_vlen = (struct ctf_enum *) dtd->dtd_vlen;
+           ctf_enum_t *t_vlen = (struct ctf_enum *) t;
+
+           memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_enum) * vlen);
+           for (i = 0; i < vlen; i++)
+             {
+               const char *name = ctf_strraw (fp, dtd_vlen[i].cte_name);
+
+               ctf_str_add_ref (fp, name, &t_vlen[i].cte_name);
+               ctf_str_add_ref (fp, name, &dtd_vlen[i].cte_name);
+             }
+           t += sizeof (struct ctf_enum) * vlen;
+
+           break;
+         }
        }
     }
 
@@ -965,6 +954,7 @@ ctf_serialize (ctf_dict_t *fp)
   ctf_varent_t *dvarents;
   ctf_strs_writable_t strtab;
   int err;
+  int num_missed_str_refs;
 
   unsigned char *t;
   unsigned long i;
@@ -983,6 +973,16 @@ ctf_serialize (ctf_dict_t *fp)
   if (!(fp->ctf_flags & LCTF_DIRTY))
     return 0;
 
+  /* The strtab refs table must be empty at this stage.  Any refs already added
+     will be corrupted by any modifications, including reserialization, after
+     strtab finalization is complete.  Only this function, and functions it
+     calls, may add refs, and all memory locations (including in the dtds)
+     containing strtab offsets must be traversed as part of serialization, and
+     refs added.  */
+
+  if (!ctf_assert (fp, fp->ctf_str_num_refs == 0))
+    return -1;                                 /* errno is set for us.  */
+
   /* Fill in an initial CTF header.  We will leave the label, object,
      and function sections empty and only output a header, type section,
      and string table.  The type section begins at a 4-byte aligned
@@ -1062,6 +1062,12 @@ ctf_serialize (ctf_dict_t *fp)
 
   assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff);
 
+  /* Every string added outside serialization by ctf_str_add_pending should
+     now have been added by ctf_add_ref.  */
+  num_missed_str_refs = ctf_dynset_elements (fp->ctf_str_pending_ref);
+  if (!ctf_assert (fp, num_missed_str_refs == 0))
+    goto err;                                  /* errno is set for us.  */
+
   /* 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.  */
@@ -1123,6 +1129,7 @@ ctf_serialize (ctf_dict_t *fp)
   nfp->ctf_dynsyms = fp->ctf_dynsyms;
   nfp->ctf_ptrtab = fp->ctf_ptrtab;
   nfp->ctf_pptrtab = fp->ctf_pptrtab;
+  nfp->ctf_typemax = fp->ctf_typemax;
   nfp->ctf_dynsymidx = fp->ctf_dynsymidx;
   nfp->ctf_dynsymmax = fp->ctf_dynsymmax;
   nfp->ctf_ptrtab_len = fp->ctf_ptrtab_len;
@@ -1163,8 +1170,10 @@ ctf_serialize (ctf_dict_t *fp)
   ctf_str_free_atoms (nfp);
   nfp->ctf_str_atoms = fp->ctf_str_atoms;
   nfp->ctf_prov_strtab = fp->ctf_prov_strtab;
+  nfp->ctf_str_pending_ref = fp->ctf_str_pending_ref;
   fp->ctf_str_atoms = NULL;
   fp->ctf_prov_strtab = NULL;
+  fp->ctf_str_pending_ref = NULL;
   memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t));
   memset (&fp->ctf_errs_warnings, 0, sizeof (ctf_list_t));
   fp->ctf_add_processing = NULL;
This page took 0.02564 seconds and 4 git commands to generate.