From: Nick Alcock Date: Fri, 25 Apr 2025 17:12:47 +0000 (+0100) Subject: libctf: serialize: finish off the serializer X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3520fb4568c003b1cba32511fa25fa07e0cd3064;p=thirdparty%2Fbinutils-gdb.git libctf: serialize: finish off the serializer The only remaining parts of serialization that need fixing up is ctf_preserialize, which despite its name does nearly all the work of serialization: the only bit it doesn't do is write the string tables (since that has to happen across dicts after all the dicts have otherwise been laid out, in order to deduplicate the strtabs). As usual in this series, there's adjustment for various field name changes (maxtypes -> ntypes, the move into ctf_serialize, etc), and extra work to figure out whether we're emitting BTF or not and to handle the distinction between CTF and BTF headers, and not try to emit CTF-only stuff like the symtypetabs into BTF dicts; we can also throw out a bunch of old code that sets compatibility flags, everything to do with forcing variables into the dynamic state in case they changed (we're going to handle that more generally for everything in the types table at a later date, outside serialization), and everything to do with special handling of variables in general. But much of that is only a couple of lines each, and most of the changes are mechanical: this is probably the simplest serialization commit in this series. --- diff --git a/libctf/ctf-serialize.c b/libctf/ctf-serialize.c index ef4bcd4313d..9c9e71676d1 100644 --- a/libctf/ctf-serialize.c +++ b/libctf/ctf-serialize.c @@ -1354,15 +1354,14 @@ int ctf_preserialize (ctf_dict_t *fp, int force_ctf) { ctf_header_t hdr, *hdrp; - ctf_dvdef_t *dvd; ctf_dtdef_t *dtd; int sym_functions = 0; + size_t hdr_len; + int ctf_adjustment = 0; unsigned char *t; - unsigned long i; size_t buf_size, type_size, objt_size, func_size; size_t funcidx_size, objtidx_size; - size_t nvars; unsigned char *buf = NULL; emit_symtypetab_state_t symstate; @@ -1400,16 +1399,14 @@ ctf_preserialize (ctf_dict_t *fp, int force_ctf) read-in buffer. You can emit such dicts using ctf_link, which can change type IDs arbitrarily, resolving all overlaps. */ - if (fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff > 0 && - fp->ctf_header->cth_parent_typemax < fp->ctf_parent->ctf_typemax) + if (fp->ctf_header->btf.bth_str_len > 0 && + fp->ctf_header->cth_parent_ntypes < fp->ctf_parent->ctf_typemax) { ctf_set_errno (fp, ECTF_NOTSERIALIZED); ctf_err_warn (fp, 0, 0, _("cannot write out already-written child dict: parent has had %u types added"), - fp->ctf_parent->ctf_typemax - fp->ctf_header->cth_parent_typemax); + fp->ctf_parent->ctf_typemax - fp->ctf_header->cth_parent_ntypes); return -1; /* errno is set for us. */ } - - fp->ctf_header->cth_parent_typemax = fp->ctf_parent->ctf_typemax; } else { @@ -1431,23 +1428,22 @@ ctf_preserialize (ctf_dict_t *fp, int force_ctf) } /* Fill in an initial CTF header. The type section begins at a 4-byte aligned - boundary past the CTF header itself (at relative offset zero). The flag - indicating a new-style function info section (an array of CTF_K_FUNCTION - type IDs in the types section) is flipped on. */ - - memset (&hdr, 0, sizeof (hdr)); - hdr.cth_magic = CTF_MAGIC; - hdr.cth_version = CTF_VERSION; - - /* This is a new-format func info section, and the symtab and strtab come out - of the dynsym and dynstr these days. */ + boundary past the CTF header itself (at relative offset zero). - /* UPTODO: remove. */ - hdr.cth_flags = (CTF_F_NEWFUNCINFO | CTF_F_DYNSTR); + It is quite possible that we will only write out the leading + ctf_btf_header_t portion of this structure. */ - /* Propagate all symbols in the symtypetabs into the dynamic state, so that - we can put them back in the right order. Symbols already in the dynamic - state, likely due to repeated serialization, are left unchanged. */ + memset (&hdr, 0, sizeof (hdr)); + hdr.btf.bth_preamble.btf_magic = CTF_BTF_MAGIC; + hdr.btf.bth_preamble.btf_version = CTF_BTF_VERSION; + hdr.btf.bth_preamble.btf_flags = 0; + hdr.btf.bth_hdr_len = sizeof (ctf_btf_header_t); + hdr.cth_preamble.ctp_magic_version = (CTFv4_MAGIC << 16) | CTF_VERSION; + + /* Propagate all symbols in the symtypetabs into the dynamic state, so that we + can put them back in the right order during sizing. Symbols already in the + dynamic state, likely due to repeated serialization, are left + unchanged. */ do { ctf_next_t *it = NULL; @@ -1470,41 +1466,53 @@ ctf_preserialize (ctf_dict_t *fp, int force_ctf) &objtidx_size, &funcidx_size) < 0) return -1; /* errno is set for us. */ - /* Propagate all vars into the dynamic state, so we can put them back later. - Variables already in the dynamic state, likely due to repeated - serialization, are left unchanged. */ - - for (i = 0; i < fp->ctf_nvars; i++) + if (!fp->ctf_serialize.cs_initialized) { - const char *name = ctf_strptr (fp, fp->ctf_vars[i].ctv_name); - - if (name != NULL && !ctf_dvd_lookup (fp, name)) - if (ctf_add_variable_forced (fp, name, fp->ctf_vars[i].ctv_type) < 0) - return -1; /* errno is set for us. */ + if (ctf_serialize_output_format (fp, force_ctf) < 0) + return -1; /* errno is set for us. */ } - for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); - dvd != NULL; dvd = ctf_list_next (dvd), nvars++); - type_size = ctf_type_sect_size (fp); /* 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_lbloff = hdr.cth_objtoff = 0; - hdr.cth_funcoff = hdr.cth_objtoff + objt_size; - hdr.cth_objtidxoff = hdr.cth_funcoff + func_size; - hdr.cth_funcidxoff = hdr.cth_objtidxoff + objtidx_size; - hdr.cth_varoff = hdr.cth_funcidxoff + funcidx_size; - hdr.cth_typeoff = hdr.cth_varoff + (nvars * sizeof (ctf_varent_t)); - hdr.cth_stroff = hdr.cth_typeoff + type_size; - hdr.cth_strlen = 0; + the buffer. (We will adjust this later with strtab length info.) + + Offsets in the BTF and CTF headers are relative to the end of te header in + question. */ + + if (fp->ctf_serialize.cs_is_btf) + { + ctf_dprintf ("Writing out as BTF\n"); + + hdr_len = sizeof (ctf_btf_header_t); + } + else + { + ctf_dprintf ("Writing out as CTF\n"); + + hdr_len = sizeof (ctf_header_t); + ctf_adjustment = sizeof (ctf_header_t) - sizeof (ctf_btf_header_t); + } + + hdr.cth_objt_off = 0; + hdr.cth_objt_len = objt_size; + hdr.cth_func_off = hdr.cth_objt_off + objt_size; + hdr.cth_func_len = func_size; + hdr.cth_objtidx_off = hdr.cth_func_off + func_size; + hdr.cth_objtidx_len = objtidx_size; + hdr.cth_funcidx_off = hdr.cth_objtidx_off + objtidx_size; + hdr.cth_funcidx_len = funcidx_size; + hdr.btf.bth_type_off = hdr.cth_funcidx_off + funcidx_size + ctf_adjustment; + hdr.btf.bth_type_len = type_size; + hdr.btf.bth_str_off = hdr.btf.bth_type_off + type_size; + hdr.btf.bth_str_len = 0; hdr.cth_parent_strlen = 0; if (fp->ctf_parent) - hdr.cth_parent_typemax = fp->ctf_parent->ctf_typemax; + hdr.cth_parent_ntypes = fp->ctf_parent->ctf_typemax; - buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen; + /* No strings yet. */ + buf_size = sizeof (ctf_btf_header_t) + hdr.btf.bth_str_off; if ((buf = malloc (buf_size)) == NULL) return (ctf_set_errno (fp, EAGAIN)); @@ -1512,53 +1520,38 @@ ctf_preserialize (ctf_dict_t *fp, int force_ctf) fp->ctf_serialize.cs_buf = buf; fp->ctf_serialize.cs_buf_size = buf_size; - memcpy (buf, &hdr, sizeof (ctf_header_t)); - t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_objtoff; + memcpy (buf, &hdr, hdr_len); + t = (unsigned char *) buf + hdr_len + hdr.cth_objt_off; hdrp = (ctf_header_t *) buf; - if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parname != NULL)) - ctf_str_add_no_dedup_ref (fp, fp->ctf_parname, &hdrp->cth_parname); - if (fp->ctf_cuname != NULL) - ctf_str_add_no_dedup_ref (fp, fp->ctf_cuname, &hdrp->cth_cuname); - - if (ctf_emit_symtypetab_sects (fp, &symstate, &t, objt_size, func_size, - objtidx_size, funcidx_size) < 0) - goto err; - assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_varoff); - - /* Work over the variable list, translating everything into ctf_varent_t's and - prepping the string table. */ - - fp->ctf_serializing_vars = (ctf_varent_t *) t; - for (i = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; - dvd = ctf_list_next (dvd), i++) + if (!fp->ctf_serialize.cs_is_btf) { - ctf_varent_t *var = &fp->ctf_serializing_vars[i]; - - ctf_str_add_ref (fp, dvd->dvd_name, &var->ctv_name); - var->ctv_type = (uint32_t) dvd->dvd_type; - - if (ctf_type_add_ref (fp, &var->ctv_type) < 0) + if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent_name != NULL)) + ctf_str_add_no_dedup_ref (fp, fp->ctf_parent_name, + &hdrp->cth_parent_name); + if (fp->ctf_cu_name != NULL) + ctf_str_add_no_dedup_ref (fp, fp->ctf_cu_name, &hdrp->cth_cu_name); + + if (ctf_emit_symtypetab_sects (fp, &symstate, &t, objt_size, func_size, + objtidx_size, funcidx_size) < 0) goto err; } - assert (i == nvars); - - t += sizeof (ctf_varent_t) * nvars; - fp->ctf_serializing_nvars = nvars; - - assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff); + assert (t == (unsigned char *) buf + sizeof (ctf_btf_header_t) + + hdr.btf.bth_type_off); /* Copy in existing static types, then emit new dynamic types. */ - memcpy (t, fp->ctf_buf + fp->ctf_header->cth_typeoff, - fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff); - t += fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff; + memcpy (t, fp->ctf_buf + fp->ctf_header->btf.bth_type_off, + fp->ctf_header->btf.bth_type_len); + t += fp->ctf_header->btf.bth_type_len; - if (ctf_emit_type_sect (fp, &t) < 0) + if (ctf_emit_type_sect (fp, &t, hdr.btf.bth_str_off + - fp->ctf_header->btf.bth_type_len) < 0) goto err; - assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff); + assert (t == (unsigned char *) buf + sizeof (ctf_btf_header_t) + + hdr.btf.bth_str_off); /* All types laid out: update all refs to types to cite the final IDs. */