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 }
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 }
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(); }
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(); }
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(); }
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(); }
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); } }