summaryrefslogtreecommitdiff
path: root/libctf/ctf-serialize.c
diff options
context:
space:
mode:
authorNick Alcock <nick.alcock@oracle.com>2021-03-18 12:37:52 +0000
committerNick Alcock <nick.alcock@oracle.com>2021-03-18 12:40:40 +0000
commit08c428aff4a793b63c7dd2229ae172879623e3a2 (patch)
treed6c1e1a4945afb465889f9ff8d0337b548c6e111 /libctf/ctf-serialize.c
parent77d724a7ecdb3fa84557b0ee5c8b7ea949ce56a5 (diff)
downloadbinutils-gdb-08c428aff4a793b63c7dd2229ae172879623e3a2.tar.gz
libctf: eliminate dtd_u, part 5: structs / unions
Eliminate the dynamic member storage for structs and unions as we have for other dynamic types. This is much like the previous enum elimination, except that structs and unions are the only types for which a full-sized ctf_type_t might be needed. Up to now, this decision has been made in the individual ctf_add_{struct,union}_sized functions and duplicated in ctf_add_member_offset. The vlen machinery lets us simplify this, always allocating a ctf_lmember_t and setting the dtd_data's ctt_size to CTF_LSIZE_SENT: we figure out whether this is really justified and (almost always) repack things down into a ctf_stype_t at ctf_serialize time. This allows us to eliminate the dynamic member paths from the iterators and query functions in ctf-types.c in favour of always using the large-structure vlen stuff for dynamic types (the diff is ugly but that's just because of the volume of reindentation this calls for). This also means the large-structure vlen stuff gets more heavily tested, which is nice because it was an almost totally unused code path before now (it only kicked in for structures of size >4GiB, and how often do you see those?) The only extra complexity here is ctf_add_type. Back in the days of the nondeduplicating linker this was called a ridiculous number of times for countless identical copies of structures: eschewing the repeated lookups of the dtd in ctf_add_member_offset and adding the members directly saved an amazing amount of time. Now the nondeduplicating linker is gone, this is extreme overoptimization: we can rip out the direct addition and use ctf_member_next and ctf_add_member_offset, just like ctf_dedup_emit does. We augment a ctf_add_type test to try adding a self-referential struct, the only thing the ctf_add_type part of this change really perturbs. This completes the elimination of dtd_u. libctf/ChangeLog 2021-03-18 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (ctf_dtdef_t) <dtu_members>: Remove. <dtd_u>: Likewise. (ctf_dmdef_t): Remove. (struct ctf_next) <u.ctn_dmd>: Remove. * ctf-create.c (INITIAL_VLEN): New, more-or-less arbitrary initial vlen size. (ctf_add_enum): Use it. (ctf_dtd_delete): Do not free the (removed) dmd; remove string refs from the vlen on struct deletion. (ctf_add_struct_sized): Populate the vlen: do it by hand if promoting forwards. Always populate the full-size lsizehi/lsizelo members. (ctf_add_union_sized): Likewise. (ctf_add_member_offset): Set up the vlen rather than the dmd. Expand it as needed, repointing string refs via ctf_str_move_pending. Add the member names as pending strings. Always populate the full-size lsizehi/lsizelo members. (membadd): Remove, folding back into... (ctf_add_type_internal): ... here, adding via an ordinary ctf_add_struct_sized and _next iteration rather than doing everything by hand. * ctf-serialize.c (ctf_copy_smembers): Remove this... (ctf_copy_lmembers): ... and this... (ctf_emit_type_sect): ... folding into here. Figure out if a ctf_stype_t is needed here, not in ctf_add_*_sized. (ctf_type_sect_size): Figure out the ctf_stype_t stuff the same way here. * ctf-types.c (ctf_member_next): Remove the dmd path and always use the vlen. Force large-structure usage for dynamic types. (ctf_type_align): Likewise. (ctf_member_info): Likewise. (ctf_type_rvisit): Likewise. * testsuite/libctf-regression/type-add-unnamed-struct-ctf.c: Add a self-referential type to this test. * testsuite/libctf-regression/type-add-unnamed-struct.c: Adjusted accordingly. * testsuite/libctf-regression/type-add-unnamed-struct.lk: Likewise.
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 5d94f44b0d0..0811b7b6efe 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: