From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2103) id 210FA3846403; Fri, 19 Apr 2024 15:52:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 210FA3846403 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1713541920; bh=/WprftBve+zCct+zRsB9MIANtxzn//RT/XmmTBV74TU=; h=From:To:Subject:Date:From; b=hn3ikoFBVGJn4e4kZaK9caJ3ovlBugO5pjr3upG3gyuIk5vcleoxl4dWNK/MFU8rH giQRCWhLJLwVYFVDZMlaFQdKyJ7//RdtEI2YBDVV52kExqA7SoYRWwIOOwmP6O81od 1Fb+FbJK3/rt3ll8iWVkDs2wz36EcwHtxAeN1kH0= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Nick Alcock To: binutils-cvs@sourceware.org Subject: [binutils-gdb] libctf: make ctf_serialize() actually serialize X-Act-Checkin: binutils-gdb X-Git-Author: Nick Alcock X-Git-Refname: refs/heads/master X-Git-Oldrev: cf9da3b0b6a6ae9d71ba36898a5e39710150f85e X-Git-Newrev: 483546ce4f36a93d3fb711f2261b15b75871f3f9 Message-Id: <20240419155200.210FA3846403@sourceware.org> Date: Fri, 19 Apr 2024 15:52:00 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D483546ce4f36= a93d3fb711f2261b15b75871f3f9 commit 483546ce4f36a93d3fb711f2261b15b75871f3f9 Author: Nick Alcock Date: Tue Mar 26 13:04:20 2024 +0000 libctf: make ctf_serialize() actually serialize =20 ctf_serialize() evolved from the old ctf_update(), which mutated the in-memory CTF dict to make all the dynamic in-memory types into static, unchanging written-to-the-dict types (by deserializing and reserializing it): back in the days when you could only do type lookups on static typ= es, this meant you could see all the types you added recently, at the small, small cost of making it impossible to change those older types ever aga= in and inducing an amortized O(n^2) cost if you actually wanted to add references to types you added at arbitrary times to later types. =20 It also reset things so that ctf_discard() would throw away only types = you added after the most recent ctf_update() call. =20 Some time ago this was all changed so that you could look up dynamic ty= pes just as easily as static types: ctf_update() changed so that only its visible side-effect of affecting ctf_discard() remained: the old ctf_update() was renamed to ctf_serialize(), made internal to libctf, a= nd called from the various functions that wrote files out. =20 ... but it was still working by serializing and deserializing the entire dict, swapping out its guts with the newly-serialized copy in an invasi= ve and horrible fashion that coupled ctf_serialize() to almost every field= in the ctf_dict_t. This is totally useless, and fixing it is easy: just r= ip all that code out and have ctf_serialize return a serialized representa= tion, and let everything use that directly. This simplifies most of its call= ers significantly. =20 (It also points up another bug: ctf_gzwrite() failed to call ctf_serial= ize() at all, so it would only ever work for a dict you just ctf_write_mem()ed yourself, just for its invisible side-effect of serializing the dict!) =20 This lets us simplify away a bunch of internal-only open-side functiona= lity for overriding the syn_ext_strtab and some just-added functionality for forcing in an existing atoms table, without loss of functionality, and = lets us lift the restriction on reserializing a dict that was ctf_open()ed r= ather than being ctf_create()d: it's now perfectly OK to open a dict, modify = it (except for adding members to existing structs, unions, or enums, which fails with -ECTF_RDONLY), and write it out again, just as one would exp= ect. =20 libctf/ =20 * ctf-serialize.c (ctf_symtypetab_sect_sizes): Fix typos. (ctf_type_sect_size): Add static type sizes too. (ctf_serialize): Return the new dict rather than updating the existing dict. No longer fail for dicts with static types; copy them onto the start of the new types table. (ctf_gzwrite): Actually serialize before gzwriting. (ctf_write_mem): Improve forced (test-mode) endian-flipping: flip dicts even if they are too small to be compressed. Improve confusing variable naming. * ctf-archive.c (arc_write_one_ctf): Don't bother to call ctf_serialize: both the functions we call do so. * ctf-string.c (ctf_str_create_atoms): Drop serializing case (atoms arg). * ctf-open.c (ctf_simple_open): Call ctf_bufopen directly. (ctf_simple_open_internal): Delete. (ctf_bufopen_internal): Delete/rename to ctf_bufopen: no longer bother with syn_ext_strtab or forced atoms table, serialization no longer needs them. * ctf-create.c (ctf_create): Call ctf_bufopen directly. * ctf-impl.h (ctf_str_create_atoms): Drop atoms arg. (ctf_simple_open_internal): Delete. (ctf_bufopen_internal): Likewise. (ctf_serialize): Adjust. * testsuite/libctf-lookup/add-to-opened.c: Adjust now that this is supposed to work. Diff: --- libctf/ctf-archive.c | 7 +- libctf/ctf-create.c | 2 +- libctf/ctf-impl.h | 19 +- libctf/ctf-open.c | 39 +-- libctf/ctf-serialize.c | 334 ++++++++-------------= ---- libctf/ctf-string.c | 73 ++---- libctf/testsuite/libctf-lookup/add-to-opened.c | 11 +- 7 files changed, 137 insertions(+), 348 deletions(-) diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c index a88c6135e1a..3f12c0da85d 100644 --- a/libctf/ctf-archive.c +++ b/libctf/ctf-archive.c @@ -253,12 +253,12 @@ ctf_arc_write (const char *file, ctf_dict_t **ctf_dic= ts, size_t ctf_dict_cnt, return err; } =20 -/* Write one CTF file out. Return the file position of the written file (= or +/* Write one CTF dict out. Return the file position of the written file (= or rather, of the file-size uint64_t that precedes it): negative return is= a negative errno or ctf_errno value. On error, the file position may no = longer be at the end of the file. */ static off_t -arc_write_one_ctf (ctf_dict_t * f, int fd, size_t threshold) +arc_write_one_ctf (ctf_dict_t *f, int fd, size_t threshold) { off_t off, end_off; uint64_t ctfsz =3D 0; @@ -266,9 +266,6 @@ arc_write_one_ctf (ctf_dict_t * f, int fd, size_t thres= hold) size_t ctfsz_len; int (*writefn) (ctf_dict_t * fp, int fd); =20 - if (ctf_serialize (f) < 0) - return f->ctf_errno * -1; - if ((off =3D lseek (fd, 0, SEEK_CUR)) < 0) return errno * -1; =20 diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index 78fb0305c20..ee79e49794d 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -133,7 +133,7 @@ ctf_create (int *errp) cts.cts_size =3D sizeof (hdr); cts.cts_entsize =3D 1; =20 - if ((fp =3D ctf_bufopen_internal (&cts, NULL, NULL, NULL, NULL, errp)) = =3D=3D NULL) + if ((fp =3D ctf_bufopen (&cts, NULL, NULL, errp)) =3D=3D NULL) goto err; =20 /* These hashes will have been initialized with a starting size of zero, diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h index 3eef232bea0..03e1a66416a 100644 --- a/libctf/ctf-impl.h +++ b/libctf/ctf-impl.h @@ -364,14 +364,7 @@ typedef struct ctf_dedup clients, who see it only as an opaque pointer. Modifications can there= fore be made freely to this structure without regard to client versioning. = The ctf_dict_t typedef appears in and declares a forward tag. - (A ctf_file_t typedef also appears there, for historical reasons.) - - NOTE: ctf_serialize requires that everything inside of ctf_dict either = be an - immediate value, a pointer to dynamically allocated data *outside* of t= he - ctf_dict itself, a pointer to statically allocated data, or specially h= andled - in ctf_serialize. If you add a pointer to ctf_dict that points to some= thing - within the ctf_dict itself, you must make corresponding changes to - ctf_serialize. */ + (A ctf_file_t typedef also appears there, for historical reasons.) */ =20 struct ctf_dict { @@ -735,7 +728,7 @@ extern const char *ctf_strraw (ctf_dict_t *, uint32_t); extern const char *ctf_strraw_explicit (ctf_dict_t *, uint32_t, ctf_strs_t *); extern const char *ctf_strptr_validate (ctf_dict_t *, uint32_t); -extern int ctf_str_create_atoms (ctf_dict_t *, ctf_dynhash_t *atoms); +extern int ctf_str_create_atoms (ctf_dict_t *); extern void ctf_str_free_atoms (ctf_dict_t *); extern uint32_t ctf_str_add (ctf_dict_t *, const char *); extern uint32_t ctf_str_add_ref (ctf_dict_t *, const char *, uint32_t *ref= ); @@ -760,15 +753,7 @@ extern void *ctf_set_open_errno (int *, int); extern void ctf_flip_header (ctf_header_t *); extern int ctf_flip (ctf_dict_t *, ctf_header_t *, unsigned char *, int); =20 -extern ctf_dict_t *ctf_simple_open_internal (const char *, size_t, const c= har *, - size_t, size_t, - const char *, size_t, - ctf_dynhash_t *, ctf_dynhash_t *, int *); -extern ctf_dict_t *ctf_bufopen_internal (const ctf_sect_t *, const ctf_sec= t_t *, - const ctf_sect_t *, ctf_dynhash_t *, - ctf_dynhash_t *, int *); extern int ctf_import_unref (ctf_dict_t *fp, ctf_dict_t *pfp); -extern int ctf_serialize (ctf_dict_t *); =20 _libctf_malloc_ extern void *ctf_mmap (size_t length, size_t offset, int fd); diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c index 6d7a276f2cd..9cbf07626cc 100644 --- a/libctf/ctf-open.c +++ b/libctf/ctf-open.c @@ -1233,9 +1233,8 @@ flip_types (ctf_dict_t *fp, void *start, size_t len, = int to_foreign) return 0; } =20 -/* Flip the endianness of BUF, given the offsets in the (already endian- - converted) CTH. If TO_FOREIGN is set, flip to foreign-endianness; if n= ot, - flip away. +/* Flip the endianness of BUF, given the offsets in the (native-endianness= ) CTH. + If TO_FOREIGN is set, flip to foreign-endianness; if not, flip away. =20 All of this stuff happens before the header is fully initialized, so the LCTF_*() macros cannot be used yet. Since we do not try to endian-conv= ert v1 @@ -1287,21 +1286,6 @@ ctf_dict_t *ctf_simple_open (const char *ctfsect, si= ze_t ctfsect_size, size_t symsect_entsize, const char *strsect, size_t strsect_size, int *errp) -{ - return ctf_simple_open_internal (ctfsect, ctfsect_size, symsect, symsect= _size, - symsect_entsize, strsect, strsect_size, NULL, - NULL, errp); -} - -/* Open a CTF file, mocking up a suitable ctf_sect and overriding the exte= rnal - strtab with a synthetic one. */ - -ctf_dict_t *ctf_simple_open_internal (const char *ctfsect, size_t ctfsect_= size, - const char *symsect, size_t symsect_size, - size_t symsect_entsize, - const char *strsect, size_t strsect_size, - ctf_dynhash_t *syn_strtab, - ctf_dynhash_t *atoms, int *errp) { ctf_sect_t skeleton; =20 @@ -1338,8 +1322,7 @@ ctf_dict_t *ctf_simple_open_internal (const char *ctf= sect, size_t ctfsect_size, strsectp =3D &str_sect; } =20 - return ctf_bufopen_internal (ctfsectp, symsectp, strsectp, syn_strtab, - atoms, errp); + return ctf_bufopen (ctfsectp, symsectp, strsectp, errp); } =20 /* Decode the specified CTF buffer and optional symbol table, and create a= new @@ -1350,16 +1333,6 @@ ctf_dict_t *ctf_simple_open_internal (const char *ct= fsect, size_t ctfsect_size, ctf_dict_t * ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, const ctf_sect_t *strsect, int *errp) -{ - return ctf_bufopen_internal (ctfsect, symsect, strsect, NULL, NULL, errp= ); -} - -/* Like ctf_bufopen, but overriding the external strtab with a synthetic o= ne. */ - -ctf_dict_t * -ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, - const ctf_sect_t *strsect, ctf_dynhash_t *syn_strtab, - ctf_dynhash_t *atoms, int *errp) { const ctf_preamble_t *pp; size_t hdrsz =3D sizeof (ctf_header_t); @@ -1370,8 +1343,7 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, cons= t ctf_sect_t *symsect, =20 libctf_init_debug(); =20 - if ((ctfsect =3D=3D NULL) || ((symsect !=3D NULL) && - ((strsect =3D=3D NULL) && syn_strtab =3D=3D NULL))) + if ((ctfsect =3D=3D NULL) || ((symsect !=3D NULL) && (strsect =3D=3D NUL= L))) return (ctf_set_open_errno (errp, EINVAL)); =20 if (symsect !=3D NULL && symsect->cts_entsize !=3D sizeof (Elf32_Sym) && @@ -1623,7 +1595,7 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, cons= t ctf_sect_t *symsect, fp->ctf_str[CTF_STRTAB_0].cts_strs =3D (const char *) fp->ctf_buf + hp->cth_stroff; fp->ctf_str[CTF_STRTAB_0].cts_len =3D hp->cth_strlen; - if (ctf_str_create_atoms (fp, atoms) < 0) + if (ctf_str_create_atoms (fp) < 0) { err =3D ENOMEM; goto bad; @@ -1669,7 +1641,6 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, cons= t ctf_sect_t *symsect, fp->ctf_str[CTF_STRTAB_1].cts_strs =3D strsect->cts_data; fp->ctf_str[CTF_STRTAB_1].cts_len =3D strsect->cts_size; } - fp->ctf_syn_ext_strtab =3D syn_strtab; =20 /* Dynamic state, for dynamic addition to this dict after loading. */ =20 diff --git a/libctf/ctf-serialize.c b/libctf/ctf-serialize.c index 82e5b7d705b..2d1f014db28 100644 --- a/libctf/ctf-serialize.c +++ b/libctf/ctf-serialize.c @@ -470,9 +470,9 @@ ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtype= tab_state_t *s, filter out reported symbols from the variable section, and filter out= all other symbols from the symtypetab sections. (If we are not linking, = the symbols are sorted; if we are linking, don't bother sorting if we are= not - filtering out reported symbols: this is almost certaily an ld -r and = only + filtering out reported symbols: this is almost certainly an ld -r and= only the linker is likely to consume these symtypetabs again. The linker - doesn't care what order the symtypetab entries is in, since it only + doesn't care what order the symtypetab entries are in, since it only iterates over symbols and does not use the ctf_lookup_by_symbol* API.= ) */ =20 s->sort_syms =3D 1; @@ -718,8 +718,8 @@ symerr: =20 /* Type section. */ =20 -/* Iterate through the dynamic type definition list and compute the - size of the CTF type section. */ +/* Iterate through the static types and the dynamic type definition list a= nd + compute the size of the CTF type section. */ =20 static size_t ctf_type_sect_size (ctf_dict_t *fp) @@ -778,7 +778,7 @@ ctf_type_sect_size (ctf_dict_t *fp) } } =20 - return type_size; + return type_size + fp->ctf_header->cth_stroff - fp->ctf_header->cth_type= off; } =20 /* Take a final lap through the dynamic type definition list and copy the @@ -933,30 +933,22 @@ ctf_sort_var (const void *one_, const void *two_, voi= d *arg_) =20 /* Overall serialization. */ =20 -/* If the specified CTF dict is writable and has been modified, reload thi= s dict - with the updated type definitions, ready for serialization. In order t= o make - this code and the rest of libctf as simple as possible, we perform upda= tes by - taking the dynamic type definitions and creating an in-memory CTF dict - containing the definitions, and then call ctf_simple_open_internal() on= it. - 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_dict_t, b= ut 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_dict_t's, and then free the old. - - We do not currently support serializing a dict that has already been - serialized in the past: but all the tables support it except for the ty= pes - table. */ +/* Emit a new CTF dict which is a serialized copy of this one: also reify + the string table and update all offsets in the current dict suitably. + (This simplifies ctf-string.c a little, at the cost of storing a second + copy of the strtab if this dict was originally read in via ctf_open.) =20 -int -ctf_serialize (ctf_dict_t *fp) + Other aspects of the existing dict are unchanged, although some + static entries may be duplicated in the dynamic state (which should + have no effect on visible operation). */ + +static unsigned char * +ctf_serialize (ctf_dict_t *fp, size_t *bufsiz) { - ctf_dict_t ofp, *nfp; ctf_header_t hdr, *hdrp; ctf_dvdef_t *dvd; ctf_varent_t *dvarents; const ctf_strs_writable_t *strtab; - int err; int sym_functions =3D 0; =20 unsigned char *t; @@ -969,13 +961,6 @@ ctf_serialize (ctf_dict_t *fp) emit_symtypetab_state_t symstate; memset (&symstate, 0, sizeof (emit_symtypetab_state_t)); =20 - /* This isn't a very nice error code, but it's close enough: it's what y= ou - get if you try to modify a type loaded out of a serialized dict, so - it makes at least a little sense that it's what you get if you try to - reserialize the dict again. */ - if (fp->ctf_stypes > 0) - return (ctf_set_errno (fp, ECTF_RDONLY)); - /* 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 @@ -993,7 +978,7 @@ ctf_serialize (ctf_dict_t *fp) =20 /* Propagate all symbols in the symtypetabs into the dynamic state, so t= hat we can put them back in the right order. Symbols already in the dyna= mic - state are left as they are. */ + state, likely due to repeated serialization, are left unchanged. */ do { ctf_next_t *it =3D NULL; @@ -1004,17 +989,17 @@ ctf_serialize (ctf_dict_t *fp) sym_functions)) !=3D CTF_ERR) if ((ctf_add_funcobjt_sym_forced (fp, sym_functions, sym_name, sym)) < 0) if (ctf_errno (fp) !=3D ECTF_DUPLICATE) - return -1; /* errno is set for us. */ + return NULL; /* errno is set for us. */ =20 if (ctf_errno (fp) !=3D ECTF_NEXT_END) - return -1; /* errno is set for us. */ + return NULL; /* errno is set for us. */ } while (sym_functions++ < 1); =20 /* Figure out how big the symtypetabs are now. */ =20 if (ctf_symtypetab_sect_sizes (fp, &symstate, &hdr, &objt_size, &func_si= ze, &objtidx_size, &funcidx_size) < 0) - return -1; /* errno is set for us. */ + return NULL; /* errno is set for us. */ =20 /* Propagate all vars into the dynamic state, so we can put them back la= ter. Variables already in the dynamic state, likely due to repeated @@ -1026,7 +1011,7 @@ ctf_serialize (ctf_dict_t *fp) =20 if (name !=3D 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. */ + return NULL; /* errno is set for us. */ } =20 for (nvars =3D 0, dvd =3D ctf_list_next (&fp->ctf_dvdefs); @@ -1050,7 +1035,10 @@ ctf_serialize (ctf_dict_t *fp) buf_size =3D sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen; =20 if ((buf =3D malloc (buf_size)) =3D=3D NULL) - return (ctf_set_errno (fp, EAGAIN)); + { + ctf_set_errno (fp, EAGAIN); + return NULL; + } =20 memcpy (buf, &hdr, sizeof (ctf_header_t)); t =3D (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_objtoff; @@ -1085,6 +1073,11 @@ ctf_serialize (ctf_dict_t *fp) =20 assert (t =3D=3D (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth= _typeoff); =20 + /* 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 +=3D fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff; ctf_emit_type_sect (fp, &t); =20 assert (t =3D=3D (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth= _stroff); @@ -1111,136 +1104,15 @@ ctf_serialize (ctf_dict_t *fp) hdrp =3D (ctf_header_t *) buf; hdrp->cth_strlen =3D strtab->cts_len; buf_size +=3D hdrp->cth_strlen; + *bufsiz =3D buf_size; =20 - /* Finally, we are ready to ctf_simple_open() the new dict. If this is - successful, we then switch nfp and fp and free the old dict. */ - - if ((nfp =3D ctf_simple_open_internal ((char *) buf, buf_size, NULL, 0, - 0, NULL, 0, fp->ctf_syn_ext_strtab, - fp->ctf_str_atoms, &err)) =3D=3D NULL) - { - free (buf); - return (ctf_set_errno (fp, err)); - } - - (void) ctf_setmodel (nfp, ctf_getmodel (fp)); - - nfp->ctf_parent =3D fp->ctf_parent; - nfp->ctf_parent_unreffed =3D fp->ctf_parent_unreffed; - nfp->ctf_refcnt =3D fp->ctf_refcnt; - if (nfp->ctf_dynbase =3D=3D NULL) - nfp->ctf_dynbase =3D buf; /* Make sure buf is freed on close. */ - nfp->ctf_dthash =3D fp->ctf_dthash; - nfp->ctf_dtdefs =3D fp->ctf_dtdefs; - nfp->ctf_dvhash =3D fp->ctf_dvhash; - nfp->ctf_dvdefs =3D fp->ctf_dvdefs; - nfp->ctf_dtoldid =3D fp->ctf_dtoldid; - nfp->ctf_add_processing =3D fp->ctf_add_processing; - nfp->ctf_snapshots =3D fp->ctf_snapshots + 1; - nfp->ctf_specific =3D fp->ctf_specific; - nfp->ctf_nfuncidx =3D fp->ctf_nfuncidx; - nfp->ctf_nobjtidx =3D fp->ctf_nobjtidx; - nfp->ctf_objthash =3D fp->ctf_objthash; - nfp->ctf_funchash =3D fp->ctf_funchash; - nfp->ctf_dynsyms =3D fp->ctf_dynsyms; - nfp->ctf_ptrtab =3D fp->ctf_ptrtab; - nfp->ctf_pptrtab =3D fp->ctf_pptrtab; - nfp->ctf_typemax =3D fp->ctf_typemax; - nfp->ctf_stypes =3D fp->ctf_stypes; - nfp->ctf_dynsymidx =3D fp->ctf_dynsymidx; - nfp->ctf_dynsymmax =3D fp->ctf_dynsymmax; - nfp->ctf_ptrtab_len =3D fp->ctf_ptrtab_len; - nfp->ctf_pptrtab_len =3D fp->ctf_pptrtab_len; - nfp->ctf_link_inputs =3D fp->ctf_link_inputs; - nfp->ctf_link_outputs =3D fp->ctf_link_outputs; - nfp->ctf_errs_warnings =3D fp->ctf_errs_warnings; - nfp->ctf_funcidx_names =3D fp->ctf_funcidx_names; - nfp->ctf_objtidx_names =3D fp->ctf_objtidx_names; - nfp->ctf_funcidx_sxlate =3D fp->ctf_funcidx_sxlate; - nfp->ctf_objtidx_sxlate =3D fp->ctf_objtidx_sxlate; - nfp->ctf_str_prov_offset =3D fp->ctf_str_prov_offset; - nfp->ctf_syn_ext_strtab =3D fp->ctf_syn_ext_strtab; - nfp->ctf_pptrtab_typemax =3D fp->ctf_pptrtab_typemax; - nfp->ctf_in_flight_dynsyms =3D fp->ctf_in_flight_dynsyms; - nfp->ctf_link_in_cu_mapping =3D fp->ctf_link_in_cu_mapping; - nfp->ctf_link_out_cu_mapping =3D fp->ctf_link_out_cu_mapping; - nfp->ctf_link_type_mapping =3D fp->ctf_link_type_mapping; - nfp->ctf_link_memb_name_changer =3D fp->ctf_link_memb_name_changer; - nfp->ctf_link_memb_name_changer_arg =3D fp->ctf_link_memb_name_changer_a= rg; - nfp->ctf_link_variable_filter =3D fp->ctf_link_variable_filter; - nfp->ctf_link_variable_filter_arg =3D fp->ctf_link_variable_filter_arg; - nfp->ctf_symsect_little_endian =3D fp->ctf_symsect_little_endian; - nfp->ctf_link_flags =3D fp->ctf_link_flags; - nfp->ctf_dedup_atoms =3D fp->ctf_dedup_atoms; - nfp->ctf_dedup_atoms_alloc =3D fp->ctf_dedup_atoms_alloc; - memcpy (&nfp->ctf_dedup, &fp->ctf_dedup, sizeof (fp->ctf_dedup)); - - nfp->ctf_snapshot_lu =3D fp->ctf_snapshots; - - memcpy (&nfp->ctf_lookups, fp->ctf_lookups, sizeof (fp->ctf_lookups)); - nfp->ctf_structs =3D fp->ctf_structs; - nfp->ctf_unions =3D fp->ctf_unions; - nfp->ctf_enums =3D fp->ctf_enums; - nfp->ctf_names =3D fp->ctf_names; - - fp->ctf_dthash =3D NULL; - ctf_str_free_atoms (nfp); - nfp->ctf_str_atoms =3D fp->ctf_str_atoms; - nfp->ctf_prov_strtab =3D fp->ctf_prov_strtab; - nfp->ctf_dynstrtab =3D fp->ctf_dynstrtab; - nfp->ctf_str_movable_refs =3D fp->ctf_str_movable_refs; - fp->ctf_str_atoms =3D NULL; - fp->ctf_prov_strtab =3D NULL; - fp->ctf_dynstrtab =3D NULL; - fp->ctf_str_movable_refs =3D NULL; - memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t)); - memset (&fp->ctf_errs_warnings, 0, sizeof (ctf_list_t)); - fp->ctf_add_processing =3D NULL; - fp->ctf_ptrtab =3D NULL; - fp->ctf_pptrtab =3D NULL; - fp->ctf_funcidx_names =3D NULL; - fp->ctf_objtidx_names =3D NULL; - fp->ctf_funcidx_sxlate =3D NULL; - fp->ctf_objtidx_sxlate =3D NULL; - fp->ctf_objthash =3D NULL; - fp->ctf_funchash =3D NULL; - fp->ctf_dynsyms =3D NULL; - fp->ctf_dynsymidx =3D NULL; - fp->ctf_link_inputs =3D NULL; - fp->ctf_link_outputs =3D NULL; - fp->ctf_syn_ext_strtab =3D NULL; - fp->ctf_link_in_cu_mapping =3D NULL; - fp->ctf_link_out_cu_mapping =3D NULL; - fp->ctf_link_type_mapping =3D NULL; - fp->ctf_dedup_atoms =3D NULL; - fp->ctf_dedup_atoms_alloc =3D NULL; - fp->ctf_parent_unreffed =3D 1; - - fp->ctf_dvhash =3D NULL; - memset (&fp->ctf_dvdefs, 0, sizeof (ctf_list_t)); - memset (fp->ctf_lookups, 0, sizeof (fp->ctf_lookups)); - memset (&fp->ctf_in_flight_dynsyms, 0, sizeof (fp->ctf_in_flight_dynsyms= )); - memset (&fp->ctf_dedup, 0, sizeof (fp->ctf_dedup)); - fp->ctf_structs =3D NULL; - fp->ctf_unions =3D NULL; - fp->ctf_enums =3D NULL; - fp->ctf_names =3D NULL; - - memcpy (&ofp, fp, sizeof (ctf_dict_t)); - memcpy (fp, nfp, sizeof (ctf_dict_t)); - memcpy (nfp, &ofp, sizeof (ctf_dict_t)); - - nfp->ctf_refcnt =3D 1; /* Force nfp to be freed. */ - ctf_dict_close (nfp); - - return 0; + return buf; =20 oom: - free (buf); - return (ctf_set_errno (fp, EAGAIN)); + ctf_set_errno (fp, EAGAIN); err: free (buf); - return -1; /* errno is set for us. */ + return NULL; /* errno is set for us. */ } =20 /* File writing. */ @@ -1255,30 +1127,27 @@ err: int ctf_gzwrite (ctf_dict_t *fp, gzFile fd) { - const unsigned char *buf; - ssize_t resid; - ssize_t len; + unsigned char *buf; + unsigned char *p; + size_t bufsiz; + size_t len, written =3D 0; =20 - resid =3D sizeof (ctf_header_t); - buf =3D (unsigned char *) fp->ctf_header; - while (resid !=3D 0) - { - if ((len =3D gzwrite (fd, buf, resid)) <=3D 0) - return (ctf_set_errno (fp, errno)); - resid -=3D len; - buf +=3D len; - } + if ((buf =3D ctf_serialize (fp, &bufsiz)) =3D=3D NULL) + return -1; /* errno is set for us. */ =20 - resid =3D fp->ctf_size; - buf =3D fp->ctf_buf; - while (resid !=3D 0) + p =3D buf; + while (written < bufsiz) { - if ((len =3D gzwrite (fd, buf, resid)) <=3D 0) - return (ctf_set_errno (fp, errno)); - resid -=3D len; - buf +=3D len; + if ((len =3D gzwrite (fd, p, bufsiz - written)) <=3D 0) + { + free (buf); + return (ctf_set_errno (fp, errno)); + } + written +=3D len; + p +=3D len; } =20 + free (buf); return 0; } =20 @@ -1288,88 +1157,95 @@ ctf_gzwrite (ctf_dict_t *fp, gzFile fd) unsigned char * ctf_write_mem (ctf_dict_t *fp, size_t *size, size_t threshold) { - unsigned char *buf; + unsigned char *rawbuf; + unsigned char *buf =3D NULL; unsigned char *bp; - ctf_header_t *hp; - unsigned char *flipped, *src; - ssize_t header_len =3D sizeof (ctf_header_t); - ssize_t compress_len; + ctf_header_t *rawhp, *hp; + unsigned char *src; + size_t rawbufsiz; + size_t alloc_len =3D 0; + int uncompressed =3D 0; int flip_endian; - int uncompressed; int rc; =20 flip_endian =3D getenv ("LIBCTF_WRITE_FOREIGN_ENDIAN") !=3D NULL; - uncompressed =3D (fp->ctf_size < threshold); =20 - if (ctf_serialize (fp) < 0) + if ((rawbuf =3D ctf_serialize (fp, &rawbufsiz)) =3D=3D NULL) return NULL; /* errno is set for us. */ =20 - compress_len =3D compressBound (fp->ctf_size); - if (fp->ctf_size < threshold) - compress_len =3D fp->ctf_size; - if ((buf =3D malloc (compress_len - + sizeof (struct ctf_header))) =3D=3D NULL) + if (!ctf_assert (fp, rawbufsiz >=3D sizeof (ctf_header_t))) + goto err; + + if (rawbufsiz >=3D threshold) + alloc_len =3D compressBound (rawbufsiz - sizeof (ctf_header_t)) + + sizeof (ctf_header_t); + + /* Trivial operation if the buffer is incompressible or too small to bot= her + compressing, and we're not doing a forced write-time flip. */ + + if (rawbufsiz < threshold || rawbufsiz < alloc_len) + { + alloc_len =3D rawbufsiz; + uncompressed =3D 1; + } + + if (!flip_endian && uncompressed) + { + *size =3D rawbufsiz; + return rawbuf; + } + + if ((buf =3D malloc (alloc_len)) =3D=3D NULL) { ctf_set_errno (fp, ENOMEM); ctf_err_warn (fp, 0, 0, _("ctf_write_mem: cannot allocate %li bytes"= ), - (unsigned long) (compress_len + sizeof (struct ctf_header))); - return NULL; + (unsigned long) (alloc_len)); + goto err; } =20 + rawhp =3D (ctf_header_t *) rawbuf; hp =3D (ctf_header_t *) buf; - memcpy (hp, fp->ctf_header, header_len); - bp =3D buf + sizeof (struct ctf_header); - *size =3D sizeof (struct ctf_header); + memcpy (hp, rawbuf, sizeof (ctf_header_t)); + bp =3D buf + sizeof (ctf_header_t); + *size =3D sizeof (ctf_header_t); =20 - if (uncompressed) - hp->cth_flags &=3D ~CTF_F_COMPRESS; - else + if (!uncompressed) hp->cth_flags |=3D CTF_F_COMPRESS; =20 - src =3D fp->ctf_buf; - flipped =3D NULL; + src =3D rawbuf + sizeof (ctf_header_t); =20 if (flip_endian) { - if ((flipped =3D malloc (fp->ctf_size)) =3D=3D NULL) - { - ctf_set_errno (fp, ENOMEM); - ctf_err_warn (fp, 0, 0, _("ctf_write_mem: cannot allocate %li bytes"), - (unsigned long) (fp->ctf_size + sizeof (struct ctf_header))); - return NULL; - } ctf_flip_header (hp); - memcpy (flipped, fp->ctf_buf, fp->ctf_size); - if (ctf_flip (fp, fp->ctf_header, flipped, 1) < 0) - { - free (buf); - free (flipped); - return NULL; /* errno is set for us. */ - } - src =3D flipped; + if (ctf_flip (fp, rawhp, src, 1) < 0) + goto err; /* errno is set for us. */ } =20 - if (uncompressed) - { - memcpy (bp, src, fp->ctf_size); - *size +=3D fp->ctf_size; - } - else + if (!uncompressed) { + size_t compress_len =3D alloc_len - sizeof (ctf_header_t); + if ((rc =3D compress (bp, (uLongf *) &compress_len, - src, fp->ctf_size)) !=3D Z_OK) + src, rawbufsiz - sizeof (ctf_header_t))) !=3D Z_OK) { ctf_set_errno (fp, ECTF_COMPRESS); ctf_err_warn (fp, 0, 0, _("zlib deflate err: %s"), zError (rc)); - free (buf); - return NULL; + goto err; } *size +=3D compress_len; } + else + { + memcpy (bp, src, rawbufsiz - sizeof (ctf_header_t)); + *size +=3D rawbufsiz - sizeof (ctf_header_t); + } =20 - free (flipped); - + free (rawbuf); return buf; +err: + free (buf); + free (rawbuf); + return NULL; } =20 /* Compress the specified CTF data stream and write it to the specified fi= le diff --git a/libctf/ctf-string.c b/libctf/ctf-string.c index 46b984bd0de..0c5bd58cdaf 100644 --- a/libctf/ctf-string.c +++ b/libctf/ctf-string.c @@ -144,15 +144,9 @@ ctf_str_free_atom (void *a) calls to ctf_str_add_external to populate external strtab entries, since these are often not quite the same as what appears in any external strtab, and the external strtab is often huge and best not aggressively - pulled in.) - - Alternatively, if passed, populate atoms from the passed-in table, but = do - not propagate their flags or refs: they are all non-freeable and - non-movable. (This is used when serializing a dict: this entire atoms - table will be thrown away shortly, so it is important that we not create - any new strings.) */ + pulled in.) */ int -ctf_str_create_atoms (ctf_dict_t *fp, ctf_dynhash_t *atoms) +ctf_str_create_atoms (ctf_dict_t *fp) { size_t i; =20 @@ -179,61 +173,26 @@ ctf_str_create_atoms (ctf_dict_t *fp, ctf_dynhash_t *= atoms) if (errno =3D=3D ENOMEM) goto oom_str_add; =20 - /* Serializing. We have existing strings in an existing atoms table with - possibly-live pointers to them which must be used unchanged. Import - them into this atoms table. */ - - if (atoms) - { - ctf_next_t *it =3D NULL; - void *k, *v; - int err; - - while ((err =3D ctf_dynhash_next (atoms, &it, &k, &v)) =3D=3D 0) - { - ctf_str_atom_t *existing =3D v; - ctf_str_atom_t *atom; - - if (existing->csa_str[0] =3D=3D 0) - continue; + /* Pull in all the strings in the strtab as new atoms. The provisional + strtab must be empty at this point, so there is no need to populate + atoms from it as well. Types in this subset are frozen and readonly, + so the refs list and movable refs list need not be populated. */ =20 - if ((atom =3D malloc (sizeof (struct ctf_str_atom))) =3D=3D NULL) - goto oom_str_add; - memcpy (atom, existing, sizeof (struct ctf_str_atom)); - memset (&atom->csa_refs, 0, sizeof(ctf_list_t)); - atom->csa_flags =3D 0; - - if (ctf_dynhash_insert (fp->ctf_str_atoms, atom->csa_str, atom) < 0) - { - free (atom); - goto oom_str_add; - } - } - } - else + for (i =3D 0; i < fp->ctf_str[CTF_STRTAB_0].cts_len; + i +=3D strlen (&fp->ctf_str[CTF_STRTAB_0].cts_strs[i]) + 1) { - /* Not serializing. Pull in all the strings in the strtab as new - atoms. The provisional strtab must be empty at this point, so - there is no need to populate atoms from it as well. Types in this - subset are frozen and readonly, so the refs list and movable refs - list need not be populated. */ - - for (i =3D 0; i < fp->ctf_str[CTF_STRTAB_0].cts_len; - i +=3D strlen (&fp->ctf_str[CTF_STRTAB_0].cts_strs[i]) + 1) - { - ctf_str_atom_t *atom; + ctf_str_atom_t *atom; =20 - if (fp->ctf_str[CTF_STRTAB_0].cts_strs[i] =3D=3D 0) - continue; + if (fp->ctf_str[CTF_STRTAB_0].cts_strs[i] =3D=3D 0) + continue; =20 - atom =3D ctf_str_add_ref_internal (fp, &fp->ctf_str[CTF_STRTAB_0].cts_s= trs[i], - 0, 0); + atom =3D ctf_str_add_ref_internal (fp, &fp->ctf_str[CTF_STRTAB_0].ct= s_strs[i], + 0, 0); =20 - if (!atom) - goto oom_str_add; + if (!atom) + goto oom_str_add; =20 - atom->csa_offset =3D i; - } + atom->csa_offset =3D i; } =20 return 0; diff --git a/libctf/testsuite/libctf-lookup/add-to-opened.c b/libctf/testsu= ite/libctf-lookup/add-to-opened.c index dc2e1f55b99..96629afe1aa 100644 --- a/libctf/testsuite/libctf-lookup/add-to-opened.c +++ b/libctf/testsuite/libctf-lookup/add-to-opened.c @@ -118,11 +118,9 @@ main (int argc, char *argv[]) if (ctf_errno (fp) !=3D ECTF_RDONLY) fprintf (stderr, "unexpected error %s attempting to set array in reado= nly portion\n", ctf_errmsg (ctf_errno (fp))); =20 - if ((ctf_written =3D ctf_write_mem (fp, &size, 4096)) !=3D NULL) - fprintf (stderr, "Writeout unexpectedly succeeded: %s\n", ctf_errmsg (= ctf_errno (fp))); - - if (ctf_errno (fp) !=3D ECTF_RDONLY) - fprintf (stderr, "unexpected error %s trying to write out previously s= erialized dict\n", ctf_errmsg (ctf_errno (fp))); + if ((ctf_written =3D ctf_write_mem (fp, &size, 4096)) =3D=3D NULL) + fprintf (stderr, "Re-writeout unexpectedly failed: %s\n", ctf_errmsg (= ctf_errno (fp))); + free (ctf_written); =20 /* Finally, make sure we can add new types, and look them up again. */ =20 @@ -138,6 +136,9 @@ main (int argc, char *argv[]) if (ctf_type_reference (fp, ptrtype) !=3D type) fprintf (stderr, "Look up of newly-added type in serialized dict yield= s ID %lx, expected %lx\n", ctf_type_reference (fp, ptrtype), type); =20 + ctf_dict_close (fp); + ctf_close (ctf); + printf ("All done.\n"); return 0;