コード例 #1
0
ファイル: filter.cpp プロジェクト: QuocHuy7a10/Arianrhod
void Filter::unfilter(upx_byte *buf_, unsigned buf_len_, bool verify_checksum)
{
    initFilter(this, buf_, buf_len_);

    const FilterImp::FilterEntry * const fe = FilterImp::getFilter(id);
    if (fe == NULL)
        throwInternalError("unfilter-1");
    if (fe->id == 0)
        return;
    if (buf_len < fe->min_buf_len)
        return;
    if (fe->max_buf_len && buf_len > fe->max_buf_len)
        return;
    if (!fe->do_unfilter)
        throwInternalError("unfilter-2");

    //printf("unfilter: %02x %p %d\n", this->id, this->buf, this->buf_len);
    int r = (*fe->do_unfilter)(this);
    //printf("unfilter: %02x %d\n", fe->id, r);
    if (r != 0)
        throwInternalError("unfilter-3");
    //OutputFile::dump("unfilter.dat", buf, buf_len);

    // verify checksum
    if (verify_checksum && clevel != 1)
    {
        if (this->adler != upx_adler32(this->buf, this->buf_len))
            throwInternalError("unfilter-4");
    }
}
コード例 #2
0
ファイル: filter.cpp プロジェクト: QuocHuy7a10/Arianrhod
bool Filter::scan(const upx_byte *buf_, unsigned buf_len_)
{
    // Note: must use const_cast here. This is fine as the scan
    //   implementations (fe->do_scan) actually don't change the buffer.
    upx_byte *b = const_cast<upx_byte *>(buf_);
    initFilter(this, b, buf_len_);

    const FilterImp::FilterEntry * const fe = FilterImp::getFilter(id);
    if (fe == NULL)
        throwInternalError("scan-1");
    if (fe->id == 0)
        return true;
    if (buf_len < fe->min_buf_len)
        return false;
    if (fe->max_buf_len && buf_len > fe->max_buf_len)
        return false;
    if (!fe->do_scan)
        throwInternalError("scan-2");

    //printf("filter: %02x %p %d\n", this->id, this->buf, this->buf_len);
    int r = (*fe->do_scan)(this);
    //printf("filter: %02x %d\n", fe->id, r);
    if (r > 0)
        throwFilterException();
    if (r == 0)
        return true;
    return false;
}
コード例 #3
0
void setupSkypeFrameWork(JNIEnv *env)
{
	currentEnv = env;

	if (XInitThreads() == 0) {
		throwInternalError(env, "Xlib don't support multi-threads.");
		return;
	}

	_display = XOpenDisplay(NULL);
	if (_display == NULL) {
		throwInternalError(env, "Opening the diplay failed.");
		return;
	}
	
	_screen = DefaultScreen(_display);
	_desktop = XRootWindow(_display, _screen);
	_dummyWindow = XCreateSimpleWindow(_display, _desktop, 0, 0, 1, 1, 0, BlackPixel(_display, _screen), BlackPixel(_display, _screen));
	
	_skypeInstanceAtom = XInternAtom(_display, "_SKYPE_INSTANCE", False);
	_skypeControlApiMessageBeginAtom = XInternAtom(_display, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
	_skypeControlApiMessageAtom = XInternAtom(_display, "SKYPECONTROLAPI_MESSAGE", False);
	_stopEventLoopAtom = XInternAtom(_display, "_STOP_EVENT_LOOP", False);
	_windowNameAtom = XInternAtom(_display, "WM_NAME", True);
	
	_dispatching = True;
}
コード例 #4
0
ファイル: filter.cpp プロジェクト: QuocHuy7a10/Arianrhod
bool Filter::filter(upx_byte *buf_, unsigned buf_len_)
{
    initFilter(this, buf_, buf_len_);

    const FilterImp::FilterEntry * const fe = FilterImp::getFilter(id);
    if (fe == NULL)
        throwInternalError("filter-1");
    if (fe->id == 0)
        return true;
    if (buf_len < fe->min_buf_len)
        return false;
    if (fe->max_buf_len && buf_len > fe->max_buf_len)
        return false;
    if (!fe->do_filter)
        throwInternalError("filter-2");

    // save checksum
    this->adler = 0;
    if (clevel != 1)
        this->adler = upx_adler32(this->buf, this->buf_len);

    //printf("filter: %02x %p %d\n", this->id, this->buf, this->buf_len);
    //OutputFile::dump("filter.dat", buf, buf_len);
    int r = (*fe->do_filter)(this);
    //printf("filter: %02x %d\n", fe->id, r);
    if (r > 0)
        throwFilterException();
    if (r == 0)
        return true;
    return false;
}
コード例 #5
0
ファイル: packhead.cpp プロジェクト: QuocHuy7a10/Arianrhod
int PackHeader::getPackHeaderSize() const
{
    if (format < 0 || version < 0)
        throwInternalError("getPackHeaderSize");

    int n = 0;
    if (version <= 3)
        n = 24;
    else if (version <= 9)
    {
        if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
            n = 20;
        else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH)
            n = 25;
        else
            n = 28;
    }
    else
    {
        if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
            n = 22;
        else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH)
            n = 27;
        else
            n = 32;
    }
    if (n < 20)
        throwCantUnpack("unknown header version");
    return n;
}
コード例 #6
0
ファイル: compress_ucl.cpp プロジェクト: allanw1/Arianrhod
int upx_ucl_compress       ( const upx_bytep src, unsigned  src_len,
                                   upx_bytep dst, unsigned* dst_len,
                                   upx_callback_p cb_parm,
                                   int method, int level,
                             const upx_compress_config_t *cconf_parm,
                                   upx_compress_result_t *cresult )
{
    int r;
    assert(level > 0); assert(cresult != NULL);

    COMPILE_TIME_ASSERT(sizeof(ucl_compress_config_t) == sizeof(REAL_ucl_compress_config_t))

    ucl_progress_callback_t cb;
    cb.callback = 0;
    cb.user = NULL;
    if (cb_parm && cb_parm->nprogress) {
        cb.callback = wrap_nprogress_ucl;
        cb.user = cb_parm;
    }

    ucl_compress_config_t cconf; cconf.reset();
    if (cconf_parm)
        memcpy(&cconf, &cconf_parm->conf_ucl, sizeof(cconf)); // cconf = cconf_parm->conf_ucl; // struct copy

    ucl_uint *res = cresult->result_ucl.result;
    // assume no info available - fill in worst case results
    //res[0] = 1;                 // min_offset_found - NOT USED
    res[1] = src_len - 1;       // max_offset_found
    //res[2] = 2;                 // min_match_found - NOT USED
    res[3] = src_len - 1;       // max_match_found
    //res[4] = 1;                 // min_run_found - NOT USED
    res[5] = src_len;           // max_run_found
    res[6] = 1;                 // first_offset_found
    //res[7] = 999999;            // same_match_offsets_found - NOT USED

    // prepare bit-buffer settings
    cconf.bb_endian = 0;
    cconf.bb_size = 0;
    if (method >= M_NRV2B_LE32 && method <= M_NRV2E_LE16)
    {
        static const unsigned char sizes[3] = {32, 8, 16};
        cconf.bb_size = sizes[(method - M_NRV2B_LE32) % 3];
    }
    else {
        throwInternalError("unknown compression method");
        return UPX_E_ERROR;
    }

    // optimize compression parms
    if (level <= 3 && cconf.max_offset == UCL_UINT_MAX)
        cconf.max_offset = 8*1024-1;
    else if (level == 4 && cconf.max_offset == UCL_UINT_MAX)
        cconf.max_offset = 32*1024-1;

    if M_IS_NRV2B(method)
        r = ucl_nrv2b_99_compress(src, src_len, dst, dst_len,
                                  &cb, level, &cconf, res);
    else if M_IS_NRV2D(method)
コード例 #7
0
ファイル: eval-avmplus.cpp プロジェクト: AdiKo/avmplus
 const wchar* AvmplusHostContext::readFileForEval(const wchar* basename, const wchar* filename, uint32_t* inputlen)
 {
     // FIXME: the mismatch between what eval needs and what the core API delivers is just stunning.
     if (nextstring == sizeof(strings)/sizeof(strings[0]))
         throwInternalError("includes too deeply nested");
     StUTF16String str(core->readFileForEval(core->newStringUTF16(basename), core->newStringUTF16(filename)));   // return value is already NUL-terminated
     wchar *s = new wchar[str.length()];
     VMPI_memcpy(s, str.c_str(), str.length()*sizeof(wchar));
     *inputlen = str.length();
     strings[nextstring++] = s;
     return s;
 }
コード例 #8
0
ファイル: compress.cpp プロジェクト: BpLife/upx
int upx_test_overlap       ( const upx_bytep buf,
                             const upx_bytep tbuf,
                                   unsigned  src_off, unsigned src_len,
                                   unsigned* dst_len,
                                   int method,
                             const upx_compress_result_t *cresult )
{
    int r = UPX_E_ERROR;

    if (cresult && cresult->method == 0)
        cresult = NULL;

    assert(*dst_len > 0);
    assert(src_len < *dst_len); // must be compressed
    unsigned overlap_overhead = src_off + src_len - *dst_len;
    assert((int)overlap_overhead > 0);

    if (0) {
    }
#if (WITH_LZMA)
    else if (M_IS_LZMA(method))
        r = upx_lzma_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult);
#endif
#if (WITH_NRV)
    else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
        r = upx_nrv_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult);
#endif
#if (WITH_UCL)
    else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
        r = upx_ucl_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult);
#endif
    else {
        throwInternalError("unknown decompression method");
    }

    return r;
}
コード例 #9
0
ファイル: compress.cpp プロジェクト: BpLife/upx
int upx_decompress         ( const upx_bytep src, unsigned  src_len,
                                   upx_bytep dst, unsigned* dst_len,
                                   int method,
                             const upx_compress_result_t *cresult )
{
    int r = UPX_E_ERROR;

    assert(*dst_len > 0);
    assert(src_len < *dst_len); // must be compressed

    if (cresult && cresult->method == 0)
        cresult = NULL;

    if (0) {
    }
#if (WITH_LZMA)
    else if (M_IS_LZMA(method))
        r = upx_lzma_decompress(src, src_len, dst, dst_len, method, cresult);
#endif
#if (WITH_NRV)
    else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
        r = upx_nrv_decompress(src, src_len, dst, dst_len, method, cresult);
#endif
#if (WITH_UCL)
    else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
        r = upx_ucl_decompress(src, src_len, dst, dst_len, method, cresult);
#endif
#if (WITH_ZLIB)
    else if (M_IS_DEFLATE(method))
        r = upx_zlib_decompress(src, src_len, dst, dst_len, method, cresult);
#endif
    else {
        throwInternalError("unknown decompression method");
    }

    return r;
}
コード例 #10
0
ファイル: packhead.cpp プロジェクト: QuocHuy7a10/Arianrhod
void PackHeader::putPackHeader(upx_bytep p)
{
    assert(get_le32(p) == UPX_MAGIC_LE32);
    if (get_le32(p+4) != UPX_MAGIC2_LE32)
    {
        //fprintf(stderr, "MAGIC2_LE32: %x %x\n", get_le32(p+4), UPX_MAGIC2_LE32);
        throwBadLoader();
    }

    int size = 0;
    int old_chksum = 0;

    // the new variable length header
    if (format < 128)
    {
        if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
        {
            size = 22;
            old_chksum = get_packheader_checksum(p, size - 1);
            set_le16(p+16,u_len);
            set_le16(p+18,c_len);
            p[20] = (unsigned char) filter;
        }
        else if (format == UPX_F_DOS_EXE)
        {
            size = 27;
            old_chksum = get_packheader_checksum(p, size - 1);
            set_le24(p+16,u_len);
            set_le24(p+19,c_len);
            set_le24(p+22,u_file_size);
            p[25] = (unsigned char) filter;
        }
        else if (format == UPX_F_DOS_EXEH)
        {
            throwInternalError("invalid format");
        }
        else
        {
            size = 32;
            old_chksum = get_packheader_checksum(p, size - 1);
            set_le32(p+16,u_len);
            set_le32(p+20,c_len);
            set_le32(p+24,u_file_size);
            p[28] = (unsigned char) filter;
            p[29] = (unsigned char) filter_cto;
            assert(n_mru == 0 || (n_mru >= 2 && n_mru <= 256));
            p[30] = (unsigned char) (n_mru ? n_mru - 1 : 0);
        }
        set_le32(p+8,u_adler);
        set_le32(p+12,c_adler);
    }
    else
    {
        size = 32;
        old_chksum = get_packheader_checksum(p, size - 1);
        set_be32(p+8,u_len);
        set_be32(p+12,c_len);
        set_be32(p+16,u_adler);
        set_be32(p+20,c_adler);
        set_be32(p+24,u_file_size);
        p[28] = (unsigned char) filter;
        p[29] = (unsigned char) filter_cto;
        assert(n_mru == 0 || (n_mru >= 2 && n_mru <= 256));
        p[30] = (unsigned char) (n_mru ? n_mru - 1 : 0);
    }

    p[4] = (unsigned char) version;
    p[5] = (unsigned char) format;
    p[6] = (unsigned char) method;
    p[7] = (unsigned char) level;

    // header_checksum
    assert(size == getPackHeaderSize());
    // check old header_checksum
    if (p[size - 1] != 0)
    {
        if (p[size - 1] != old_chksum)
        {
            //printf("old_checksum: %d %d\n", p[size - 1], old_chksum);
            throwBadLoader();
        }
    }
    // store new header_checksum
    p[size - 1] = get_packheader_checksum(p, size - 1);
}
コード例 #11
0
ファイル: work.cpp プロジェクト: tfauck/upx
void do_one_file(const char *iname, char *oname)
{
    int r;
    struct stat st;
    memset(&st, 0, sizeof(st));
#if (HAVE_LSTAT)
    r = lstat(iname, &st);
#else
    r = stat(iname, &st);
#endif
    if (r != 0)
    {
        if (errno == ENOENT)
            throw FileNotFoundException(iname, errno);
        else
            throwIOException(iname, errno);
    }
    if (!(S_ISREG(st.st_mode)))
        throwIOException("not a regular file -- skipped");
#if defined(__unix__)
    // no special bits may be set
    if ((st.st_mode & (S_ISUID | S_ISGID | S_ISVTX)) != 0)
        throwIOException("file has special permissions -- skipped");
#endif
    if (st.st_size <= 0)
        throwIOException("empty file -- skipped");
    if (st.st_size < 512)
        throwIOException("file is too small -- skipped");
    if (!mem_size_valid_bytes(st.st_size))
        throwIOException("file is too large -- skipped");
    if ((st.st_mode & S_IWUSR) == 0)
    {
        bool skip = true;
        if (opt->output_name)
            skip = false;
        else if (opt->to_stdout)
            skip = false;
        else if (opt->backup)
            skip = false;
        if (skip)
            throwIOException("file is write protected -- skipped");
    }

    InputFile fi;
    fi.st = st;
    fi.sopen(iname, O_RDONLY | O_BINARY, SH_DENYWR);

#if (USE_FTIME)
    struct ftime fi_ftime;
    memset(&fi_ftime, 0, sizeof(fi_ftime));
    if (opt->preserve_timestamp)
    {
        if (getftime(fi.getFd(), &fi_ftime) != 0)
            throwIOException("cannot determine file timestamp");
    }
#endif

    // open output file
    OutputFile fo;
    if (opt->cmd == CMD_COMPRESS || opt->cmd == CMD_DECOMPRESS)
    {
        if (opt->to_stdout)
        {
            if (!fo.openStdout(1, opt->force ? true : false))
                throwIOException("data not written to a terminal; Use '-f' to force.");
        }
        else
        {
            char tname[ACC_FN_PATH_MAX+1];
            if (opt->output_name)
                strcpy(tname,opt->output_name);
            else
            {
                if (!maketempname(tname, sizeof(tname), iname, ".upx"))
                    throwIOException("could not create a temporary file name");
            }
            if (opt->force >= 2)
            {
#if (HAVE_CHMOD)
                r = chmod(tname, 0777);
                IGNORE_ERROR(r);
#endif
                r = unlink(tname);
                IGNORE_ERROR(r);
            }
            int flags = O_CREAT | O_WRONLY | O_BINARY;
            if (opt->force)
                flags |= O_TRUNC;
            else
                flags |= O_EXCL;
            int shmode = SH_DENYWR;
#if defined(__MINT__)
            flags |= O_TRUNC;
            shmode = O_DENYRW;
#endif
            // cannot rely on open() because of umask
            //int omode = st.st_mode | 0600;
            int omode = 0600;
            if (!opt->preserve_mode)
                omode = 0666;
            fo.sopen(tname,flags,shmode,omode);
            // open succeeded - now set oname[]
            strcpy(oname,tname);
        }
    }

    // handle command
    PackMaster pm(&fi, opt);
    if (opt->cmd == CMD_COMPRESS)
        pm.pack(&fo);
    else if (opt->cmd == CMD_DECOMPRESS)
        pm.unpack(&fo);
    else if (opt->cmd == CMD_TEST)
        pm.test();
    else if (opt->cmd == CMD_LIST)
        pm.list();
    else if (opt->cmd == CMD_FILEINFO)
        pm.fileInfo();
    else
        throwInternalError("invalid command");

    // copy time stamp
    if (opt->preserve_timestamp && oname[0] && fo.isOpen())
    {
#if (USE_FTIME)
        r = setftime(fo.getFd(), &fi_ftime);
        IGNORE_ERROR(r);
#elif (USE__FUTIME)
        struct _utimbuf u;
        u.actime = st.st_atime;
        u.modtime = st.st_mtime;
        r = _futime(fo.getFd(), &u);
        IGNORE_ERROR(r);
#endif
    }

    // close files
    fo.closex();
    fi.closex();

    // rename or delete files
    if (oname[0] && !opt->output_name)
    {
        // FIXME: .exe or .cof etc.
        if (!opt->backup)
        {
#if (HAVE_CHMOD)
            r = chmod(iname, 0777);
            IGNORE_ERROR(r);
#endif
            File::unlink(iname);
        }
        else
        {
            // make backup
            char bakname[ACC_FN_PATH_MAX+1];
            if (!makebakname(bakname, sizeof(bakname), iname))
                throwIOException("could not create a backup file name");
            File::rename(iname,bakname);
        }
        File::rename(oname,iname);
    }

    // copy file attributes
    if (oname[0])
    {
        oname[0] = 0;
        const char *name = opt->output_name ? opt->output_name : iname;
        UNUSED(name);
#if (USE_UTIME)
        // copy time stamp
        if (opt->preserve_timestamp)
        {
            struct utimbuf u;
            u.actime = st.st_atime;
            u.modtime = st.st_mtime;
            r = utime(name, &u);
            IGNORE_ERROR(r);
        }
#endif
#if (HAVE_CHMOD)
        // copy permissions
        if (opt->preserve_mode)
        {
            r = chmod(name, st.st_mode);
            IGNORE_ERROR(r);
        }
#endif
#if (HAVE_CHOWN)
        // copy the ownership
        if (opt->preserve_ownership)
        {
            r = chown(name, st.st_uid, st.st_gid);
            IGNORE_ERROR(r);
        }
#endif
    }

    UiPacker::uiConfirmUpdate();
}
コード例 #12
0
ファイル: except.cpp プロジェクト: QuocHuy7a10/Arianrhod
void throwBadLoader()
{
    throwInternalError("bad loader");
}
コード例 #13
0
ファイル: p_unix.cpp プロジェクト: tfauck/upx
void PackUnix::packExtent(
    const Extent &x,
    unsigned &total_in,
    unsigned &total_out,
    Filter *ft,
    OutputFile *fo,
    unsigned hdr_u_len
)
{
    unsigned const init_u_adler = ph.u_adler;
    unsigned const init_c_adler = ph.c_adler;
    MemBuffer hdr_ibuf;
    if (hdr_u_len) {
        hdr_ibuf.alloc(hdr_u_len);
        fi->seek(0, SEEK_SET);
        int l = fi->readx(hdr_ibuf, hdr_u_len);
        (void)l;
    }
    fi->seek(x.offset, SEEK_SET);
    for (off_t rest = x.size; 0 != rest; ) {
        int const filter_strategy = ft ? getStrategy(*ft) : 0;
        int l = fi->readx(ibuf, UPX_MIN(rest, (off_t)blocksize));
        if (l == 0) {
            break;
        }
        rest -= l;

        // Note: compression for a block can fail if the
        //       file is e.g. blocksize + 1 bytes long

        // compress
        ph.c_len = ph.u_len = l;
        ph.overlap_overhead = 0;
        unsigned end_u_adler = 0;
        if (ft) {
            // compressWithFilters() updates u_adler _inside_ compress();
            // that is, AFTER filtering.  We want BEFORE filtering,
            // so that decompression checks the end-to-end checksum.
            end_u_adler = upx_adler32(ibuf, ph.u_len, ph.u_adler);
            ft->buf_len = l;

                // compressWithFilters() requirements?
            ph.filter = 0;
            ph.filter_cto = 0;
            ft->id = 0;
            ft->cto = 0;

            compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy,
                                0, 0, 0, hdr_ibuf, hdr_u_len);
        }
        else {
            (void) compress(ibuf, ph.u_len, obuf);    // ignore return value
        }

        if (ph.c_len < ph.u_len) {
            const upx_bytep tbuf = NULL;
            if (ft == NULL || ft->id == 0) tbuf = ibuf;
            ph.overlap_overhead = OVERHEAD;
            if (!testOverlappingDecompression(obuf, tbuf, ph.overlap_overhead)) {
                // not in-place compressible
                ph.c_len = ph.u_len;
            }
        }
        if (ph.c_len >= ph.u_len) {
            // block is not compressible
            ph.c_len = ph.u_len;
            memcpy(obuf, ibuf, ph.c_len);
            // must update checksum of compressed data
            ph.c_adler = upx_adler32(ibuf, ph.u_len, ph.saved_c_adler);
        }

        // write block sizes
        b_info tmp;
        if (hdr_u_len) {
            unsigned hdr_c_len = 0;
            MemBuffer hdr_obuf;
            hdr_obuf.allocForCompression(hdr_u_len);
            int r = upx_compress(hdr_ibuf, hdr_u_len, hdr_obuf, &hdr_c_len, 0,
                ph.method, 10, NULL, NULL);
            if (r != UPX_E_OK)
                throwInternalError("header compression failed");
            if (hdr_c_len >= hdr_u_len)
                throwInternalError("header compression size increase");
            ph.saved_u_adler = upx_adler32(hdr_ibuf, hdr_u_len, init_u_adler);
            ph.saved_c_adler = upx_adler32(hdr_obuf, hdr_c_len, init_c_adler);
            ph.u_adler = upx_adler32(ibuf, ph.u_len, ph.saved_u_adler);
            ph.c_adler = upx_adler32(obuf, ph.c_len, ph.saved_c_adler);
            end_u_adler = ph.u_adler;
            memset(&tmp, 0, sizeof(tmp));
            set_te32(&tmp.sz_unc, hdr_u_len);
            set_te32(&tmp.sz_cpr, hdr_c_len);
            tmp.b_method = (unsigned char) ph.method;
            fo->write(&tmp, sizeof(tmp));
            b_len += sizeof(b_info);
            fo->write(hdr_obuf, hdr_c_len);
            total_out += hdr_c_len;
            total_in  += hdr_u_len;
            hdr_u_len = 0;  // compress hdr one time only
        }
        memset(&tmp, 0, sizeof(tmp));
        set_te32(&tmp.sz_unc, ph.u_len);
        set_te32(&tmp.sz_cpr, ph.c_len);
        if (ph.c_len < ph.u_len) {
            tmp.b_method = (unsigned char) ph.method;
            if (ft) {
                tmp.b_ftid = (unsigned char) ft->id;
                tmp.b_cto8 = ft->cto;
            }
        }
        fo->write(&tmp, sizeof(tmp));
        b_len += sizeof(b_info);

        if (ft) {
            ph.u_adler = end_u_adler;
        }
        // write compressed data
        if (ph.c_len < ph.u_len) {
            fo->write(obuf, ph.c_len);
            // Checks ph.u_adler after decompression, after unfiltering
            verifyOverlappingDecompression(ft);
        }
        else {
            fo->write(ibuf, ph.u_len);
        }

        total_in += ph.u_len;
        total_out += ph.c_len;
    }
}
コード例 #14
0
static jfieldID
getFieldReference (JNIEnv * env, jobject field, const char *type)
{
  jclass classClass;
  jclass fieldClass;
  jclass declaringClass;
  jclass typeClass;
  jfieldID fid;
  const char *field_name;
  const char *type_name;
  int type_len;
  jmethodID mid;
  jstring name;
  jstring tname;
  int i;

  fieldClass = (*env)->GetObjectClass (env, field);

  mid =
    (*env)->GetMethodID (env, fieldClass, "getName", "()Ljava/lang/String;");
  if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL)
    {
      throwInternalError (env);
      return NULL;
    }

  name = (*env)->CallObjectMethod (env, field, mid);
  field_name = (*env)->GetStringUTFChars (env, name, NULL);

  mid = (*env)->GetMethodID (env, fieldClass,
			     "getDeclaringClass", "()Ljava/lang/Class;");
  if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL)
    {
      throwInternalError (env);
      return NULL;
    }

  declaringClass = (*env)->CallObjectMethod (env, field, mid);

  /* Do we need to find out the exact type descriptor of the field? */
  if (type == NULL)
    {
      char *the_type;

      mid = (*env)->GetMethodID (env, fieldClass,
				 "getType", "()Ljava/lang/Class;");

      if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL)
	{
	  throwInternalError (env);
	  return NULL;
	}

      typeClass = (*env)->CallObjectMethod (env, field, mid);
      classClass = (*env)->FindClass (env, "java/lang/Class");

      mid = (*env)->GetMethodID (env, classClass,
				 "getName", "()Ljava/lang/String;");

      if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL)
	{
	  throwInternalError (env);
	  return NULL;
	}

      tname = (*env)->CallObjectMethod (env, typeClass, mid);
      type_name = (*env)->GetStringUTFChars (env, tname, NULL);

      /*
       * If it isn't an array class then the actual field type descriptor
       * starts with 'L', ends with ';' and has '/' instead of '.'.
       */
      type_len = strlen (type_name);
      if (type_name[0] != '[')
	{
	  /* XXX - FIXME - should not use dynamic allocation in core lib. */
	  the_type = (char *) malloc (type_len + 3);
	  the_type[0] = 'L';
	  the_type[type_len + 1] = ';';
	  the_type[type_len + 2] = '\0';
	  the_type++;
	}
      else
	{
	  /* XXX - FIXME - should not use dynamic allocation in core lib. */
	  the_type = (char *) malloc (type_len + 1);
	  the_type[type_len] = '\0';
	}

      for (i = 0; i < type_len; i++)
	if (type_name[i] == '.')
	  the_type[i] = '/';
	else
	  the_type[i] = type_name[i];

      if (type_name[0] != '[')
	the_type--;

      (*env)->ReleaseStringUTFChars (env, tname, type_name);
      fid = (*env)->GetFieldID (env, declaringClass, field_name, the_type);
      free (the_type);
    }
  else
    {
      type_len = -1;
      fid = (*env)->GetFieldID (env, declaringClass, field_name, type);
    }

  if (fid == NULL)
    {
      throwInternalError (env);
      return NULL;
    }
  (*env)->ReleaseStringUTFChars (env, name, field_name);

  return fid;
}
コード例 #15
0
ファイル: compress.cpp プロジェクト: BpLife/upx
int upx_compress           ( const upx_bytep src, unsigned  src_len,
                                   upx_bytep dst, unsigned* dst_len,
                                   upx_callback_p cb,
                                   int method, int level,
                             const upx_compress_config_t *cconf,
                                   upx_compress_result_t *cresult )
{
    int r = UPX_E_ERROR;
    upx_compress_result_t cresult_buffer;

    assert(method > 0); assert(level > 0);

#if 1
    // set available bytes in dst
    if (*dst_len == 0)
        *dst_len = MemBuffer::getSizeForCompression(src_len);
#else
    // force users to provide *dst_len
    assert(*dst_len != 0);
#endif
    // for UPX, we always require a reasonably sized outbut buffer
    assert(*dst_len >= MemBuffer::getSizeForCompression(src_len));

    if (!cresult)
        cresult = &cresult_buffer;
    memset(cresult, 0, sizeof(*cresult));
#if 1
    // debug
    cresult->method = method;
    cresult->level = level;
    cresult->u_len = src_len;
    cresult->c_len = 0;
#endif

    if (0) {
    }
#if (WITH_LZMA)
    else if (M_IS_LZMA(method))
        r = upx_lzma_compress(src, src_len, dst, dst_len,
                              cb, method, level, cconf, cresult);
#endif
#if (WITH_NRV)
    else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
        r = upx_nrv_compress(src, src_len, dst, dst_len,
                             cb, method, level, cconf, cresult);
#endif
#if (WITH_UCL)
    else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
        r = upx_ucl_compress(src, src_len, dst, dst_len,
                             cb, method, level, cconf, cresult);
#endif
    else {
        throwInternalError("unknown compression method");
    }

#if 1
    // debug
    cresult->c_len = *dst_len;
#endif
    return r;
}
コード例 #16
0
ファイル: p_armpe.cpp プロジェクト: BiteFoo/UPX-Visual-Studio
void PackArmPe::pack(OutputFile *fo)
{
    // FIXME: we need to think about better support for --exact
    if (opt->exact)
        throwCantPackExact();

    const unsigned objs = ih.objects;
    isection = new pe_section_t[objs];
    fi->seek(pe_offset+sizeof(ih),SEEK_SET);
    fi->readx(isection,sizeof(pe_section_t)*objs);

    rvamin = isection[0].vaddr;

    infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs);

    // check the PE header
    // FIXME: add more checks
    if (!opt->force && (
           (ih.cpu != 0x1c0 && ih.cpu != 0x1c2)
        || (ih.opthdrsize != 0xe0)
        || ((ih.flags & EXECUTABLE) == 0)
        || (ih.subsystem != 9)
        || (ih.entry == 0 /*&& !isdll*/)
        || (ih.ddirsentries != 16)
//        || IDSIZE(PEDIR_EXCEPTION) // is this used on arm?
//        || IDSIZE(PEDIR_COPYRIGHT)
       ))
        throwCantPack("unexpected value in PE header (try --force)");

    if (IDSIZE(PEDIR_SEC))
        IDSIZE(PEDIR_SEC) = IDADDR(PEDIR_SEC) = 0;
    //    throwCantPack("compressing certificate info is not supported");

    if (IDSIZE(PEDIR_COMRT))
        throwCantPack(".NET files (win32/net) are not yet supported");

    if (isdll)
        opt->win32_pe.strip_relocs = false;
    else if (opt->win32_pe.strip_relocs < 0)
        opt->win32_pe.strip_relocs = (ih.imagebase >= 0x10000);
    if (opt->win32_pe.strip_relocs)
    {
        if (ih.imagebase < 0x10000)
            throwCantPack("--strip-relocs is not allowed when imagebase < 0x10000");
        else
            ih.flags |= RELOCS_STRIPPED;
    }

    if (memcmp(isection[0].name,"UPX",3) == 0)
        throwAlreadyPackedByUPX();
    if (!opt->force && IDSIZE(15))
        throwCantPack("file is possibly packed/protected (try --force)");
    if (ih.entry && ih.entry < rvamin)
        throwCantPack("run a virus scanner on this file!");
    if (!opt->force && ih.subsystem == 1)
        throwCantPack("subsystem 'native' is not supported (try --force)");
    if (ih.filealign < 0x200)
        throwCantPack("filealign < 0x200 is not yet supported");

    handleStub(fi,fo,pe_offset);
    const unsigned usize = ih.imagesize;
    const unsigned xtrasize = UPX_MAX(ih.datasize, 65536u) + IDSIZE(PEDIR_IMPORT) + IDSIZE(PEDIR_BOUNDIM) + IDSIZE(PEDIR_IAT) + IDSIZE(PEDIR_DELAYIMP) + IDSIZE(PEDIR_RELOC);
    ibuf.alloc(usize + xtrasize);

    // BOUND IMPORT support. FIXME: is this ok?
    fi->seek(0,SEEK_SET);
    fi->readx(ibuf,isection[0].rawdataptr);

    Interval holes(ibuf);

    unsigned ic,jc,overlaystart = 0;
    ibuf.clear(0, usize);
    for (ic = jc = 0; ic < objs; ic++)
    {
        if (isection[ic].rawdataptr && overlaystart < isection[ic].rawdataptr + isection[ic].size)
            overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size,ih.filealign);
        if (isection[ic].vsize == 0)
            isection[ic].vsize = isection[ic].size;
        if ((isection[ic].flags & PEFL_BSS) || isection[ic].rawdataptr == 0
            || (isection[ic].flags & PEFL_INFO))
        {
            holes.add(isection[ic].vaddr,isection[ic].vsize);
            continue;
        }
        if (isection[ic].vaddr + isection[ic].size > usize)
            throwCantPack("section size problem");
        if (((isection[ic].flags & (PEFL_WRITE|PEFL_SHARED))
            == (PEFL_WRITE|PEFL_SHARED)))
            if (!opt->force)
                throwCantPack("writable shared sections not supported (try --force)");
        if (jc && isection[ic].rawdataptr - jc > ih.filealign)
            throwCantPack("superfluous data between sections");
        fi->seek(isection[ic].rawdataptr,SEEK_SET);
        jc = isection[ic].size;
        if (jc > isection[ic].vsize)
            jc = isection[ic].vsize;
        if (isection[ic].vsize == 0) // hack for some tricky programs - may this break other progs?
            jc = isection[ic].vsize = isection[ic].size;
        if (isection[ic].vaddr + jc > ibuf.getSize())
            throwInternalError("buffer too small 1");
        fi->readx(ibuf + isection[ic].vaddr,jc);
        jc += isection[ic].rawdataptr;
    }

    // check for NeoLite
    if (find(ibuf + ih.entry, 64+7, "NeoLite", 7) >= 0)
        throwCantPack("file is already compressed with another packer");

    unsigned overlay = file_size - stripDebug(overlaystart);
    if (overlay >= (unsigned) file_size)
    {
#if 0
        if (overlay < file_size + ih.filealign)
            overlay = 0;
        else if (!opt->force)
            throwNotCompressible("overlay problem (try --force)");
#endif
        overlay = 0;
    }
    checkOverlay(overlay);

    Resource res;
    Interval tlsiv(ibuf);
    Export xport((char*)(unsigned char*)ibuf);

    const unsigned dllstrings = processImports();
    processTls(&tlsiv); // call before processRelocs!!
    processResources(&res);
    processExports(&xport);
    processRelocs();

    //OutputFile::dump("x1", ibuf, usize);

    // some checks for broken linkers - disable filter if necessary
    bool allow_filter = true;
    if (ih.codebase == ih.database
        || ih.codebase + ih.codesize > ih.imagesize
        || (isection[virta2objnum(ih.codebase,isection,objs)].flags & PEFL_CODE) == 0)
        allow_filter = false;

    const unsigned oam1 = ih.objectalign - 1;

    // FIXME: disabled: the uncompressor would not allocate enough memory
    //objs = tryremove(IDADDR(PEDIR_RELOC),objs);

    // FIXME: if the last object has a bss then this won't work
    // newvsize = (isection[objs-1].vaddr + isection[objs-1].size + oam1) &~ oam1;
    // temporary solution:
    unsigned newvsize = (isection[objs-1].vaddr + isection[objs-1].vsize + oam1) &~ oam1;

    //fprintf(stderr,"newvsize=%x objs=%d\n",newvsize,objs);
    if (newvsize + soimport + sorelocs > ibuf.getSize())
         throwInternalError("buffer too small 2");
    memcpy(ibuf+newvsize,oimport,soimport);
    memcpy(ibuf+newvsize+soimport,orelocs,sorelocs);

    cimports = newvsize - rvamin;   // rva of preprocessed imports
    crelocs = cimports + soimport;  // rva of preprocessed fixups

    ph.u_len = newvsize + soimport + sorelocs;

    // some extra data for uncompression support
    unsigned s = 0;
    upx_byte * const p1 = ibuf + ph.u_len;
    memcpy(p1 + s,&ih,sizeof (ih));
    s += sizeof (ih);
    memcpy(p1 + s,isection,ih.objects * sizeof(*isection));
    s += ih.objects * sizeof(*isection);
    if (soimport)
    {
        set_le32(p1 + s,cimports);
        set_le32(p1 + s + 4,dllstrings);
        s += 8;
    }
    if (sorelocs)
    {
        set_le32(p1 + s,crelocs);
        p1[s + 4] = (unsigned char) (big_relocs & 6);
        s += 5;
    }
    if (soresources)
    {
        set_le16(p1 + s,icondir_count);
        s += 2;
    }
    // end of extra data
    set_le32(p1 + s,ptr_diff(p1,ibuf) - rvamin);
    s += 4;
    ph.u_len += s;
    obuf.allocForCompression(ph.u_len);

    // prepare packheader
    ph.u_len -= rvamin;
    // prepare filter
    Filter ft(ph.level);
    ft.buf_len = ih.codesize;
    ft.addvalue = ih.codebase - rvamin;
    // compress
    int filter_strategy = allow_filter ? 0 : -3;

    // disable filters for files with broken headers
    if (ih.codebase + ih.codesize > ph.u_len)
    {
        ft.buf_len = 1;
        filter_strategy = -3;
    }

    // limit stack size needed for runtime decompression
    upx_compress_config_t cconf; cconf.reset();
    cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
    compressWithFilters(&ft, 2048, &cconf, filter_strategy,
                        ih.codebase, rvamin, 0, NULL, 0);
// info: see buildLoader()
    newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1;
    /*
    if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4)
    tlsindex = 0;
    */

    const unsigned lsize = getLoaderSize();

    int identsize = 0;
    const unsigned codesize = getLoaderSection("IDENTSTR",&identsize);
    assert(identsize > 0);
    getLoaderSection("UPX1HEAD",(int*)&ic);
    identsize += ic;

    pe_section_t osection[4];
    // section 0 : bss
    //         1 : [ident + header] + packed_data + unpacker + tls
    //         2 : not compressed data
    //         3 : resource data -- wince 5 needs a new section for this

    // identsplit - number of ident + (upx header) bytes to put into the PE header
    int identsplit = pe_offset + sizeof(osection) + sizeof(oh);
    if ((identsplit & 0x1ff) == 0)
        identsplit = 0;
    else if (((identsplit + identsize) ^ identsplit) < 0x200)
        identsplit = identsize;
    else
        identsplit = ALIGN_GAP(identsplit, 0x200);
    ic = identsize - identsplit;

    const unsigned c_len = ((ph.c_len + ic) & 15) == 0 ? ph.c_len : ph.c_len + 16 - ((ph.c_len + ic) & 15);
    obuf.clear(ph.c_len, c_len - ph.c_len);

    const unsigned s1size = ALIGN_UP(ic + c_len + codesize,4u) + sotls;
    const unsigned s1addr = (newvsize - (ic + c_len) + oam1) &~ oam1;

    const unsigned ncsection = (s1addr + s1size + oam1) &~ oam1;
    const unsigned upxsection = s1addr + ic + c_len;

    Reloc rel(1024); // new relocations are put here
    static const char* symbols_to_relocate[] = {
        "ONAM", "BIMP", "BREL", "FIBE", "FIBS", "ENTR", "DST0", "SRC0"
    };
    for (unsigned s2r = 0; s2r < TABLESIZE(symbols_to_relocate); s2r++)
    {
        unsigned off = linker->getSymbolOffset(symbols_to_relocate[s2r]);
        if (off != 0xdeaddead)
            rel.add(off + upxsection, 3);
    }

    // new PE header
    memcpy(&oh,&ih,sizeof(oh));
    oh.filealign = 0x200; // identsplit depends on this
    memset(osection,0,sizeof(osection));

    oh.entry = upxsection;
    oh.objects = 4;
    oh.chksum = 0;

    // fill the data directory
    ODADDR(PEDIR_DEBUG) = 0;
    ODSIZE(PEDIR_DEBUG) = 0;
    ODADDR(PEDIR_IAT) = 0;
    ODSIZE(PEDIR_IAT) = 0;
    ODADDR(PEDIR_BOUNDIM) = 0;
    ODSIZE(PEDIR_BOUNDIM) = 0;


    // tls is put into section 1
    ic = s1addr + s1size - sotls;
    super::processTls(&rel,&tlsiv,ic);
    ODADDR(PEDIR_TLS) = sotls ? ic : 0;
    ODSIZE(PEDIR_TLS) = sotls ? 0x18 : 0;
    ic += sotls;

    // these are put into section 2

    ic = ncsection;

    // wince wants relocation data at the beginning of a section
    processRelocs(&rel);
    ODADDR(PEDIR_RELOC) = soxrelocs ? ic : 0;
    ODSIZE(PEDIR_RELOC) = soxrelocs;
    ic += soxrelocs;

    processImports(ic, linker->getSymbolOffset("IATT") + upxsection);
    ODADDR(PEDIR_IMPORT) = ic;
    ODSIZE(PEDIR_IMPORT) = soimpdlls;
    ic += soimpdlls;

    processExports(&xport,ic);
    ODADDR(PEDIR_EXPORT) = soexport ? ic : 0;
    ODSIZE(PEDIR_EXPORT) = soexport;
    if (!isdll && opt->win32_pe.compress_exports)
    {
        ODADDR(PEDIR_EXPORT) = IDADDR(PEDIR_EXPORT);
        ODSIZE(PEDIR_EXPORT) = IDSIZE(PEDIR_EXPORT);
    }
    ic += soexport;

    ic = (ic + oam1) &~ oam1;
    const unsigned res_start = ic;
    if (soresources)
        processResources(&res,ic);
    ODADDR(PEDIR_RESOURCE) = soresources ? ic : 0;
    ODSIZE(PEDIR_RESOURCE) = soresources;
    ic += soresources;

    const unsigned onam = ncsection + soxrelocs + ih.imagebase;
    linker->defineSymbol("start_of_dll_names", onam);
    linker->defineSymbol("start_of_imports", ih.imagebase + rvamin + cimports);
    linker->defineSymbol("start_of_relocs", crelocs + rvamin + ih.imagebase);
    linker->defineSymbol("filter_buffer_end", ih.imagebase + ih.codebase + ih.codesize);
    linker->defineSymbol("filter_buffer_start", ih.imagebase + ih.codebase);
    linker->defineSymbol("original_entry", ih.entry + ih.imagebase);
    linker->defineSymbol("uncompressed_length", ph.u_len);
    linker->defineSymbol("start_of_uncompressed", ih.imagebase + rvamin);
    linker->defineSymbol("compressed_length", ph.c_len);
    linker->defineSymbol("start_of_compressed", ih.imagebase + s1addr + identsize - identsplit);
    defineDecompressorSymbols();
    relocateLoader();

    MemBuffer loader(lsize);
    memcpy(loader, getLoader(), lsize);
    patchPackHeader(loader, lsize);

    // this is computed here, because soxrelocs changes some lines above
    const unsigned ncsize = soxrelocs + soimpdlls + soexport;
    const unsigned fam1 = oh.filealign - 1;

    // fill the sections
    strcpy(osection[0].name,"UPX0");
    strcpy(osection[1].name,"UPX1");
    strcpy(osection[2].name, "UPX2");
    strcpy(osection[3].name, ".rsrc");

    osection[0].vaddr = rvamin;
    osection[1].vaddr = s1addr;
    osection[2].vaddr = ncsection;
    osection[3].vaddr = res_start;

    osection[0].size = 0;
    osection[1].size = (s1size + fam1) &~ fam1;
    osection[2].size = (ncsize + fam1) &~ fam1;
    osection[3].size = (soresources + fam1) &~ fam1;

    osection[0].vsize = osection[1].vaddr - osection[0].vaddr;
    //osection[1].vsize = (osection[1].size + oam1) &~ oam1;
    //osection[2].vsize = (osection[2].size + oam1) &~ oam1;
    osection[1].vsize = osection[1].size;
    osection[2].vsize = osection[2].size;
    osection[3].vsize = osection[3].size;

    osection[0].rawdataptr = 0;
    osection[1].rawdataptr = (pe_offset + sizeof(oh) + sizeof(osection) + fam1) &~ fam1;
    osection[2].rawdataptr = osection[1].rawdataptr + osection[1].size;
    osection[3].rawdataptr = osection[2].rawdataptr + osection[2].size;

    osection[0].flags = (unsigned) (PEFL_BSS|PEFL_EXEC|PEFL_WRITE|PEFL_READ);
    osection[1].flags = (unsigned) (PEFL_DATA|PEFL_EXEC|PEFL_WRITE|PEFL_READ);
    osection[2].flags = (unsigned) (PEFL_DATA|PEFL_READ);
    osection[3].flags = (unsigned) (PEFL_DATA|PEFL_READ);

    oh.imagesize = (osection[3].vaddr + osection[3].vsize + oam1) &~ oam1;
    oh.bsssize  = osection[0].vsize;
    oh.datasize = osection[2].vsize + osection[3].vsize;
    oh.database = osection[2].vaddr;
    oh.codesize = osection[1].vsize;
    oh.codebase = osection[1].vaddr;
    oh.headersize = osection[1].rawdataptr;
    if (rvamin < osection[0].rawdataptr)
        throwCantPack("object alignment too small");

    if (opt->win32_pe.strip_relocs && !isdll)
        oh.flags |= RELOCS_STRIPPED;

    //for (ic = 0; ic < oh.filealign; ic += 4)
    //    set_le32(ibuf + ic,get_le32("UPX "));
    ibuf.clear(0, oh.filealign);

    info("Image size change: %u -> %u KiB",
         ih.imagesize / 1024, oh.imagesize / 1024);

    infoHeader("[Writing compressed file]");

    if (soresources == 0)
    {
        oh.objects = 3;
        memset(&osection[3], 0, sizeof(osection[3]));
    }
    // write loader + compressed file
    fo->write(&oh,sizeof(oh));
    fo->write(osection,sizeof(osection));
    // some alignment
    if (identsplit == identsize)
    {
        unsigned n = osection[1].rawdataptr - fo->getBytesWritten() - identsize;
        assert(n <= oh.filealign);
        fo->write(ibuf, n);
    }
    fo->write(loader + codesize,identsize);
    infoWriting("loader", fo->getBytesWritten());
    fo->write(obuf,c_len);
    infoWriting("compressed data", c_len);
    fo->write(loader,codesize);
    if (opt->debug.dump_stub_loader)
        OutputFile::dump(opt->debug.dump_stub_loader, loader, codesize);
    if ((ic = fo->getBytesWritten() & 3) != 0)
        fo->write(ibuf,4 - ic);
    fo->write(otls,sotls);
    if ((ic = fo->getBytesWritten() & fam1) != 0)
        fo->write(ibuf,oh.filealign - ic);
    fo->write(oxrelocs,soxrelocs);
    fo->write(oimpdlls,soimpdlls);
    fo->write(oexport,soexport);

    if ((ic = fo->getBytesWritten() & fam1) != 0)
        fo->write(ibuf,oh.filealign - ic);

    fo->write(oresources,soresources);
    if ((ic = fo->getBytesWritten() & fam1) != 0)
        fo->write(ibuf,oh.filealign - ic);

#if 0
    printf("%-13s: program hdr  : %8ld bytes\n", getName(), (long) sizeof(oh));
    printf("%-13s: sections     : %8ld bytes\n", getName(), (long) sizeof(osection));
    printf("%-13s: ident        : %8ld bytes\n", getName(), (long) identsize);
    printf("%-13s: compressed   : %8ld bytes\n", getName(), (long) c_len);
    printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) codesize);
    printf("%-13s: tls          : %8ld bytes\n", getName(), (long) sotls);
    printf("%-13s: resources    : %8ld bytes\n", getName(), (long) soresources);
    printf("%-13s: imports      : %8ld bytes\n", getName(), (long) soimpdlls);
    printf("%-13s: exports      : %8ld bytes\n", getName(), (long) soexport);
    printf("%-13s: relocs       : %8ld bytes\n", getName(), (long) soxrelocs);
#endif

    // verify
    verifyOverlappingDecompression();

    // copy the overlay
    copyOverlay(fo, overlay, &obuf);

    // finally check the compression ratio
    if (!checkFinalCompressionRatio(fo))
        throwNotCompressible();
}