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 }