00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #if defined(_MSC_VER) && _MSC_VER <= 1200
00024 #pragma warning(disable:4786)
00025 #endif
00026
00027 #include "BinaryFile.h"
00028 #include "DOS4GWBinaryFile.h"
00029 #include "config.h"
00030 #include <iostream>
00031 #include <sstream>
00032 #include <assert.h>
00033
00034 extern "C" {
00035 int microX86Dis(void* p);
00036 }
00037
00038 DOS4GWBinaryFile::DOS4GWBinaryFile() : m_pFileName(0)
00039 { }
00040
00041 DOS4GWBinaryFile::~DOS4GWBinaryFile()
00042 {
00043 for (int i=0; i < m_iNumSections; i++) {
00044 if (m_pSections[i].pSectionName)
00045 ;
00046 }
00047
00048 }
00049
00050 bool DOS4GWBinaryFile::Open(const char* sName) {
00051
00052 return false;
00053 }
00054
00055 void DOS4GWBinaryFile::Close() {
00056 UnLoad();
00057 }
00058
00059 std::list<SectionInfo*>& DOS4GWBinaryFile::GetEntryPoints(
00060 const char* pEntry)
00061 {
00062 fprintf(stderr,"really don't know how to implement GetEntryPoints\n");
00063 exit(0);
00064 static std::list<SectionInfo*> l;
00065 return l;
00066 }
00067
00068 ADDRESS DOS4GWBinaryFile::GetEntryPoint()
00069 {
00070 return (ADDRESS)(LMMH(m_pLXObjects[LMMH(m_pLXHeader->eipobjectnum)].RelocBaseAddr) + LMMH(m_pLXHeader->eip));
00071 }
00072
00073 ADDRESS DOS4GWBinaryFile::GetMainEntryPoint() {
00074 ADDRESS aMain = GetAddressByName ("main", true);
00075 if (aMain != NO_ADDRESS)
00076 return aMain;
00077 aMain = GetAddressByName ("__CMain", true);
00078 if (aMain != NO_ADDRESS)
00079 return aMain;
00080
00081
00082
00083 unsigned p = LMMH(m_pLXHeader->eip);
00084 unsigned lim = p + 0x300;
00085 unsigned char op1, op2;
00086 unsigned addr, lastOrdCall = 0;
00087 bool gotSubEbp = false;
00088 bool lastWasCall = false;
00089
00090 SectionInfo* si = GetSectionInfoByName("seg0");
00091 if (si == NULL) si = GetSectionInfoByName(".text");
00092 if (si == NULL) si = GetSectionInfoByName("CODE");
00093 assert(si);
00094 ADDRESS nativeOrigin = si->uNativeAddr;
00095 unsigned textSize = si->uSectionSize;
00096 if (textSize < 0x300)
00097 lim = p + textSize;
00098
00099 while (p < lim) {
00100 op1 = *(unsigned char*)(p + base);
00101 op2 = *(unsigned char*)(p + base + 1);
00102
00103 switch (op1) {
00104 case 0xE8: {
00105
00106 if (gotSubEbp) {
00107
00108 addr = nativeOrigin + p + 5 + LMMH(*(p + base + 1));
00109
00110 return addr;
00111 }
00112 lastOrdCall = p;
00113 lastWasCall = true;
00114 break;
00115 }
00116 case 0x2B:
00117 if (op2 == 0xED && lastWasCall)
00118 gotSubEbp = true;
00119 lastWasCall = false;
00120 break;
00121 default:
00122 gotSubEbp = false;
00123 lastWasCall = false;
00124 break;
00125 case 0xEB:
00126 if (op2 >= 0x80)
00127 break;
00128
00129 p += op2+2;
00130 continue;
00131 }
00132 int size = microX86Dis(p + base);
00133 if (size == 0x40) {
00134 fprintf(stderr, "Warning! Microdisassembler out of step at offset 0x%x\n", p);
00135 size = 1;
00136 }
00137 p += size;
00138 }
00139 return NO_ADDRESS;
00140 }
00141
00142
00143 bool DOS4GWBinaryFile::RealLoad(const char* sName)
00144 {
00145 m_pFileName = sName;
00146 FILE *fp = fopen(sName,"rb");
00147
00148 DWord lxoffLE, lxoff;
00149 fseek(fp, 0x3c, SEEK_SET);
00150 fread(&lxoffLE, 4, 1, fp);
00151 lxoff = LMMH(lxoffLE);
00152
00153 fseek(fp, lxoff, SEEK_SET);
00154 m_pLXHeader = new LXHeader;
00155
00156 fread(m_pLXHeader, sizeof(LXHeader), 1, fp);
00157
00158 if (m_pLXHeader->sigLo != 'L' || (m_pLXHeader->sigHi != 'X' && m_pLXHeader->sigHi != 'E')) {
00159 fprintf(stderr,"error loading file %s, bad LE/LX magic\n", sName);
00160 return false;
00161 }
00162
00163 fseek(fp, lxoff + LMMH(m_pLXHeader->objtbloffset), SEEK_SET);
00164 m_pLXObjects = new LXObject[LMMH(m_pLXHeader->numobjsinmodule)];
00165 fread(m_pLXObjects, sizeof(LXObject), LMMH(m_pLXHeader->numobjsinmodule), fp);
00166
00167
00168
00169 #if 0
00170 unsigned npagetblentries = 0;
00171 m_cbImage = 0;
00172 for (unsigned n = 0; n < LMMH(m_pLXHeader->numobjsinmodule); n++) {
00173 if (LMMH(m_pLXObjects[n].PageTblIdx) + LMMH(m_pLXObjects[n].NumPageTblEntries) - 1 > npagetblentries)
00174 npagetblentries = LMMH(m_pLXObjects[n].PageTblIdx) + LMMH(m_pLXObjects[n].NumPageTblEntries) - 1;
00175 if (LMMH(m_pLXObjects[n].ObjectFlags) & 0x40)
00176 if (LMMH(m_pLXObjects[n].RelocBaseAddr) + LMMH(m_pLXObjects[n].VirtualSize) > m_cbImage)
00177 m_cbImage = LMMH(m_pLXObjects[n].RelocBaseAddr) + LMMH(m_pLXObjects[n].VirtualSize);
00178 }
00179 m_cbImage -= LMMH(m_pLXObjects[0].RelocBaseAddr);
00180
00181 fseek(fp, lxoff + LMMH(m_pLXHeader->objpagetbloffset), SEEK_SET);
00182 m_pLXPages = new LXPage[npagetblentries];
00183 fread(m_pLXPages, sizeof(LXPage), npagetblentries, fp);
00184 #endif
00185
00186 unsigned npages = 0;
00187 m_cbImage = 0;
00188 for (unsigned n = 0; n < LMMH(m_pLXHeader->numobjsinmodule); n++)
00189 if (LMMH(m_pLXObjects[n].ObjectFlags) & 0x40) {
00190 if (LMMH(m_pLXObjects[n].PageTblIdx) + LMMH(m_pLXObjects[n].NumPageTblEntries) - 1 > npages)
00191 npages = LMMH(m_pLXObjects[n].PageTblIdx) + LMMH(m_pLXObjects[n].NumPageTblEntries) - 1;
00192 m_cbImage = LMMH(m_pLXObjects[n].RelocBaseAddr) + LMMH(m_pLXObjects[n].VirtualSize);
00193 }
00194
00195 m_cbImage -= LMMH(m_pLXObjects[0].RelocBaseAddr);
00196
00197 base = (char *)malloc(m_cbImage);
00198
00199 m_iNumSections = LMMH(m_pLXHeader->numobjsinmodule);
00200 m_pSections = new SectionInfo[m_iNumSections];
00201 for (unsigned n = 0; n < LMMH(m_pLXHeader->numobjsinmodule); n++)
00202 if (LMMH(m_pLXObjects[n].ObjectFlags) & 0x40){
00203 printf("vsize %x reloc %x flags %x page %i npage %i\n",
00204 LMMH(m_pLXObjects[n].VirtualSize), LMMH(m_pLXObjects[n].RelocBaseAddr),
00205 LMMH(m_pLXObjects[n].ObjectFlags), LMMH(m_pLXObjects[n].PageTblIdx),
00206 LMMH(m_pLXObjects[n].NumPageTblEntries));
00207
00208 m_pSections[n].pSectionName = new char[9];
00209 sprintf(m_pSections[n].pSectionName, "seg%i", n);
00210 m_pSections[n].uNativeAddr=(ADDRESS)LMMH(m_pLXObjects[n].RelocBaseAddr);
00211 m_pSections[n].uHostAddr=(ADDRESS)(LMMH(m_pLXObjects[n].RelocBaseAddr) - LMMH(m_pLXObjects[0].RelocBaseAddr) + base);
00212 m_pSections[n].uSectionSize=LMMH(m_pLXObjects[n].VirtualSize);
00213 DWord Flags = LMMH(m_pLXObjects[n].ObjectFlags);
00214 m_pSections[n].bBss = 0;
00215 m_pSections[n].bCode = Flags&0x4?1:0;
00216 m_pSections[n].bData = Flags&0x4?0:1;
00217 m_pSections[n].bReadOnly = Flags&0x1?0:1;
00218
00219 fseek(fp, m_pLXHeader->datapagesoffset + (LMMH(m_pLXObjects[n].PageTblIdx) - 1) * LMMH(m_pLXHeader->pagesize), SEEK_SET);
00220 char *p = base + LMMH(m_pLXObjects[n].RelocBaseAddr) - LMMH(m_pLXObjects[0].RelocBaseAddr);
00221 fread(p, LMMH(m_pLXObjects[n].NumPageTblEntries), LMMH(m_pLXHeader->pagesize), fp);
00222 }
00223
00224
00225
00226
00227 #if 0
00228
00229 dlprocptrs[0x101ac] = "main";
00230 dlprocptrs[0x10a24] = "vfprintf";
00231 dlprocptrs[0x12d2c] = "atoi";
00232 dlprocptrs[0x12d74] = "malloc";
00233 dlprocptrs[0x12d84] = "__LastFree";
00234 dlprocptrs[0x12eaa] = "__ExpandDGROUP";
00235 dlprocptrs[0x130a7] = "free";
00236 dlprocptrs[0x130b7] = "_nfree";
00237 dlprocptrs[0x130dc] = "start";
00238 dlprocptrs[0x132fa] = "__exit_";
00239 dlprocptrs[0x132fc] = "__exit_with_msg_";
00240 dlprocptrs[0x1332a] = "__GETDS";
00241 dlprocptrs[0x13332] = "inp";
00242 dlprocptrs[0x1333d] = "outp";
00243 dlprocptrs[0x13349] = "_dos_getvect";
00244 dlprocptrs[0x13383] = "_dos_setvect";
00245 dlprocptrs[0x133ba] = "int386";
00246 dlprocptrs[0x133f9] = "sprintf";
00247 dlprocptrs[0x13423] = "vsprintf";
00248 dlprocptrs[0x13430] = "segread";
00249 dlprocptrs[0x1345d] = "int386x";
00250 dlprocptrs[0x1347e] = "creat";
00251 dlprocptrs[0x13493] = "setmode";
00252 dlprocptrs[0x1355f] = "close";
00253 dlprocptrs[0x1384a] = "read";
00254 dlprocptrs[0x13940] = "write";
00255 dlprocptrs[0x13b2e] = "filelength";
00256 dlprocptrs[0x13b74] = "printf";
00257 dlprocptrs[0x13b94] = "__null_int23_exit";
00258 dlprocptrs[0x13b95] = "exit";
00259 dlprocptrs[0x13bad] = "_exit";
00260 dlprocptrs[0x13bc4] = "tell";
00261 dlprocptrs[0x13cba] = "rewind";
00262 dlprocptrs[0x13cd3] = "fread";
00263 dlprocptrs[0x13fe1] = "strcat";
00264 dlprocptrs[0x1401c] = "__open_flags";
00265 dlprocptrs[0x141a8] = "fopen";
00266 dlprocptrs[0x141d0] = "freopen";
00267 dlprocptrs[0x142c4] = "__MemAllocator";
00268 dlprocptrs[0x14374] = "__MemFree";
00269 dlprocptrs[0x1447f] = "__nmemneed";
00270 dlprocptrs[0x14487] = "sbrk";
00271 dlprocptrs[0x14524] = "__brk";
00272 dlprocptrs[0x145d0] = "__CMain";
00273 dlprocptrs[0x145ff] = "_init_files";
00274 dlprocptrs[0x1464c] = "__InitRtns";
00275 dlprocptrs[0x1468b] = "__FiniRtns";
00276 dlprocptrs[0x146ca] = "__prtf";
00277 dlprocptrs[0x14f58] = "__int386x_";
00278 dlprocptrs[0x14fb3] = "_DoINTR_";
00279 dlprocptrs[0x15330] = "__Init_Argv";
00280 dlprocptrs[0x15481] = "isatty";
00281 dlprocptrs[0x154a1] = "_dosret0";
00282 dlprocptrs[0x154bd] = "_dsretax";
00283 dlprocptrs[0x154d4] = "_EINVAL";
00284 dlprocptrs[0x154e5] = "_set_errno";
00285 dlprocptrs[0x15551] = "__CHK";
00286 dlprocptrs[0x15561] = "__STK";
00287 dlprocptrs[0x15578] = "__STKOVERFLOW";
00288 dlprocptrs[0x15588] = "__GRO";
00289 dlprocptrs[0x155c2] = "__fprtf";
00290 dlprocptrs[0x15640] = "__ioalloc";
00291 dlprocptrs[0x156c3] = "__chktty";
00292 dlprocptrs[0x156f0] = "__qread";
00293 dlprocptrs[0x15721] = "fgetc";
00294 dlprocptrs[0x1578f] = "__filbuf";
00295 dlprocptrs[0x157b9] = "__fill_buffer";
00296 dlprocptrs[0x15864] = "fflush";
00297 dlprocptrs[0x1591c] = "ftell";
00298 dlprocptrs[0x15957] = "tolower";
00299 dlprocptrs[0x159b4] = "remove";
00300 dlprocptrs[0x159e9] = "utoa";
00301 dlprocptrs[0x15a36] = "itoa";
00302 dlprocptrs[0x15a97] = "ultoa";
00303 dlprocptrs[0x15ae4] = "ltoa";
00304 dlprocptrs[0x15b14] = "toupper";
00305 dlprocptrs[0x15b29] = "fputc";
00306 dlprocptrs[0x15bca] = "__full_io_exit";
00307 dlprocptrs[0x15c0b] = "fcloseall";
00308 dlprocptrs[0x15c3e] = "flushall";
00309 dlprocptrs[0x15c49] = "__flushall";
00310 dlprocptrs[0x15c85] = "getche";
00311 dlprocptrs[0x15caa] = "__qwrite";
00312 dlprocptrs[0x15d1f] = "unlink";
00313 dlprocptrs[0x15d43] = "putch";
00314 #endif
00315
00316
00317 fseek(fp, LMMH(m_pLXHeader->fixuppagetbloffset) + lxoff, SEEK_SET);
00318 unsigned int *fixuppagetbl = new unsigned int[npages+1];
00319 fread(fixuppagetbl, sizeof(unsigned int), npages+1, fp);
00320
00321
00322
00323
00324
00325 fseek(fp, LMMH(m_pLXHeader->fixuprecordtbloffset) + lxoff, SEEK_SET);
00326 LXFixup fixup;
00327 unsigned srcpage = 0;
00328 do {
00329 fread(&fixup, sizeof(fixup), 1, fp);
00330 if (fixup.src != 7 || (fixup.flags & ~0x50)) {
00331 fprintf(stderr, "unknown fixup type %02x %02x\n", fixup.src, fixup.flags);
00332 return false;
00333 }
00334
00335 unsigned long src = srcpage * LMMH(m_pLXHeader->pagesize) + (short)LMMHw(fixup.srcoff);
00336 unsigned short object = 0;
00337 if (fixup.flags & 0x40)
00338 fread(&object, 2, 1, fp);
00339 else
00340 fread(&object, 1, 1, fp);
00341 unsigned int trgoff = 0;
00342 if (fixup.flags & 0x10)
00343 fread(&trgoff, 4, 1, fp);
00344 else
00345 fread(&trgoff, 2, 1, fp);
00346 unsigned long target = LMMH(m_pLXObjects[object - 1].RelocBaseAddr) + LMMHw(trgoff);
00347
00348 *(unsigned int *)(base + src) = target;
00349
00350 while (ftell(fp) - (LMMH(m_pLXHeader->fixuprecordtbloffset) + lxoff) >= LMMH(fixuppagetbl[srcpage+1]))
00351 srcpage++;
00352 } while (srcpage < npages);
00353
00354 fclose(fp);
00355 return true;
00356 }
00357
00358 bool DOS4GWBinaryFile::IsDynamicLinkedProc(ADDRESS uNative)
00359 {
00360 if (dlprocptrs.find(uNative) != dlprocptrs.end() &&
00361 dlprocptrs[uNative] != "main" && dlprocptrs[uNative] != "_start")
00362 return true;
00363 return false;
00364 }
00365
00366
00367 void DOS4GWBinaryFile::UnLoad()
00368 {
00369 }
00370
00371 bool DOS4GWBinaryFile::PostLoad(void* handle)
00372 {
00373 return false;
00374 }
00375
00376 const char* DOS4GWBinaryFile::SymbolByAddress(ADDRESS dwAddr)
00377 {
00378 std::map<ADDRESS, std::string>::iterator it = dlprocptrs.find(dwAddr);
00379 if (it == dlprocptrs.end())
00380 return 0;
00381 return (char*) it->second.c_str();
00382 }
00383
00384 ADDRESS DOS4GWBinaryFile::GetAddressByName(const char* pName,
00385 bool bNoTypeOK ) {
00386
00387
00388 std::map<ADDRESS, std::string>::iterator it = dlprocptrs.begin();
00389 while (it != dlprocptrs.end()) {
00390
00391 if (strcmp(it->second.c_str(), pName) == 0)
00392 return it->first;
00393 it++;
00394 }
00395 return NO_ADDRESS;
00396 }
00397
00398 void DOS4GWBinaryFile::AddSymbol(ADDRESS uNative, const char *pName)
00399 {
00400 dlprocptrs[uNative] = pName;
00401 }
00402
00403 bool DOS4GWBinaryFile::DisplayDetails(const char* fileName, FILE* f
00404 )
00405 {
00406 return false;
00407 }
00408
00409 int DOS4GWBinaryFile::dos4gwRead2(short* ps) const {
00410 unsigned char* p = (unsigned char*)ps;
00411
00412 int n = (int)(p[0] + (p[1] << 8));
00413 return n;
00414 }
00415
00416 int DOS4GWBinaryFile::dos4gwRead4(int* pi) const{
00417 short* p = (short*)pi;
00418 int n1 = dos4gwRead2(p);
00419 int n2 = dos4gwRead2(p+1);
00420 int n = (int) (n1 | (n2 << 16));
00421 return n;
00422 }
00423
00424
00425 int DOS4GWBinaryFile::readNative1(ADDRESS nat) {
00426 PSectionInfo si = GetSectionInfoByAddr(nat);
00427 if (si == 0)
00428 si = GetSectionInfo(0);
00429 char* host = (char*)(si->uHostAddr - si->uNativeAddr + nat);
00430 return *host;
00431 }
00432
00433
00434 int DOS4GWBinaryFile::readNative2(ADDRESS nat) {
00435 PSectionInfo si = GetSectionInfoByAddr(nat);
00436 if (si == 0) return 0;
00437 ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
00438 int n = dos4gwRead2((short*)host);
00439 return n;
00440 }
00441
00442
00443 int DOS4GWBinaryFile::readNative4(ADDRESS nat) {
00444 PSectionInfo si = GetSectionInfoByAddr(nat);
00445 if (si == 0) return 0;
00446 ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
00447 int n = dos4gwRead4((int*)host);
00448 return n;
00449 }
00450
00451
00452 QWord DOS4GWBinaryFile::readNative8(ADDRESS nat) {
00453 int raw[2];
00454 #ifdef WORDS_BIGENDIAN // This tests the host machine
00455
00456 raw[1] = readNative4(nat);
00457 raw[0] = readNative4(nat+4);
00458 #else
00459
00460 raw[0] = readNative4(nat);
00461 raw[1] = readNative4(nat+4);
00462 #endif
00463 return *(QWord*)raw;
00464 }
00465
00466
00467 float DOS4GWBinaryFile::readNativeFloat4(ADDRESS nat) {
00468 int raw = readNative4(nat);
00469
00470
00471 return *(float*)&raw;
00472 }
00473
00474
00475 double DOS4GWBinaryFile::readNativeFloat8(ADDRESS nat) {
00476 int raw[2];
00477 #ifdef WORDS_BIGENDIAN // This tests the host machine
00478
00479 raw[1] = readNative4(nat);
00480 raw[0] = readNative4(nat+4);
00481 #else
00482
00483 raw[0] = readNative4(nat);
00484 raw[1] = readNative4(nat+4);
00485 #endif
00486
00487 return *(double*)raw;
00488 }
00489
00490 bool DOS4GWBinaryFile::IsDynamicLinkedProcPointer(ADDRESS uNative)
00491 {
00492 if (dlprocptrs.find(uNative) != dlprocptrs.end())
00493 return true;
00494 return false;
00495 }
00496
00497 const char *DOS4GWBinaryFile::GetDynamicProcName(ADDRESS uNative)
00498 {
00499 return dlprocptrs[uNative].c_str();
00500 }
00501
00502 LOAD_FMT DOS4GWBinaryFile::GetFormat() const
00503 {
00504 return LOADFMT_LX;
00505 }
00506
00507 MACHINE DOS4GWBinaryFile::GetMachine() const
00508 {
00509 return MACHINE_PENTIUM;
00510 }
00511
00512 bool DOS4GWBinaryFile::isLibrary() const
00513 {
00514 return false;
00515 }
00516
00517 ADDRESS DOS4GWBinaryFile::getImageBase()
00518 {
00519 return m_pLXObjects[0].RelocBaseAddr;
00520 }
00521
00522 size_t DOS4GWBinaryFile::getImageSize()
00523 {
00524 return 0;
00525 }
00526
00527 std::list<const char *> DOS4GWBinaryFile::getDependencyList()
00528 {
00529 return std::list<const char *>();
00530 }
00531
00532 DWord DOS4GWBinaryFile::getDelta()
00533 {
00534
00535
00536
00537 return (DWord)base - (DWord)m_pLXObjects[0].RelocBaseAddr;
00538 }
00539
00540
00541
00542
00543
00544 extern "C" {
00545 #ifdef _WIN32
00546 __declspec(dllexport)
00547 #endif
00548 BinaryFile* construct()
00549 {
00550 return new DOS4GWBinaryFile;
00551 }
00552 }