⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p_tos.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        throwCantPack("program is too small");    return true;}void PackTos::fileInfo(){    if (!readFileHeader())        return;    con_fprintf(stdout, "    text: %d, data: %d, sym: %d, bss: %d, flags=0x%x\n",                (int)ih.fh_text, (int)ih.fh_data, (int)ih.fh_sym, (int)ih.fh_bss, (int)ih.fh_flag);}/*************************************************************************//**************************************************************************/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 || defined(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 || defined(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 || defined(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: ~28KB 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 || defined(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();}/*************************************************************************//**************************************************************************/int PackTos::canUnpack(){    if (!readFileHeader())        return false;    if (!readPackHeader(768))        return false;    // check header as set by packer    if ((ih.fh_text & 3) != 0 || (ih.fh_data & 3) != 0 || (ih.fh_bss & 3) != 0        || ih.fh_sym != 0 || ih.fh_reserved != 0 || ih.fh_reloc > 1)        throwCantUnpack("program header damaged");    // generic check    if (!checkFileHeader())        throwCantUnpack("unsupported header flags");    return true;}/*************************************************************************//**************************************************************************/void PackTos::unpack(OutputFile *fo){    ibuf.alloc(ph.c_len);    obuf.allocForUncompression(ph.u_len);    fi->seek(FH_SIZE + ph.buf_offset + ph.getPackHeaderSize(), SEEK_SET);    fi->readx(ibuf, ph.c_len);    // decompress    decompress(ibuf,obuf);    // write original header & decompressed file    if (fo)    {        unsigned overlay = file_size - (FH_SIZE + ih.fh_text + ih.fh_data);        if (ih.fh_reloc == 0 && overlay >= 4)            overlay -= 4;                           // this is our empty fixup        checkOverlay(overlay);        fo->write(obuf+ph.u_len-FH_SIZE, FH_SIZE);  // orig. file_hdr        fo->write(obuf, ph.u_len-FH_SIZE);          // orig. text+data+relocs        // copy any overlay        copyOverlay(fo, overlay, &obuf);    }}/*vi:ts=4:et*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -