Exemplo n.º 1
0
Arquivo: p_sys.cpp Projeto: BpLife/upx
void PackSys::patchLoader(OutputFile *fo,
                          upx_byte *loader, int lsize,
                          unsigned calls)
{
    const int e_len = getLoaderSectionStart("SYSCUTPO");
    const int d_len = lsize - e_len;
    assert(e_len > 0 && e_len < 128);
    assert(d_len > 0 && d_len < 256);

    if (ph.u_len + d_len + ph.overlap_overhead > 0xfffe)
        throwNotCompressible();

    // use some fields of the original file
    linker->defineSymbol("attribute", get_le16(ibuf + 4));
    linker->defineSymbol("interrupt", get_le16(ibuf + 8));

    unsigned copy_to = ph.u_len + d_len + ph.overlap_overhead;

    linker->defineSymbol("calltrick_calls", calls);
    linker->defineSymbol("copy_source", ph.c_len + lsize - 1);
    linker->defineSymbol("copy_destination", copy_to);
    linker->defineSymbol("neg_e_len", 0 - e_len);
    linker->defineSymbol("NRV2B160", ph.u_len + ph.overlap_overhead + 1);
    linker->defineSymbol("original_strategy", get_le16(ibuf + 6));

    relocateLoader();
    loader = getLoader();

    patchPackHeader(loader,e_len);
    // write loader + compressed file
    fo->write(loader,e_len);            // entry
    fo->write(obuf,ph.c_len);
    fo->write(loader+e_len,d_len);      // decompressor
}
Exemplo n.º 2
0
void PackCom::patchLoader(OutputFile *fo,
                          upx_byte *loader, int lsize,
                          unsigned calls)
{
    const int e_len = getLoaderSectionStart("COMCUTPO");
    const int d_len = lsize - e_len;
    assert(e_len > 0 && e_len < 128);
    assert(d_len > 0 && d_len < 256);

    const unsigned upper_end = ph.u_len + ph.overlap_overhead + d_len + 0x100;
    unsigned stacksize = 0x60;
    if (upper_end + stacksize > 0xfffe)
        stacksize = 0x56;
    if (upper_end + stacksize > 0xfffe)
        throwCantPack("file is too big for dos/com");

    linker->defineSymbol("calltrick_calls", calls);
    linker->defineSymbol("sp_limit", upper_end + stacksize);
    linker->defineSymbol("bytes_to_copy", ph.c_len + lsize);
    linker->defineSymbol("copy_source", ph.c_len + lsize + 0x100);
    linker->defineSymbol("copy_destination", upper_end);
    linker->defineSymbol("neg_e_len", 0 - e_len);
    linker->defineSymbol("NRV2B160", ph.u_len + ph.overlap_overhead);

    relocateLoader();
    loader = getLoader();

    // some day we could use the relocation stuff for patchPackHeader too
    patchPackHeader(loader,e_len);
    // write loader + compressed file
    fo->write(loader,e_len);            // entry
    fo->write(obuf,ph.c_len);
    fo->write(loader+e_len,d_len);      // decompressor
#if 0
    printf("%-13s: entry        : %8ld bytes\n", getName(), (long) e_len);
    printf("%-13s: compressed   : %8ld bytes\n", getName(), (long) ph.c_len);
    printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) d_len);
#endif
}
Exemplo n.º 3
0
void PackTos::pack(OutputFile *fo)
{
    unsigned t;
    unsigned nrelocs = 0;
    unsigned relocsize = 0;
    unsigned overlay = 0;

    const unsigned i_text = ih.fh_text;
    const unsigned i_data = ih.fh_data;
    const unsigned i_sym = ih.fh_sym;
    const unsigned i_bss = ih.fh_bss;

    symbols.reset();
    symbols.need_reloc = false;
    // prepare symbols for buildLoader() - worst case
    symbols.loop1.init(65536 + 1);
    symbols.loop2.init((160 - 1) / 4);
    symbols.loop3.init(65536 + 1);
    symbols.up21_d4 = 65536 + 1;
    symbols.up21_a6 = 65536 + 1;
    symbols.up31_base_d4 = 65536 + 1;
    symbols.up31_base_a6 = 65536 + 1;

    // read file
    const unsigned isize = file_size - i_sym;
    ibuf.alloc(isize);
    fi->seek(FH_SIZE, SEEK_SET);
    // read text + data
    t = i_text + i_data;
    fi->readx(ibuf,t);
    // skip symbols
    if (i_sym && opt->exact)
        throwCantPackExact();
    fi->seek(i_sym,SEEK_CUR);
    // read relocations + overlay
    overlay = file_size - (FH_SIZE + i_text + i_data + i_sym);
    fi->readx(ibuf+t,overlay);

#if 0 || (TESTING)
    printf("text: %d, data: %d, sym: %d, bss: %d, flags=0x%x\n",
           i_text, i_data, i_sym, i_bss, (int)ih.fh_flag);
    printf("xx1 reloc: %d, overlay: %d, fixup: %d\n", relocsize, overlay, overlay >= 4 ? (int)get_be32(ibuf+t) : -1);
#endif

    // Check relocs (see load_and_reloc() in freemint/sys/memory.c).
    // Must work around TOS bugs and lots of broken programs.
    if (overlay < 4)
    {
        // Bug workaround: Whatever this is, silently keep it in
        // the (unused) relocations for byte-identical unpacking.
        relocsize = overlay;
        overlay = 0;
    }
    else if (get_be32(ibuf+t) == 0)
    {
        // Bug workaround - check the empty fixup before testing fh_reloc.
        relocsize = 4;
        overlay -= 4;
    }
    else if (ih.fh_reloc != 0)
        relocsize = 0;
    else {
        int r = check_relocs(ibuf+t, overlay, t, &nrelocs, &relocsize, &overlay);
        if (r != 0)
            throwCantPack("bad relocation table");
        symbols.need_reloc = true;
    }

#if 0 || (TESTING)
    printf("xx2: %d relocs: %d, overlay: %d, t: %d\n", nrelocs, relocsize, overlay, t);
#endif

    checkOverlay(overlay);

    // Append original fileheader.
    t += relocsize;
    ih.fh_sym = 0;                      // we stripped all symbols
    memcpy(ibuf+t, &ih, FH_SIZE);
    t += FH_SIZE;
#if 0 || (TESTING)
    printf("xx3 reloc: %d, overlay: %d, t: %d\n", relocsize, overlay, t);
#endif
    assert(t <= isize);

    // Now the data in ibuf[0..t] looks like this:
    //   text + data + relocs + original file header
    // After compression this will become the first part of the
    // data segement. The second part will be the decompressor.

    // alloc buffer (4096 is for decompressor and the various alignments)
    obuf.allocForCompression(t, 4096);

    // prepare packheader
    ph.u_len = t;
    // prepare filter
    Filter ft(ph.level);
    // compress (max_match = 65535)
    upx_compress_config_t cconf; cconf.reset();
    cconf.conf_ucl.max_match = 65535;
    cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
    compressWithFilters(&ft, 512, &cconf);

    //
    // multipass buildLoader()
    //

    // save initial loader
    const unsigned initial_lsize = getLoaderSize();
    unsigned last_lsize = initial_lsize;
    MemBuffer last_loader(last_lsize);
    memcpy(last_loader, getLoader(), last_lsize);

    unsigned o_text, o_data, o_bss;
    unsigned e_len, d_len, d_off;
    for (;;)
    {
        // The decompressed data will now get placed at this offset:
        unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;

        // get loader
        const unsigned lsize = getLoaderSize();
        e_len = getLoaderSectionStart("CUTPOINT");
        d_len = lsize - e_len;
        assert((e_len & 3) == 0 && (d_len & 1) == 0);

        // compute section sizes
        o_text = e_len;
        o_data = ph.c_len;
        o_bss = i_bss;

        // word align len of compressed data
        while (o_data & 1)
        {
            obuf[o_data++] = 0;
            offset++;
        }

        // append decompressor (part 2 of loader)
        d_off = o_data;
        ////memcpy(obuf + d_off, getLoader() + e_len, d_len); // must be done after relocation
        o_data += d_len;

        // dword align the len of the final data segment
        while (o_data & 3)
        {
            obuf[o_data++] = 0;
            offset++;
        }
        // dword align offset
        while (offset & 3)
            offset++;

        // new bss
        if (i_text + i_data + i_bss > o_text + o_data + o_bss)
            o_bss = (i_text + i_data + i_bss) - (o_text + o_data);

        // dirty bss
        unsigned dirty_bss = (o_data + offset) - (i_text + i_data);
        //printf("real dirty_bss: %d\n", dirty_bss);
        // dword align (or 16 - for speedup when clearing the dirty bss)
        const unsigned dirty_bss_align = opt->small ? 4 : 16;
        while (dirty_bss & (dirty_bss_align - 1))
            dirty_bss++;
        // adjust bss, assert room for some stack
        unsigned stack = 512 + getDecompressorWrkmemSize();
        if (dirty_bss + stack > o_bss)
            o_bss = dirty_bss + stack;

        // dword align the len of the final bss segment
        while (o_bss & 3)
            o_bss++;

        // update symbols for buildLoader()
        if (opt->small)
        {
            symbols.loop1.init(o_data / 4);
            symbols.loop2.init(0);
        }
        else
        {
            symbols.loop1.init(o_data / 160);
            symbols.loop2.init((o_data % 160) / 4);
        }
        symbols.loop3.init(dirty_bss / dirty_bss_align);

        symbols.up21_d4 = o_data + offset;
        symbols.up31_base_d4 = d_off + offset;
        symbols.up21_a6 = symbols.up21_d4 - (i_text + i_data);
        symbols.up31_base_a6 = symbols.up31_base_d4 - (i_text + i_data);
        assert((int)symbols.up21_a6 > 0);
        assert((int)symbols.up31_base_a6 > 0);

        const unsigned c = linker->getSymbolOffset("code_on_stack");
        unsigned d;
        d = linker->getSymbolOffset("flush_cache_rts") - c;
        symbols.flush_cache_rts_offset = d;
        d = linker->getSymbolOffset("clear_dirty_stack_loop") - c;
        symbols.clear_dirty_stack_len = (d + 3) / 4 + 32 - 1;
        d = linker->getSymbolOffset("code_on_stack_end") - c;
        symbols.copy_to_stack_len = d / 2 - 1;

        // now re-build loader
        buildLoader(&ft);
        unsigned new_lsize = getLoaderSize();
        //printf("buildLoader %d %d\n", new_lsize, initial_lsize);
        assert(new_lsize <= initial_lsize);
        if (new_lsize == last_lsize && memcmp(getLoader(), last_loader, last_lsize) == 0)
            break;
        last_lsize = new_lsize;
        memcpy(last_loader, getLoader(), last_lsize);
    }

    //
    // define symbols and reloc
    //

    defineDecompressorSymbols();

    linker->defineSymbol("loop1_count", symbols.loop1.value);
    linker->defineSymbol("loop2_count", symbols.loop2.value);
    linker->defineSymbol("loop3_count", symbols.loop3.value);

    linker->defineSymbol("orig_p_tlen", i_text);
    linker->defineSymbol("orig_p_dlen", i_data);
    linker->defineSymbol("orig_p_blen", i_bss);

    if (symbols.up21_a6 <= 32767)
        linker->defineSymbol("up21_a6", symbols.up21_a6);
    else
        linker->defineSymbol("up21_d4", symbols.up21_d4);

    if (symbols.up31_a6 <= 32767)
        linker->defineSymbol("up31_a6", symbols.up31_a6);
    else if (symbols.up31_d4 <= 32767)
        linker->defineSymbol("up31_d4", symbols.up31_d4);
    else if (symbols.up31_a6 <= 65534)
        linker->defineSymbol("up31_a6", symbols.up31_a6 - 32767);
    else
        linker->defineSymbol("up31_d4", symbols.up31_d4);
#if 0
    printf("relocsize = %d\n", relocsize);
    printf("upx21(d4) = %d\n", symbols.up21_d4);
    printf("upx21(a6) = %d\n", symbols.up21_a6);
    printf("upx31(d4) = %d\n", symbols.up31_d4);
    printf("upx31(a6) = %d\n", symbols.up31_a6);
#endif

    linker->defineSymbol("flush_cache_rts_offset", symbols.flush_cache_rts_offset);
    linker->defineSymbol("copy_to_stack_len", symbols.copy_to_stack_len);
    linker->defineSymbol("clear_dirty_stack_len", symbols.clear_dirty_stack_len);

    relocateLoader();

    //
    // write
    //

    // set new file_hdr
    memcpy(&oh, &ih, FH_SIZE);
    if (opt->atari_tos.split_segments)
    {
        oh.fh_text = o_text;
        oh.fh_data = o_data;
    }
    else
    {
        // put everything into the text segment
        oh.fh_text = o_text + o_data;
        oh.fh_data = 0;
    }
    oh.fh_bss = o_bss;
    oh.fh_sym = 0;
    oh.fh_reserved = 0;
    // only keep the following flags:
    oh.fh_flag = ih.fh_flag & (F_FASTLOAD | F_ALTALLOC | F_SMALLTPA | F_ALLOCZERO | F_KEEP);
    // add an empty relocation fixup to workaround a bug in some TOS versions
    oh.fh_reloc = 0;

#if 0 || (TESTING)
    printf("old text: %6d, data: %6d, bss: %6d, reloc: %d, overlay: %d\n",
           i_text, i_data, i_bss, relocsize, overlay);
    printf("new text: %6d, data: %6d, bss: %6d, flag=0x%x\n",
           o_text, o_data, o_bss, (int)oh.fh_flag);
    linker->dumpSymbols();
#endif

    // prepare loader
    MemBuffer loader(o_text);
    memcpy(loader, getLoader(), o_text);
    patchPackHeader(loader, o_text);

    // write new file header, loader and compressed file
    fo->write(&oh, FH_SIZE);
    fo->write(loader, o_text);  // entry
    if (opt->debug.dump_stub_loader)
        OutputFile::dump(opt->debug.dump_stub_loader, loader, o_text);
    memcpy(obuf + d_off, getLoader() + e_len, d_len); // copy decompressor
    fo->write(obuf, o_data);    // compressed + decompressor

    // write empty relocation fixup
    fo->write("\x00\x00\x00\x00", 4);

    // verify
    verifyOverlappingDecompression();

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

    // finally check the compression ratio
    if (!checkFinalCompressionRatio(fo))
        throwNotCompressible();
}
Exemplo n.º 4
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();
}
Exemplo n.º 5
0
void PackWcle::pack(OutputFile *fo)
{
    handleStub(fo);

    if (ih.byte_order || ih.word_order
        || ih.exe_format_level
        || ih.cpu_type < 2 || ih.cpu_type > 5
        || ih.target_os != 1
        || ih.module_type != 0x200
        || ih.object_iterate_data_map_offset
        || ih.resource_entries
        || ih.module_directives_entries
        || ih.imported_modules_count
        || ih.object_table_entries > 255)
        throwCantPack("watcom/le: unexpected value in header");

    readObjectTable();
    readPageMap();
    readResidentNames();
    readEntryTable();
    readFixupPageTable();
    readFixups();
    readImage();
    readNonResidentNames();

//    if (find_le32(iimage,20,get_le32("UPX ")) >= 0)
    if (find_le32(iimage,UPX_MIN(soimage,256u),UPX_MAGIC_LE32) >= 0)
        throwAlreadyPacked();

    if (ih.init_ss_object != objects)
        throwCantPack("the stack is not in the last object");

    preprocessFixups();

    const unsigned text_size = IOT(ih.init_cs_object-1,npages) * mps;
    const unsigned text_vaddr = IOT(ih.init_cs_object-1,my_base_address);

    // attach some useful data at the end of preprocessed fixups
    ifixups[sofixups++] = (unsigned char) (ih.automatic_data_object & 0xff);
    unsigned ic = objects*sizeof(*iobject_table);
    memcpy(ifixups+sofixups,iobject_desc,ic);
    iobject_desc.dealloc();

    sofixups += ic;
    set_le32(ifixups+sofixups,ih.init_esp_offset+IOT(ih.init_ss_object-1,my_base_address)); // old stack pointer
    set_le32(ifixups+sofixups+4,ih.init_eip_offset+text_vaddr); // real entry point
    set_le32(ifixups+sofixups+8,mps*pages); // virtual address of unpacked relocations
    ifixups[sofixups+12] = (unsigned char) (unsigned) objects;
    sofixups += 13;

    // prepare filter
    Filter ft(ph.level);
    ft.buf_len = text_size;
    ft.addvalue = text_vaddr;
    // compress
    encodeImage(&ft);

    const unsigned lsize = getLoaderSize();
    neweip = getLoaderSection("WCLEMAIN");
    int e_len = getLoaderSectionStart("WCLECUTP");
    const unsigned d_len = lsize - e_len;
    assert(e_len > 0 && e_len < RESERVED);

    memmove(oimage+e_len,oimage+RESERVED,soimage);
    soimage += lsize;

    opages = (soimage+mps-1)/mps;
    oh.bytes_on_last_page = soimage%mps;

    encodeObjectTable();
    encodeFixups();
    encodeFixupPageTable();
    encodePageMap();
    encodeEntryTable();

    encodeResidentNames();
    encodeNonResidentNames();

    // patch loader
    ic = (OOT(0,virtual_size) - d_len) &~ 15;
    assert(ic > ((ph.u_len + ph.overlap_overhead + 31) &~ 15));

    linker->defineSymbol("WCLECUTP", ic);

    linker->defineSymbol("original_entry", ih.init_eip_offset + text_vaddr);
    linker->defineSymbol("original_stack", ih.init_esp_offset +
                         IOT(ih.init_ss_object - 1, my_base_address));
    linker->defineSymbol("start_of_relocs", mps*pages);
    defineDecompressorSymbols();
    defineFilterSymbols(&ft);
    linker->defineSymbol("filter_buffer_start", text_vaddr);

    unsigned jpos = (((ph.c_len + 3) &~ 3) + d_len + 3) / 4;
    linker->defineSymbol("words_to_copy", jpos);
    linker->defineSymbol("copy_dest", ((ic + d_len + 3) &~ 3) - 4);
    linker->defineSymbol("copy_source", e_len + jpos * 4 - 4);

    relocateLoader();

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

    memcpy(oimage, loader, e_len);
    memcpy(oimage + soimage - d_len, loader + e_len, d_len);

    writeFile(fo, opt->watcom_le.le);

    // verify
    verifyOverlappingDecompression(oimage + e_len, oimage.getSize() - e_len);

    // copy the overlay
    const unsigned overlaystart = ih.data_pages_offset + exe_offset
        + getImageSize();
    const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
    checkOverlay(overlay);
    copyOverlay(fo, overlay, &oimage);

    // finally check the compression ratio
    if (!checkFinalCompressionRatio(fo))
        throwNotCompressible();
}
Exemplo n.º 6
0
void PackBvmlinuzI386::pack(OutputFile *fo)
{
    readKernel();

    // prepare filter
    Filter ft(ph.level);
    ft.buf_len = (filter_len ? filter_len : (ph.u_len * 3)/5);
    // May 2008: 3/5 is heuristic to cover most .text but avoid non-instructions.
    // Otherwise "call trick" filter cannot find a free marker byte,
    // especially when it searches over tables of data.
    ft.addvalue = 0;  // The destination buffer might be relocated at runtime.

    upx_compress_config_t cconf; cconf.reset();
    // LINUZ001 allows most of low memory as stack for Bvmlinuz
    cconf.conf_lzma.max_num_probs = (0x90000 - 0x10000)>>1; // ushort: 512 KiB stack

    compressWithFilters(&ft, 512, &cconf, getStrategy(ft));

    // align everything to dword boundary - it is easier to handle
    unsigned c_len = ph.c_len;
    memset(obuf + c_len, 0, 4);
    c_len = ALIGN_UP(c_len, 4u);

    const unsigned lsize = getLoaderSize();

    if (M_IS_LZMA(ph.method)) {
        const lzma_compress_result_t *res = &ph.compress_result.result_lzma;
        upx_uint32_t properties = // lc, lp, pb, dummy
            (res->lit_context_bits << 0) |
            (res->lit_pos_bits << 8) |
            (res->pos_bits << 16);
        if (linker->bele->isBE()) // big endian - bswap32
            acc_swab32s(&properties);
        linker->defineSymbol("lzma_properties", properties);
        // -2 for properties
        linker->defineSymbol("lzma_c_len", ph.c_len - 2);
        linker->defineSymbol("lzma_u_len", ph.u_len);
        unsigned const stack = getDecompressorWrkmemSize();
        linker->defineSymbol("lzma_stack_adjust", 0u - stack);
    }

    const int e_len = getLoaderSectionStart("LZCUTPOI");
    assert(e_len > 0);

    if (0==page_offset) {  // not relocatable kernel
        const unsigned d_len4 = ALIGN_UP(lsize - e_len, 4u);
        const unsigned decompr_pos = ALIGN_UP(ph.u_len + ph.overlap_overhead, 16u);
        const unsigned copy_size = c_len + d_len4;
        const unsigned edi = decompr_pos + d_len4 - 4;          // copy to
        const unsigned esi = ALIGN_UP(c_len + lsize, 4u) - 4;   // copy from

        linker->defineSymbol("decompressor", decompr_pos - bzimage_offset + physical_start);
        linker->defineSymbol("src_for_decompressor", physical_start + decompr_pos - c_len);
        linker->defineSymbol("words_to_copy", copy_size / 4);
        linker->defineSymbol("copy_dest", physical_start + edi);
        linker->defineSymbol("copy_source", bzimage_offset + esi);
    }

    defineFilterSymbols(&ft);
    defineDecompressorSymbols();
    if (0==page_offset) {
        linker->defineSymbol("original_entry", physical_start);
    }
    linker->defineSymbol("stack_offset", stack_offset_during_uncompression);
    relocateLoader();

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

    boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
    bs->sys_size = (ALIGN_UP(lsize + c_len, 16u) / 16);

    fo->write(setup_buf, setup_buf.getSize());

    unsigned const e_pfx = (0==page_offset) ? 0 : getLoaderSectionStart("LINUZ110");
    if (0!=page_offset) {
        fo->write(loader, e_pfx);
    }
    else {
        fo->write(loader, e_len);
    }
    fo->write(obuf, c_len);
    if (0!=page_offset) {
        fo->write(loader + e_pfx, e_len - e_pfx);
    }
    fo->write(loader + e_len, lsize - e_len);
#if 0
    printf("%-13s: setup        : %8ld bytes\n", getName(), (long) setup_buf.getSize());
    printf("%-13s: entry        : %8ld bytes\n", getName(), (long) e_len);
    printf("%-13s: compressed   : %8ld bytes\n", getName(), (long) c_len);
    printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) (lsize - e_len));
#endif

    // verify
    verifyOverlappingDecompression();

    // finally check the compression ratio
    if (!checkFinalCompressionRatio(fo))
        throwNotCompressible();
}
Exemplo n.º 7
0
void PackBvmlinuzI386::buildLoader(const Filter *ft)
{
    // prepare loader
    initLoader(stub_i386_linux_kernel_vmlinuz, sizeof(stub_i386_linux_kernel_vmlinuz));
    if (0!=page_offset) { // relocatable kernel
        assert(0==ft->id || 0x40==(0xf0 & ft->id));  // others assume fixed buffer address
        addLoader("LINUZ000,LINUZ001,LINUZVGA,LINUZ101,LINUZ110",
            ((0!=config_physical_align) ? "LINUZ120" : "LINUZ130"),
            "LINUZ140,LZCUTPOI,LINUZ141",
            (ft->id ? "LINUZ145" : ""),
            (ph.first_offset_found == 1 ? "LINUZ010" : ""),
            NULL);
    }
    else {
        addLoader("LINUZ000,LINUZ001,LINUZVGA,LINUZ005",
              ph.first_offset_found == 1 ? "LINUZ010" : "",
              (0x40==(0xf0 & ft->id)) ? "LZCKLLT1" : (ft->id ? "LZCALLT1" : ""),
              "LBZIMAGE,IDENTSTR",
              "+40", // align the stuff to 4 byte boundary
              "UPX1HEAD", // 32 byte
              "LZCUTPOI",
              NULL);
        // fake alignment for the start of the decompressor
        //linker->defineSymbol("LZCUTPOI", 0x1000);
    }

    addLoader(getDecompressorSections(), NULL);

    if (ft->id)
    {
            assert(ft->calls > 0);
        if (0x40==(0xf0 & ft->id)) {
            addLoader("LZCKLLT9", NULL);
        }
        else {
            addLoader("LZCALLT9", NULL);
        }
        addFilter32(ft->id);
    }
    if (0!=page_offset) {
        addLoader("LINUZ150,IDENTSTR,+40,UPX1HEAD", NULL);
        unsigned const l_len = getLoaderSize();
        unsigned const c_len = ALIGN_UP(ph.c_len, 4u);
        unsigned const e_len = getLoaderSectionStart("LINUZ141") -
                               getLoaderSectionStart("LINUZ110");
        linker->defineSymbol("compressed_length", c_len);
        linker->defineSymbol("load_physical_address", physical_start);  // FIXME
        if (0!=config_physical_align) {
            linker->defineSymbol("neg_config_physical_align", 0u - config_physical_align);
        }
        linker->defineSymbol("neg_length_mov", 0u - ALIGN_UP(c_len + l_len, 4u));
        linker->defineSymbol("neg_page_offset", 0u - page_offset);
        //linker->defineSymbol("physical_start", physical_start);
        linker->defineSymbol("unc_length", ph.u_len);
        linker->defineSymbol("dec_offset", ph.overlap_overhead + e_len);
        linker->defineSymbol("unc_offset", ph.overlap_overhead + ph.u_len - c_len);
    }
    else {
        addLoader("LINUZ990", NULL);
    }
}