aboutsummaryrefslogtreecommitdiff
path: root/libctf/ctf-serialize.c
diff options
context:
space:
mode:
Diffstat (limited to 'libctf/ctf-serialize.c')
-rw-r--r--libctf/ctf-serialize.c117
1 files changed, 59 insertions, 58 deletions
diff --git a/libctf/ctf-serialize.c b/libctf/ctf-serialize.c
index 5d94f44..0811b7b 100644
--- a/libctf/ctf-serialize.c
+++ b/libctf/ctf-serialize.c
@@ -719,57 +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;
-}
-
/* Iterate through the dynamic type definition list and compute the
size of the CTF type section. */
@@ -784,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 (lsize <= CTF_MAX_SIZE)
+ type_ctt_size = lsize;
+ }
- if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
+ if (type_ctt_size != CTF_LSIZE_SENT)
type_size += sizeof (ctf_stype_t);
else
type_size += sizeof (ctf_type_t);
@@ -807,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;
@@ -836,13 +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;
- if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
+ /* 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 (type_ctt_size != CTF_LSIZE_SENT)
len = sizeof (ctf_stype_t);
else
len = sizeof (ctf_type_t);
@@ -855,6 +827,7 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr)
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)
@@ -880,12 +853,40 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr)
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: