⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 init.c

📁 < 虚拟机设计与实现> 的source code, linux版本
💻 C
字号:
#include "init.h"

#include "dbgdata.h"

struct HeaderRec readHeaderRec(FILE * fptr);

/*
	init execution environment ( same way BIOS would boot a PC )
	1) open executable and read header and debug data
	2) validate header data
	3) user header data to allocate RAM and init registers ( 4GB limit imposed here )
	4) load bytecode into RAM[]
*/

U1 initHEC(struct CmdLine cl)
{
	U8 fileSize;			/* size of bytecode file in bytes */
	FILE * fptr;			/* pointer to open file */

	struct HeaderRec hr;	/*header read from file*/

	U8 bytecodeStart;		/*byte offsets into executable file*/
	U8 bytecodeEnd;

	U8 exec_bytes;			/* bytes in bytecode section of RAM[] */
	U8 total_bytes;			/* total bytes allocated for RAM[] */
	U8 free_bytes;			/* available physical RAM */

	U8 index;				/*index into file*/
	U8 i;					/*index into RAM[]*/
	int read_byte;		

	/*1) open executable and read header and debug data */

	fileSize = getFileSize(cl.binaryFile);

	if (fileSize == 0)
	{
		ERROR0("initHEC(): executable has zero size");
		return FALSE;	
	}

	fptr = fopen(cl.binaryFile, "rb");
	if (fptr == NULL)
	{
		ERROR1("initHEC(): cannot open %s", cl.binaryFile);
		return FALSE;
	}

	hr.magic = 0;
	hr.szByteCode = 0;
	hr.szStrTbl = 0;
	hr.szSymTbl = 0;
	
	hr = readHeaderRec(fptr);
	if (nErrors > 0)
	{
		if (fclose(fptr))
		{ 
			ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
		}
		fptr = NULL;
		return FALSE;
	}

	DBG_INIT0("finished reading header and symbol table\n");
	DBG_INIT1("magic number=%X\n", hr.magic);
	DBG_INIT1("symbol table size=%lu\n", hr.szSymTbl);
	DBG_INIT1("string table size=%lu\n", hr.szStrTbl);
	DBG_INIT1("bytecode table size=%lu\n", hr.szByteCode);

	if ((hr.szSymTbl != 0) || (hr.szStrTbl != 0))
	{
		populateDebugData(hr, &debugData, fptr);
		if (nErrors > 0)
		{
            if (fclose(fptr))
			{ 
			    ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
			}
		    fptr = NULL;
		    return FALSE;
		}
	}

	/*2) validate header data */

	if (hr.magic != (U2)APPLICATION)
	{
		ERROR0("initHEC(): file not HEC executable");
		if (fclose(fptr))
		{ 
			ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
		}
		fptr = NULL;
		return FALSE;
	}

	if (hr.szByteCode == 0)
	{
		ERROR1("initHEC(): no bytecode in %s", cl.binaryFile);
		if (fclose(fptr))
		{ 
			ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
		}
		fptr = NULL;
		return FALSE;
	}

	/*3) user header data to allocate RAM and init registers*/
	
	bytecodeStart = SIZE_HEADER + hr.szSymTbl + hr.szStrTbl;
	bytecodeEnd = bytecodeStart + (hr.szByteCode - 1);

	DBG_INIT1("bytecodeStart in file=%lu\n", bytecodeStart);
	DBG_INIT1("bytecodeEnd in file=%lu\n", bytecodeEnd);

	exec_bytes = bytecodeEnd - bytecodeStart + 1;
	total_bytes = exec_bytes + cl.heapRequest * 1024 + cl.stackRequest * 1024;

	free_bytes = getAvailableMemory();
	if (total_bytes > free_bytes)
	{
		ERROR0("initHEC(): not enough memory to init runtime");
		if (fclose(fptr))
		{ 
			ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
		}
		fptr = NULL;
		return FALSE;
	}

	DBG_INIT1("available physical RAM= %lu\n", free_bytes );
    DBG_INIT1("file size= %lu\n", fileSize );
	DBG_INIT1("size of bytecode in file= %lu\n", exec_bytes );
	DBG_INIT1("heap bytes= %lu\n", cl.heapRequest * 1024 );
	DBG_INIT1("stack bytes= %lu\n", cl.stackRequest * 1024 );
	DBG_INIT1("total required bytes= %lu\n", total_bytes );

	/* we're legal, so can allocate RAM  */

	printf("allocating %lu bytes\n", total_bytes); 

	/* U4 size limit is imposed here!!!! */
	if (RAM != NULL)
	{
		ERROR0("initHEC(): RAM IS NOT NULL in init runtime");
		if (fclose(fptr))
		{ 
			ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
		}
		fptr = NULL;
		return FALSE;
	}
	RAM = ( U1* )malloc((U4)total_bytes); 
    if (RAM == NULL)
	{
		ERROR0("initHEC(): not enough memory.");
		if (fclose(fptr))
		{ 
			ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
		}
		fptr = NULL;
		return FALSE;
	}
	
	/*
		now set up registers
		
		memory layout:  [0 -> $BE] [$HS -> $HE] [$SS -> $TOP]
	*/

	DBG_INIT0("setting up registers\n");

	R[$IP] = 0;
	R[$SP] = total_bytes - 1;
	R[$FP] = 0;
	R[$BE] = exec_bytes - 1;

	R[$HS] = exec_bytes;
	R[$HE] = exec_bytes + (cl.heapRequest * 1024) - 1;

	R[$SS] = exec_bytes + (cl.heapRequest * 1024);
	R[$TOP] = total_bytes - 1; 

	appMetaData.fileSize = fileSize;
	appMetaData.szSymTbl = hr.szSymTbl;
	appMetaData.szStrTbl = hr.szStrTbl;
	appMetaData.szByteCode = hr.szByteCode;
	appMetaData.bCodeFileStart = bytecodeStart;
	appMetaData.bCodeFileEnd = bytecodeEnd;
	appMetaData.heapSize = cl.heapRequest * 1024;
	appMetaData.stackSize = cl.stackRequest * 1024;
	appMetaData.ram = total_bytes;

	/*4) load bytecode into RAM[] */

	/*load bytecode into RAM*/

	rewind(fptr);	/* rewind to start of file */

	/* 
	note: fseek starts index at zero, so our scheme is correct
	note: (U4) cast, limits us to 4GB file
	*/

	if (fseek(fptr, (U4)bytecodeStart, SEEK_SET))
	{
		ERROR0("initHEC(): could not find bytecode start");
		if (fclose(fptr))
		{ 
			ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
		}
		fptr = NULL;
		return FALSE;
	}

	i = 0;
	for (index = bytecodeStart; index <= bytecodeEnd; index++)
	{
		read_byte = fgetc(fptr);
		if (read_byte == EOF)
		{
			ERROR0("initHEC(): error reading bytecode file");
			if (fclose(fptr))
			{ 
			    ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
			}
		    fptr = NULL;
			return FALSE;
		}
		RAM[i] = (U1)read_byte;
		i++;
	}

	if (fclose(fptr))
	{ 
	    ERROR1("initHEC(): could not close file %s", cl.binaryFile); 
	}
    fptr = NULL;
	return TRUE;

} /*end initHEC*/

void closeHEC()
{
	if (RAM != NULL)
	{ 
		free(RAM); 
		RAM = NULL;

		DBG_INIT0("RAM freed.\n");
	}
	else
	{  
		printf("closeHEC(): no RAM[] allocated\n"); 
	}
}

struct HeaderRec readHeaderRec(FILE * fptr)
{
	struct HeaderRec hr;
	int i;
	U1 debugbytes[SIZE_HEADER];

	hr.magic = 0;
	hr.szByteCode = 0;
	hr.szStrTbl = 0;
	hr.szSymTbl = 0;

	i = fread(debugbytes, sizeof(U1), SIZE_HEADER, fptr);
	if (i < SIZE_HEADER)
	{
		ERROR0("error occurred when reading header record.");
        return hr;
	}
	
	if ((debugbytes[0] == 0xDE) && (debugbytes[1] == 0xED))
	{ 
		hr.magic = 0xDEED; 
	}
	else
	{ 
		hr.magic = 0xBAD; 
	}

#ifdef ENDIANCHANGE_NEEDED 
	hr.szSymTbl = bytecodeToQWord(&(debugbytes[2]));
	hr.szStrTbl = bytecodeToQWord(&(debugbytes[10]));
	hr.szByteCode = bytecodeToQWord(&(debugbytes[18]));
#else
    hr.szSymTbl = (U8)*((U8 *)&debugbytes[2]);
    hr.szStrTbl = (U8)*((U8 *)&debugbytes[10]);
    hr.szByteCode = (U8)*((U8 *)&debugbytes[18]);
#endif

	return hr;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -