示例#1
0
void PackTmt::pack(OutputFile *fo)
{
    big_relocs = 0;

    Packer::handleStub(fi,fo,adam_offset);

    const unsigned usize = ih.imagesize;
    const unsigned rsize = ih.relocsize;

    ibuf.alloc(usize+rsize+128);
    obuf.allocForCompression(usize+rsize+128);

    MemBuffer wrkmem;
    wrkmem.alloc(rsize+EXTRA_INFO); // relocations

    fi->seek(adam_offset+sizeof(ih),SEEK_SET);
    fi->readx(ibuf,usize);
    fi->readx(wrkmem+4,rsize);
    const unsigned overlay = file_size - fi->tell();

    if (find_le32(ibuf,128,get_le32("UPX ")) >= 0)
        throwAlreadyPacked();
    if (rsize == 0)
        throwCantPack("file is already compressed with another packer");

    checkOverlay(overlay);

    unsigned relocsize = 0;
    //if (rsize)
    {
        for (unsigned ic=4; ic<=rsize; ic+=4)
            set_le32(wrkmem+ic,get_le32(wrkmem+ic)-4);
        relocsize = ptr_diff(optimizeReloc32(wrkmem+4,rsize/4,wrkmem,ibuf,1,&big_relocs), wrkmem);
    }

    wrkmem[relocsize++] = 0;
    set_le32(wrkmem+relocsize,ih.entry); // save original entry point
    relocsize += 4;
    set_le32(wrkmem+relocsize,relocsize+4);
    relocsize += 4;
    memcpy(ibuf+usize,wrkmem,relocsize);

    // prepare packheader
    ph.u_len = usize + relocsize;
    // prepare filter
    Filter ft(ph.level);
    ft.buf_len = usize;
    // compress
    upx_compress_config_t cconf; cconf.reset();
    // limit stack size needed for runtime decompression
    cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
    compressWithFilters(&ft, 512, &cconf);

    const unsigned lsize = getLoaderSize();
    const unsigned s_point = getLoaderSection("TMTMAIN1");
    int e_len = getLoaderSectionStart("TMTCUTPO");
    const unsigned d_len = lsize - e_len;
    assert(e_len > 0  && s_point > 0);

    // patch loader
    linker->defineSymbol("original_entry", ih.entry);
    defineDecompressorSymbols();
    defineFilterSymbols(&ft);

    linker->defineSymbol("bytes_to_copy", ph.c_len + d_len);
    linker->defineSymbol("copy_dest", 0u - (ph.u_len + ph.overlap_overhead + d_len - 1));
    linker->defineSymbol("copy_source", ph.c_len + lsize - 1);
    //fprintf(stderr,"\nelen=%x dlen=%x copy_len=%x  copy_to=%x  oo=%x  jmp_pos=%x  ulen=%x  c_len=%x \n\n",
    //                e_len,d_len,copy_len,copy_to,ph.overlap_overhead,jmp_pos,ph.u_len,ph.c_len);

    linker->defineSymbol("TMTCUTPO", ph.u_len + ph.overlap_overhead);
    relocateLoader();

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

    memcpy(&oh,&ih,sizeof(oh));
    oh.imagesize = ph.c_len + lsize; // new size
    oh.entry = s_point; // new entry point
    oh.relocsize = 4;

    // write loader + compressed file
    fo->write(&oh,sizeof(oh));
    fo->write(loader,e_len);
    fo->write(obuf,ph.c_len);
    fo->write(loader+lsize-d_len,d_len); // decompressor
    char rel_entry[4];
    set_le32(rel_entry,5 + s_point);
    fo->write(rel_entry,sizeof (rel_entry));

    // verify
    verifyOverlappingDecompression();

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

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