Profiling zlib Link to heading

git clone https://github.com/madler/zlib.git
cd zlib
CFLAGS="-O3 -g" ./configure
make -j
# verify debug symbol
objdump --syms libz.a | grep debug

Create gunzip.c

// A simple command line program in C for Linux that reads a .gz file from stdin and decompresses and writes to stdout
// Make use of zlib library

#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>

#define CHUNK 16384 // Buffer size

// Decompress from source to dest until EOF on source
int decompress(FILE *source, FILE *dest) {
    int ret; // Return value
    unsigned have; // Number of bytes in output buffer
    z_stream strm; // Stream structure
    unsigned char in[CHUNK]; // Input buffer
    unsigned char out[CHUNK]; // Output buffer

    // Initialize stream structure
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;

    // Initialize inflation
    ret = inflateInit2(&strm, 15 + 32); // 15 + 32 to enable gzip decoding
    if (ret != Z_OK) {
        return ret; // Error occurred
    }

    // Inflate until end of input
    do {
        // Read from source into input buffer
        strm.avail_in = fread(in, 1, CHUNK, source);
        if (ferror(source)) {
            (void)inflateEnd(&strm); // Clean up
            return Z_ERRNO; // Error occurred
        }
        if (strm.avail_in == 0) {
            break; // End of input
        }
        strm.next_in = in;

        // Inflate into output buffer until output buffer is full or end of stream is reached
        do {
            strm.avail_out = CHUNK;
            strm.next_out = out;
            ret = inflate(&strm, Z_NO_FLUSH); // No flush
            if (ret == Z_STREAM_ERROR) {
                return ret; // Error occurred
            }
            switch (ret) {
                case Z_NEED_DICT:
                    ret = Z_DATA_ERROR; // Fall through
                case Z_DATA_ERROR:
                case Z_MEM_ERROR:
                    (void)inflateEnd(&strm); // Clean up
                    return ret; // Error occurred
            }
            have = CHUNK - strm.avail_out; // Number of bytes in output buffer

            // Write output buffer to dest
            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
                (void)inflateEnd(&strm); // Clean up
                return Z_ERRNO; // Error occurred
            }
        } while (strm.avail_out == 0);

        // Done when inflate() says it's done
    } while (ret != Z_STREAM_END);

    // Clean up and return
    (void)inflateEnd(&strm);
    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}

// Main function
int main(int argc, char **argv) {
    int ret; // Return value

    // Check arguments
    if (argc != 1) {
        fprintf(stderr, "Usage: %s < input.gz > output\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // Decompress from stdin to stdout
    ret = decompress(stdin, stdout);
    
    // Check for errors and exit accordingly
    if (ret != Z_OK) {
        fprintf(stderr, "An error occurred while decompressing: %d\n", ret);
        exit(EXIT_FAILURE);
    } else {
        fprintf(stderr, "Decompression successful\n");
        exit(EXIT_SUCCESS);
    }
}

Compile and link

gcc gunzip.c -O3 -g -o gunzip -L`pwd` -I`pwd` -l:libz.a