Skip to content
Snippets Groups Projects
SMPDataFlowAnalysis.cpp 215 KiB
Newer Older
clc5q's avatar
clc5q committed
	StdlibLibraryFuncNames.insert("div");
	StdlibLibraryFuncNames.insert("labs");
	StdlibLibraryFuncNames.insert("ldiv");
	StdlibLibraryFuncNames.insert("mblen");
	StdlibLibraryFuncNames.insert("mbtowc");
	StdlibLibraryFuncNames.insert("wctomb");
	StdlibLibraryFuncNames.insert("mbstowcs");
	StdlibLibraryFuncNames.insert("wcstombs");

	// Add special functions often inserted by gcc.
	StdlibLibraryFuncNames.insert("stack_chk_fail");

	// Funcs with buffers as arguments; could analyze static size of buffers.
	BufferArgLibraryFuncNames.insert("strcpy");
	BufferArgLibraryFuncNames.insert("strcpy_chk"); // GNU safer version, but crashes on error
	BufferArgLibraryFuncNames.insert("memcpy");
	BufferArgLibraryFuncNames.insert("memmove");
	BufferArgLibraryFuncNames.insert("strcat");
	BufferArgLibraryFuncNames.insert("strcmp");

	return;
} // end of InitLibraryFuncNames()

bool IsMathLibraryFunc(string CalleeName) {
	set<string>::const_iterator FuncIter = MathLibraryFuncNames.find(CalleeName);
	return (FuncIter != MathLibraryFuncNames.cend());
}

bool IsStdioLibraryFunc(string CalleeName) {
	set<string>::const_iterator FuncIter = StdioLibraryFuncNames.find(CalleeName);
	return (FuncIter != StdioLibraryFuncNames.cend());
}

clc5q's avatar
clc5q committed
bool IsStdlibLibraryFunc(string CalleeName) {
	set<string>::const_iterator FuncIter = StdlibLibraryFuncNames.find(CalleeName);
	return (FuncIter != StdlibLibraryFuncNames.cend());
}

// Is FuncName a function that operates on buffers that might be of analyzeable buffer length?
bool IsBufferArgFuncName(const string CalleeName) {
	set<string>::const_iterator FuncIter = BufferArgLibraryFuncNames.find(CalleeName);
	return (FuncIter != BufferArgLibraryFuncNames.cend());
}

// Utility to count bits set in an unsigned int, e.g. ArgPosBits.
unsigned int CountBitsSet(unsigned int ArgPosBits) {
	unsigned int count; // count accumulates the total bits set in ArgPosBits
	for (count = 0; ArgPosBits; ++count) {
		ArgPosBits &= (ArgPosBits - 1); // clear the least significant bit set
	}
	// Brian Kernighan's method goes through as many iterations as there are set bits. 
	//  So if we have a 32-bit word with only the high bit set, then it will only go once through the loop.
	// Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan and Dennis M. Ritchie) mentions this in exercise 2-9.
	//  On April 19, 2006 Don Knuth pointed out to me that this method "was first published by Peter Wegner in CACM 3 (1960), 322.
	//  (Also discovered independently by Derrick Lehmer and published in 1964 in a book edited by Beckenbach.)"
	return count;
}

// Utility to get highest bit set in a byte, numbered 0 (lowest) to 7 (highest).
unsigned int HighestBitSet(uint8_t Byte) {
clc5q's avatar
clc5q committed
	unsigned int RetVal = 0;
	if (Byte & 0xf0) { // check upper 4 bits
		RetVal |= 4;  // at least bit 4 or higher is set
		Byte >>= 4;   // shift upper nibble to lower nibble
	}
	if (Byte & 0xc) { // check upper two bits of lower nibble
		RetVal |= 2;  // At least bit 2 or higher is set
		Byte >>= 2;   // shift upper two bits of lower nibble into lowest two bits
	}
	if (Byte & 0x2) { // Check second least significant bit
		RetVal |= 1;
	}
	return RetVal;
// Utility to get lowest bit set in a byte, numbered 0 (lowest) to 7 (highest).
unsigned int LowestBitSet(unsigned char Byte) {
	unsigned int RetVal = 0;
	if (Byte & 0x03) { // check lower 2 bits
		RetVal = (Byte & 1) ? 0 : 1;
	}
	else if (Byte & 0x0c) { // check upper two bits of lower nibble
		RetVal = (Byte & 4) ? 2 : 3;
	}
	else if (Byte & 0x30) { // Check lower two bits of upper nibble
		RetVal = (Byte & 16) ? 4 : 5;
	}
	else {
		assert(Byte & 0xc0);
		RetVal = (Byte & 64) ? 6 : 7;
	}
	return RetVal;
}

// Utility to get highest bit set in an uint32_t, numbered 0 (lowest) to 31 (highest).
// Assumes that UintVal is non-zero and has some bit set.
unsigned int HighestBitSetInUint(uint32_t UintVal) {
	unsigned int RetVal = 0;
	uint8_t Byte0 = UintVal & 0xff;
	uint8_t Byte1 = UintVal & 0xff00;
	uint8_t Byte2 = UintVal & 0xff0000;
	uint8_t Byte3 = UintVal & 0xff000000;
	if (Byte3 > 0) {
		RetVal = HighestBitSet(Byte3) + 24;
	}
	else if (Byte2 > 0) {
		RetVal = HighestBitSet(Byte2) + 16;
	}
	else if (Byte1 > 0) {
		RetVal = HighestBitSet(Byte1) + 8;
	}
	else if (Byte0 > 0) {
		RetVal = HighestBitSet(Byte0);
	}
	return RetVal;
} // end of HighestBitSetInUint()
// Initialize the FG info for the return register from any library function
//  whose name implies that we know certain return values (e.g. atoi() returns
//  a signed integer, while strtoul() returns an unsigned long).
void GetLibFuncFGInfo(string FuncName, struct FineGrainedInfo &InitFGInfo) {
	map<string, struct FineGrainedInfo>::iterator FindIter;

	FindIter = ReturnRegisterTypeMap.find(FuncName);
	if (FindIter == ReturnRegisterTypeMap.end()) { // not found
		InitFGInfo.SignMiscInfo = 0;
		InitFGInfo.SizeInfo = 0;
	}
	else { // found
		InitFGInfo = FindIter->second;
	}
	return;
} // end of GetLibFuncFGInfo()

// Is FuncName a standard library function name?
bool IsLibFuncName(std::string CalleeName) {
	// Return true if we find the name in any of our function type maps.

	map<string, struct FineGrainedInfo>::iterator RetTypeIter = ReturnRegisterTypeMap.find(CalleeName);
	if (RetTypeIter != ReturnRegisterTypeMap.end()) { // found
		return true;
	}

	map<string, unsigned int>::iterator PtrArgIter = PointerArgPositionMap.find(CalleeName);
	if (PtrArgIter != PointerArgPositionMap.end()) { // found it
		return true;
	}

	map<string, unsigned int>::iterator TaintIter = TaintWarningArgPositionMap.find(CalleeName);
	if (TaintIter != TaintWarningArgPositionMap.end()) { // found it
		return true;
	}

	map<string, unsigned int>::iterator UnsignedIter = UnsignedArgPositionMap.find(CalleeName);
	if (UnsignedIter != UnsignedArgPositionMap.end()) { // found it
		return true;
	}

	map<string, string>::iterator SinkIter = IntegerErrorCallSinkMap.find(CalleeName);
	if (SinkIter != IntegerErrorCallSinkMap.end()) { // found it
		return true;
	}

	// Put searches for additional library function names here.
	if (0 == CalleeName.compare("setuid")) {
		return true;
	}
	else if (IsStdioLibraryFunc(CalleeName)) {
		return true;
	}
	else if (IsMathLibraryFunc(CalleeName)) {
		return true;
	}
clc5q's avatar
clc5q committed
	else if (IsStdlibLibraryFunc(CalleeName)) {
		return true;
	}

// Is FuncName a startup func called before main(), or a wrapup function called by the system?
bool IsStartupFuncName(const std::string FuncName) {
	bool NameMatched = false;
	char IDA_func_name[STARS_MAXSTR];
	std::size_t SkipCount;

	SkipCount = strspn(FuncName.c_str(), "._");
	std::string TempFuncName = FuncName.substr(SkipCount); // remove leading periods and underscores

	if (0 == TempFuncName.compare("init_proc")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("init")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("start")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("gmon_start")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("call_gmon_start")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("libc_start_main")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("call_gmon_start__")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("libc_start_main__")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("libc_csu_init")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("libc_csu_fini")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("do_global_dtors_aux")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("term_proc")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("fini")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("frame_dummy")) {
		NameMatched = true;
	}