📄 p_tos.cpp
字号:
/* p_tos.cpp -- This file is part of the UPX executable compressor. Copyright (C) 1996-2007 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996-2007 Laszlo Molnar All Rights Reserved. UPX and the UCL library are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Markus F.X.J. Oberhumer Laszlo Molnar <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net> */#include "conf.h"#include "file.h"#include "filter.h"#include "packer.h"#include "p_tos.h"#include "linker.h"static const#include "stub/m68k-atari.tos.h"//#define TESTING 1/*************************************************************************//**************************************************************************/#define FH_SIZE sizeof(tos_header_t)PackTos::PackTos(InputFile *f) : super(f){ bele = &N_BELE_RTP::be_policy; COMPILE_TIME_ASSERT(FH_SIZE == 28);}const int *PackTos::getCompressionMethods(int method, int level) const{ bool small = ih.fh_text + ih.fh_data <= 256*1024; return Packer::getDefaultCompressionMethods_8(method, level, small);}const int *PackTos::getFilters() const{ return NULL;}Linker* PackTos::newLinker() const{ return new ElfLinkerM68k;}void PackTos::LinkerSymbols::LoopInfo::init(unsigned count_, bool allow_dbra){ count = value = count_; if (count == 0) mode = LOOP_NONE; else if (count <= 65536 && allow_dbra) { mode = LOOP_DBRA; value -= 1; value &= 0xffff; } else if (count <= 65536) { mode = LOOP_SUBQ_W; value &= 0xffff; } else mode = LOOP_SUBQ_L;}unsigned PackTos::getDecomprOffset(int method, int small) const{ UNUSED(small); if (M_IS_NRV2B(method)) return 2; // FIXME: do not hardcode this value else if (M_IS_NRV2D(method)) return 2; // FIXME: do not hardcode this value else if (M_IS_NRV2E(method)) return 2; // FIXME: do not hardcode this value else if (M_IS_LZMA(method)) return linker->getSectionSize("__mulsi3"); else throwBadLoader(); return 0;}void PackTos::buildLoader(const Filter *ft){ assert(ft->id == 0); initLoader(stub_m68k_atari_tos, sizeof(stub_m68k_atari_tos)); //linker->dumpSymbols(); // // part 1a // addLoader("entry"); if (symbols.up21_a6 <= 32767) addLoader("set_up21_a6.w"); else if (symbols.up21_d4 <= 32767) addLoader("set_up21_d4.w"); else addLoader("set_up21_d4.l"); assert(symbols.loop1.count || symbols.loop2.count); if (symbols.loop1.count) { if (symbols.loop1.value <= 127) addLoader("loop1_set_count.b"); else if (symbols.loop1.value <= 65535) addLoader("loop1_set_count.w"); else addLoader("loop1_set_count.l"); addLoader("loop1_label"); addLoader(opt->small ? "loop1.small" : "loop1.fast"); if (symbols.loop1.mode == symbols.LOOP_SUBQ_L) addLoader("loop1_subql"); else if (symbols.loop1.mode == symbols.LOOP_SUBQ_W) addLoader("loop1_subqw"); else if (symbols.loop1.mode == symbols.LOOP_DBRA) addLoader("loop1_dbra"); else throwBadLoader(); } if (symbols.loop2.count) { assert(symbols.loop2.mode == symbols.LOOP_DBRA); addLoader(opt->small ? "loop2.small" : "loop2.fast"); } addLoader("copy_to_stack"); if (M_IS_NRV2B(ph.method)) addLoader("nrv2b.init"); else if (M_IS_NRV2D(ph.method)) addLoader("nrv2d.init"); else if (M_IS_NRV2E(ph.method)) addLoader("nrv2e.init"); else if (M_IS_LZMA(ph.method)) addLoader("lzma.init"); else throwBadLoader(); symbols.up31_d4 = symbols.up31_base_d4 + getDecomprOffset(ph.method, opt->small); symbols.up31_a6 = symbols.up31_base_a6 + getDecomprOffset(ph.method, opt->small); if (symbols.up31_a6 <= 32767) addLoader("jmp_decompressor_a6.w"); else if (symbols.up31_d4 <= 32767) addLoader("jmp_decompressor_d4.w"); else if (symbols.up31_a6 <= 65534) addLoader("jmp_decompressor_a6.w2"); else addLoader("jmp_decompressor_d4.l"); // // part 1b // addLoader("code_on_stack"); addLoader("clear_dirty_bss"); addLoader("loop3_label"); addLoader(opt->small ? "loop3.small" : "loop3.fast"); if (symbols.loop3.mode == symbols.LOOP_SUBQ_L) addLoader("loop3_subql"); else if (symbols.loop3.mode == symbols.LOOP_SUBQ_W) addLoader("loop3_subqw"); else if (symbols.loop3.mode == symbols.LOOP_DBRA) addLoader("loop3_dbra"); else throwBadLoader(); addLoader("flush_cache"); addLoader("restore_stack");#if 0 addLoader("clear_dirty_stack");#endif addLoader("start_program"); addLoader("IDENTSTR,+40D,UPX1HEAD,CUTPOINT"); // // part 2 // if (M_IS_NRV2B(ph.method)) { addLoader(opt->small ? "nrv2b_8.small" : "nrv2b_8.fast"); } else if (M_IS_NRV2D(ph.method)) { addLoader(opt->small ? "nrv2d_8.small" : "nrv2d_8.fast"); } else if (M_IS_NRV2E(ph.method)) { addLoader(opt->small ? "nrv2e_8.small" : "nrv2e_8.fast"); } else if (M_IS_LZMA(ph.method)) { addLoader("__mulsi3"); addLoader(opt->small ? "lzma.small" : "lzma.fast"); addLoader("lzma.finish"); } else throwBadLoader(); if (symbols.need_reloc) addLoader("reloc"); assert(symbols.loop3.count); if (symbols.loop3.value <= 127) addLoader("loop3_set_count.b"); else if (symbols.loop3.value <= 65535) addLoader("loop3_set_count.w"); else addLoader("loop3_set_count.l"); addLoader("jmp_stack");}/*************************************************************************//**************************************************************************//* flags for curproc->memflags *//* also used for program headers fh_flag */#define F_FASTLOAD 0x01 // don't zero heap#define F_ALTLOAD 0x02 // OK to load in alternate ram#define F_ALTALLOC 0x04 // OK to malloc from alt. ram#define F_SMALLTPA 0x08 // used in MagiC: TPA can be allocated // as specified in the program header // rather than the biggest free memory // block#define F_MEMFLAGS 0xf0 // reserved for future use#define F_SHTEXT 0x800 // program's text may be shared#define F_MINALT 0xf0000000 // used to decide which type of RAM to load in#define F_ALLOCZERO 0x2000 // zero mem, for bugged (GEM...) programs/* Bit in Mxalloc's arg for "don't auto-free this memory" */#define F_KEEP 0x4000#define F_OS_SPECIAL 0x8000 // mark as a special process/* flags for curproc->memflags (that is, fh_flag) and also Mxalloc mode. *//* (Actually, when users call Mxalloc, they add 0x10 to what you see here) */#define F_PROTMODE 0xf0 // protection mode bits#define F_PROT_P 0x00 // no read or write#define F_PROT_G 0x10 // any access OK#define F_PROT_S 0x20 // any super access OK#define F_PROT_PR 0x30 // any read OK, no write#define F_PROT_I 0x40 // invalid page/*************************************************************************// util// readFileHeader() reads ih and checks for illegal values// checkFileHeader() checks ih for legal but unsupported values**************************************************************************/int PackTos::readFileHeader(){ fi->seek(0,SEEK_SET); fi->readx(&ih, FH_SIZE); if (ih.fh_magic != 0x601a) return 0; if (FH_SIZE + ih.fh_text + ih.fh_data + ih.fh_sym > (unsigned) file_size) return 0; return UPX_F_ATARI_TOS;}bool PackTos::checkFileHeader(){ const unsigned f = ih.fh_flag; //printf("flags: 0x%x, text: %d, data: %d, bss: %d, sym: %d\n", f, (int)ih.fh_text, (int)ih.fh_data, (int)ih.fh_bss, (int)ih.fh_sym); if ((ih.fh_text & 1) || (ih.fh_data & 1)) throwCantPack("odd size values in text/data"); if (f & F_OS_SPECIAL) throwCantPack("I won't pack F_OS_SPECIAL programs"); if ((f & F_PROTMODE) > F_PROT_I) throwCantPack("invalid protection mode"); if ((f & F_PROTMODE) != F_PROT_P) { if (opt->force < 1) throwCantPack("no private memory protection; use option '-f' to force packing"); } if (f & F_SHTEXT) { if (opt->force < 1) throwCantPack("shared text segment; use option '-f' to force packing"); }#if 0 // fh_reserved seems to be unused if (ih.fh_reserved != 0) { if (opt->force < 1) throwCantPack("reserved header field set; use option '-f' to force packing"); }#endif return true;}/*************************************************************************// relocs**************************************************************************/// Check relocation for errors to make sure our loader can handle it.static int check_relocs(const upx_byte *relocs, unsigned rsize, unsigned isize, unsigned *nrelocs, unsigned *relocsize, unsigned *overlay){ unsigned fixup = get_be32(relocs); unsigned last_fixup = fixup; unsigned i = 4; assert(isize >= 4); assert(fixup > 0); *nrelocs = 1; for (;;) { if (fixup & 1) // must be word-aligned return -1; if (fixup + 4 > isize) // too far return -1; if (i >= rsize) // premature EOF in relocs return -1; unsigned c = relocs[i++]; if (c == 0) // end marker break; else if (c == 1) // increase fixup, no reloc fixup += 254; else if (c & 1) // must be word-aligned return -1; else // next reloc is here { fixup += c; if (fixup - last_fixup < 4) // overlapping relocation return -1; last_fixup = fixup; *nrelocs += 1; } } *relocsize = i; *overlay = rsize - i; return 0;}/*************************************************************************//**************************************************************************/bool PackTos::canPack(){ if (!readFileHeader()) return false; unsigned char buf[768]; fi->readx(buf, sizeof(buf)); checkAlreadyPacked(buf, sizeof(buf)); if (!checkFileHeader()) throwCantPack("unsupported header flags"); if (file_size < 1024)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -