Skip to content
Snippets Groups Projects
STARSProgram.cpp 597 KiB
Newer Older
/* STARSProgram.cpp: Base class
 * Copyright 2015 by Zephyr Software LLC 
 */

#include <cstring>
#include <algorithm>
#include <iostream>
#include <sstream>
#include "interfaces/STARSTypes.h"
#include "interfaces/SMPDBInterface.h"
// #include "interfaces/abstract/all.h"
#include "base/SMPDataFlowAnalysis.h"


void STARS_Program_t::MDInitializeCallerSavedRegs(void) {
	this->STARS_MDCallerSavedRegs.clear();
	bool x86_64_ISA_flag = false;
#ifdef __EA64__
	x86_64_ISA_flag = (this->GetSTARS_ISA_Bitwidth() == 64);
#endif
	if (!x86_64_ISA_flag) {
		// 32-bit x86 uses EAX, ECX, EDX as caller-saved.
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_ax);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_cx);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_dx);
	}
	else {
		// 64-bit x86 uses EDI, ESI, EDX, ECX, R8 and R9
		//  in that order. After six arguments that fit into
		//  these regs, arguments are passed on the stack.
		// In addition, registers EAX, R10 and R11 are caller-saved
		//  but are not used to pass arguments.
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_ax);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_cx);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_dx);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_si);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_di);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_r8);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_r9);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_r10);
		this->STARS_MDCallerSavedRegs.push_back(STARS_x86_R_r11);
	}
	return;
} // end of STARS_IDA_Program_t::MDInitializeCallerSavedRegs()

void STARS_Program_t::MDInitializeArgumentRegs(void) {
	bool x86_64_ISA_flag = false;
#ifdef __EA64__
	x86_64_ISA_flag = (this->GetSTARS_ISA_Bitwidth() == 64);
#endif
	if (x86_64_ISA_flag) {
		this->STARS_MDArgumentRegs.push_back(STARS_x86_R_di);
		this->STARS_MDArgumentRegs.push_back(STARS_x86_R_si);
		this->STARS_MDArgumentRegs.push_back(STARS_x86_R_dx);
		this->STARS_MDArgumentRegs.push_back(STARS_x86_R_cx);
		this->STARS_MDArgumentRegs.push_back(STARS_x86_R_r8);
		this->STARS_MDArgumentRegs.push_back(STARS_x86_R_r9);
	}
	else {
		this->STARS_MDArgumentRegs.clear();
	}
	return;
} // end of STARS_IDA_Program_t::MDInitializeArgumentRegs()

void STARS_Program_t::MDInitializeCalleeSavedRegs(void) {
	this->STARS_MDCalleeSavedRegs.clear();
	bool x86_64_ISA_flag = false;
#ifdef __EA64__
	x86_64_ISA_flag = (this->GetSTARS_ISA_Bitwidth() == 64);
#endif
	if (!x86_64_ISA_flag) {
		// 32-bit x86 uses EAX, ECX, EDX as caller-saved, EBX, EBP, ESI, EDI as callee-saved.
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_bx);
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_bp);
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_si);
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_di);
	}
	else {
		// 64-bit x86 uses EDI, ESI, EDX, ECX, R8 and R9
		//  in that order. After six arguments that fit into
		//  these regs, arguments are passed on the stack.
		// In addition, registers EAX, R10 and R11 are caller-saved
		//  but are not used to pass arguments. The rest, besides RSP,
		//  are callee-saved.
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_bx);
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_bp);
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_r12);
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_r13);
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_r14);
		this->STARS_MDCalleeSavedRegs.push_back(STARS_x86_R_r15);
	}
	return;
} // end of STARS_IDA_Program_t::MDInitializeCalleeSavedRegs()

bool STARS_Program_t::OpenFiles(void) {
	bool success = this->OpenSecondaryFilesOnly();
	if (success) {
		this->STARS_AnnotFile = SMP_fopen(this->AnnotFileName.c_str(), "w");
		if (NULL == this->STARS_AnnotFile) {
			SMP_msg("FATAL ERROR: Cannot open annotations file %s\n", this->AnnotFileName.c_str());
			(void)SMP_fclose(this->STARS_XrefsFile);
			(void)SMP_fclose(this->STARS_CallReturnFile);
			(void)SMP_fclose(this->STARS_UninitVarFile);
			(void)SMP_fclose(this->ZST_AlarmFile);
			(void)SMP_fclose(this->STARS_InfoAnnotFile);
			if (global_STARS_program->ShouldSTARSTranslateToSPARKAda()) {
				(void)SMP_fclose(this->ZST_SPARKHeaderFile);
				(void)SMP_fclose(this->ZST_SPARKSourceFile);
			}
			success = false;
		}
	}

	return success;
} // end of STARS_Program_t::OpenFiles()

bool STARS_Program_t::OpenMainAnnotationFile(void) {
	bool success = true;
	this->STARS_AnnotFile = SMP_fopen(this->AnnotFileName.c_str(), "w");
	if (NULL == this->STARS_AnnotFile) {
		SMP_msg("FATAL ERROR: Cannot open annotations file %s\n", this->AnnotFileName.c_str());
		success = false;
	}
	return success;
} // end of STARS_Program_t::OpenMainAnnotationFile()


bool STARS_Program_t::OpenSecondaryFilesOnly(void) {
	// Open the output files except for the main annotation file.
	assert(0 < this->RootFileName.size());  // SetRootFileName() must be called previously.

	string ZSTAlarmFileName(this->GetRootFileName());
	string AlarmFileSuffix(".alarms");
	ZSTAlarmFileName += AlarmFileSuffix;
	string XrefsFileName(this->GetRootFileName());
	string XrefsFileSuffix(".STARSxrefs");
	XrefsFileName += XrefsFileSuffix;
	string CallRetFileName(this->GetRootFileName());
	string CallRetFileSuffix(".STARScallreturn");
	CallRetFileName += CallRetFileSuffix;
	string UninitVarFileName(this->GetRootFileName());
	string UninitVarFileSuffix(".STARSuninit");
	UninitVarFileName += UninitVarFileSuffix;
	string LoopsFileName(this->GetRootFileName());
	string LoopsFileSuffix(".STARSloops");
	LoopsFileName += LoopsFileSuffix;

	string SPARKSourceFileName("");
	string SPARKHeaderFileName("");
	if (global_STARS_program->ShouldSTARSTranslateToSPARKAda()) {
		// Extract "foo" from "foo.exe" to get the Ada package name
		istringstream StreamRootName(this->RootFileName);
		(void)std::getline(StreamRootName, this->PackageName, '.');
		if (this->PackageName.empty()) {
			SMP_msg("ERROR: Could not extract an Ada package name from the root of file name %s\n", this->RootFileName.c_str());
			return false;
		}
		// Convert dashes to underscores in the package name to suit Ada standards.
		replace(this->PackageName.begin(), this->PackageName.end(), '-', '_');
		SPARKSourceFileName += this->PackageName;
		string SPARKSourceFileSuffix(".ZSTSPARK.adb");
		SPARKSourceFileName += SPARKSourceFileSuffix;
		SPARKHeaderFileName += this->PackageName;
		string SPARKHeaderFileSuffix(".ZSTSPARK.ads");
		SPARKHeaderFileName += SPARKHeaderFileSuffix;
	}

	this->STARS_XrefsFile = SMP_fopen(XrefsFileName.c_str(), "w");
	if (NULL == this->STARS_XrefsFile) {
		SMP_msg("FATAL ERROR: Cannot open STARS code xrefs file %s\n", XrefsFileName.c_str());
		return false;
	}

	this->STARS_CallReturnFile = SMP_fopen(CallRetFileName.c_str(), "w");
	if (NULL == this->STARS_CallReturnFile) {
		SMP_msg("FATAL ERROR: Cannot open STARS calls and returns info file %s\n", CallRetFileName.c_str());
		(void)SMP_fclose(this->STARS_XrefsFile);
		return false;
	}

	this->STARS_UninitVarFile = SMP_fopen(UninitVarFileName.c_str(), "w");
	if (NULL == this->STARS_UninitVarFile) {
		SMP_msg("FATAL ERROR: Cannot open STARS uninitialized vars info file %s\n", UninitVarFileName.c_str());
		(void)SMP_fclose(this->STARS_XrefsFile);
		(void)SMP_fclose(this->STARS_CallReturnFile);
		return false;
	}

	this->ZST_AlarmFile = SMP_fopen(ZSTAlarmFileName.c_str(), "w");
	if (NULL == this->ZST_AlarmFile) {
Loading
Loading full blame...