Skip to content
Snippets Groups Projects
SMPDataFlowAnalysis.cpp 393 KiB
Newer Older
	// To change a field within a set, we must grab a copy, change the copy,
	//  delete the old set member, and insert the updated copy as a new member.
	set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp);
	assert(CurrRef != this->Refs.end());
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetNoOverflow(NoOverflowFlag);
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	CurrRef = InsertResult.first;
	return CurrRef;
} // end of DefOrUseSet::SetNoOverflow()

// Debug printing.
	set<DefOrUse, LessDefUse>::iterator CurrRef;
	for (CurrRef = this->Refs.begin(); CurrRef != this->Refs.end(); ++CurrRef) {
		CurrRef->Dump();
	}
clc5q's avatar
clc5q committed
// Do all types agree, ignoring any flags registers in the set? This is used
//  for conditional move instructions; if all types agree, it does not matter
//  whether the move happens or not.
bool DefOrUseSet::TypesAgreeNoFlags(void) {
	bool FoundFirstUse = false;
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	SMPOperandType UseType = UNINIT;
	for (CurrUse = this->Refs.begin(); CurrUse != this->Refs.end(); ++CurrUse) {
		if (!(CurrUse->GetOp()->MatchesReg(X86_FLAGS_REG))) { // ignore flags
			if (!FoundFirstUse) {
				FoundFirstUse = true;
				UseType = CurrUse->GetType();
			}
			else {
				if (IsNotEqType(CurrUse->GetType(), UseType)) {
					return false; // inconsistent types
				}
			}
		}
	}
	return true;
} // end of DefOrUseSet::TypesAgreeNoFlags()

clc5q's avatar
clc5q committed
// *****************************************************************
// Class DefOrUseList
// *****************************************************************

// Default constructor.
DefOrUseList::DefOrUseList(void) {
clc5q's avatar
clc5q committed
	return;
}

// Set a Def or Use into the list, along with its type.
void DefOrUseList::SetRef(STARSOpndTypePtr Ref, SMPOperandType Type, int SSASub) {
clc5q's avatar
clc5q committed
	DefOrUse CurrRef(Ref, Type, SSASub);
	this->Refs.push_back(CurrRef);
clc5q's avatar
clc5q committed
	return;
}

// Get a reference by index.
clc5q's avatar
clc5q committed
DefOrUse DefOrUseList::GetRef(size_t index) const {
clc5q's avatar
clc5q committed
	return Refs[index];
}

// Change the SSA subscript for a reference.
void DefOrUseList::SetSSANum(size_t index, int NewSSASub) {
	this->Refs[index].SetSSANum(NewSSASub);
	return;
}

// Change the operand type for a reference.
void DefOrUseList::SetType(size_t index, SMPOperandType Type, const SMPInstr* Instr) {
	this->Refs[index].SetType(Type,Instr);
	return;
}

// Debug printing.
void DefOrUseList::Dump(void) const {
	for (size_t index = 0; index < this->Refs.size(); ++index) {
		Refs[index].Dump();
	}
	return;
}

// Erase duplicate entries, in case SMPInstr::MDFixupDefUseLists() adds one.
void DefOrUseList::EraseDuplicates(void) {
	set<STARSOpndTypePtr, LessOp> TempRefs; // Use STL set to find duplicates
	set<STARSOpndTypePtr, LessOp>::iterator TempIter;
	vector<DefOrUse>::iterator RefIter;

	RefIter = this->Refs.begin();
	while (RefIter != this->Refs.end()) {
		TempIter = TempRefs.find(RefIter->GetOp());
		if (TempIter == TempRefs.end()) { // not already in set
			TempRefs.insert(RefIter->GetOp());
			++RefIter;
		}
		else { // found it in set already
			RefIter = this->Refs.erase(RefIter);
		}
	}
	return;
} // end of DefOrUseList::EraseDuplicates()

clc5q's avatar
clc5q committed
// *****************************************************************
// Class SMPPhiFunction
// *****************************************************************

// Constructor
SMPPhiFunction::SMPPhiFunction(int GlobIndex, const DefOrUse &Def) {
clc5q's avatar
clc5q committed
	this->index = GlobIndex;
clc5q's avatar
clc5q committed
	return;
clc5q's avatar
clc5q committed
}

DefOrUse SMPPhiFunction::GetDefCopy(void) const {
	DefOrUse DefCopy(this->DefName);
	return DefCopy;
}

clc5q's avatar
clc5q committed
// Add a phi item to the list
void SMPPhiFunction::PushBack(DefOrUse Ref) {
	this->SubscriptedOps.SetRef(Ref.GetOp(), Ref.GetType(), Ref.GetSSANum());
	return;
}

// Set the SSA number of the defined variable.
void SMPPhiFunction::SetSSADef(int NewSSASub) {
	this->DefName.SetSSANum(NewSSASub);
	return;
}

// Set the SSA number of the input variable.
void SMPPhiFunction::SetSSARef(size_t index, int NewSSASub) {
	this->SubscriptedOps.SetSSANum(index, NewSSASub);
	return;
}

// Set the type of the defined variable.
void SMPPhiFunction::SetDefType(SMPOperandType Type, const SMPInstr* Instr) {
	this->DefName.SetType(Type, Instr);
	return;
}

// Set the type of the input variable.
void SMPPhiFunction::SetRefType(size_t index, SMPOperandType Type, const SMPInstr* Instr) {
	this->SubscriptedOps.SetType(index, Type, Instr);
// Set the metadata status of the DEF variable.
void SMPPhiFunction::SetDefMetadata(SMPMetadataType Status) {
	this->DefName.SetMetadataStatus(Status);
	return;
} // end of SMPPhiFunction::SetDefMetadata()

// Does at least one USE have a type other than UNINIT?
bool SMPPhiFunction::HasTypedUses(void) {
	size_t index;
	for (index = 0; index < this->GetPhiListSize(); ++index) {
		if (UNINIT != this->GetUseType(index))
			return true;
	}
	return false;
} // end of SMPPhiFunction::HasTypedUses()

// Return the result of applying the conditional type propagation meet operator
//  over all the USE types.
SMPOperandType SMPPhiFunction::ConditionalMeetType(SMPBasicBlock *CurrBlock) const {
	SMPOperandType MeetType;
	SMPOperandType PtrType = UNINIT;
	SMPOperandType NumericType = UNINIT; // can end up NUMERIC or CODEPTR
	bool FoundUNINIT  = false; // any USE type UNINIT?
	bool FoundNUMERIC = false; // any USE type NUMERIC?
	bool FoundZero = false; // was DEF to zero? (could be POINTER or NUMERIC
	bool FoundPOINTER = false; // includes all POINTER subtypes
	bool FoundUNKNOWN = false; // any USE type UNKNOWN?
	bool FoundPTROFFSET = false; // any USE type PTROFFSET?
	bool FoundNEGATEDPTR = false; // any USE type NEGATEDPTR?
	bool ProfilerDerived = false; // was any USE type Profiler-derived?
	list<size_t> ZeroConstIndices;
	ea_t BlockStartAddr = CurrBlock->GetFirstAddr(); // for debugging
	STARSOpndTypePtr PhiOp = this->GetAnyOp();

	for (size_t index = 0; index < this->GetPhiListSize(); ++index) {
		SMPOperandType UseType = this->GetUseType(index);
		if (IsEqType(UseType, UNINIT))
			FoundUNINIT = true;
		else if (IsNumeric(UseType)) {
			// Check for possibility that we aggressively declared NUMERIC when register was set to zero.
			int UseSSANum = this->GetUseSSANum(index);
			bool CurrentUseZeroCase = false;
			if (MDIsDataFlowOpnd(PhiOp, false)) {
				ea_t DefAddr = CurrBlock->GetFunc()->GetGlobalDefAddr(PhiOp, UseSSANum);
				// Handle simple case: DEF is in an instruction.
				if ((BADADDR != DefAddr) && (DefAddr < STARS_PSEUDO_ID_MIN)) {
					SMPInstr *DefInst = CurrBlock->GetFunc()->GetInstFromAddr(DefAddr);
					CurrentUseZeroCase = DefInst->IsSetToZero();
				}
			}
			if (CurrentUseZeroCase) {
				FoundZero = true;
				ZeroConstIndices.push_back(index);
				FoundNUMERIC = true;
				if (IsEqType(NumericType, CODEPTR)) {
					// Already refined. If current type agrees, leave it
					//  alone, else revert to generic type NUMERIC.
					if (IsNotEqType(UseType, NumericType))
						NumericType = NUMERIC;
				}
				else {
					// Have not yet refined NumericType; might still be UNINIT.
					if (IsEqType(UNINIT, NumericType))
						NumericType = UseType;
					else { // NumericType is NUMERIC; leave it as NUMERIC.
						assert(IsEqType(NUMERIC, NumericType));
					}
				}
			}
		}
		else if (IsDataPtr(UseType)) {
			FoundPOINTER = true;
			// Perform a meet over the pointer types.
			if (IsRefinedDataPtr(PtrType)) {
				// Already refined. If current type agrees, leave it
				//  alone, else revert to generic type POINTER.
				if (IsNotEqType(UseType, PtrType))
					PtrType = POINTER;
			}
			else {
				// Have not yet refined PtrType; might still be UNINIT.
				if (IsEqType(UNINIT, PtrType))
					PtrType = UseType;
				else { // PtrType is POINTER because we saw POINTER or
					// had a conflict between pointer refinements; leave
					// it as POINTER.
					assert(IsEqType(POINTER, PtrType));
				}
			}
		}
		else if (IsEqType(PTROFFSET, UseType)) 
			FoundPTROFFSET = true;
		else if (IsEqType(NEGATEDPTR, UseType)) 
			FoundNEGATEDPTR = true;
		else if (IsUnknown(UseType))
			FoundUNKNOWN = true;

		if (IsProfDerived(UseType))
			ProfilerDerived = true;
	}

	// Use the boolean flags to compute the meet function.
	if (FoundUNKNOWN || (FoundNUMERIC && FoundPOINTER) 
		|| ((FoundNUMERIC || FoundPOINTER || FoundNEGATEDPTR) && FoundPTROFFSET)
		|| ((FoundNUMERIC || FoundPOINTER || FoundPTROFFSET) && FoundNEGATEDPTR))
		MeetType = UNKNOWN;
	else if (FoundNUMERIC)
		MeetType = NumericType;
		if (FoundZero) { // mixture of POINTER and const zero DEFs, i.e. ptr := NULL;
			// Undo the aggressive NUMERIC inference when registers are set to zero.
			//  NOTE: There cannot be any alterations to the reg between the zero DEF and
			//  the current block on at least one path, or it would not show up in the Phi function with the
			//  current SSA number.
			do {
				size_t ZeroConstIndex = ZeroConstIndices.front();
				int UseSSANum = this->GetUseSSANum(ZeroConstIndex);
				ea_t DefAddr = CurrBlock->GetFunc()->GetGlobalDefAddr(PhiOp, UseSSANum);
				// Handle simple case: DEF is in an instruction.
				if ((BADADDR != DefAddr) && (DefAddr < STARS_PSEUDO_ID_MIN)) {
					SMPInstr *DefInst = CurrBlock->GetFunc()->GetInstFromAddr(DefAddr);
					set<DefOrUse, LessDefUse>::iterator DefIter = DefInst->SetDefType(PhiOp, PtrType);
					SMP_msg("INFO: Converting zeroed reg from NUMERIC to POINTER at %lx for Block at %lx\n",
						(unsigned long) DefAddr, (unsigned long) BlockStartAddr);
					CurrBlock->GetFunc()->ResetProcessedBlocks();
					SMPBasicBlock *DefBlock = CurrBlock->GetFunc()->GetBlockFromInstAddr(DefAddr);
#if 0 // Causes infinite loops, crashes; need to debug !!!!****!!!!
					DefBlock->PropagateGlobalDefType(PhiOp, PtrType, UseSSANum, false, true);
#else
					DefBlock->PropagateGlobalDefType(PhiOp, PtrType, UseSSANum, false, false);
#endif
				}
				ZeroConstIndices.pop_front();
			} while (!ZeroConstIndices.empty());
		}
	}
	else if (FoundPTROFFSET)
		MeetType = PTROFFSET;
	else if (FoundNEGATEDPTR)
		MeetType = NEGATEDPTR;
	else if (FoundZero && (!FoundUNINIT)) // nothing but zeroes
		MeetType = NUMERIC;
	else {
		assert(FoundUNINIT);
		MeetType = UNINIT;
	}
	if (ProfilerDerived)
		MeetType = MakeProfDerived(MeetType);
	return MeetType;
} // end of SMPPhiFunction::ConditionalMeetType()

// Debug printing.
void SMPPhiFunction::Dump(void) const {
// *****************************************************************
// Class SMPDefUseChain
// *****************************************************************

// Constructors
SMPDefUseChain::SMPDefUseChain(void) {
	this->RefInstrs.push_back((unsigned short) BADADDR);
SMPDefUseChain::SMPDefUseChain(STARSOpndTypePtr Name, ea_t Def) {
void SMPDefUseChain::SetName(STARSOpndTypePtr Name) {
	STARSOpndTypePtr Name2 = nullptr;
	if (Name->IsRegOp()) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name2 = CloneIfSubwordReg(Name);
		CanonicalizeOpnd(Name2);
	}
	else {
		Name2 = Name;
	return;
}

// Set the DEF instruction.
void SMPDefUseChain::SetDef(ea_t Def) {
	this->RefInstrs[0] = (unsigned short) Def;
	return;
}

// Push a USE onto the list
void SMPDefUseChain::PushUse(ea_t Use) {
	this->RefInstrs.push_back((unsigned short) Use);
// Set the indirect memory write flag.
void SMPDefUseChain::SetIndWrite(bool IndMemWrite) {
	this->IndWrite = IndMemWrite;
	return;
}

void SMPDefUseChain::Dump(int SSANum) const {
	PrintListOperand(this->SSAName, SSANum);
	if (this->RefInstrs.size() < 1) {
	SMP_msg("\n DEF: %x USEs: ", this->RefInstrs.at(0));
	size_t index;
	for (index = 1; index < this->RefInstrs.size(); ++index)
		SMP_msg("%x ", this->RefInstrs.at(index));
	SMP_msg("\n");
	return;
} // end of SMPDefUseChain::Dump()

// *****************************************************************
// Class SMPDUChainArray
// *****************************************************************
SMPDUChainArray::SMPDUChainArray(void) {
	this->DUChains.clear();
SMPDUChainArray::SMPDUChainArray(STARSOpndTypePtr Name, ea_t FirstAddrMinusOne) {
	STARSOpndTypePtr Name2 = nullptr;
	if (Name->IsRegOp()) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name2 = CloneIfSubwordReg(Name);
		CanonicalizeOpnd(Name2);
	else {
		Name2 = Name;
	}
	this->SSAName = Name2;
	this->BaseAddr = FirstAddrMinusOne;
	this->DUChains.clear();
ea_t SMPDUChainArray::GetLastUse(int SSANum) const {
	ea_t TempAddr = DUChains.at(SSANum).GetLastUse();
	if (BADADDR != TempAddr) {
		// If BADADDR, leave it as BADADDR. Otherwise, add in BaseAddr.
		TempAddr += this->BaseAddr;
	}
	return TempAddr;
}

void SMPDUChainArray::SetName(STARSOpndTypePtr Name, ea_t FirstAddrMinusOne) {
	STARSOpndTypePtr Name2 = nullptr;
	if (Name->IsRegOp()) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name2 = CloneIfSubwordReg(Name);
		CanonicalizeOpnd(Name2);
	}
	else {
		Name2 = Name;
	this->BaseAddr = FirstAddrMinusOne;
	for (index = 0; index < this->GetSize(); ++index) {
		this->DUChains.at(index).Dump((int) index);
	}
	return;
}

// *****************************************************************
// Class SMPCompleteDUChains
// *****************************************************************

// DEBUG dump.
void SMPCompleteDUChains::Dump(void) const {
	size_t index;
	for (index = 0; index < this->ChainsByName.size(); ++index) {
		this->ChainsByName.at(index).Dump();
	}
	return;
} // end of SMPCompleteDUChains::Dump()

// *****************************************************************
// Class STARSBitSet
// *****************************************************************

// Constructors.
STARSBitSet::STARSBitSet() {
	this->BitLimit = 0;
}

// Get methods
bool STARSBitSet::GetBit(size_t BitIndex) const {
	size_t ByteIndex = BitIndex / 8;
	size_t BitNumber = BitIndex % 8;
	return (0 != (this->STARSBits.at(ByteIndex) & STARSBitMasks[BitNumber]));
}

// Set methods
void STARSBitSet::AllocateBits(size_t Size) {
	size_t Bytes = Size / 8;
	size_t ExtraBits = Size % 8;
		this->STARSBits.resize(1 + Bytes);
		this->STARSBits.resize(Bytes);
	}
	for (Bytes = 0; Bytes < this->STARSBits.size(); ++Bytes) {
		this->STARSBits[Bytes] = 0;
	}
}

void STARSBitSet::SetBit(size_t BitIndex) {
	size_t ByteIndex = BitIndex / 8;
	size_t BitNumber = BitIndex % 8;
	this->STARSBits[ByteIndex] |= STARSBitMasks[BitNumber];
	return;
}

void STARSBitSet::ResetBit(size_t BitIndex) {
	size_t ByteIndex = BitIndex / 8;
	size_t BitNumber = BitIndex % 8;
	this->STARSBits[ByteIndex] &= (~STARSBitMasks[BitNumber]);
	return;
}

// Query methods

// Returns false if all bits are zero, true otherwise.
bool STARSBitSet::IsAnyBitSet(void) const {
	bool FoundSetBit = false;
	size_t ByteIndex;
	for (ByteIndex = 0; ByteIndex < this->STARSBits.size(); ++ByteIndex) {
		if (0 != this->STARSBits[ByteIndex]) {
			FoundSetBit = true;
			break;
		}
	}

	return FoundSetBit;
}

// Map system or library call name to FG info about its return value.
static map<string, struct FineGrainedInfo> ReturnRegisterTypeMap;

// Map system or library call name to the annotation substring that
//  guides saturating arithmetic or other continuation policies in 
//  the case of integer error detection of a value passed to that call.
// If we don't care about a certain call, we return an empty string.
static map<string, string> IntegerErrorCallSinkMap;

void InitIntegerErrorCallSinkMap(void) {
	pair<string, string> MapEntry;
	pair<map<string, string>::iterator, bool> InsertResult;

	MapEntry.first = string("malloc");
	MapEntry.second = string("SINKMALLOC");
	InsertResult = IntegerErrorCallSinkMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("calloc");
	MapEntry.second = string("SINKMALLOC");
	InsertResult = IntegerErrorCallSinkMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("realloc");
	MapEntry.second = string("SINKMALLOC");
	InsertResult = IntegerErrorCallSinkMap.insert(MapEntry);
	assert(InsertResult.second);

	return;
}

// Return sink string for call name from the sink map.
// If we don't care find the call name, we return an empty string.
void GetSinkStringForCallName(string CalleeName, string &SinkString) {
	map<string, string>::iterator MapIter;

	SinkString.clear(); // empty string, append map string if found later
	MapIter = IntegerErrorCallSinkMap.find(CalleeName);

	if (MapIter != IntegerErrorCallSinkMap.end()) { // found it
		SinkString.append(MapIter->second);
	}
	return;
}

// Map system or library call name to the argument number that
//  should have an unsigned value and should be guarded from the
//  signedness error that results from copying a signed value
//  into the outgoing argument. Argument numbers are zero-based.
//  We will return 0 when there is no argument to worry about
//  for a particular library or system call name.
static map<string, unsigned int> UnsignedArgPositionMap;

void InitUnsignedArgPositionMap(void) {
	pair<string, unsigned int> MapEntry;
	pair<map<string, unsigned int>::iterator, bool> InsertResult;

	// <string.h>
	MapEntry.first = string("memchr");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcmp");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcpy");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memmove");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memset");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncat");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncmp");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncpy");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strxfrm");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdlib.h>
	MapEntry.first = string("malloc");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("calloc");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("realloc");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("bsearch");
	MapEntry.second = (STARS_ARG_POS_2 | STARS_ARG_POS_3);
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("qsort");
	MapEntry.second = (STARS_ARG_POS_1 | STARS_ARG_POS_2);
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mblen");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbtowc");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbstowcs");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("wcstombs");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdio.h>
	MapEntry.first = string("setvbuf");
	MapEntry.second = STARS_ARG_POS_3;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <time.h>
	MapEntry.first = string("strftime");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

} // end of InitUnsignedArgPositionMap()
// Return unsigned arg position bitset for call name from the unsigned arg map.
// If we don't find the call name, we return 0 in ArgPosBits.
void GetUnsignedArgPositionsForCallName(string CalleeName, unsigned int &ArgPosBits) {
	map<string, unsigned int>::iterator MapIter;

	ArgPosBits = 0; // Change if found later
	MapIter = UnsignedArgPositionMap.find(CalleeName);

	if (MapIter != UnsignedArgPositionMap.end()) { // found it
		ArgPosBits = MapIter->second;
	}
	return;
}

// Map of function names to arguments that are dangerous to supply
//  with user-tainted input values.
static map<string, unsigned int> TaintWarningArgPositionMap;

void InitTaintWarningArgPositionMap(void) {
	pair<string, unsigned int> MapEntry;
	pair<map<string, unsigned int>::iterator, bool> InsertResult;

	// <string.h>
	MapEntry.first = string("memchr");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcmp");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcpy");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memmove");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memset");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncat");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncmp");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncpy");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strxfrm");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdlib.h>
	MapEntry.first = string("malloc");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("calloc");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("realloc");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("bsearch");
	MapEntry.second = (STARS_ARG_POS_2 | STARS_ARG_POS_3);
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("qsort");
	MapEntry.second = (STARS_ARG_POS_1 | STARS_ARG_POS_2);
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mblen");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbtowc");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbstowcs");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("wcstombs");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdio.h>
	MapEntry.first = string("setvbuf");
	MapEntry.second = STARS_ARG_POS_3;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	return;
} // end of InitTaintWarningArgPositionMap()
// Return dangerous-to-taint arg position bitset for call name from the taint warning map.
// If we don't find the call name, we return 0 in ArgPosBits.
void GetTaintWarningArgPositionsForCallName(string CalleeName, unsigned int &ArgPosBits) {
	map<string, unsigned int>::iterator MapIter;

	ArgPosBits = 0; // Change if found later
	MapIter = TaintWarningArgPositionMap.find(CalleeName);

	if (MapIter != TaintWarningArgPositionMap.end()) { // found it
		ArgPosBits = MapIter->second;
	}
	return;
}

// Map of function names to POINTER argument positions.
static map<string, unsigned int> PointerArgPositionMap;

// Init map of system or library call name to the argument number that
//  should have a POINTER value.
void InitPointerArgPositionMap(void) {
	pair<string, unsigned int> MapEntry;
	pair<map<string, unsigned int>::iterator, bool> InsertResult;

	// <locale.h>
	MapEntry.first = string("setlocale");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <math.h>
	MapEntry.first = string("modf");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <string.h>
	MapEntry.first = string("memchr");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcmp");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcpy");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memmove");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memset");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcat");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncat");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcmp");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncmp");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcpy");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncpy");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcoll");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strxfrm");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strchr");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcspn");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strpbrk");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strrchr");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strspn");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strstr");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strtok");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strlen");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdlib.h>
	MapEntry.first = string("atof");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("atoi");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("atol");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strtod");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strtol");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strtoul");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("free");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("realloc");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);