RE: [PATCH] Add support for ARCv2

2022-12-15 Thread Shahab Vahedi via Elfutils-devel
Hi Mark,

On Tue, 2022-12-13 at 15:06, Mark Wielaard via Elfutils-devel wrote:

> Let me know if I should wait for that or review the v2 patch
> ignoring the elf.h changes.

Please ignore v2 of the patch and kindly wait for v3.  I will send it
this week (50).


Cheers,
Shahab


Re: [PATCHv2] support ZSTD compression algorithm

2022-12-15 Thread Mark Wielaard
Hi Martin,

On Tue, 2022-11-29 at 13:05 +0100, Martin Liška wrote:
> There's second version of the patch that fully support both
> compression and decompression.
> 
> Changes from the v1:
> - compression support added
> - zstd detection is fixed
> - new tests are added
> - builds fine w/ and w/o the ZSTD library
> 
> What's currently missing and where I need a help:
> 
> 1) When I build ./configure --without-zstd, I don't have
> a reasonable error message (something similar to binutils's readelf:
> readelf: Warning: section '.debug_str' has unsupported compress type:
> 2)
> even though, __libelf_decompress returns NULL and __libelf_seterrno).
> One can see a garbage in the console.
> 
> How to handle that properly?

Is there a particular way you are running eu-readelf? Is it with
generic -w or -a, or decoding a specific section type?

> 2) How should I run my newly added tests conditionally if zstd
> configuration support is enabled?

eu_ZIP will define an AM_CONDITIONAL for ZSTD (note this is different
from the HAVE_ZSTD, which is the am conditional added for having the
zstd program itself). You could use it in tests/Makefile.am as:

  if ZSTD
  TESTS += run-zstd-compress-test.sh
  endif

If you had a separate test... Otherwise add some variable to
TESTS_ENVIRONMENT (and installed_TESTS_ENVIRONMENT) based on the Make
variable that is tested inside the shell script (somewhat like
USE_VALGRIND) maybe.

>   configure.ac   |   8 +-
>   libelf/Makefile.am |   2 +-
>   libelf/elf_compress.c  | 294 ++--
> -
>   libelf/elf_compress_gnu.c  |   5 +-
>   libelf/libelfP.h   |   4 +-
>   src/elfcompress.c  | 144 ++
>   src/readelf.c  |  18 ++-
>   tests/run-compress-test.sh |  24 +++
>   8 files changed, 373 insertions(+), 126 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index 59be27ac..07cfa54b 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -410,6 +410,11 @@ dnl Test for bzlib and xz/lzma/zstd, gives 
> BZLIB/LZMALIB/ZSTD .am
>   dnl conditional and config.h USE_BZLIB/USE_LZMALIB/USE_ZSTD #define.
>   save_LIBS="$LIBS"
>   LIBS=
> +eu_ZIPLIB(zstd,ZSTD,zstd,ZSTD_decompress,[ZSTD (zst)])
> +AS_IF([test "x$with_zstd" = xyes], [LIBZSTD="libzstd"], [LIBLZSTD=""])
> +AC_SUBST([LIBZSTD])
> +zstd_LIBS="$LIBS"
> +AC_SUBST([zstd_LIBS])
>   eu_ZIPLIB(bzlib,BZLIB,bz2,BZ2_bzdopen,bzip2)
>   # We need this since bzip2 doesn't have a pkgconfig file.
>   BZ2_LIB="$LIBS"
> @@ -417,9 +422,6 @@ AC_SUBST([BZ2_LIB])
>   eu_ZIPLIB(lzma,LZMA,lzma,lzma_auto_decoder,[LZMA (xz)])
>   AS_IF([test "x$with_lzma" = xyes], [LIBLZMA="liblzma"], [LIBLZMA=""])
>   AC_SUBST([LIBLZMA])
> -eu_ZIPLIB(zstd,ZSTD,zstd,ZSTD_decompress,[ZSTD (zst)])
> -AS_IF([test "x$with_zstd" = xyes], [LIBZSTD="libzstd"], [LIBLZSTD=""])
> -AC_SUBST([LIBZSTD])
>   zip_LIBS="$LIBS"
>   LIBS="$save_LIBS"
>   AC_SUBST([zip_LIBS])

Doing AC_SUBST([zstd_LIBS]) seems correct. Why is the test moved
earlier?

You are testing for ZSTD_decompress, is that enough? Asking because I
see you are using ZSTD_compressStream2, which seems to requires libzstd
v1.4.0+.

In general how stable is the libzstd api?

You'll also need to use the AC_SUBST for LIBZSTD in config/libelf.pc.in
now, as used in the libdw.pc.in:

  Requires.private: zlib @LIBZSTD@

> diff --git a/libelf/Makefile.am b/libelf/Makefile.am
> index 560ed45f..24c25cf8 100644
> --- a/libelf/Makefile.am
> +++ b/libelf/Makefile.am
> @@ -106,7 +106,7 @@ libelf_pic_a_SOURCES =
>   am_libelf_pic_a_OBJECTS = $(libelf_a_SOURCES:.c=.os)
>   
>   libelf_so_DEPS = ../lib/libeu.a
> -libelf_so_LDLIBS = $(libelf_so_DEPS) -lz
> +libelf_so_LDLIBS = $(libelf_so_DEPS) -lz $(zstd_LIBS)
>   if USE_LOCKS
>   libelf_so_LDLIBS += -lpthread
>   endif

OK.

Haven't read the actual code yet. I'll get back to that later today.

Cheers,

Mark


Re: [PATCHv2] support ZSTD compression algorithm

2022-12-15 Thread Mark Wielaard
Hi Martin,

On Tue, Nov 29, 2022 at 01:05:45PM +0100, Martin Liška wrote:
> diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c
> index d7f53af2..7a6e37a4 100644
> --- a/libelf/elf_compress.c
> +++ b/libelf/elf_compress.c
> @@ -39,6 +39,10 @@
>  #include 
>  #include 
> +#ifdef USE_ZSTD
> +#include 
> +#endif
> +
>  /* Cleanup and return result.  Don't leak memory.  */
>  static void *
>  do_deflate_cleanup (void *result, z_stream *z, void *out_buf,

OK.

> @@ -54,53 +58,14 @@ do_deflate_cleanup (void *result, z_stream *z, void 
> *out_buf,
>  #define deflate_cleanup(result, cdata) \
>  do_deflate_cleanup(result, &z, out_buf, cdata)
> -/* Given a section, uses the (in-memory) Elf_Data to extract the
> -   original data size (including the given header size) and data
> -   alignment.  Returns a buffer that has at least hsize bytes (for the
> -   caller to fill in with a header) plus zlib compressed date.  Also
> -   returns the new buffer size in new_size (hsize + compressed data
> -   size).  Returns (void *) -1 when FORCE is false and the compressed
> -   data would be bigger than the original data.  */
>  void *
>  internal_function
> -__libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
> -size_t *orig_size, size_t *orig_addralign,
> -size_t *new_size, bool force)
> +__libelf_compress_zlib (Elf_Scn *scn, size_t hsize, int ei_data,
> + size_t *orig_size, size_t *orig_addralign,
> + size_t *new_size, bool force,
> + Elf_Data *data, Elf_Data *next_data,
> + void *out_buf, size_t out_size, size_t block)
>  {
> -  /* The compressed data is the on-disk data.  We simplify the
> - implementation a bit by asking for the (converted) in-memory
> - data (which might be all there is if the user created it with
> - elf_newdata) and then convert back to raw if needed before
> - compressing.  Should be made a bit more clever to directly
> - use raw if that is directly available.  */
> -  Elf_Data *data = elf_getdata (scn, NULL);
> -  if (data == NULL)
> -return NULL;
> -
> -  /* When not forced and we immediately know we would use more data by
> - compressing, because of the header plus zlib overhead (five bytes
> - per 16 KB block, plus a one-time overhead of six bytes for the
> - entire stream), don't do anything.  */
> -  Elf_Data *next_data = elf_getdata (scn, data);
> -  if (next_data == NULL && !force
> -  && data->d_size <= hsize + 5 + 6)
> -return (void *) -1;
> -
> -  *orig_addralign = data->d_align;
> -  *orig_size = data->d_size;
> -
> -  /* Guess an output block size. 1/8th of the original Elf_Data plus
> - hsize.  Make the first chunk twice that size (25%), then increase
> - by a block (12.5%) when necessary.  */
> -  size_t block = (data->d_size / 8) + hsize;
> -  size_t out_size = 2 * block;
> -  void *out_buf = malloc (out_size);
> -  if (out_buf == NULL)
> -{
> -  __libelf_seterrno (ELF_E_NOMEM);
> -  return NULL;
> -}
> -
>/* Caller gets to fill in the header at the start.  Just skip it here.  */
>size_t used = hsize;

OK, all this is moved lower and then calls either
__libelf_compress_zlib or __libelf_compress_zstd.

> @@ -205,9 +170,186 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int 
> ei_data,
>return out_buf;
>  }
> +#ifdef USE_ZSTD
> +/* Cleanup and return result.  Don't leak memory.  */
> +static void *
> +do_zstd_cleanup (void *result, ZSTD_CCtx * const cctx, void *out_buf,
> +  Elf_Data *cdatap)
> +{
> +  ZSTD_freeCCtx (cctx);
> +  free (out_buf);
> +  if (cdatap != NULL)
> +free (cdatap->d_buf);
> +  return result;
> +}
>
> +#define zstd_cleanup(result, cdata) \
> +do_zstd_cleanup(result, cctx, out_buf, cdata)
> +

OK, mimics do_deflate_cleanup.

>  void *
>  internal_function
> -__libelf_decompress (void *buf_in, size_t size_in, size_t size_out)
> +__libelf_compress_zstd (Elf_Scn *scn, size_t hsize, int ei_data,
> + size_t *orig_size, size_t *orig_addralign,
> + size_t *new_size, bool force,
> + Elf_Data *data, Elf_Data *next_data,
> + void *out_buf, size_t out_size, size_t block)
> +{
> +  /* Caller gets to fill in the header at the start.  Just skip it here.  */
> +  size_t used = hsize;
> +
> +  ZSTD_CCtx* const cctx = ZSTD_createCCtx();
> +  Elf_Data cdata;
> +  cdata.d_buf = NULL;
> +
> +  /* Loop over data buffers.  */
> +  ZSTD_EndDirective mode = ZSTD_e_continue;
> +
> +  do
> +{
> +  /* Convert to raw if different endianness.  */
> +  cdata = *data;
> +  bool convert = ei_data != MY_ELFDATA && data->d_size > 0;
> +  if (convert)
> + {
> +   /* Don't do this conversion in place, we might want to keep
> +  the original data around, caller decides.  */
> +   cdata.d_buf = malloc (data->d_size);
> +   if (cdata.d_buf == NULL)
> +