home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
dosdisas.zip
/
dccsrcoo.zip
/
frontend.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-14
|
18KB
|
653 lines
/*****************************************************************************
*$Log: frontend.c,v $
* 14/10/97 MVE Modified for ExeLoader object (if -DLOADER used)
*
* Revision 2.12 94/02/22 15:16:17 cifuente
* Code generation is done.
* ,.
*
* Revision 2.11 93/12/08 16:58:34 cifuente
* FrontEnd is a void function now.
*
* Revision 2.10 93/11/18 11:39:32 emmerik
* Extra parameter to interactDis()
*
* Revision 2.9 93/11/17 16:28:38 cifuente
* Call graph references
*
* Revision 2.8 93/10/20 14:39:09 cifuente
* New level of indirection for icode array (Icode.icode[])
*
* Revision 2.7 93/10/11 11:37:33 cifuente
* First walk of HIGH_LEVEL icodes.
*
* Revision 2.6 93/10/01 08:59:28 cifuente
* boolT type - for compilation under unix SVR4.2
*
* Revision 2.5 93/09/29 10:46:38 cifuente
* LOW_LEVEL and HIGH_LEVEL icode definitions. Increases llIcode indirection
* by 2 levels.
*
* Revision 2.3 93/08/23 12:15:26 cifuente
* Interactive mode with curses
*
* Revision 2.1 93/03/30 14:51:09 cifuente
* Compiled with gcc.
*
* RevComp project Front End module
* Loads a program into simulated main memory and builds the procedure list.
****************************************************************************/
#include "dcc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __BORLAND__
#include <alloc.h>
#else
#include <malloc.h> /* For malloc, free, realloc */
#endif
#ifdef LOADER
#include "ExeLoader.h"
static ExeLoader L; // An instance of class ExeLoader
#else
typedef struct { /* PSP structure */
word int20h; /* interrupt 20h */
word eof; /* segment, end of allocation block */
byte res1; /* reserved */
byte dosDisp[5]; /* far call to DOS function dispatcher */
byte int22h[4]; /* vector for terminate routine */
byte int23h[4]; /* vector for ctrl+break routine */
byte int24h[4]; /* vector for error routine */
byte res2[22]; /* reserved */
word segEnv; /* segment address of environment block */
byte res3[34]; /* reserved */
byte int21h[6]; /* opcode for int21h and far return */
byte res4[6]; /* reserved */
byte fcb1[16]; /* default file control block 1 */
byte fcb2[16]; /* default file control block 2 */
byte res5[4]; /* reserved */
byte cmdTail[0x80]; /* command tail and disk transfer area */
} PSP;
typedef struct { /* EXE file header */
byte sigLo; /* .EXE signature: 0x4D 0x5A */
byte sigHi;
word lastPageSize; /* Size of the last page */
word numPages; /* Number of pages in the file */
word numReloc; /* Number of relocation items */
word numParaHeader; /* # of paragraphs in the header */
word minAlloc; /* Minimum number of paragraphs */
word maxAlloc; /* Maximum number of paragraphs */
word initSS; /* Segment displacement of stack */
word initSP; /* Contents of SP at entry */
word checkSum; /* Complemented checksum */
word initIP; /* Contents of IP at entry */
word initCS; /* Segment displacement of code */
word relocTabOffset; /* Relocation table offset */
word overlayNum; /* Overlay number */
} HEADER;
static HEADER header;
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
#endif /* ifdef LOADER */
static void LoadImage(char *filename);
static void displayLoadInfo(HEADER* pHeader);
static void displayMemMap(void);
/*****************************************************************************
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
* rewritter, and displays any useful information.
****************************************************************************/
void FrontEnd (char *filename, PCALL_GRAPH *pcallGraph)
{
PPROC pProc;
PSYM psym;
Int i, c;
/* Load program into memory */
LoadImage(filename);
if (option.verbose)
{
#ifdef LOADER
PSECTIONINFO pHdrScn = L.GetSectionInfoByName("$HEADER");
HEADER* pHeader = (HEADER*) pHdrScn->uHostAddr;
displayLoadInfo(pHeader);
#else
displayLoadInfo(&header);
#endif
}
/* Do depth first flow analysis building call graph and procedure list,
* and attaching the I-code to each procedure */
parse (pcallGraph);
if (option.asm1)
{
printf("dcc: writing assembler file %s\n", asm1_name);
}
/* Search through code looking for impure references and flag them */
for (pProc = pProcList; pProc; pProc = pProc->next)
{
for (i = 0; i < pProc->Icode.GetNumIcodes(); i++)
{
if (pProc->Icode.GetLlFlag(i) & (SYM_USE | SYM_DEF))
{
psym = &symtab.sym[pProc->Icode.GetIcode(i)->ic.ll.caseTbl.numEntries];
for (c = (Int)psym->label; c < (Int)psym->label+psym->size; c++)
{
if (BITMAP(c, BM_CODE))
{
pProc->Icode.SetLlFlag(i, IMPURE);
pProc->flg |= IMPURE;
break;
}
}
}
}
/* Print assembler listing */
if (option.asm1)
disassem(1, pProc);
}
if (option.Interact)
{
interactDis(pProcList, 0); /* Interactive disassembler */
}
/* Converts jump target addresses to icode offsets */
for (pProc = pProcList; pProc; pProc = pProc->next)
bindIcodeOff (pProc);
/* Print memory bitmap */
if (option.Map)
displayMemMap();
}
/****************************************************************************
* displayLoadInfo - Displays low level loader type info.
***************************************************************************/
static void displayLoadInfo(HEADER* pHeader)
{
Int i;
printf("File type is %s\n", (prog.fCOM)?"COM":"EXE");
if (! prog.fCOM) {
printf("Signature = %02X%02X\n", pHeader->sigLo, pHeader->sigHi);
printf("File size %% 512 = %04X\n", LH(&pHeader->lastPageSize));
printf("File size / 512 = %04X pages\n", LH(&pHeader->numPages));
printf("# relocation items = %04X\n", LH(&pHeader->numReloc));
printf("Offset to load image = %04X paras\n", LH(&pHeader->numParaHeader));
printf("Minimum allocation = %04X paras\n", LH(&pHeader->minAlloc));
printf("Maximum allocation = %04X paras\n", LH(&pHeader->maxAlloc));
}
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
if (option.VeryVerbose && prog.cReloc)
{
printf("\nRelocation Table\n");
for (i = 0; i < prog.cReloc; i++)
{
printf("%06X -> [%04X]\n", prog.relocTable[i],
LH(prog.Image + prog.relocTable[i]));
}
}
printf("\n");
}
#if 0
static void displayLoadInfo(void)
{
Int i;
printf("File type is %s\n", (prog.fCOM)?"COM":"EXE");
if (! prog.fCOM) {
printf("Signature = %02X%02X\n", header.sigLo, header.sigHi);
printf("File size %% 512 = %04X\n", LH(&header.lastPageSize));
printf("File size / 512 = %04X pages\n", LH(&header.numPages));
printf("# relocation items = %04X\n", LH(&header.numReloc));
printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
}
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
if (option.VeryVerbose && prog.cReloc)
{
printf("\nRelocation Table\n");
for (i = 0; i < prog.cReloc; i++)
{
printf("%06X -> [%04X]\n", prog.relocTable[i],
LH(prog.Image + prog.relocTable[i]));
}
}
printf("\n");
}
#endif
/*****************************************************************************
* fill - Fills line for displayMemMap()
****************************************************************************/
static void fill(Int ip, char *bf)
{
static byte type[4] = {'.', 'd', 'c', 'x'};
byte i;
for (i = 0; i < 16; i++, ip++)
{
*bf++ = ' ';
*bf++ = (ip < prog.cbImage)?
type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
}
*bf = '\0';
}
/*****************************************************************************
* displayMemMap - Displays the memory bitmap
****************************************************************************/
static void displayMemMap(void)
{
char c, b1[33], b2[33], b3[33];
byte i;
Int ip = 0;
printf("\nMemory Map\n");
while (ip < prog.cbImage)
{
fill(ip, b1);
printf("%06X %s\n", ip, b1);
ip += 16;
for (i = 3, c = b1[1]; i < 32 && c == b1[i]; i += 2)
; /* Check if all same */
if (i > 32)
{
fill(ip, b2); /* Skip until next two are not same */
fill(ip+16, b3);
if (! (strcmp(b1, b2) || strcmp(b1, b3)))
{
printf(" :\n");
do
{
ip += 16;
fill(ip+16, b1);
} while (! strcmp(b1, b2));
}
}
}
printf("\n");
}
/*****************************************************************************
* LoadImage
****************************************************************************/
#ifdef LOADER
static void LoadImage(char *filename)
{
/* Open the input file */
if (L.Load(filename) == 0)
{
fatalError(CANNOT_OPEN, filename);
}
PSECTIONINFO pSectHdr = L.GetSectionInfoByName("$HEADER");
PSECTIONINFO pSectImage = L.GetSectionInfoByName(".text");
PSECTIONINFO pSectReloc = L.GetSectionInfoByName("$RELOC");
prog.Image = (byte*) pSectImage->uHostAddr;
prog.cbImage = pSectImage->uSectionSize;
char* pHeader = (char*)pSectHdr->uHostAddr;
if (prog.fCOM = (boolT)((pHeader[0] == 'M') && (pHeader[1] == 'Z')))
{
unsigned initPC = L.GetInitPC();
unsigned initSP = L.GetInitSP();
prog.initCS = initPC >> 16;
prog.initIP = initPC & 0xFFFF;
prog.initSS = initSP >> 16;
prog.initSP = initSP & 0xFFFF;
// Relocation table
prog.cReloc = pSectReloc->uSectionSize / sizeof(dword);
/* Allocate the relocation table */
if (prog.cReloc)
{
prog.relocTable = (dword*) pSectReloc->uHostAddr;
}
}
else
{ /* COM file
/* COM programs start off with an ORG 100H (to leave room for a PSP)
* This is also the implied start address so if we load the image
* at offset 100H addresses should all line up properly again.
*/
prog.initCS = 0;
prog.initIP = 0x100;
prog.initSS = 0;
prog.initSP = 0xFFFE;
prog.cReloc = 0;
}
/* Set up memory map */
int cb = (prog.cbImage + 3) / 4;
prog.map = (byte *)memset(allocMem(cb), BM_UNKNOWN, (size_t)cb);
/* Note that relocation of the segment constants is done in the
ExeLoader object */
// Don't UnLoad here, since prog.Image (etc) point to the loaded
// image in the ExeLoader object.
}
void UnLoadImage()
{
L.UnLoad();
}
#else // Old loader
static void LoadImage(char *filename)
{
FILE *fp;
Int i, cb;
byte buf[4];
/* Open the input file */
if ((fp = fopen(filename, "rb")) == NULL)
{
fatalError(CANNOT_OPEN, filename);
}
/* Read in first 2 bytes to check EXE signature */
if (fread(&header, 1, 2, fp) != 2)
{
fatalError(CANNOT_READ, filename);
}
if (! (prog.fCOM = (boolT)(header.sigLo != 0x4D || header.sigHi != 0x5A))) {
/* Read rest of header */
fseek(fp, 0, SEEK_SET);
if (fread(&header, sizeof(header), 1, fp) != 1)
{
fatalError(CANNOT_READ, filename);
}
/* This is a typical DOS kludge! */
if (LH(&header.relocTabOffset) == 0x40)
{
fatalError(NEWEXE_FORMAT);
}
/* Calculate the load module size.
* This is the number of pages in the file
* less the length of the header and reloc table
* less the number of bytes unused on last page
*/
cb = (dword)LH(&header.numPages) * 512 - (dword)LH(&header.numParaHeader) * 16;
if (header.lastPageSize)
{
cb -= 512 - LH(&header.lastPageSize);
}
/* We quietly ignore minAlloc and maxAlloc since for our
* purposes it doesn't really matter where in real memory
* the program would end up. EXE programs can't really rely on
* their load location so setting the PSP segment to 0 is fine.
* Certainly programs that prod around in DOS or BIOS are going
* to have to load DS from a constant so it'll be pretty
* obvious.
*/
prog.initCS = (int16)LH(&header.initCS) + EXE_RELOCATION;
prog.initIP = (int16)LH(&header.initIP);
prog.initSS = (int16)LH(&header.initSS) + EXE_RELOCATION;
prog.initSP = (int16)LH(&header.initSP);
prog.cReloc = (int16)LH(&header.numReloc);
/* Allocate the relocation table */
if (prog.cReloc)
{
prog.relocTable = (dword*)allocMem(prog.cReloc * sizeof(Int));
fseek(fp, LH(&header.relocTabOffset), SEEK_SET);
/* Read in seg:offset pairs and convert to Image ptrs */
for (i = 0; i < prog.cReloc; i++)
{
fread(buf, 1, 4, fp);
prog.relocTable[i] = LH(buf) +
(((Int)LH(buf+2) + EXE_RELOCATION)<<4);
}
}
/* Seek to start of image */
fseek(fp, (Int)LH(&header.numParaHeader) * 16, SEEK_SET);
}
else
{ /* COM file
* In this case the load module size is just the file length
*/
fseek(fp, 0, SEEK_END);
cb = ftell(fp);
/* COM programs start off with an ORG 100H (to leave room for a PSP)
* This is also the implied start address so if we load the image
* at offset 100H addresses should all line up properly again.
*/
prog.initCS = 0;
prog.initIP = 0x100;
prog.initSS = 0;
prog.initSP = 0xFFFEU;
prog.cReloc = 0;
fseek(fp, 0, SEEK_SET);
}
/* Allocate a block of memory for the program. */
prog.cbImage = cb + sizeof(PSP);
prog.Image = (byte*)allocMem(prog.cbImage);
prog.Image[0] = 0xCD; /* Fill in PSP Int 20h location */
prog.Image[1] = 0x20; /* for termination checking */
/* Read in the image past where a PSP would go */
#ifdef __DOSWIN__
if (cb > 0xFFFF)
{
printf("Image size of %ld bytes too large for fread!\n", cb);
fatalError(CANNOT_READ, filename);
}
#endif
if (cb != (Int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
{
fatalError(CANNOT_READ, filename);
}
/* Set up memory map */
cb = (prog.cbImage + 3) / 4;
prog.map = (byte *)memset(allocMem(cb), BM_UNKNOWN, (size_t)cb);
/* Relocate segment constants */
if (prog.cReloc)
{
for (i = 0; i < prog.cReloc; i++)
{
byte *p = &prog.Image[prog.relocTable[i]];
word w = (word)LH(p) + EXE_RELOCATION;
*p++ = (byte)(w & 0x00FF);
*p = (byte)((w & 0xFF00) >> 8);
}
}
fclose(fp);
}
#endif // ifdef LOADER
/*****************************************************************************
* allocMem - malloc with failure test
****************************************************************************/
void *allocMem(Int cb)
{
byte *p;
//printf("Attempt to allocMem %5ld bytes\n", cb);
#if 0 /* Microsoft specific heap debugging code */
switch (_heapset('Z'))
{
case _HEAPBADBEGIN: printf("aM: Bad heap begin\n"); break;
case _HEAPBADNODE: printf("aM: Bad heap node\n");
printf("Attempt to allocMem %5d bytes\n", cb);
{
_HEAPINFO hinfo;
int heapstatus;
boolT cont = TRUE;
hinfo._pentry = NULL;
while (cont)
{
switch (heapstatus = _heapwalk(&hinfo))
{
case _HEAPOK:
printf("%6s block at %Fp of size %4.4X\n",
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
hinfo._pentry, hinfo._size);
break;
case _HEAPBADBEGIN:
printf("Heap bad begin\n");
break;
case _HEAPBADNODE:
printf("BAD NODE %6s block at %Fp of size %4.4X\n",
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
hinfo._pentry, hinfo._size);
break;
case _HEAPEND:
cont = FALSE;
break;
case _HEAPBADPTR:
printf("INFO BAD %6s block at %Fp of size %4.4X\n",
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
hinfo._pentry, hinfo._size);
cont=FALSE;
}
}
}
getchar();
exit(1);
case _HEAPEMPTY: printf("aM: Heap empty\n"); getchar(); break;
case _HEAPOK:putchar('.');break;
}
#endif
if (! (p = (byte*)malloc((size_t)cb)))
/* if (! (p = (byte*)calloc((size_t)cb, 1))) */
{
fatalError(MALLOC_FAILED, cb);
}
/*printf("allocMem: %p\n", p);/**/
return p;
}
/*****************************************************************************
* reallocVar - reallocs extra variable space
****************************************************************************/
void *reallocVar(void *p, Int newsize)
{
/*printf("Attempt to reallocVar %5d bytes\n", newsize);/**/
#if 0
switch (_heapset('Z'))
{
case _HEAPBADBEGIN: printf("aV: Bad heap begin\n"); /*getchar()*/; break;
case _HEAPBADNODE: printf("aV: Bad heap node\n");
printf("Attempt to reallocVar %5d bytes at %p\n", newsize, p);/**/
{
_HEAPINFO hinfo;
int heapstatus;
boolT cont = TRUE;
hinfo._pentry = NULL;
while (cont)
{
switch (heapstatus = _heapwalk(&hinfo))
{
case _HEAPOK:
printf("%6s block at %Fp of size %4.4X\n",
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
hinfo._pentry, hinfo._size);
break;
case _HEAPBADBEGIN:
printf("Heap bad begin\n");
break;
case _HEAPBADNODE:
printf("BAD NODE %6s block at %Fp of size %4.4X\n",
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
hinfo._pentry, hinfo._size);
break;
case _HEAPEND:
cont = FALSE;
break;
case _HEAPBADPTR:
printf("INFO BAD %6s block at %Fp of size %4.4X\n",
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
hinfo._pentry, hinfo._size);
cont=FALSE;
}
}
}
getchar();
break;
case _HEAPEMPTY: printf("aV: Heap empty\n"); getchar(); break;
case _HEAPOK:putchar('!');break;
}
#endif
void* newp;
if (! (newp = realloc((byte *)p, (size_t)newsize)))
{
fatalError(MALLOC_FAILED, newsize);
}
if (p && (newp != p) && option.verbose)
{
printf("Warning! realloc of %d bytes moved from %p to %p\n",
newsize, p, newp);
}
/*printf("reallocVar: %p\n", newp);/**/
return newp;
}
#if 0
void free(void *p)
{
_ffree(p);
switch (_heapset('Z'))
{
case _HEAPBADBEGIN: printf("f: Bad heap begin\n"); getchar(); break;
case _HEAPBADNODE: printf("f: Bad heap node\n"); getchar(); break;
case _HEAPEMPTY: printf("f: Heap empty\n"); getchar(); break;
case _HEAPOK:putchar('!');break;
}/**/
}
#endif