HpSomBinaryFile.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2000-2001, The University of Queensland
00003  *
00004  * See the file "LICENSE.TERMS" for information on usage and
00005  * redistribution of this file, and for a DISCLAIMER OF ALL
00006  * WARRANTIES.
00007  *
00008  */
00009 
00010 /*==============================================================================
00011  * FILE:        HpSomBinaryFile.cc
00012  * OVERVIEW:    This file contains the implementation of the class
00013  *              HpSomBinaryFile, for decoding PA/RISC SOM executable files.
00014  *              Derived from class BinaryFile
00015  *============================================================================*/
00016 
00017 /*
00018  * $Revision: 1.8 $
00019  *
00020  * 22 Jun 00 - Mike: Initial version
00021  * 15 May 02 - Mike: Fixed several UINT4(&...) that were needed for endianness
00022 */
00023 
00024 #include <assert.h>
00025 #if defined(_MSC_VER) && _MSC_VER <= 1200
00026 #include "exp.h"        // For MSVC 5.00
00027 #endif
00028 
00029 #include "HpSomBinaryFile.h"
00030 
00031 // Macro to convert a pointer to a Big Endian integer into a host integer
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 // Functions to recognise various instruction patterns
00049 // Note: these are not presently used. May be needed again if it turns out
00050 // that addresses in the PLT do not always point to the BOR (Bind On Reference,
00051 // a kind of stub)
00052 #if 0
00053 bool isLDW(unsigned instr, int& offset, unsigned dest)
00054 {
00055     if (((instr >> 26) == 0x12) &&              // Opcode
00056         (instr & 1) &&                          // Offset is neg
00057         (((instr >> 21) & 0x1f) == 27) &&       // register b 
00058         (((instr >> 16) & 0x1f) == dest)) {     // register t
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     // Looking for LDSID       (%s0,%r21),%r1
00068     return (instr == 0x02a010a1);
00069 }
00070 
00071 bool isMSTP(unsigned instr) {
00072     // Looking for MTSP        %r1,%s0
00073     return (instr == 0x00011820);
00074 }
00075 
00076 bool isBE(unsigned instr) {
00077     // Looking for BE          0(%s0,%r21)
00078     return (instr == 0xe2a00000);
00079 }
00080 
00081 bool isSTW(unsigned instr) {
00082     // Looking for STW         %r2,-24(%s0,%r30)
00083     return (instr == 0x6bc23fd1);
00084 }
00085 
00086 bool isStub(ADDRESS hostAddr, int& offset) {
00087     // Looking for this pattern:
00088     // 2600: 4b753f91  LDW         -56(%s0,%r27),%r21
00089     // 2604: 4b733f99  LDW         -52(%s0,%r27),%r19
00090     // 2608: 02a010a1  LDSID       (%s0,%r21),%r1
00091     // 260c: 00011820  MTSP        %r1,%s0
00092     // 2610: e2a00000  BE          0(%s0,%r21)
00093     // 2614: 6bc23fd1  STW         %r2,-24(%s0,%r30)
00094     // Where the only things that vary are the first two offsets (here -56 and
00095     // -52)
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     // Allocate a buffer for the image
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     // Check type at offset 0x0; should be 0x0210 or 0x20B then
00145     // 0107, 0108, or 010B
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     // Find the array of aux headers
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     // Get the size of the aux headers
00163     unsigned sizeAux = UINT4(m_pImage + 0x20);
00164     // Search through the auxillary headers. There should be one of type 4
00165     // ("Exec Auxilliary Header")
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         // Skip this one; length is at the second word. Rightshift by 2 for
00174         // sizeof(unsigned).
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     // Allocate the section information. There will be just four entries:
00183     // one for the header, one for text, one for initialised data, one for BSS
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     // Find the main symbol table, if it exists
00196     ADDRESS symPtr = (ADDRESS)m_pImage + UINT4(m_pImage + 0x5C);
00197     unsigned numSym = UINT4(m_pImage + 0x60);
00198 
00199     // Find the DL Table, if it exists
00200     // The DL table (Dynamic Link info?) is supposed to be at the start of
00201     // the $TEXT$ space, but the only way I can presently find that is to
00202     // assume that the first subspace entry points to it
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);    // Number of import strings
00208     import_entry* import_list = (import_entry*)(DLTable +
00209       UINT4(DLTable + 0x10));
00210     unsigned numExports = UINT4(DLTable + 0x24);    // Number of export strings
00211     export_entry* export_list = (export_entry*)(DLTable +
00212       UINT4(DLTable + 0x20));
00213 
00214 // A convenient macro for accessing the fields (0-11) of the auxilliary header
00215 // Fields 0, 1 are the header (flags, aux header type, and size)
00216 #define AUXHDR(idx) (UINT4(m_pImage + (int)(auxHeaders+idx)))
00217 
00218     // Section 0: header
00219     m_pSections[0].pSectionName = "$HEADER$";
00220     m_pSections[0].uNativeAddr = 0;         // Not applicable
00221     m_pSections[0].uHostAddr = (ADDRESS)m_pImage;
00222 //  m_pSections[0].uSectionSize = AUXHDR(4);
00223     // There is nothing that appears in memory space here; to give this a size
00224     // is to invite GetSectionInfoByAddr to return this section!
00225     m_pSections[0].uSectionSize = 0;
00226 
00227     m_pSections[0].uSectionEntrySize = 1;   // Not applicable
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     // Section 1: text (code)
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;   // Not applicable
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     // Section 2: initialised data
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;   // Not applicable
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     // Section 3: BSS
00256     m_pSections[3].pSectionName = "$BSS$";
00257     // For now, assume that BSS starts at the end of the initialised data
00258     m_pSections[3].uNativeAddr = AUXHDR(6) + AUXHDR(5);
00259     m_pSections[3].uHostAddr = 0;           // Not applicable
00260     m_pSections[3].uSectionSize = AUXHDR(8);
00261     m_pSections[3].uSectionEntrySize = 1;   // Not applicable
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     // Work through the imports, and find those for which there are stubs using that import entry.
00268     // Add the addresses of any such stubs.
00269     int deltaText = m_pSections[1].uHostAddr - m_pSections[1].uNativeAddr;
00270     int deltaData = m_pSections[2].uHostAddr - m_pSections[2].uNativeAddr;
00271     // The "end of data" where r27 points is not necessarily the same as
00272     // the end of the $DATA$ space. So we have to call getSubSpaceInfo
00273     std::pair<unsigned, int> pr = getSubspaceInfo("$GLOBAL$");
00274 //  ADDRESS endData = pr.first + pr.second;
00275     pr = getSubspaceInfo("$PLT$");
00276 //  int minPLT = pr.first - endData;
00277 //  int maxPLT = minPLT + pr.second;
00278     ADDRESS pltStart = pr.first;
00279 //cout << "Offset limits are " << dec << minPLT << " and " << maxPLT << endl;
00280     // Note: DLT entries come before PLT entries in the import array, but
00281     // the $DLT$ subsection is not necessarilly just before the $PLT$
00282     // subsection in memory.
00283     int numDLT = UINT4(DLTable + 0x40);
00284 
00285     // This code was for pattern patching the BOR (Bind On Reference, or library call stub) routines. It appears to be
00286     // unnecessary, since as they appear in the file, the PLT entries point to the BORs
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         // Test this location for a BOR (library stub)
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                 // This stub corresponds with an import entry
00298                 u = (offset - minPLT) / sizeof(plt_record);
00299                 // Add an offset for the DLT entries
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     // For each PLT import table entry, add a symbol
00309     // u runs through import table; v through $PLT$ subspace
00310     // There should be a one to one correspondance between (DLT + PLT) entries and import table entries.
00311     // The DLT entries always come first in the import table
00312     unsigned u = (unsigned)numDLT, v = 0;
00313     plt_record* PLTs = (plt_record*)(pltStart + deltaData);
00314     for (; u < numImports; u++, v++) {
00315 //cout << "Importing " << (pDlStrings+import_list[u].name) << endl;
00316         symbols.Add(PLTs[v].value, pDlStrings + UINT4(&import_list[u].name));
00317         // Add it to the set of imports; needed by IsDynamicLinkedProc()
00318         imports.insert(PLTs[v].value);
00319 //cout << "Added import sym " << (import_list[u].name + pDlStrings) << ", value " << hex << PLTs[v].value << endl;
00320     }
00321     // Work through the exports, and find main. This isn't main itself,
00322     // but in fact a call to main.
00323     for (u=0; u < numExports; u++) {
00324 //cout << "Exporting " << (pDlStrings+UINT4(&export_list[u].name)) << " value " << hex << UINT4(&export_list[u].value) << endl;
00325         if (strncmp(pDlStrings+UINT4(&export_list[u].name), "main", 4) == 0) {
00326             // Enter the symbol "_callmain" for this address
00327             symbols.Add(UINT4(&export_list[u].value), "_callmain");
00328             // Found call to main. Extract the offset. See assemble_17
00329             // in pa-risc 1.1 manual page 5-9
00330             // +--------+--------+--------+----+------------+-+-+
00331             // | 3A (6) |  t (5) | w1 (5) |0(3)|   w2 (11)  |n|w|  BL
00332             // +--------+--------+--------+----+------------+-+-+
00333             //  31    26|25    21|20    16|1513|12         2|1|0
00334             // +----------------------+--------+-----+----------+
00335             // |wwww...              w| w1 (5) |w2lsb| w2 msb's | offset
00336             // +----------------------+--------+-----+----------+
00337             //  31                  16|15    11| 10  |9        0
00338 
00339             unsigned bincall = *(unsigned*) (UINT4(&export_list[u].value) + deltaText);
00340             int offset = ((((bincall & 1) << 31) >> 15) |     // w
00341                            ((bincall & 0x1f0000) >> 5) |      // w1
00342                            ((bincall &        4) << 8) |      // w2@10
00343                            ((bincall &   0x1ff8) >> 3));      // w2@0..9
00344             // Address of main is st + 8 + offset << 2
00345             symbols.Add(UINT4(&export_list[u].value) + 8 + (offset << 2), "main");
00346             break;
00347         }
00348     }
00349 
00350     // Read the main symbol table, if any
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 // cout << "Symbol " << pNames+SYMBOLNM(u) << ", type " << SYMBOLTY(u) << ", value " << hex << SYMBOLVAL(u) << ", aux " << SYMBOLAUX(u) << endl; 
00360             unsigned symbol_type = SYMBOLTY(u);
00361             // Only interested in type 3 (code), 8 (stub), and 12 (millicode)
00362             if ((symbol_type != 3) && (symbol_type != 8) && (symbol_type != 12))
00363                 continue;
00364 //          if ((symbol_type == 10) || (symbol_type == 11))
00365                 // These are extension entries; not interested
00366 //              continue;
00367             char* pSymName = pNames + SYMBOLNM(u);
00368             // Ignore symbols starting with one $; for example, there are many
00369             // $CODE$ (but we want to see helper functions like $$remU)
00370             if ((pSymName[0] == '$') && (pSymName[1] != '$')) continue;
00371 //          if ((symbol_type == 6) && (strcmp("main", pSymName) == 0))
00372                 // Entry point for main. Make sure to ignore this entry, else it
00373                 // ends up being the main entry point
00374 //              continue;
00375             ADDRESS value = SYMBOLVAL(u);
00376 //          if ((symbol_type >= 3) && (symbol_type <= 8))
00377                 // Addresses of code; remove the privilege bits
00378                 value &= ~3;
00379 //if (strcmp("main", pNames+SYMBOLNM(u)) == 0) {    // HACK!
00380 //  cout << "main at " << hex << value << " has type " << SYMBOLTY(u) << endl;}
00381             // HP's symbol table is crazy. It seems that imports like printf have entries of type 3 with the wrong
00382             // value. So we have to check whether the symbol has already been entered (assume first one is correct).
00383             if (symbols.find(pSymName) == NO_ADDRESS)
00384                 symbols.Add(value, pSymName);
00385 //cout << "Symbol " << pNames+SYMBOLNM(u) << ", type " << SYMBOLTY(u) << ", value " << hex << value << ", aux " << SYMBOLAUX(u) << endl;  // HACK!
00386         }
00387     }       // if (numSym)
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); /* FIXME: Someone who understands this file please implement */
00403     return 0;
00404 }
00405 
00406 // This is provided for completeness only...
00407 std::list<SectionInfo*>& HpSomBinaryFile::GetEntryPoints(const char* pEntry
00408  /* = "main" */) {
00409     std::list<SectionInfo*>* ret = new std::list<SectionInfo*>;
00410     SectionInfo* pSect = GetSectionInfoByName("code1");
00411     if (pSect == 0)
00412         return *ret;               // Failed
00413     ret->push_back(pSect);
00414     return *ret;
00415 }
00416 
00417 
00418 bool HpSomBinaryFile::Open(const char* sName)
00419 {
00420     // Not implemented yet
00421     return false;
00422 }
00423 void HpSomBinaryFile::Close()
00424 {
00425     // Not implemented yet
00426     return; 
00427 }
00428 bool HpSomBinaryFile::PostLoad(void* handle)
00429 {
00430     // Not needed: for archives only
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 *>(); /* FIXME */
00454 }
00455 
00456 ADDRESS HpSomBinaryFile::getImageBase()
00457 {
00458     return 0; /* FIXME */
00459 }
00460 
00461 size_t HpSomBinaryFile::getImageSize()
00462 {
00463     return UINT4(m_pImage + 0x24);
00464 }
00465 
00466 // We at least need to be able to name the main function and system calls
00467 const char* HpSomBinaryFile::SymbolByAddress(ADDRESS a) {
00468     return symbols.find(a);
00469 }
00470 
00471 ADDRESS HpSomBinaryFile::GetAddressByName(char* pName, bool bNoTypeOK /* = false */)
00472 {
00473     // For now, we ignore the symbol table and do a linear search of our
00474     // SymTab table
00475     ADDRESS res = symbols.find(pName);
00476     if (res == NO_ADDRESS)
00477         return 0;           // Till the failure return value is fixed
00478     return res;
00479 }
00480 
00481 bool HpSomBinaryFile::IsDynamicLinkedProc(ADDRESS uNative)
00482 {
00483     // Look up the address in the set of imports
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     // Get the start and length of the subspace with the given name
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 //cout << "Subspace " << thisName << " starts " << hex << subSpaces[u].subspace_start << " length " << subSpaces[u].subspace_length << endl;
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     // Failed. Return the zeroes
00508     return ret;
00509 }
00510 
00511 // Specific to BinaryFile objects that implement a "global pointer"
00512 // Gets a pair of unsigned integers representing the address of %agp
00513 // (first) and the value for GLOBALOFFSET (unused for ra-risc)
00514 // The understanding at present is that the global data pointer (%r27 for
00515 // pa-risc) points just past the end of the $GLOBAL$ subspace.
00516 std::pair<unsigned,unsigned> HpSomBinaryFile::GetGlobalPointerInfo()
00517 {
00518     std::pair<unsigned, unsigned> ret(0, 0);
00519     // Search the subspace names for "$GLOBAL$
00520     std::pair<ADDRESS, int> info = getSubspaceInfo("$GLOBAL$");
00521     // We want the end of the $GLOBAL$ section, which is the sum of the start
00522     // address and the size
00523     ret.first = info.first + info.second;
00524     return ret;
00525 }
00526 
00527 /*==============================================================================
00528  * FUNCTION:    HpSomBinaryFile::GetDynamicGlobalMap
00529  * OVERVIEW:    Get a map from ADDRESS to const char*. This map contains the
00530  *                native addresses and symbolic names of global data items
00531  *                (if any) which are shared with dynamically linked libraries.
00532  *                Example: __iob (basis for stdout). The ADDRESS is the native
00533  *                address of a pointer to the real dynamic data object.
00534  * NOTE:        The caller should delete the returned map.
00535  * PARAMETERS:  None
00536  * RETURNS:     Pointer to a new map with the info
00537  *============================================================================*/
00538 std::map<ADDRESS, const char*>* HpSomBinaryFile::GetDynamicGlobalMap()
00539 {
00540     // Find the DL Table, if it exists
00541     // The DL table (Dynamic Link info) is supposed to be at the start of
00542     // the $TEXT$ space, but the only way I can presently find that is to
00543     // assume that the first subspace entry points to it
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     // Offset 0x38 in the DL table has the offset relative to $DATA$ (section 2)
00550     unsigned* p = (unsigned*)(UINT4(DLTable + 0x38) + m_pSections[2].uHostAddr);
00551 
00552     // The DLT is paralelled by the first <numDLT> entries in the import table;
00553     // the import table has the symbolic names
00554     const import_entry* import_list = (import_entry*)(DLTable +
00555       UINT4(DLTable + 0x10));
00556     // Those names are in the DLT string table
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         // ? Sometimes the names are just -1
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         // This means we didn't find an export table entry for main
00576         // didn't load the file
00577         fprintf(stderr, "Did not find export entry for `main'\n");
00578         return 0;
00579     }
00580     // Expect a bl <main>, rp instruction
00581     unsigned instr = UINT4(m_pSections[1].uHostAddr + mainExport -
00582         m_pSections[1].uNativeAddr);
00583     int disp;
00584     // Standard form: sub-opcode 0, target register = 2
00585     if ((instr >> 26 == 0x3A) && (((instr >> 21) & 0x1F) == 2) &&
00586       (((instr >> 13) & 0x7) == 0)) {
00587         disp = (instr & 1) << 16 |          // w
00588             ((instr >> 16) & 0x1F) << 11 |  // w1
00589             ((instr >> 2) & 1) << 10 |      // w2{10}
00590             ((instr >> 3) & 0x3FF);         // w2{0..9}
00591         // Sign extend
00592         disp <<= 15; disp >>= 15;
00593     }
00594     // Alternate (v2 only?) form: sub-opcode 5, t field becomes w3
00595     // (extra 5 bits of address range)
00596     else if ((instr >> 26 == 0x3A) && (((instr >> 13) & 0x7) == 5)) {
00597         disp = (instr & 1) << 21 |          // w
00598             ((instr >> 21) & 0x1F) << 16 |  // w3
00599             ((instr >> 16) & 0x1F) << 11 |  // w1
00600             ((instr >> 2) & 1) << 10 |      // w2{10}
00601             ((instr >> 3) & 0x3FF);         // w2{0..9}
00602         // Sign extend
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     // Return the effective destination address
00611     return mainExport + (disp << 2) + 8;
00612 #endif
00613 }
00614 
00615 // This function is called via dlopen/dlsym; it returns a new BinaryFile
00616 // derived concrete object. After this object is returned, the virtual function
00617 // call mechanism will call the rest of the code in this library
00618 // It needs to be C linkage so that it its name is not mangled
00619 extern "C" {
00620 #ifdef _WIN32
00621      __declspec(dllexport)
00622 #endif
00623     BinaryFile* construct()
00624     {
00625         return new HpSomBinaryFile;
00626     }    
00627 }

Generated on Tue Sep 19 21:18:24 2006 for Boomerang by  doxygen 1.4.6