00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <assert.h>
00025 #if defined(_MSC_VER) && _MSC_VER <= 1200
00026 #include "exp.h"
00027 #endif
00028
00029 #include "HpSomBinaryFile.h"
00030
00031
00032 #define UC(p) ((unsigned char*)p)
00033 #define UINT4(p) ((UC(p)[0] << 24) + (UC(p)[1] << 16) + (UC(p)[2] << 8) + \
00034 UC(p)[3])
00035
00036 HpSomBinaryFile::HpSomBinaryFile()
00037 : m_pImage(0)
00038 {
00039 }
00040
00041 HpSomBinaryFile::~HpSomBinaryFile()
00042 {
00043 if (m_pImage) {
00044 delete m_pImage;
00045 }
00046 }
00047
00048
00049
00050
00051
00052 #if 0
00053 bool isLDW(unsigned instr, int& offset, unsigned dest)
00054 {
00055 if (((instr >> 26) == 0x12) &&
00056 (instr & 1) &&
00057 (((instr >> 21) & 0x1f) == 27) &&
00058 (((instr >> 16) & 0x1f) == dest)) {
00059 offset = ((((int)instr << 31) >> 18) |
00060 ((instr & 0x3ffe) >> 1));
00061 return true;
00062 } else
00063 return false;
00064 }
00065
00066 bool isLDSID(unsigned instr) {
00067
00068 return (instr == 0x02a010a1);
00069 }
00070
00071 bool isMSTP(unsigned instr) {
00072
00073 return (instr == 0x00011820);
00074 }
00075
00076 bool isBE(unsigned instr) {
00077
00078 return (instr == 0xe2a00000);
00079 }
00080
00081 bool isSTW(unsigned instr) {
00082
00083 return (instr == 0x6bc23fd1);
00084 }
00085
00086 bool isStub(ADDRESS hostAddr, int& offset) {
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 unsigned instr;
00097 int offset1, offset2;
00098 instr = *((unsigned*)hostAddr); hostAddr += 4;
00099 if (!isLDW(instr, offset1, 21)) return false;
00100 instr = *((unsigned*)hostAddr); hostAddr += 4;
00101 if (!isLDW(instr, offset2, 19)) return false;
00102 instr = *((unsigned*)hostAddr); hostAddr += 4;
00103 if (!isLDSID(instr)) return false;
00104 instr = *((unsigned*)hostAddr); hostAddr += 4;
00105 if (!isMSTP(instr)) return false;
00106 instr = *((unsigned*)hostAddr); hostAddr += 4;
00107 if (!isBE(instr)) return false;
00108 instr = *((unsigned*)hostAddr);
00109 if (!isSTW(instr)) return false;
00110 if ((offset2 - offset1) != 4) return false;
00111 offset = offset1;
00112 return true;
00113 }
00114 #endif
00115
00116
00117 bool HpSomBinaryFile::RealLoad(const char* sName) {
00118 FILE *fp;
00119
00120 m_pFileName = sName;
00121
00122 if ((fp = fopen(sName, "rb")) == NULL) {
00123 fprintf(stderr, "Could not open binary file %s\n", sName);
00124 return false;
00125 }
00126
00127 fseek(fp, 0, SEEK_END);
00128 long size = ftell(fp);
00129
00130
00131 m_pImage = new unsigned char[size];
00132 if (m_pImage == 0) {
00133 fprintf(stderr, "Could not allocate %ld bytes for image\n", size);
00134 return false;
00135 }
00136 memset(m_pImage, size, 0);
00137
00138 fseek(fp, 0, SEEK_SET);
00139 if (fread(m_pImage, 1, size, fp) != (unsigned)size) {
00140 fprintf(stderr, "Error reading binary file %s\n", sName);
00141 return false;
00142 }
00143
00144
00145
00146 unsigned magic = UINT4(m_pImage);
00147 unsigned system_id = magic >> 16;
00148 unsigned a_magic = magic & 0xFFFF;
00149 if (((system_id != 0x210) && (system_id != 0x20B)) ||
00150 ((a_magic != 0x107) && (a_magic != 0x108) && (a_magic != 0x10B))) {
00151 fprintf(stderr, "%s is not a standard PA/RISC executable file, with "
00152 "system ID %X and magic number %X\n", sName, system_id, a_magic);
00153 return false;
00154 }
00155
00156
00157 unsigned* auxHeaders = (unsigned*)UINT4(m_pImage + 0x1c);
00158 if (auxHeaders == 0) {
00159 fprintf(stderr, "Error: auxilliary header array is not present\n");
00160 return false;
00161 }
00162
00163 unsigned sizeAux = UINT4(m_pImage + 0x20);
00164
00165
00166 bool found = false;
00167 unsigned* maxAux = auxHeaders + sizeAux;
00168 while (auxHeaders < maxAux) {
00169 if ((UINT4(m_pImage + (int)auxHeaders) & 0xFFFF) == 0x0004) {
00170 found = true;
00171 break;
00172 }
00173
00174
00175 auxHeaders += (UINT4((UC(auxHeaders+1)))) >> 2;
00176 }
00177 if (!found) {
00178 fprintf(stderr, "Error: Exec auxilliary header not found\n");
00179 return false;
00180 }
00181
00182
00183
00184 m_pSections = new SectionInfo[4];
00185 m_iNumSections = 4;
00186 if (m_pSections == 0) {
00187 fprintf(stderr, "Could not allocate section info array of 4 items\n");
00188 if (m_pImage) {
00189 delete m_pImage;
00190 m_pImage = 0;
00191 }
00192 return false;
00193 }
00194
00195
00196 ADDRESS symPtr = (ADDRESS)m_pImage + UINT4(m_pImage + 0x5C);
00197 unsigned numSym = UINT4(m_pImage + 0x60);
00198
00199
00200
00201
00202
00203 char* subspace_location = (char*)m_pImage + UINT4(m_pImage + 0x34);
00204 ADDRESS first_subspace_fileloc = UINT4(subspace_location + 8);
00205 char* DLTable = (char*)m_pImage + first_subspace_fileloc;
00206 char* pDlStrings = DLTable + UINT4(DLTable + 0x28);
00207 unsigned numImports = UINT4(DLTable + 0x14);
00208 import_entry* import_list = (import_entry*)(DLTable +
00209 UINT4(DLTable + 0x10));
00210 unsigned numExports = UINT4(DLTable + 0x24);
00211 export_entry* export_list = (export_entry*)(DLTable +
00212 UINT4(DLTable + 0x20));
00213
00214
00215
00216 #define AUXHDR(idx) (UINT4(m_pImage + (int)(auxHeaders+idx)))
00217
00218
00219 m_pSections[0].pSectionName = "$HEADER$";
00220 m_pSections[0].uNativeAddr = 0;
00221 m_pSections[0].uHostAddr = (ADDRESS)m_pImage;
00222
00223
00224
00225 m_pSections[0].uSectionSize = 0;
00226
00227 m_pSections[0].uSectionEntrySize = 1;
00228 m_pSections[0].bCode = 0;
00229 m_pSections[0].bData = 0;
00230 m_pSections[0].bBss = 0;
00231 m_pSections[0].bReadOnly = 0;
00232
00233
00234 m_pSections[1].pSectionName = "$TEXT$";
00235 m_pSections[1].uNativeAddr = AUXHDR(3);
00236 m_pSections[1].uHostAddr = (ADDRESS)m_pImage + AUXHDR(4);
00237 m_pSections[1].uSectionSize = AUXHDR(2);
00238 m_pSections[1].uSectionEntrySize = 1;
00239 m_pSections[1].bCode = 1;
00240 m_pSections[1].bData = 0;
00241 m_pSections[1].bBss = 0;
00242 m_pSections[1].bReadOnly = 1;
00243
00244
00245 m_pSections[2].pSectionName = "$DATA$";
00246 m_pSections[2].uNativeAddr = AUXHDR(6);
00247 m_pSections[2].uHostAddr = (ADDRESS)m_pImage + AUXHDR(7);
00248 m_pSections[2].uSectionSize = AUXHDR(5);
00249 m_pSections[2].uSectionEntrySize = 1;
00250 m_pSections[2].bCode = 0;
00251 m_pSections[2].bData = 1;
00252 m_pSections[2].bBss = 0;
00253 m_pSections[2].bReadOnly = 0;
00254
00255
00256 m_pSections[3].pSectionName = "$BSS$";
00257
00258 m_pSections[3].uNativeAddr = AUXHDR(6) + AUXHDR(5);
00259 m_pSections[3].uHostAddr = 0;
00260 m_pSections[3].uSectionSize = AUXHDR(8);
00261 m_pSections[3].uSectionEntrySize = 1;
00262 m_pSections[3].bCode = 0;
00263 m_pSections[3].bData = 0;
00264 m_pSections[3].bBss = 1;
00265 m_pSections[3].bReadOnly = 0;
00266
00267
00268
00269 int deltaText = m_pSections[1].uHostAddr - m_pSections[1].uNativeAddr;
00270 int deltaData = m_pSections[2].uHostAddr - m_pSections[2].uNativeAddr;
00271
00272
00273 std::pair<unsigned, int> pr = getSubspaceInfo("$GLOBAL$");
00274
00275 pr = getSubspaceInfo("$PLT$");
00276
00277
00278 ADDRESS pltStart = pr.first;
00279
00280
00281
00282
00283 int numDLT = UINT4(DLTable + 0x40);
00284
00285
00286
00287 #if 0
00288 ADDRESS startText = m_pSections[1].uHostAddr;
00289 ADDRESS endText = startText + m_pSections[1].uSectionSize - 0x10;
00290 ADDRESS host;
00291 for (host = startText; host != endText; host += 4) {
00292
00293 int offset;
00294 if (isStub(host, offset)) {
00295 cout << "Found a stub with offset " << dec << offset << endl;
00296 if ((offset >= minPLT) && (offset < maxPLT)) {
00297
00298 u = (offset - minPLT) / sizeof(plt_record);
00299
00300 u += numDLT;
00301 symbols[import_list[u].name + pDlStrings] = host - deltaText;
00302 cout << "Added sym " << (import_list[u].name + pDlStrings) << ", value " << hex << (host - deltaText) << endl;
00303 }
00304 }
00305 }
00306 #endif
00307
00308
00309
00310
00311
00312 unsigned u = (unsigned)numDLT, v = 0;
00313 plt_record* PLTs = (plt_record*)(pltStart + deltaData);
00314 for (; u < numImports; u++, v++) {
00315
00316 symbols.Add(PLTs[v].value, pDlStrings + UINT4(&import_list[u].name));
00317
00318 imports.insert(PLTs[v].value);
00319
00320 }
00321
00322
00323 for (u=0; u < numExports; u++) {
00324
00325 if (strncmp(pDlStrings+UINT4(&export_list[u].name), "main", 4) == 0) {
00326
00327 symbols.Add(UINT4(&export_list[u].value), "_callmain");
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 unsigned bincall = *(unsigned*) (UINT4(&export_list[u].value) + deltaText);
00340 int offset = ((((bincall & 1) << 31) >> 15) |
00341 ((bincall & 0x1f0000) >> 5) |
00342 ((bincall & 4) << 8) |
00343 ((bincall & 0x1ff8) >> 3));
00344
00345 symbols.Add(UINT4(&export_list[u].value) + 8 + (offset << 2), "main");
00346 break;
00347 }
00348 }
00349
00350
00351 if (numSym) {
00352 char* pNames = (char*) (m_pImage+(int)UINT4(m_pImage+0x6C));
00353 #define SYMSIZE 20 // 5 4-byte words per symbol entry
00354 #define SYMBOLNM(idx) (UINT4(symPtr + idx*SYMSIZE + 4))
00355 #define SYMBOLAUX(idx) (UINT4(symPtr + idx*SYMSIZE + 8))
00356 #define SYMBOLVAL(idx) (UINT4(symPtr + idx*SYMSIZE + 16))
00357 #define SYMBOLTY(idx) ((UINT4(symPtr + idx*SYMSIZE) >> 24) & 0x3f)
00358 for (u=0; u < numSym; u++) {
00359
00360 unsigned symbol_type = SYMBOLTY(u);
00361
00362 if ((symbol_type != 3) && (symbol_type != 8) && (symbol_type != 12))
00363 continue;
00364
00365
00366
00367 char* pSymName = pNames + SYMBOLNM(u);
00368
00369
00370 if ((pSymName[0] == '$') && (pSymName[1] != '$')) continue;
00371
00372
00373
00374
00375 ADDRESS value = SYMBOLVAL(u);
00376
00377
00378 value &= ~3;
00379
00380
00381
00382
00383 if (symbols.find(pSymName) == NO_ADDRESS)
00384 symbols.Add(value, pSymName);
00385
00386 }
00387 }
00388
00389 return true;
00390 }
00391
00392 void HpSomBinaryFile::UnLoad()
00393 {
00394 if (m_pImage) {
00395 delete [] m_pImage;
00396 m_pImage = 0;
00397 }
00398 }
00399
00400 ADDRESS HpSomBinaryFile::GetEntryPoint()
00401 {
00402 assert(0);
00403 return 0;
00404 }
00405
00406
00407 std::list<SectionInfo*>& HpSomBinaryFile::GetEntryPoints(const char* pEntry
00408 ) {
00409 std::list<SectionInfo*>* ret = new std::list<SectionInfo*>;
00410 SectionInfo* pSect = GetSectionInfoByName("code1");
00411 if (pSect == 0)
00412 return *ret;
00413 ret->push_back(pSect);
00414 return *ret;
00415 }
00416
00417
00418 bool HpSomBinaryFile::Open(const char* sName)
00419 {
00420
00421 return false;
00422 }
00423 void HpSomBinaryFile::Close()
00424 {
00425
00426 return;
00427 }
00428 bool HpSomBinaryFile::PostLoad(void* handle)
00429 {
00430
00431 return false;
00432 }
00433
00434 LOAD_FMT HpSomBinaryFile::GetFormat() const
00435 {
00436 return LOADFMT_PAR;
00437 }
00438
00439 MACHINE HpSomBinaryFile::GetMachine() const
00440 {
00441 return MACHINE_HPRISC;
00442 }
00443
00444 bool HpSomBinaryFile::isLibrary() const
00445 {
00446 int type = UINT4(m_pImage)&0xFFFF;
00447 return ( type == 0x0104 || type == 0x010D ||
00448 type == 0x010E || type == 0x0619 );
00449 }
00450
00451 std::list<const char *> HpSomBinaryFile::getDependencyList()
00452 {
00453 return std::list<const char *>();
00454 }
00455
00456 ADDRESS HpSomBinaryFile::getImageBase()
00457 {
00458 return 0;
00459 }
00460
00461 size_t HpSomBinaryFile::getImageSize()
00462 {
00463 return UINT4(m_pImage + 0x24);
00464 }
00465
00466
00467 const char* HpSomBinaryFile::SymbolByAddress(ADDRESS a) {
00468 return symbols.find(a);
00469 }
00470
00471 ADDRESS HpSomBinaryFile::GetAddressByName(char* pName, bool bNoTypeOK )
00472 {
00473
00474
00475 ADDRESS res = symbols.find(pName);
00476 if (res == NO_ADDRESS)
00477 return 0;
00478 return res;
00479 }
00480
00481 bool HpSomBinaryFile::IsDynamicLinkedProc(ADDRESS uNative)
00482 {
00483
00484 return imports.find(uNative) != imports.end();
00485 }
00486
00487 std::pair<ADDRESS, int> HpSomBinaryFile::getSubspaceInfo(const char* ssname)
00488 {
00489 std::pair<ADDRESS, int> ret(0, 0);
00490
00491 struct subspace_dictionary_record* subSpaces =
00492 (struct subspace_dictionary_record*)(m_pImage + UINT4(m_pImage + 0x34));
00493 unsigned numSubSpaces = UINT4(m_pImage + 0x38);
00494 const char* spaceStrings = (const char*)
00495 (m_pImage + UINT4(m_pImage + 0x44));
00496 for (unsigned u=0; u < numSubSpaces; u++) {
00497 char* thisName = (char*)(spaceStrings + UINT4(&subSpaces[u].name));
00498 unsigned thisNameSize = UINT4(spaceStrings + UINT4(&subSpaces[u].name) - 4);
00499
00500 if ((thisNameSize == strlen(ssname)) &&
00501 ((strcmp(thisName, ssname) == 0))) {
00502 ret.first = UINT4(&subSpaces[u].subspace_start);
00503 ret.second = UINT4(&subSpaces[u].subspace_length);
00504 return ret;
00505 }
00506 }
00507
00508 return ret;
00509 }
00510
00511
00512
00513
00514
00515
00516 std::pair<unsigned,unsigned> HpSomBinaryFile::GetGlobalPointerInfo()
00517 {
00518 std::pair<unsigned, unsigned> ret(0, 0);
00519
00520 std::pair<ADDRESS, int> info = getSubspaceInfo("$GLOBAL$");
00521
00522
00523 ret.first = info.first + info.second;
00524 return ret;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 std::map<ADDRESS, const char*>* HpSomBinaryFile::GetDynamicGlobalMap()
00539 {
00540
00541
00542
00543
00544 const char* subspace_location = (char*)m_pImage + UINT4(m_pImage + 0x34);
00545 ADDRESS first_subspace_fileloc = UINT4(subspace_location + 8);
00546 const char* DLTable = (char*)m_pImage + first_subspace_fileloc;
00547
00548 unsigned numDLT = UINT4(DLTable + 0x40);
00549
00550 unsigned* p = (unsigned*)(UINT4(DLTable + 0x38) + m_pSections[2].uHostAddr);
00551
00552
00553
00554 const import_entry* import_list = (import_entry*)(DLTable +
00555 UINT4(DLTable + 0x10));
00556
00557 const char* pDlStrings = DLTable + UINT4(DLTable + 0x28);
00558
00559 std::map<ADDRESS, const char*>* ret = new std::map<ADDRESS, const char*>;
00560 for (unsigned u=0; u < numDLT; u++) {
00561
00562 if (import_list[u].name == -1)
00563 continue;
00564 const char* str = pDlStrings + import_list[u].name;
00565 (*ret)[*p++] = str;
00566 }
00567 return ret;
00568 }
00569
00570 ADDRESS HpSomBinaryFile::GetMainEntryPoint()
00571 {
00572 return symbols.find("main");
00573 #if 0
00574 if (mainExport == 0) {
00575
00576
00577 fprintf(stderr, "Did not find export entry for `main'\n");
00578 return 0;
00579 }
00580
00581 unsigned instr = UINT4(m_pSections[1].uHostAddr + mainExport -
00582 m_pSections[1].uNativeAddr);
00583 int disp;
00584
00585 if ((instr >> 26 == 0x3A) && (((instr >> 21) & 0x1F) == 2) &&
00586 (((instr >> 13) & 0x7) == 0)) {
00587 disp = (instr & 1) << 16 |
00588 ((instr >> 16) & 0x1F) << 11 |
00589 ((instr >> 2) & 1) << 10 |
00590 ((instr >> 3) & 0x3FF);
00591
00592 disp <<= 15; disp >>= 15;
00593 }
00594
00595
00596 else if ((instr >> 26 == 0x3A) && (((instr >> 13) & 0x7) == 5)) {
00597 disp = (instr & 1) << 21 |
00598 ((instr >> 21) & 0x1F) << 16 |
00599 ((instr >> 16) & 0x1F) << 11 |
00600 ((instr >> 2) & 1) << 10 |
00601 ((instr >> 3) & 0x3FF);
00602
00603 disp <<= 10; disp >>= 10;
00604 }
00605 else {
00606 fprintf(stderr, "Error: expected BL instruction at %X, found %X\n",
00607 mainExport, instr);
00608 return 0;
00609 }
00610
00611 return mainExport + (disp << 2) + 8;
00612 #endif
00613 }
00614
00615
00616
00617
00618
00619 extern "C" {
00620 #ifdef _WIN32
00621 __declspec(dllexport)
00622 #endif
00623 BinaryFile* construct()
00624 {
00625 return new HpSomBinaryFile;
00626 }
00627 }