ExeBinaryFile.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1997,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 /* File: ExeBinaryFile.cc
00011  * Desc: This file contains the implementation of the class ExeBinaryFile.
00012 */
00013 
00014 /* EXE binary file format.
00015     This file implements the class ExeBinaryFile, derived from class BinaryFile.
00016     See ExeBinaryFile.h and BinaryFile.h for details
00017     MVE 08/10/97
00018  * 21 May 02 - Mike: Slight mod for gcc 3.1
00019 */
00020 
00021 #if defined(_MSC_VER) && _MSC_VER <= 1200
00022 #pragma warning(disable:4786)
00023 #endif
00024 
00025 #include "ExeBinaryFile.h"
00026 
00027 ExeBinaryFile::ExeBinaryFile()
00028 {
00029 }
00030 
00031 bool ExeBinaryFile::RealLoad(const char* sName)
00032 {
00033     FILE   *fp;
00034     int     i, cb;
00035     Byte    buf[4];
00036     int     fCOM;
00037 
00038         m_pFileName = sName;
00039 
00040     // Always just 3 sections
00041     m_pSections = new SectionInfo[3];
00042     if (m_pSections == 0)
00043     {
00044         fprintf(stderr, "Could not allocate section information\n");
00045         return 0;
00046     }
00047     m_iNumSections = 3;
00048     m_pHeader = new exeHeader;
00049     if (m_pHeader == 0)
00050     {
00051         fprintf(stderr, "Could not allocate header memory\n");
00052         return 0;
00053     }
00054 
00055     /* Open the input file */
00056     if ((fp = fopen(sName, "rb")) == NULL)
00057     {
00058         fprintf(stderr, "Could not open file %s\n", sName);
00059         return 0;
00060     }
00061 
00062     /* Read in first 2 bytes to check EXE signature */
00063     if (fread(m_pHeader, 1, 2, fp) != 2)
00064     {
00065         fprintf(stderr, "Cannot read file %s\n", sName);
00066         return 0;
00067     }
00068 
00069     // Check for the "MZ" exe header
00070     if (! (fCOM = (m_pHeader->sigLo != 0x4D || m_pHeader->sigHi != 0x5A)))
00071     {
00072         /* Read rest of m_pHeader */
00073         fseek(fp, 0, SEEK_SET);
00074         if (fread(m_pHeader, sizeof(exeHeader), 1, fp) != 1)
00075         {
00076             fprintf(stderr, "Cannot read file %s\n", sName);
00077             return 0;
00078         }
00079 
00080         /* This is a typical DOS kludge! */
00081         if (LH(&m_pHeader->relocTabOffset) == 0x40)
00082         {
00083             fprintf(stderr, "Error - NE format executable\n");
00084             return 0;
00085         }
00086 
00087         /* Calculate the load module size.
00088          * This is the number of pages in the file
00089          * less the length of the m_pHeader and reloc table
00090          * less the number of bytes unused on last page
00091         */
00092         cb = (dword)LH(&m_pHeader->numPages) * 512 -
00093             (dword)LH(&m_pHeader->numParaHeader) * 16;
00094         if (m_pHeader->lastPageSize)
00095         {
00096             cb -= 512 - LH(&m_pHeader->lastPageSize);
00097         }
00098         
00099         /* We quietly ignore minAlloc and maxAlloc since for our
00100          * purposes it doesn't really matter where in real memory
00101          * the m_am would end up.  EXE m_ams can't really rely on
00102          * their load location so setting the PSP segment to 0 is fine.
00103          * Certainly m_ams that prod around in DOS or BIOS are going
00104          * to have to load DS from a constant so it'll be pretty 
00105          * obvious.
00106         */
00107         m_cReloc = (SWord)LH(&m_pHeader->numReloc);
00108 
00109         /* Allocate the relocation table */
00110         if (m_cReloc)
00111         {
00112             m_pRelocTable = new dword[m_cReloc];
00113             if (m_pRelocTable == 0)
00114             {
00115                 fprintf(stderr, "Could not allocate relocation table "
00116                     "(%d entries)\n", m_cReloc);
00117                 return 0;
00118             }
00119             fseek(fp, LH(&m_pHeader->relocTabOffset), SEEK_SET);
00120 
00121             /* Read in seg:offset pairs and convert to Image ptrs */
00122             for (i = 0; i < m_cReloc; i++)
00123             {
00124                 fread(buf, 1, 4, fp);
00125                 m_pRelocTable[i] = LH(buf) + 
00126                     (((int)LH(buf+2))<<4);
00127             }
00128         }
00129 
00130         /* Seek to start of image */
00131         fseek(fp, (int)LH(&m_pHeader->numParaHeader) * 16, SEEK_SET);
00132 
00133         // Initial PC and SP. Note that we fake the seg:offset by putting
00134         // the segment in the top half, and offset int he bottom
00135         m_uInitPC = ((LH(&m_pHeader->initCS)) << 16) + LH(&m_pHeader->initIP);
00136         m_uInitSP = ((LH(&m_pHeader->initSS)) << 16) + LH(&m_pHeader->initSP);
00137     }
00138     else
00139     {   /* COM file
00140          * In this case the load module size is just the file length
00141         */
00142         fseek(fp, 0, SEEK_END);
00143         cb = ftell(fp);
00144 
00145         /* COM programs start off with an ORG 100H (to leave room for a PSP)
00146          * This is also the implied start address so if we load the image
00147          * at offset 100H addresses should all line up properly again.
00148         */
00149         m_uInitPC = 0x100;
00150         m_uInitSP = 0xFFFE;
00151         m_cReloc = 0;
00152 
00153         fseek(fp, 0, SEEK_SET);
00154     }
00155 
00156     /* Allocate a block of memory for the image. */
00157     m_cbImage  = cb;
00158     m_pImage    = new Byte[m_cbImage];
00159 
00160     if (cb != (int)fread(m_pImage, 1, (size_t)cb, fp))
00161     {
00162         fprintf(stderr, "Cannot read file %s\n", sName);
00163         return 0;
00164     }
00165 
00166     /* Relocate segment constants */
00167     if (m_cReloc)
00168     {
00169         for (i = 0; i < m_cReloc; i++)
00170         {
00171             Byte *p = &m_pImage[m_pRelocTable[i]];
00172             SWord  w = (SWord)LH(p);
00173             *p++    = (Byte)(w & 0x00FF);
00174             *p      = (Byte)((w & 0xFF00) >> 8);
00175         }
00176     }
00177 
00178     fclose(fp);
00179 
00180     m_pSections[0].pSectionName = "$HEADER";    // Special header section
00181 //  m_pSections[0].fSectionFlags = ST_HEADER;
00182     m_pSections[0].uNativeAddr = 0;             // Not applicable
00183     m_pSections[0].uHostAddr = (DWord)m_pHeader;
00184     m_pSections[0].uSectionSize = sizeof(exeHeader);
00185     m_pSections[0].uSectionEntrySize = 1;       // Not applicable
00186 
00187     m_pSections[1].pSectionName = ".text";      // The text and data section
00188     m_pSections[1].bCode = true;
00189     m_pSections[1].bData = true;
00190     m_pSections[1].uNativeAddr = 0;
00191     m_pSections[1].uHostAddr = (DWord)m_pImage;
00192     m_pSections[1].uSectionSize = m_cbImage;
00193     m_pSections[1].uSectionEntrySize = 1;       // Not applicable
00194 
00195     m_pSections[2].pSectionName = "$RELOC";     // Special relocation section
00196 //  m_pSections[2].fSectionFlags = ST_RELOC;    // Give it a special flag
00197     m_pSections[2].uNativeAddr = 0;             // Not applicable
00198     m_pSections[2].uHostAddr = (DWord)m_pRelocTable;
00199     m_pSections[2].uSectionSize = sizeof(DWord) * m_cReloc;
00200     m_pSections[2].uSectionEntrySize = sizeof(DWord);
00201 
00202     return 1;
00203 
00204 }
00205 
00206 // Clean up and unload the binary image
00207 void ExeBinaryFile::UnLoad()
00208 {
00209     if (m_pHeader) delete m_pHeader;
00210     if (m_pImage) delete [] m_pImage;
00211     if (m_pRelocTable) delete [] m_pRelocTable;
00212 } 
00213 
00214 char* ExeBinaryFile::SymbolByAddr(ADDRESS dwAddr)
00215 {
00216     if (dwAddr == GetMainEntryPoint())
00217         return "main";
00218 
00219     // No symbol table handled at present
00220     return 0;
00221 }
00222 
00223 bool ExeBinaryFile::DisplayDetails(const char* fileName, FILE* f
00224      /* = stdout */)
00225 {
00226     return false;
00227 }
00228 
00229 LOAD_FMT ExeBinaryFile::GetFormat() const
00230 {
00231     return LOADFMT_EXE;
00232 }
00233 
00234 MACHINE ExeBinaryFile::GetMachine() const
00235 {
00236     return MACHINE_PENTIUM;
00237 }
00238 
00239 bool ExeBinaryFile::Open(const char* sName)
00240 {
00241     // Not implemented yet
00242     return false;
00243 }
00244 void ExeBinaryFile::Close()
00245 {
00246     // Not implemented yet
00247     return; 
00248 }
00249 bool ExeBinaryFile::PostLoad(void* handle)
00250 {
00251     // Not needed: for archives only
00252     return false;
00253 }
00254 
00255 bool ExeBinaryFile::isLibrary() const
00256 {
00257     return false;
00258 }
00259 
00260 std::list<const char *> ExeBinaryFile::getDependencyList()
00261 {
00262     return std::list<const char *>(); /* for now */
00263 }
00264 
00265 ADDRESS ExeBinaryFile::getImageBase()
00266 {
00267     return 0; /* FIXME */
00268 }
00269 
00270 size_t ExeBinaryFile::getImageSize()
00271 {
00272     return 0; /* FIXME */
00273 }
00274 
00275 // Should be doing a search for this
00276 ADDRESS ExeBinaryFile::GetMainEntryPoint()
00277 {
00278     return NO_ADDRESS;
00279 }
00280 
00281 ADDRESS ExeBinaryFile::GetEntryPoint()
00282 {
00283     // Check this...
00284     return (ADDRESS)((LH(&m_pHeader->initCS) << 4) + LH(&m_pHeader->initIP));
00285 }
00286 
00287 // This is provided for completeness only...
00288 std::list<SectionInfo*>& ExeBinaryFile::GetEntryPoints(const char* pEntry
00289   /* = "main"*/) {
00290     std::list<SectionInfo*>* ret = new std::list<SectionInfo*>;
00291 #if 0           // Copied from PalmBinaryFile.cc
00292     SectionInfo* pSect = GetSectionInfoByName("code1");
00293     if (pSect == 0)
00294         return *ret;               // Failed
00295     ret->push_back(pSect);
00296 #endif
00297     return *ret;
00298 }
00299 
00300 // This function is called via dlopen/dlsym; it returns a new BinaryFile
00301 // derived concrete object. After this object is returned, the virtual function
00302 // call mechanism will call the rest of the code in this library
00303 // It needs to be C linkage so that it its name is not mangled
00304 extern "C" {
00305 #ifdef _WIN32
00306     __declspec(dllexport)
00307 #endif
00308     BinaryFile* construct()
00309     {
00310         return new ExeBinaryFile;
00311     }    
00312 }
00313 

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