mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 15:15:42 +00:00
libctf: fix CTF dict compression
Commit 483546ce4f ("libctf: make ctf_serialize() actually serialize")
accidentally broke dict compression. There were two bugs:
- ctf_arc_write_one_ctf was still making its own decision about
whether to compress the dict via direct ctf_size comparison, which is
unfortunate because now that it no longer calls ctf_serialize itself,
ctf_size is always zero when it does this: it should let the writing
functions decide on the threshold, which they contain code to do which is
simply not used for lack of one trivial wrapper to write to an fd and
also provide a compression threshold
- ctf_write_mem, the function underlying all writing as of the commit
above, was calling zlib's compressBound and avoiding compression if this
returned a value larger than the input. Unfortunately compressBound does
not do a trial compression and determine whether the result is
compressible: it just adds zlib header sizes to the value passed in, so
our test would *always* have concluded that the value was incompressible!
Avoid by simply always compressing if the raw size is larger than the
threshold: zlib is quite clever enough to avoid actually compressing
if the data is incompressible.
Add a testcase for this.
libctf/
* ctf-impl.h (ctf_write_thresholded): New...
* ctf-serialize.c (ctf_write_thresholded): ... defined here,
a wrapper around...
(ctf_write_mem): ... this. Don't check compressibility.
(ctf_compress_write): Reimplement as a ctf_write_thresholded
wrapper.
(ctf_write): Likewise.
* ctf-archive.c (arc_write_one_ctf): Just call
ctf_write_thresholded rather than trying to work out whether
to compress.
* testsuite/libctf-writable/ctf-compressed.*: New test.
This commit is contained in:
@@ -1180,10 +1180,10 @@ ctf_write_mem (ctf_dict_t *fp, size_t *size, size_t threshold)
|
||||
alloc_len = compressBound (rawbufsiz - sizeof (ctf_header_t))
|
||||
+ sizeof (ctf_header_t);
|
||||
|
||||
/* Trivial operation if the buffer is incompressible or too small to bother
|
||||
compressing, and we're not doing a forced write-time flip. */
|
||||
/* Trivial operation if the buffer is too small to bother compressing, and
|
||||
we're not doing a forced write-time flip. */
|
||||
|
||||
if (rawbufsiz < threshold || rawbufsiz < alloc_len)
|
||||
if (rawbufsiz < threshold)
|
||||
{
|
||||
alloc_len = rawbufsiz;
|
||||
uncompressed = 1;
|
||||
@@ -1248,10 +1248,10 @@ err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Compress the specified CTF data stream and write it to the specified file
|
||||
descriptor. */
|
||||
/* Write the compressed CTF data stream to the specified file descriptor,
|
||||
possibly compressed. Internal only (for now). */
|
||||
int
|
||||
ctf_compress_write (ctf_dict_t *fp, int fd)
|
||||
ctf_write_thresholded (ctf_dict_t *fp, int fd, size_t threshold)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned char *bp;
|
||||
@@ -1260,7 +1260,7 @@ ctf_compress_write (ctf_dict_t *fp, int fd)
|
||||
ssize_t len;
|
||||
int err = 0;
|
||||
|
||||
if ((buf = ctf_write_mem (fp, &tmp, 0)) == NULL)
|
||||
if ((buf = ctf_write_mem (fp, &tmp, threshold)) == NULL)
|
||||
return -1; /* errno is set for us. */
|
||||
|
||||
buf_len = tmp;
|
||||
@@ -1283,36 +1283,17 @@ ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Compress the specified CTF data stream and write it to the specified file
|
||||
descriptor. */
|
||||
int
|
||||
ctf_compress_write (ctf_dict_t *fp, int fd)
|
||||
{
|
||||
return ctf_write_thresholded (fp, fd, 0);
|
||||
}
|
||||
|
||||
/* Write the uncompressed CTF data stream to the specified file descriptor. */
|
||||
int
|
||||
ctf_write (ctf_dict_t *fp, int fd)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned char *bp;
|
||||
size_t tmp;
|
||||
ssize_t buf_len;
|
||||
ssize_t len;
|
||||
int err = 0;
|
||||
|
||||
if ((buf = ctf_write_mem (fp, &tmp, (size_t) -1)) == NULL)
|
||||
return -1; /* errno is set for us. */
|
||||
|
||||
buf_len = tmp;
|
||||
bp = buf;
|
||||
|
||||
while (buf_len > 0)
|
||||
{
|
||||
if ((len = write (fd, bp, buf_len)) < 0)
|
||||
{
|
||||
err = ctf_set_errno (fp, errno);
|
||||
ctf_err_warn (fp, 0, 0, _("ctf_compress_write: error writing"));
|
||||
goto ret;
|
||||
}
|
||||
buf_len -= len;
|
||||
bp += len;
|
||||
}
|
||||
|
||||
ret:
|
||||
free (buf);
|
||||
return err;
|
||||
return ctf_write_thresholded (fp, fd, (size_t) -1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user