home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dosdisas.zip / dccsrcoo.zip / ExeLoader.cpp < prev    next >
C/C++ Source or Header  |  1997-10-14  |  6KB  |  213 lines

  1. /* EXE binary file format.
  2.     This file implements the class ExeLoader, derived from class Loader.
  3.     See ExeLoader.h and Loader.h for details
  4.     MVE 08/10/97
  5. */
  6.  
  7. #include "ExeLoader.h"
  8.  
  9. ExeLoader::ExeLoader()
  10. {
  11. }
  12.  
  13. int ExeLoader::Load(const char* sName)
  14. {
  15.     FILE   *fp;
  16.     int        i, cb;
  17.     byte    buf[4];
  18.     int        fCOM;
  19.  
  20.     // Always just 3 sections
  21.     m_pSections = new SECTIONINFO[3];
  22.     if (m_pSections == 0)
  23.     {
  24.         printf("Could not allocate section information\n");
  25.         return 0;
  26.     }
  27.     m_iNumSections = 3;
  28.  
  29.     m_pHeader = new HEADER;
  30.     if (m_pHeader == 0)
  31.     {
  32.         printf("Could not allocate header memory\n");
  33.         return 0;
  34.     }
  35.  
  36.     /* Open the input file */
  37.     if ((fp = fopen(sName, "rb")) == NULL)
  38.     {
  39.         printf("Could not open file %s\n", sName);
  40.         return 0;
  41.     }
  42.  
  43.     /* Read in first 2 bytes to check EXE signature */
  44.     if (fread(m_pHeader, 1, 2, fp) != 2)
  45.     {
  46.         printf("Cannot read file %s\n", sName);
  47.         return 0;
  48.     }
  49.  
  50.     // Check for the "MZ" exe header
  51.     if (! (fCOM = (m_pHeader->sigLo != 0x4D || m_pHeader->sigHi != 0x5A)))
  52.     {
  53.         /* Read rest of m_pHeader */
  54.         fseek(fp, 0, SEEK_SET);
  55.         if (fread(m_pHeader, sizeof(HEADER), 1, fp) != 1)
  56.         {
  57.             printf("Cannot read file %s\n", sName);
  58.             return 0;
  59.         }
  60.  
  61.         /* This is a typical DOS kludge! */
  62.         if (LH(&m_pHeader->relocTabOffset) == 0x40)
  63.         {
  64.             printf("Error - NE format executable\n");
  65.             return 0;
  66.         }
  67.  
  68.         /* Calculate the load module size.
  69.          * This is the number of pages in the file
  70.          * less the length of the m_pHeader and reloc table
  71.          * less the number of bytes unused on last page
  72.         */
  73.         cb = (dword)LH(&m_pHeader->numPages) * 512 -
  74.             (dword)LH(&m_pHeader->numParaHeader) * 16;
  75.         if (m_pHeader->lastPageSize)
  76.         {
  77.             cb -= 512 - LH(&m_pHeader->lastPageSize);
  78.         }
  79.         
  80.         /* We quietly ignore minAlloc and maxAlloc since for our
  81.          * purposes it doesn't really matter where in real memory
  82.          * the m_am would end up.  EXE m_ams can't really rely on
  83.          * their load location so setting the PSP segment to 0 is fine.
  84.          * Certainly m_ams that prod around in DOS or BIOS are going
  85.          * to have to load DS from a constant so it'll be pretty 
  86.          * obvious.
  87.         */
  88.         m_cReloc = (int16)LH(&m_pHeader->numReloc);
  89.  
  90.         /* Allocate the relocation table */
  91.         if (m_cReloc)
  92.         {
  93.             m_pRelocTable = new dword[m_cReloc];
  94.             if (m_pRelocTable == 0)
  95.             {
  96.                 printf("Could not allocate relocation table (%d entries)\n",
  97.                     m_cReloc);
  98.                 return 0;
  99.             }
  100.             fseek(fp, LH(&m_pHeader->relocTabOffset), SEEK_SET);
  101.  
  102.             /* Read in seg:offset pairs and convert to Image ptrs */
  103.             for (i = 0; i < m_cReloc; i++)
  104.             {
  105.                 fread(buf, 1, 4, fp);
  106.                 m_pRelocTable[i] = LH(buf) + 
  107.                     (((int)LH(buf+2) + EXE_RELOCATION)<<4);
  108.             }
  109.         }
  110.  
  111.         /* Seek to start of image */
  112.         fseek(fp, (int)LH(&m_pHeader->numParaHeader) * 16, SEEK_SET);
  113.  
  114.         // Initial PC and SP. Note that we fake the seg:offset by putting
  115.         // the segment in the top half, and offset int he bottom
  116.         m_uInitPC = (LH(&m_pHeader->initCS) + EXE_RELOCATION) << 16 +
  117.             LH(&m_pHeader->initIP);
  118.         m_uInitSP = (LH(&m_pHeader->initSS) + EXE_RELOCATION) << 16 +
  119.             LH(&m_pHeader->initSP);
  120.     }
  121.     else
  122.     {    /* COM file
  123.          * In this case the load module size is just the file length
  124.         */
  125.         fseek(fp, 0, SEEK_END);
  126.         cb = ftell(fp);
  127.  
  128.         /* COM programs start off with an ORG 100H (to leave room for a PSP)
  129.          * This is also the implied start address so if we load the image
  130.          * at offset 100H addresses should all line up properly again.
  131.         */
  132.         m_uInitPC = 0x100;
  133.         m_uInitSP = 0xFFFE;
  134.         m_cReloc = 0;
  135.  
  136.         fseek(fp, 0, SEEK_SET);
  137.     }
  138.  
  139.     /* Allocate a block of memory for the image. */
  140.     m_cbImage  = cb + sizeof(PSP);
  141.     m_pImage    = new byte[m_cbImage];
  142.     m_pImage[0] = 0xCD;        /* Fill in PSP int 20h location */
  143.     m_pImage[1] = 0x20;        /* for termination checking     */
  144.  
  145.     /* Read in the image past where a PSP would go */
  146. #ifdef __DOSWIN__
  147.     if (cb > 0xFFFF)
  148.     {
  149.         printf("Image size of %ld bytes too large for fread!\n", cb);
  150.         return 0;
  151.     }
  152. #endif
  153.     if (cb != (int)fread(m_pImage + sizeof(PSP), 1, (size_t)cb, fp))
  154.     {
  155.         printf("Cannot read file %s\n", sName);
  156.         return 0;
  157.     }
  158.  
  159.     /* Relocate segment constants */
  160.     if (m_cReloc)
  161.     {
  162.         for (i = 0; i < m_cReloc; i++)
  163.         {
  164.             byte *p = &m_pImage[m_pRelocTable[i]];
  165.             word  w = (word)LH(p) + EXE_RELOCATION;
  166.             *p++    = (byte)(w & 0x00FF);
  167.             *p      = (byte)((w & 0xFF00) >> 8);
  168.         }
  169.     }
  170.  
  171.     fclose(fp);
  172.  
  173.     m_pSections[0].pSectionName = "$HEADER";    // Special header section
  174.     m_pSections[0].fSectionFlags = ST_HEADER;
  175.     m_pSections[0].uNativeAddr = 0;                // Not applicable
  176.     m_pSections[0].uHostAddr = (unsigned)m_pHeader;
  177.     m_pSections[0].uSectionSize = sizeof(HEADER);
  178.     m_pSections[0].uSectionEntrySize = 1;        // Not applicable
  179.  
  180.     m_pSections[1].pSectionName = ".text";        // The text and data section
  181.     m_pSections[1].fSectionFlags = ST_CODE | ST_DATA | ST_PRIMARY;
  182.     m_pSections[1].uNativeAddr = 0x00100000;    // x86 address 0010:0000
  183.     m_pSections[1].uHostAddr = (unsigned)m_pImage;
  184.     m_pSections[1].uSectionSize = m_cbImage;
  185.     m_pSections[1].uSectionEntrySize = 1;        // Not applicable
  186.  
  187.     m_pSections[2].pSectionName = "$RELOC";        // Special relocation section
  188.     m_pSections[2].fSectionFlags = ST_RELOC;    // Give it a special flag
  189.     m_pSections[2].uNativeAddr = 0;                // Not applicable
  190.     m_pSections[2].uHostAddr = (unsigned)m_pRelocTable;
  191.     m_pSections[2].uSectionSize = sizeof(dword) * m_cReloc;
  192.     m_pSections[2].uSectionEntrySize = sizeof(dword);
  193.  
  194.     return 1;
  195.  
  196. }
  197.  
  198. int ExeLoader::GetNextPart()
  199. {
  200.     // Never another part
  201.     return 0;
  202. }
  203.  
  204. // Clean up and unload the binary image
  205. void ExeLoader::UnLoad()
  206. {
  207.     if (m_pHeader) delete m_pHeader;
  208.     if (m_pImage) delete [] m_pImage;
  209.     if (m_pRelocTable) delete [] m_pRelocTable;
  210.  
  211.  
  212.