00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "log.h"
00022 #include "htendian.h"
00023 #include "htiobox.h"
00024 #include "htne.h"
00025 #include "htneent.h"
00026 #include "htnehead.h"
00027 #include "htneimp.h"
00028 #include "htnenms.h"
00029 #include "htneobj.h"
00030 #include "htneimg.h"
00031 #include "htnewexe.h"
00032 #include "nestruct.h"
00033 #include "tools.h"
00034
00035 #include <stdlib.h>
00036 #include <string.h>
00037
00038 static format_viewer_if *htne_ifs[] = {
00039 &htneheader_if,
00040 &htnesegments_if,
00041 &htneimports_if,
00042 &htneentrypoints_if,
00043 &htnenames_if,
00044 &htneimage_if,
00045 0
00046 };
00047
00048 static int compare_keys_ne_import_rec(Object *key_a, Object *key_b)
00049 {
00050 ne_import_rec *a=(ne_import_rec*)key_a;
00051 ne_import_rec *b=(ne_import_rec*)key_b;
00052 if (a->module == b->module) {
00053 if (a->byname == b->byname) {
00054 if (a->byname) {
00055 return a->name_ofs - b->name_ofs;
00056 } else {
00057 return a->ord - b->ord;
00058 }
00059 }
00060 return a->byname - b->byname;
00061 }
00062 return a->module - b->module;
00063 }
00064
00065 static ht_view *htne_init(bounds *b, ht_streamfile *file, ht_format_group *format_group)
00066 {
00067 byte nemagic[2];
00068 FILEOFS h = get_newexe_header_ofs(file);
00069 file->seek(h);
00070 file->read(nemagic, 2);
00071 if ((nemagic[0]!=NE_MAGIC0) || (nemagic[1]!=NE_MAGIC1))
00072 return 0;
00073
00074 ht_ne *g=new ht_ne();
00075 g->init(b, file, htne_ifs, format_group, h);
00076 return g;
00077 }
00078
00079 format_viewer_if htne_if = {
00080 htne_init,
00081 0
00082 };
00083
00084 void ht_ne::init(bounds *b, ht_streamfile *f, format_viewer_if **ifs, ht_format_group *format_group, FILEOFS h)
00085 {
00086 ht_format_group::init(b, VO_BROWSABLE | VO_SELECTABLE | VO_RESIZE, DESC_NE, f, false, true, 0, format_group);
00087 VIEW_DEBUG_NAME("ht_ne");
00088
00089 LOG("%s: NE: found header at %08x", file->get_filename(), h);
00090
00091 ht_ne_shared_data *ne_shared = (ht_ne_shared_data*)malloc(sizeof (ht_ne_shared_data));
00092 shared_data = ne_shared;
00093
00094 ne_shared->fake_segment = 0;
00095 ne_shared->hdr_ofs = h;
00096 ne_shared->entrypoints = NULL;
00097 ne_shared->imports = NULL;
00098 ne_shared->v_image = NULL;
00099
00100 file->seek(h);
00101 file->read(&ne_shared->hdr, sizeof ne_shared->hdr);
00102 create_host_struct(&ne_shared->hdr, NE_HEADER_struct, little_endian);
00103
00104
00105 ne_shared->segments.segment_count = ne_shared->hdr.cseg;
00106 ne_shared->segments.segments = (NE_SEGMENT *)malloc(sizeof (NE_SEGMENT) * ne_shared->segments.segment_count);
00107
00108 bool reloc_needed = false;
00109 NE_SEGMENT *s = ne_shared->segments.segments;
00110 file->seek(h+ne_shared->hdr.segtab);
00111 for (dword i = 0; i < ne_shared->segments.segment_count; i++) {
00112 file->read(s, sizeof *s);
00113 create_host_struct(s, NE_SEGMENT_struct, little_endian);
00114 if (s->flags & NE_HASRELOC) reloc_needed = true;
00115 s++;
00116 }
00117
00118 FILEOFS o = h + ne_shared->hdr.enttab;
00119 NE_ENTRYPOINT_HEADER e;
00120 file->seek(o);
00121 file->read(&e, sizeof e);
00122 create_host_struct(&e, NE_ENTRYPOINT_HEADER_struct, little_endian);
00123 o += sizeof e;
00124
00125 ht_clist *ep = new ht_clist();
00126 ep->init();
00127
00128 dword index = 1;
00129 while (o<h+ne_shared->hdr.enttab+ne_shared->hdr.cbenttab) {
00130 for (int i=0; i<e.entry_count; i++) {
00131 if (e.seg_index==0) {
00132 } else if (e.seg_index==0xff) {
00133 o+=sizeof (NE_ENTRYPOINT_MOVABLE);
00134
00135 NE_ENTRYPOINT_MOVABLE me;
00136 file->read(&me, sizeof me);
00137 create_host_struct(&me, NE_ENTRYPOINT_MOVABLE_struct, little_endian);
00138
00139 ep->set(index, new ht_ne_entrypoint(index, me.seg, me.offset, 0));
00140 } else {
00141 o+=sizeof (NE_ENTRYPOINT_FIXED);
00142
00143 NE_ENTRYPOINT_FIXED fe;
00144 file->seek(o);
00145 file->read(&fe, sizeof fe);
00146 create_host_struct(&fe, NE_ENTRYPOINT_FIXED_struct, little_endian);
00147 ep->set(index, new ht_ne_entrypoint(index, e.seg_index, fe.offset, 0));
00148 }
00149 index++;
00150 }
00151 file->seek(o);
00152 file->read(&e, sizeof e);
00153 create_host_struct(&e, NE_ENTRYPOINT_HEADER_struct, little_endian);
00154 o += sizeof e;
00155 }
00156
00157 ne_shared->entrypoints = ep;
00158
00159
00160 o = h + ne_shared->hdr.modtab;
00161 FILEOFS no = h + ne_shared->hdr.imptab;
00162 file->seek(o);
00163 ne_shared->modnames_count = ne_shared->hdr.cmod;
00164 ne_shared->modnames = (char**)malloc(sizeof *ne_shared->modnames * ne_shared->modnames_count);
00165 for (UINT i=0; i<ne_shared->hdr.cmod; i++) {
00166 char buf[2];
00167 file->seek(o+i*2);
00168 if (file->read(buf, 2) != 2) break;
00169 int w = create_host_int(buf, 2, little_endian);
00170 file->seek(no+w);
00171 ne_shared->modnames[i] = getstrp(file);
00172 }
00173
00174
00175 if (reloc_needed) {
00176 ht_ne_reloc_file *rf = new ht_ne_reloc_file();
00177 rf->init(file, false, (ht_ne_shared_data*)shared_data);
00178
00179 if (relocate(rf)) {
00180 rf->finalize();
00181 file = rf;
00182 own_file = true;
00183 LOG("%s: NE: relocations present, relocation simulation layer enabled", file->get_filename());
00184 } else {
00185 LOG_EX(LOG_WARN, "%s: NE relocations seem to be corrupted.", file->get_filename());
00186 errorbox("%s: NE relocations seem to be corrupted.", file->get_filename());
00187 rf->done();
00188 delete rf;
00189 }
00190 }
00191
00192 ht_format_group::init_ifs(ifs);
00193 }
00194
00195 void ht_ne::done()
00196 {
00197 ht_format_group::done();
00198
00199 ht_ne_shared_data *ne_shared = (ht_ne_shared_data*)shared_data;
00200
00201 if (ne_shared->segments.segments) {
00202 free(ne_shared->segments.segments);
00203 }
00204
00205 if (ne_shared->modnames) {
00206 for (UINT i=0; i<ne_shared->modnames_count; i++) {
00207 free(ne_shared->modnames[i]);
00208 }
00209 free(ne_shared->modnames);
00210 }
00211
00212 if (ne_shared->entrypoints) {
00213 ne_shared->entrypoints->destroy();
00214 delete ne_shared->entrypoints;
00215 }
00216
00217 if (ne_shared->imports) {
00218 ne_shared->imports->destroy();
00219 delete ne_shared->imports;
00220 }
00221 free(shared_data);
00222 }
00223
00224 void ht_ne::loc_enum_start()
00225 {
00226
00227 }
00228
00229 bool ht_ne::loc_enum_next(ht_format_loc *loc)
00230 {
00231 #if 0
00232 ht_ne_shared_data *sh=(ht_ne_shared_data*)shared_data;
00233 if (loc_enum) {
00234 loc->name="ne";
00235 loc->start=sh->hdr_ofs;
00236 loc->length=file->get_size()-loc->start;
00237
00238 loc_enum=false;
00239 return true;
00240 }
00241 #endif
00242 return false;
00243 }
00244
00245 bool ht_ne::create_fake_segment()
00246 {
00247 ht_ne_shared_data *ne_shared = (ht_ne_shared_data*)shared_data;
00248 UINT i = ne_shared->hdr.cseg;
00249 NE_SEGMENT *newsegs = (NE_SEGMENT*)malloc(sizeof *newsegs * (ne_shared->segments.segment_count+1));
00250 memcpy(newsegs, ne_shared->segments.segments, sizeof *newsegs * ne_shared->segments.segment_count);
00251 ne_shared->segments.segment_count++;
00252 free(ne_shared->segments.segments);
00253 ne_shared->segments.segments = newsegs;
00254 newsegs[i].offset = 0;
00255 newsegs[i].size = 0;
00256 newsegs[i].flags = NE_DATA;
00257 newsegs[i].minalloc = 0;
00258 ne_shared->fake_segment = i;
00259 return true;
00260 }
00261
00262 bool ht_ne::relocate(ht_reloc_file *rf)
00263 {
00264 ht_ne_shared_data *ne_shared = (ht_ne_shared_data*)shared_data;
00265 if (!create_fake_segment()) return false;
00266
00267 ht_stree *imports = new ht_stree();
00268 imports->init(compare_keys_ne_import_rec);
00269
00270 int fake_entry_count = 0;
00271
00272
00273 UINT c = (ne_shared->hdr.flags & NE_FLAGS_SELFLOAD) ? 1 : ne_shared->segments.segment_count;
00274 for (dword i = 0; i < c; i++) {
00275 if (ne_shared->segments.segments[i].flags & NE_HASRELOC) {
00276 FILEOFS seg_ofs = NE_get_seg_ofs(ne_shared, i);
00277 FILEOFS f = seg_ofs + NE_get_seg_psize(ne_shared, i);
00278 char buf[2];
00279 file->seek(f);
00280 file->read(buf, 2);
00281 f += 2;
00282 int c = create_host_int(buf, 2, little_endian);
00283 for (int j = 0; j < c; j++) {
00284 NE_RELOC_HEADER reloc;
00285 file->seek(f);
00286 file->read(&reloc, sizeof reloc);
00287 create_host_struct(&reloc, NE_RELOC_HEADER_struct, little_endian);
00288 f += sizeof reloc;
00289 switch (reloc.flags & NE_RF_RT_MASK) {
00290 case NE_RF_INTERNAL: {
00291 NE_RELOC_INTERNAL sreloc;
00292 file->read(&sreloc, sizeof sreloc);
00293 create_host_struct(&sreloc, NE_RELOC_INTERNAL_struct, little_endian);
00294 f += sizeof sreloc;
00295 if (sreloc.seg == 0xff) {
00296
00297 if (!relocate_single(rf, i, seg_ofs + reloc.src_ofs, reloc.type, reloc.flags, 0xf1, 0)) return false;
00298 } else {
00299 if (!relocate_single(rf, i, seg_ofs + reloc.src_ofs, reloc.type, reloc.flags, sreloc.seg, sreloc.ofs)) return false;
00300 }
00301 break;
00302 }
00303 case NE_RF_IMPORT_ORD: {
00304 NE_RELOC_IMPORT sreloc;
00305 file->read(&sreloc, sizeof sreloc);
00306 create_host_struct(&sreloc, NE_RELOC_IMPORT_struct, little_endian);
00307 f += sizeof sreloc;
00308 if (imports->insert(new ne_import_rec(fake_entry_count, sreloc.module, false, sreloc.ord), NULL)) {
00309
00310 if (!relocate_single(rf, i, seg_ofs + reloc.src_ofs, reloc.type, reloc.flags, ne_shared->fake_segment+1, fake_entry_count)) return false;
00311 fake_entry_count++;
00312 }
00313 break;
00314 }
00315 case NE_RF_IMPORT_NAME: {
00316 NE_RELOC_IMPORT sreloc;
00317 file->read(&sreloc, sizeof sreloc);
00318 create_host_struct(&sreloc, NE_RELOC_IMPORT_struct, little_endian);
00319 f += sizeof sreloc;
00320 if (imports->insert(new ne_import_rec(fake_entry_count, sreloc.module, true, sreloc.name_ofs), NULL)) {
00321
00322 if (!relocate_single(rf, i, seg_ofs + reloc.src_ofs, reloc.type, reloc.flags, ne_shared->fake_segment+1, fake_entry_count)) return false;
00323 fake_entry_count++;
00324 }
00325 break;
00326 }
00327 case NE_RF_OSFIXUP: {
00328 NE_RELOC_FIXUP sreloc;
00329 file->read(&sreloc, sizeof sreloc);
00330 create_host_struct(&sreloc, NE_RELOC_FIXUP_struct, little_endian);
00331 f += sizeof sreloc;
00332 if (!relocate_single(rf, i, seg_ofs + reloc.src_ofs, reloc.type, reloc.flags, 0xdead, 0xcafebabe)) return false;
00333 break;
00334 }
00335 }
00336 }
00337 }
00338 }
00339 ne_shared->imports = imports;
00340 return true;
00341 }
00342
00343 bool ht_ne::relocate_single(ht_reloc_file *rf, UINT seg, FILEOFS ofs, UINT type, UINT flags, word value_seg, word value_ofs)
00344 {
00345 ht_ne_shared_data *ne_shared = (ht_ne_shared_data*)shared_data;
00346 while (1) {
00347 if (flags & NE_RF_ADD) break;
00348 switch (type & NE_RT_MASK) {
00349 case NE_RT_SEG16:
00350 case NE_RT_PTR32:
00351 case NE_RT_OFS16:
00352 case NE_RT_PTR48:
00353 case NE_RT_OFS32:
00354 break;
00355 case NE_RT_OFS8:
00356
00357
00358
00359 default:
00360
00361 return false;
00362 }
00363 rf->insert_reloc(ofs, new ht_ne_reloc_entry(type, flags & NE_RF_ADD, value_seg, value_ofs));
00364 char buf[2];
00365 file->seek(ofs);
00366 file->read(buf, 2);
00367 word r = create_host_int(buf, 2, little_endian);
00368 if (r == 0xffff) break;
00369 NEAddress a = NE_MAKE_ADDR(seg+1, r);
00370 if (!NE_addr_to_ofs(ne_shared, a, &ofs)) {
00371 return false;
00372 }
00373 }
00374 return true;
00375 }
00376
00377
00378
00379
00380
00381 ht_ne_entrypoint::ht_ne_entrypoint(UINT Ordinal, UINT Seg, UINT Offset, UINT Flags)
00382 {
00383 ordinal = Ordinal;
00384 seg = Seg;
00385 offset = Offset;
00386 flags = Flags;
00387 name = NULL;
00388 }
00389
00390 ht_ne_entrypoint::~ht_ne_entrypoint()
00391 {
00392 if (name) free(name);
00393 }
00394
00395
00396
00397
00398
00399 ht_ne_reloc_entry::ht_ne_reloc_entry(UINT Mode, bool Add, word Seg, word Ofs)
00400 {
00401 mode = Mode;
00402 add = Add;
00403 seg = Seg;
00404 ofs = Ofs;
00405 }
00406
00407
00408
00409
00410
00411 void ht_ne_reloc_file::init(ht_streamfile *s, bool os, ht_ne_shared_data *d)
00412 {
00413 ht_reloc_file::init(s, os);
00414 data = d;
00415 }
00416
00417 void ht_ne_reloc_file::reloc_apply(Object *reloc, byte *data)
00418 {
00419 ht_ne_reloc_entry *e = (ht_ne_reloc_entry*)reloc;
00420
00421 switch (e->mode & NE_RT_MASK) {
00422 case NE_RT_OFS8:
00423 create_foreign_int(data, e->ofs, 1, little_endian);
00424 break;
00425 case NE_RT_SEG16:
00426 create_foreign_int(data, e->seg, 2, little_endian);
00427 break;
00428 case NE_RT_OFS16:
00429 create_foreign_int(data, e->ofs, 2, little_endian);
00430 break;
00431 case NE_RT_PTR32:
00432 create_foreign_int(data, e->ofs, 2, little_endian);
00433 create_foreign_int(data+2, e->seg, 2, little_endian);
00434 break;
00435 case NE_RT_OFS32:
00436 create_foreign_int(data, e->ofs, 4, little_endian);
00437 break;
00438 case NE_RT_PTR48:
00439 create_foreign_int(data, e->ofs, 4, little_endian);
00440 create_foreign_int(data+4, e->seg, 2, little_endian);
00441 break;
00442 }
00443 }
00444
00445 bool ht_ne_reloc_file::reloc_unapply(Object *reloc, byte *data)
00446 {
00447 return false;
00448
00449 }
00450
00451
00452
00453
00454
00455 FILEOFS NE_get_seg_ofs(ht_ne_shared_data *NE_shared, UINT i)
00456 {
00457 return (NE_shared->segments.segments[i].offset << NE_shared->hdr.align);
00458 }
00459
00460 NEAddress NE_get_seg_addr(ht_ne_shared_data *NE_shared, UINT i)
00461 {
00462 return NE_MAKE_ADDR(i+1, 0);
00463 }
00464
00465 UINT NE_get_seg_psize(ht_ne_shared_data *NE_shared, UINT i)
00466 {
00467 return (NE_shared->segments.segments[i].size || !NE_shared->segments.segments[i].offset)
00468 ? NE_shared->segments.segments[i].size : 0x10000;
00469
00470 }
00471
00472 UINT NE_get_seg_vsize(ht_ne_shared_data *NE_shared, UINT i)
00473 {
00474 return NE_shared->segments.segments[i].minalloc ? NE_shared->segments.segments[i].minalloc : 0x10000;
00475
00476 }
00477
00478 bool NE_addr_to_segment(ht_ne_shared_data *NE_shared, NEAddress Addr, int *segment)
00479 {
00480 for (UINT i = 0; i < NE_shared->segments.segment_count; i++) {
00481 NEAddress base = NE_get_seg_addr(NE_shared, i);
00482 UINT evsize = MAX(NE_get_seg_vsize(NE_shared, i), NE_get_seg_psize(NE_shared, i));
00483 if ((Addr >= base) && (Addr < base + evsize)) {
00484 *segment = i;
00485 return true;
00486 }
00487 }
00488 return false;
00489 }
00490
00491 bool NE_addr_is_physical(ht_ne_shared_data *NE_shared, NEAddress Addr)
00492 {
00493 for (UINT i = 0; i < NE_shared->segments.segment_count; i++) {
00494 NEAddress base = NE_get_seg_addr(NE_shared, i);
00495 UINT epsize = MIN(NE_get_seg_vsize(NE_shared, i), NE_get_seg_psize(NE_shared, i));
00496 if ((Addr >= base) && (Addr < base + epsize)) return true;
00497 }
00498 return false;
00499 }
00500
00501 bool NE_addr_to_ofs(ht_ne_shared_data *NE_shared, NEAddress Addr, FILEOFS *ofs)
00502 {
00503 for (UINT i = 0; i < NE_shared->segments.segment_count; i++) {
00504 NEAddress base = NE_get_seg_addr(NE_shared, i);
00505 UINT epsize = MIN(NE_get_seg_vsize(NE_shared, i), NE_get_seg_psize(NE_shared, i));
00506 if ((Addr >= base) && (Addr < base + epsize)) {
00507 *ofs = NE_get_seg_ofs(NE_shared, i) + (Addr - base);
00508 return true;
00509 }
00510 }
00511 return false;
00512 }
00513
00514 bool NE_ofs_to_addr(ht_ne_shared_data *NE_shared, FILEOFS ofs, NEAddress *Addr)
00515 {
00516 for (UINT i = 0; i < NE_shared->segments.segment_count; i++) {
00517 FILEOFS sofs = NE_get_seg_ofs(NE_shared, i);
00518 if ((ofs >= sofs) && (ofs < sofs + NE_get_seg_psize(NE_shared, i))) {
00519 *Addr = NE_get_seg_addr(NE_shared, i) + (ofs - sofs);
00520 return true;
00521 }
00522 }
00523 return false;
00524 }