?? htle.cc
字號:
/* * HT Editor * htle.cc * * Copyright (C) 1999-2002 Stefan Weyergraf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * 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; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "errno.h"#include <stdlib.h>#include "endianess.h"#include "htle.h"#include "htlehead.h"#include "htleimg.h"#include "htleobj.h"#include "htleent.h"#include "htlepage.h"#include "htlevxd.h"#include "htiobox.h"#include "htnewexe.h"#include "lestruct.h"#include "log.h"#include "tools.h"#define LE_SEG_ADDR(i) (LE_shared->objmap.header[(i)].page_map_index-1) *\ LE_shared->hdr.pagesize + LE_BASE_ADDRstatic format_viewer_if *htle_ifs[] = { &htleheader_if, &htlevxd_if, &htlepagemaps_if, &htleobjects_if, &htleentrypoints_if, &htleimage_if, 0};static ht_view *htle_init(Bounds *b, File *file, ht_format_group *format_group){ byte lemagic[2]; FileOfs h=get_newexe_header_ofs(file); file->seek(h); if (file->read(lemagic, 2) != 2 || lemagic[0] != LE_MAGIC0 || lemagic[1] != LE_MAGIC1) return 0; ht_le *g=new ht_le(); g->init(b, file, htle_ifs, format_group, h); return g;}format_viewer_if htle_if = { htle_init, 0};void ht_le::init(Bounds *b, File *file, format_viewer_if **ifs, ht_format_group *format_group, FileOfs h){ ht_format_group::init(b, VO_BROWSABLE | VO_SELECTABLE | VO_RESIZE, DESC_LE, file, false, true, 0, format_group); VIEW_DEBUG_NAME("ht_le"); String fn; LOG("%y: LE: found header at 0x%08qx", &file->getFilename(fn), h); ht_le_shared_data *le_shared = ht_malloc(sizeof (ht_le_shared_data)); shared_data = le_shared; le_shared->v_header = NULL; le_shared->v_objects = NULL; le_shared->v_pagemaps = NULL; le_shared->v_image = NULL; le_shared->v_le_vxd = NULL; le_shared->hdr_ofs = h; le_shared->linear_file = NULL; le_shared->reloc_file = NULL; le_shared->best_entrypoint = LE_ADDR_INVALID; // FIXME: byteorder handling... le_shared->byteorder = little_endian; /* read LE header */ file->seek(h); file->readx(&le_shared->hdr, sizeof le_shared->hdr); createHostStruct(&le_shared->hdr, LE_HEADER_struct, le_shared->byteorder); le_shared->is_vxd = le_shared->hdr.winresoff || le_shared->hdr.winreslen || le_shared->hdr.devid || le_shared->hdr.ddkver; read_pagemap(); read_objects(); ht_le_page_file *lfile = new ht_le_page_file(file, false, &le_shared->pagemap, le_shared->pagemap.count, le_shared->hdr.pagesize); le_shared->linear_file = lfile; do_fixups(); check_vxd(); ht_format_group::init_ifs(ifs);}void ht_le::done(){ ht_format_group::done(); ht_le_shared_data *le_shared=(ht_le_shared_data*)shared_data; free(le_shared->objmap.header); free(le_shared->objmap.vsize); free(le_shared->objmap.psize); free(le_shared->pagemap.offset); free(le_shared->pagemap.vsize); free(le_shared->pagemap.psize); delete le_shared->linear_file; delete le_shared->reloc_file; free(le_shared);}void ht_le::do_fixups(){ ht_le_shared_data *le_shared = (ht_le_shared_data*)shared_data; FileOfs h = le_shared->hdr_ofs; uint32 *page_fixup_ofs = ht_malloc(sizeof (uint32) * (le_shared->hdr.pagecnt+1)); uint32 *page_fixup_size = ht_malloc(sizeof (uint32) * (le_shared->hdr.pagecnt)); file->seek(h+le_shared->hdr.fpagetab); for (uint i=0; i<le_shared->hdr.pagecnt+1; i++) { char buf[4]; file->readx(buf, 4); uint32 ofs = createHostInt(buf, 4, little_endian); page_fixup_ofs[i] = ofs; } for (uint i=0; i<le_shared->hdr.pagecnt; i++) { page_fixup_size[i] = page_fixup_ofs[i+1] - page_fixup_ofs[i]; } ht_le_reloc_file *rfile = new ht_le_reloc_file(le_shared->linear_file, false, le_shared); le_shared->reloc_file = rfile; uint error_count = 0; for (uint i=0; i < le_shared->hdr.pagecnt; i++) { // size of fixup record table for segment uint32 size = page_fixup_size[i]; uint obj_ofs = i * le_shared->hdr.pagesize; file->seek(h+le_shared->hdr.frectab+page_fixup_ofs[i]); bool error = false; while (size>0 && !error) { // addr_type + reloc_type LE_FIXUP f; if (sizeof f > size) { error = true; break; } size -= sizeof f; file->readx(&f, sizeof f); createHostStruct(&f, LE_FIXUP_struct, le_shared->byteorder); /* only internal references (16/32) supported for now... */ if ((f.reloc_type != 0) && (f.reloc_type != 16)) { error = true; break; } // is address_type supported ? switch (f.address_type & LE_FIXUP_ADDR_TYPE_MASK) { case LE_FIXUP_ADDR_TYPE_0_8: case LE_FIXUP_ADDR_TYPE_16_0: case LE_FIXUP_ADDR_TYPE_16_16: case LE_FIXUP_ADDR_TYPE_0_16: case LE_FIXUP_ADDR_TYPE_16_32: case LE_FIXUP_ADDR_TYPE_0_32: case LE_FIXUP_ADDR_TYPE_REL32: break; default: error = true; break; } if (error) break; uint multi_count = 0; uint16 src_ofs; bool multi_ofs = (f.address_type & LE_FIXUP_ADDR_MULTIPLE); if (multi_ofs) { // number of entries in offset table char buf[1]; if (sizeof buf > size) { error = true; break; } size -= sizeof buf; file->readx(buf, sizeof buf); multi_count = createHostInt(buf, 1, little_endian); } else { // single source offset char buf[2]; if (sizeof buf > size) { error = true; break; } size -= sizeof buf; file->readx(buf, sizeof buf); src_ofs = createHostInt(buf, 2, little_endian); } switch (f.reloc_type & LE_FIXUP_RELOC_TYPE_MASK) { case LE_FIXUP_RELOC_TYPE_INTERNAL: uint16 target_seg; uint32 target_ofs; if (f.reloc_type & LE_FIXUP_RELOC_TARGET32) { LE_FIXUP_INTERNAL32 x; if (sizeof x > size) { error = true; break; } size -= sizeof x; file->readx(&x, sizeof x); createHostStruct(&x, LE_FIXUP_INTERNAL32_struct, le_shared->byteorder); target_seg = x.seg-1; target_ofs = x.ofs; } else { LE_FIXUP_INTERNAL16 x; if (sizeof x > size) { error = true; break; } size -= sizeof x; file->readx(&x, sizeof x); createHostStruct(&x, LE_FIXUP_INTERNAL16_struct, le_shared->byteorder); target_seg = x.seg-1; target_ofs = x.ofs; } if (multi_ofs) { for (uint j=0; j<multi_count; j++) { char buf[2]; if (sizeof buf > size) { error = true; break; } size -= sizeof buf; file->readx(buf, sizeof buf); src_ofs = createHostInt(buf, sizeof buf, little_endian); rfile->insert_reloc(obj_ofs + src_ofs, new ht_le_reloc_entry(obj_ofs + src_ofs, target_seg, LE_MAKE_ADDR(le_shared, target_seg, target_ofs), f.address_type, f.reloc_type)); } } else { rfile->insert_reloc(obj_ofs + src_ofs, new ht_le_reloc_entry(obj_ofs + src_ofs, target_seg, LE_MAKE_ADDR(le_shared, target_seg, target_ofs), f.address_type, f.reloc_type)); } break; case LE_FIXUP_RELOC_TYPE_IMPORT_ORD: error = true; break; case LE_FIXUP_RELOC_TYPE_IMPORT_NAME: error = true; break; case LE_FIXUP_RELOC_TYPE_OSFIXUP: error = true; break; } } if (error) error_count++; } free(page_fixup_ofs); free(page_fixup_size); if (error_count) { String fn; // FIXME: once complete: // "%s: NE relocations seem to be corrupted.", file->get_filename()); LOG_EX(LOG_WARN, "%y: LE: invalid and/or unsupported relocations found.", &file->getFilename(fn)); errorbox("%y: LE: invalid and/or unsupported relocations found.", &fn); } else { String fn; LOG("%y: LE: relocations present, relocation simulation layer enabled", &file->getFilename(fn)); } rfile->finalize();}void ht_le::check_vxd(){ ht_le_shared_data *le_shared = (ht_le_shared_data*)shared_data; FileOfs h = le_shared->hdr_ofs; /* VxD */ if (le_shared->is_vxd) { /* test if really VxD and find VxD descriptor */ LE_ENTRYPOINT_BUNDLE b; file->seek(h+le_shared->hdr.enttab); file->readx(&b, sizeof b); le_shared->is_vxd = false; if ((b.entry_count == 1) && (b.flags & LE_ENTRYPOINT_BUNDLE_VALID) && (b.flags & LE_ENTRYPOINT_BUNDLE_32BIT) && (b.obj_index == 1)) { LE_ENTRYPOINT32 e; file->readx(&e, sizeof e); createHostStruct(&e, LE_ENTRYPOINT32_struct, le_shared->byteorder); if (e.flags & LE_ENTRYPOINT_EXPORTED) { /* linearized address for ht_le_page_file */ uint32 vxd_desc_ofs = (le_shared->objmap.header[0]. page_map_index-1)*le_shared->hdr.pagesize + e.offset; le_shared->reloc_file->seek(vxd_desc_ofs); le_shared->reloc_file->readx(&le_shared->vxd_desc, sizeof le_shared->vxd_desc); createHostStruct(&le_shared->vxd_desc, LE_VXD_DESCRIPTOR_struct, le_shared->byteorder); le_shared->vxd_desc_linear_ofs = vxd_desc_ofs; le_shared->is_vxd = true; } } }}void ht_le::read_pagemap(){ ht_le_shared_data *le_shared = (ht_le_shared_data*)shared_data; FileOfs h = le_shared->hdr_ofs; le_shared->pagemap.count=le_shared->hdr.pagecnt; le_shared->pagemap.offset = ht_malloc(le_shared->pagemap.count*sizeof *le_shared->pagemap.offset); le_shared->pagemap.psize = ht_malloc(le_shared->pagemap.count*sizeof *le_shared->pagemap.psize); le_shared->pagemap.vsize = ht_malloc(le_shared->pagemap.count*sizeof *le_shared->pagemap.vsize); uint32 last_page_offset=0, last_page=0; for (uint32 i=0; i<le_shared->hdr.pagecnt; i++) { LE_PAGE_MAP_ENTRY e; file->seek(h+le_shared->hdr.pagemap+i*4); file->readx(&e, sizeof e); createHostStruct(&e, LE_PAGE_MAP_ENTRY_struct, le_shared->byteorder); /* FIXME: is this formula correct ? it comes straight from my docs... */ uint32 eofs=(e.high+e.low-1)*le_shared->hdr.pagesize+le_shared->hdr.datapage; le_shared->pagemap.offset[i] = eofs; if (le_shared->pagemap.offset[i]>last_page_offset) { last_page_offset = le_shared->pagemap.offset[i]; last_page = i; } } for (uint32 i=0; i<le_shared->hdr.pagecnt; i++) { le_shared->pagemap.vsize[i]=0; /* filled by read_objects() */ if (i==last_page) le_shared->pagemap.psize[i]=le_shared->hdr.lastpagesize; else le_shared->pagemap.psize[i]=le_shared->hdr.pagesize; }}void ht_le::read_objects(){ ht_le_shared_data *le_shared = (ht_le_shared_data*)shared_data; FileOfs h = le_shared->hdr_ofs; le_shared->objmap.count = le_shared->hdr.objcnt; le_shared->objmap.header = ht_malloc(le_shared->objmap.count*sizeof *le_shared->objmap.header); le_shared->objmap.vsize = ht_malloc(le_shared->objmap.count * sizeof *le_shared->objmap.vsize); le_shared->objmap.psize = ht_malloc(le_shared->objmap.count * sizeof *le_shared->objmap.psize); for (uint i=0; i<le_shared->hdr.objcnt; i++) { file->seek(h+le_shared->hdr.objtab+i*24); file->readx(&le_shared->objmap.header[i], sizeof *le_shared->objmap.header);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -