# Node ID 06b2d6551a01a573140e774b2f1aac11ad746635 # Parent 2375b33bddc61ea484b3bd194ba02f7889095624 diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc --- a/src/base/loader/object_file.cc +++ b/src/base/loader/object_file.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,50 @@ } } +static bool +hasGzipMagic(int fd) +{ + uint8_t buf[2] = {0}; + size_t sz = pread(fd, buf, 2, 0); + panic_if(sz != 2, "Couldn't read magic bytes from object file"); + return ((buf[0] == 0x1f) && (buf[1] == 0x8b)); +} + +static uint8_t* +doGzipLoad(int fd) +{ + const size_t blk_sz = 4096; + gzFile fdz = gzdopen(fd, "rb"); + if (!fdz) { + return nullptr; + } + auto buf = new uint8_t[blk_sz]; + FILE* tmp = tmpfile(); + size_t len = 0; // total length of uncompressed data + int r; // size of (r)emaining uncopied data in (buf)fer + while((r = gzread(fdz, buf, blk_sz)) > 0) { + len += r; + auto p = buf; // pointer into buffer + while (r > 0) { + auto sz = fwrite(p, 1, r, tmp); + assert(sz <= r); + r -= sz; + p += sz; + } + } + delete[] buf; + gzclose(fdz); // also closes underlying fd 'fd' + if (r < 0) { // error + fclose(tmp); + return nullptr; + } + assert(r == 0); // finished successfully + fflush(tmp); + uint8_t* p = (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, + fileno(tmp), 0); + fclose(tmp); + return(p); // return pointer to mmap()'d decompressed data +} ObjectFile * createObjectFile(const string &fname, bool raw) @@ -111,15 +156,23 @@ return NULL; } - // find the length of the file by seeking to the end - off_t off = lseek(fd, 0, SEEK_END); - fatal_if(off < 0, "Failed to determine size of object file %s\n", fname); - size_t len = static_cast(off); + size_t len = 0; + uint8_t *fileData = 0; - // mmap the whole shebang - uint8_t *fileData = - (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); - close(fd); + // decompress GZ files + if (hasGzipMagic(fd)) { + fileData = doGzipLoad(fd); + } else { + // find the length of the file by seeking to the end + off_t off = lseek(fd, 0, SEEK_END); + fatal_if(off < 0, + "Failed to determine size of object file %s\n", fname); + len = static_cast(off); + + // mmap the whole shebang + fileData = (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + } if (fileData == MAP_FAILED) { return NULL; }