1 /* compress-debug.c - compress debug sections 2 Copyright (C) 2010-2024 Free Software Foundation, Inc. 3 4 This file is part of GAS, the GNU Assembler. 5 6 GAS is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 GAS is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GAS; see the file COPYING. If not, write to the Free 18 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 19 02110-1301, USA. */ 20 21 #include "config.h" 22 #include <stdio.h> 23 #include <string.h> 24 #include <zlib.h> 25 #if HAVE_ZSTD 26 #include <zstd.h> 27 #endif 28 #include "ansidecl.h" 29 #include "compress-debug.h" 30 31 /* Initialize the compression engine. */ 32 33 void * 34 compress_init (bool use_zstd) 35 { 36 if (use_zstd) { 37 #if HAVE_ZSTD 38 return ZSTD_createCCtx (); 39 #endif 40 } 41 42 static struct z_stream_s strm; 43 memset (&strm, 0, sizeof (strm)); 44 deflateInit (&strm, Z_DEFAULT_COMPRESSION); 45 return &strm; 46 } 47 48 /* Stream the contents of a frag to the compression engine. Output 49 from the engine goes into the current frag on the obstack. */ 50 51 int 52 compress_data (bool use_zstd, void *ctx, const char **next_in, int *avail_in, 53 char **next_out, int *avail_out) 54 { 55 if (use_zstd) 56 { 57 #if HAVE_ZSTD 58 ZSTD_outBuffer ob = { *next_out, *avail_out, 0 }; 59 ZSTD_inBuffer ib = { *next_in, *avail_in, 0 }; 60 size_t ret = ZSTD_compressStream2 (ctx, &ob, &ib, ZSTD_e_continue); 61 *next_in += ib.pos; 62 *avail_in -= ib.pos; 63 *next_out += ob.pos; 64 *avail_out -= ob.pos; 65 if (ZSTD_isError (ret)) 66 return -1; 67 return (int)ob.pos; 68 #endif 69 } 70 71 struct z_stream_s *strm = ctx; 72 73 strm->next_in = (Bytef *) (*next_in); 74 strm->avail_in = *avail_in; 75 strm->next_out = (Bytef *) (*next_out); 76 strm->avail_out = *avail_out; 77 78 int x = deflate (strm, Z_NO_FLUSH); 79 if (x != Z_OK) 80 return -1; 81 82 int out_size = *avail_out - strm->avail_out; 83 *next_in = (char *) (strm->next_in); 84 *avail_in = strm->avail_in; 85 *next_out = (char *) (strm->next_out); 86 *avail_out = strm->avail_out; 87 88 return out_size; 89 } 90 91 /* Finish the compression and consume the remaining compressed output. 92 Returns -1 for error, 0 when done, 1 when more output buffer is 93 needed. */ 94 95 int 96 compress_finish (bool use_zstd, void *ctx, char **next_out, 97 int *avail_out, int *out_size) 98 { 99 if (use_zstd) 100 { 101 #if HAVE_ZSTD 102 ZSTD_outBuffer ob = { *next_out, *avail_out, 0 }; 103 ZSTD_inBuffer ib = { 0, 0, 0 }; 104 size_t ret = ZSTD_compressStream2 (ctx, &ob, &ib, ZSTD_e_end); 105 *out_size = ob.pos; 106 *next_out += ob.pos; 107 *avail_out -= ob.pos; 108 if (ZSTD_isError (ret)) 109 return -1; 110 if (ret == 0) 111 ZSTD_freeCCtx (ctx); 112 return ret ? 1 : 0; 113 #endif 114 } 115 116 int x; 117 struct z_stream_s *strm = ctx; 118 119 strm->avail_in = 0; 120 strm->next_out = (Bytef *) (*next_out); 121 strm->avail_out = *avail_out; 122 123 x = deflate (strm, Z_FINISH); 124 125 *out_size = *avail_out - strm->avail_out; 126 *next_out = (char *) (strm->next_out); 127 *avail_out = strm->avail_out; 128 129 if (x == Z_STREAM_END) 130 { 131 deflateEnd (strm); 132 return 0; 133 } 134 if (strm->avail_out != 0) 135 return -1; 136 return 1; 137 } 138