Newer
Older
MeetType = Type1;
else if (IsNumeric(Type1)) {
if (IsNumeric(Type2)) // one is NUMERIC, one is CODEPTR
MeetType = NUMERIC;
else if (IsDataPtr(Type2) || IsUnknown(Type2))
MeetType = UNKNOWN;
else
clc5q
committed
SMP_msg("ERROR #1 in SMPTypeMeet.\n");
}
else if (IsDataPtr(Type1)) {
if (IsDataPtr(Type2)) // two different POINTER subtypes
MeetType = POINTER;
else if (IsNumeric(Type2) || IsUnknown(Type2))
MeetType = UNKNOWN;
else
clc5q
committed
SMP_msg("ERROR #2 in SMPTypeMeet.\n");
if (ProfDerived && IsNotEqType(UNINIT, MeetType))
MeetType = MakeProfDerived(MeetType);
// Meet function for SCCP constant propagation; updates NewConstStruct
void STARSConstantTypeMeet(struct STARS_SCCP_Const_Struct OldConstStruct, struct STARS_SCCP_Const_Struct &NewConstStruct) {
if ((OldConstStruct.ConstType != STARS_CONST_BOTTOM) && (NewConstStruct.ConstType != STARS_CONST_TOP)) {
// We have four possibilities. Three of them have NewConstStruct lower in the type lattice, which means the final
// result is simply the NewConstStruct (i.e. if Old == TOP, New == CONST or BOTTOM; or Old == CONST, New == BOTTOM).
// The fourth possibility is that Old == CONST, New == CONST, and we have to check the const values for consistency,
// lowering NewConstStruct to BOTTOM if they are inconsistent.
if ((OldConstStruct.ConstType == STARS_CONST_HAS_VALUE) && (NewConstStruct.ConstType == STARS_CONST_HAS_VALUE)) {
if (OldConstStruct.ConstValue != NewConstStruct.ConstValue) { // inconsistent const values
NewConstStruct.ConstType = STARS_CONST_BOTTOM;
}
}
}
else {
NewConstStruct = OldConstStruct;
}
return;
} // end of STARSConstantTypeMeet()
// *****************************************************************
// Class DisAsmString
// *****************************************************************
DisAsmString::DisAsmString(void) {
this->CurrAddr = BADADDR;
this->StringLen = 0;
this->CachedDisAsm[0] = '\0';
return;
}
char *DisAsmString::GetDisAsm(ea_t InstAddr) {
if (InstAddr != this->CurrAddr) {
this->CurrAddr = InstAddr;
bool IDAsuccess = generate_disasm_line(InstAddr, this->CachedDisAsm, sizeof(this->CachedDisAsm) - 1);
if (IDAsuccess) {
// Remove interactive color-coding tags.
this->StringLen = tag_remove(this->CachedDisAsm, this->CachedDisAsm, 0);
if (-1 >= StringLen) {
SMP_msg("ERROR: tag_remove failed at addr %lx \n", (unsigned long) InstAddr);
this->CachedDisAsm[0] = '\0';
}
}
else {
SMP_msg("ERROR: generate_disasm_line failed at addr %lx \n", (unsigned long) InstAddr);
this->CachedDisAsm[0] = '\0';
}
}
return (char *) this->CachedDisAsm;
} // end of DisAsmString::GetDisasm()
// Set the disasm text for the SSA marker instructions, which have no IDA Pro disasm because
// they are pseudo-instructions that we add at the top of each function to hold LiveIn name info.
void DisAsmString::SetMarkerInstText(ea_t InstAddr) {
if (InstAddr != this->CurrAddr) {
this->CurrAddr = InstAddr;
clc5q
committed
SMP_strncpy(this->CachedDisAsm, "\tfnop\t; Top of function SSA marker for SMP",
sizeof(this->CachedDisAsm) - 1);
this->StringLen = (ssize_t) strlen(this->CachedDisAsm);
}
return;
} // end of DisAsmString::SetMarkerInstText()
// *****************************************************************
// Class DefOrUse
// *****************************************************************
// Default constructor to make the compilers happy.
DefOrUse::DefOrUse(void) {
this->Operand.type = o_void;
this->OpType = UNINIT;
this->NonSpeculativeOpType = UNINIT;
this->MetadataStatus = DEF_METADATA_UNANALYZED;
return;
}
// Constructor.
DefOrUse::DefOrUse(op_t Ref, SMPOperandType Type, int SSASub) {
if (o_reg == Ref.type) {
// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
// and type inference systems.
CanonicalizeOpnd(Ref);
assert(!IsProfDerived(Type));
this->NonSpeculativeOpType = Type;
this->MetadataStatus = DEF_METADATA_UNANALYZED;
// Copy constructor.
DefOrUse::DefOrUse(const DefOrUse &CopyIn) {
*this = CopyIn;
return;
}
// Assignment operator for copy constructor use.
DefOrUse &DefOrUse::operator=(const DefOrUse &rhs) {
this->Operand = rhs.Operand;
this->OpType = rhs.OpType;
this->NonSpeculativeOpType = rhs.NonSpeculativeOpType;
this->SSANumber = rhs.SSANumber;
this->MetadataStatus = rhs.MetadataStatus;
return *this;
}
// Set the operand type for this DEF or USE - don't forget to take
// into account the speculative (profiler) status.
void DefOrUse::SetType(SMPOperandType Type, const SMPInstr *Instr)
{
SMPOperandType OldType = this->OpType;
SMPOperandType NewType = Type;
if (Instr->GetBlock()->GetFunc()->GetIsSpeculative()) {
NewType = (SMPOperandType)(((int)NewType) | PROF_BASE);
if (!IsProfDerived(OldType))
this->NonSpeculativeOpType = OldType;
}
}
// Debug printing.
void DefOrUse::Dump(void) const {
PrintListOperand(this->Operand, this->SSANumber);
if (IsEqType(this->OpType , NUMERIC))
clc5q
committed
SMP_msg("N ");
else if (IsEqType(this->OpType , CODEPTR))
clc5q
committed
SMP_msg("C ");
else if (IsEqType(this->OpType , POINTER))
clc5q
committed
SMP_msg("P ");
else if (IsEqType(this->OpType , STACKPTR))
clc5q
committed
SMP_msg("S ");
else if (IsEqType(this->OpType , GLOBALPTR))
clc5q
committed
SMP_msg("G ");
else if (IsEqType(this->OpType , HEAPPTR))
clc5q
committed
SMP_msg("H ");
else if (IsEqType(this->OpType , PTROFFSET))
clc5q
committed
SMP_msg("O ");
clc5q
committed
else if (IsEqType(this->OpType , NEGATEDPTR))
clc5q
committed
SMP_msg("NegP ");
else if (IsEqType(this->OpType , UNKNOWN))
clc5q
committed
SMP_msg("U ");
/* emit the profile bit */
clc5q
committed
SMP_msg("Pr ");
// Don't write anything for UNINIT OpType
// Emit the metadata status.
if (DEF_METADATA_UNUSED == this->MetadataStatus)
clc5q
committed
SMP_msg("Mn ");
else if (DEF_METADATA_USED == this->MetadataStatus)
clc5q
committed
SMP_msg("Mu ");
else if (DEF_METADATA_REDUNDANT == this->MetadataStatus)
clc5q
committed
SMP_msg("Mr ");
// Is the DEF possibly aliased because of an indirect write in
// the DEF-USE chain?
clc5q
committed
SMP_msg("Al* ");
return;
} // end of DefOrUse::Dump()
// *****************************************************************
// Class DefOrUseSet
// *****************************************************************
// Default constructor.
DefOrUseSet::DefOrUseSet(void) {
this->Refs.clear();
clc5q
committed
// Destructor.
DefOrUseSet::~DefOrUseSet() {
this->Refs.clear();
return;
clc5q
committed
}
// Find the reference for a given operand type.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::FindRef(op_t SearchOp) {
set<DefOrUse, LessDefUse>::iterator CurrRef;
DefOrUse DummyRef(SearchOp);
CurrRef = this->Refs.find(DummyRef);
return CurrRef;
}
// Insert a new DEF or USE; must be new, insert must succeed else we assert.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::InsertRef(DefOrUse Ref) {
pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
InsertResult = this->Refs.insert(Ref);
assert(InsertResult.second);
return InsertResult.first;
}
// Set a Def or Use into the list, along with its type.
void DefOrUseSet::SetRef(op_t Ref, SMPOperandType Type, int SSASub) {
pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
DefOrUse CurrRef(Ref, Type, SSASub);
InsertResult = this->Refs.insert(CurrRef);
if ((!(InsertResult.second)) && (o_reg != Ref.type)) {
SMP_msg("ERROR: Inserted duplicate DEF or USE.\n");
}
// Change the indirect write status for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetOp(set<DefOrUse, LessDefUse>::iterator CurrRef, op_t NewOp) {
// 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.
assert(CurrRef != this->Refs.end());
DefOrUse NewCopy = (*CurrRef);
NewCopy.SetOp(NewOp);
this->Refs.erase(CurrRef);
pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
InsertResult = this->Refs.insert(NewCopy);
assert(InsertResult.second);
return InsertResult.first;
} // end of DefOrUseSet::SetOp()
// Change the SSA subscript for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetSSANum(op_t CurrOp, int NewSSASub) {
// 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());
set<DefOrUse, LessDefUse>::iterator NextRef = CurrRef;
++NextRef;
DefOrUse NewCopy = (*CurrRef);
NewCopy.SetSSANum(NewSSASub);
this->Refs.erase(CurrRef);
CurrRef = this->Refs.insert(NextRef, NewCopy);
return CurrRef;
} // end of DefOrUseSet::SetSSANum()
// Change the operand type for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetType(op_t CurrOp, SMPOperandType Type, const SMPInstr* Instr) {
// 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());
#if 1
if (o_imm == CurrOp.type) {
if (UNINIT != CurrRef->GetType() && Type != CurrRef->GetType()) {
SMP_msg("ERROR: Changing type of immediate from %d to %d at %lx: ", CurrRef->GetType(), Type, (unsigned long) Instr->GetAddr());
clc5q
committed
SMP_msg("\n");
SMPInstr InstCopy = (*Instr);
InstCopy.Dump();
DefOrUse NewCopy = (*CurrRef);
NewCopy.SetType(Type,Instr);
this->Refs.erase(CurrRef);
pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
InsertResult = this->Refs.insert(NewCopy);
assert(InsertResult.second);
CurrRef = InsertResult.first;
} // end of DefOrUseSet::SetType()
// Change the Metadata type for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetMetadata(op_t CurrOp, SMPMetadataType Status) {
// 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.SetMetadataStatus(Status);
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::SetMetadata()
// Change the indirect write status for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetIndWrite(op_t CurrOp, bool IndWriteFlag) {
// 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.SetIndWrite(IndWriteFlag);
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::SetIndWrite()
// Change the ignore apparent truncation flag for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetNoTruncation(op_t CurrOp, bool NoTruncFlag) {
// 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.SetNoTruncation(NoTruncFlag);
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::SetNoTruncation()
clc5q
committed
// Change the ignore apparent overflow flag for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetNoOverflow(op_t CurrOp, bool NoOverflowFlag) {
// 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()
clc5q
committed
void DefOrUseSet::Dump(void) const {
set<DefOrUse, LessDefUse>::iterator CurrRef;
for (CurrRef = this->Refs.begin(); CurrRef != this->Refs.end(); ++CurrRef) {
CurrRef->Dump();
}
clc5q
committed
SMP_msg("\n");
// 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.
clc5q
committed
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().is_reg(X86_FLAGS_REG))) { // ignore flags
if (!FoundFirstUse) {
FoundFirstUse = true;
UseType = CurrUse->GetType();
}
else {
clc5q
committed
if (IsNotEqType(CurrUse->GetType(), UseType)) {
clc5q
committed
return false; // inconsistent types
}
}
}
}
return true;
} // end of DefOrUseSet::TypesAgreeNoFlags()
// *****************************************************************
// Class DefOrUseList
// *****************************************************************
// Default constructor.
DefOrUseList::DefOrUseList(void) {
this->Refs.clear();
return;
}
// Set a Def or Use into the list, along with its type.
void DefOrUseList::SetRef(op_t Ref, SMPOperandType Type, int SSASub) {
DefOrUse CurrRef(Ref, Type, SSASub);
this->Refs.push_back(CurrRef);
DefOrUse DefOrUseList::GetRef(size_t index) const {
// 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();
}
clc5q
committed
SMP_msg("\n");
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
return;
}
// Erase duplicate entries, in case SMPInstr::MDFixupDefUseLists() adds one.
void DefOrUseList::EraseDuplicates(void) {
set<op_t, LessOp> TempRefs; // Use STL set to find duplicates
set<op_t, 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()
// *****************************************************************
// Class SMPPhiFunction
// *****************************************************************
// Constructor
SMPPhiFunction::SMPPhiFunction(int GlobIndex, const DefOrUse &Def) {
this->DefName = Def;
clc5q
committed
this->SubscriptedOps.clear();
DefOrUse SMPPhiFunction::GetDefCopy(void) const {
DefOrUse DefCopy(this->DefName);
return DefCopy;
}
// 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?
clc5q
committed
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
op_t 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 (o_reg == PhiOp.type) {
ea_t DefAddr = CurrBlock->GetFunc()->GetGlobalDefAddr(PhiOp, UseSSANum);
// Handle simple case: DEF is in an instruction.
if ((BADADDR != DefAddr) && (DefAddr >= CurrBlock->GetFunc()->GetFirstFuncAddr())) {
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));
}
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
}
}
}
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));
}
}
}
clc5q
committed
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.
clc5q
committed
if (FoundUNKNOWN || (FoundNUMERIC && FoundPOINTER)
|| ((FoundNUMERIC || FoundPOINTER || FoundNEGATEDPTR) && FoundPTROFFSET)
|| ((FoundNUMERIC || FoundPOINTER || FoundPTROFFSET) && FoundNEGATEDPTR))
MeetType = UNKNOWN;
else if (FoundNUMERIC)
MeetType = NumericType;
else if (FoundPOINTER) {
MeetType = PtrType;
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
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 >= CurrBlock->GetFunc()->GetFirstFuncAddr())) {
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());
}
}
clc5q
committed
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 {
clc5q
committed
SMP_msg(" DEF: ");
this->DefName.Dump();
clc5q
committed
SMP_msg(" USEs: ");
this->SubscriptedOps.Dump();
return;
}
// *****************************************************************
// Class SMPDefUseChain
// *****************************************************************
// Constructors
SMPDefUseChain::SMPDefUseChain(void) {
this->SSAName.type = o_void;
clc5q
committed
this->RefInstrs.clear();
this->RefInstrs.push_back((unsigned short) BADADDR);
this->IndWrite = false;
return;
}
SMPDefUseChain::SMPDefUseChain(op_t Name, ea_t Def) {
this->SetName(Name);
this->RefInstrs.push_back(Def);
this->IndWrite = false;
return;
}
// Set the variable name.
void SMPDefUseChain::SetName(op_t Name) {
if (o_reg == Name.type) {
// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
// and type inference systems.
CanonicalizeOpnd(Name);
this->SSAName = 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);
return;
}
// Set the indirect memory write flag.
void SMPDefUseChain::SetIndWrite(bool IndMemWrite) {
this->IndWrite = IndMemWrite;
return;
}
// DEBUG dump.
clc5q
committed
void SMPDefUseChain::Dump(int SSANum) const {
clc5q
committed
SMP_msg("DEF-USE chain for: ");
PrintListOperand(this->SSAName, SSANum);
if (this->RefInstrs.size() < 1) {
clc5q
committed
SMP_msg(" no references.\n");
return;
}
clc5q
committed
SMP_msg("\n DEF: %x USEs: ", this->RefInstrs.at(0));
size_t index;
for (index = 1; index < this->RefInstrs.size(); ++index)
clc5q
committed
SMP_msg("%x ", this->RefInstrs.at(index));
SMP_msg("\n");
return;
} // end of SMPDefUseChain::Dump()
// *****************************************************************
// Class SMPDUChainArray
// *****************************************************************
SMPDUChainArray::SMPDUChainArray(void) {
this->SSAName.type = o_void;
this->DUChains.clear();
return;
}
SMPDUChainArray::SMPDUChainArray(op_t Name, ea_t FirstAddrMinusOne) {
if (o_reg == Name.type) {
// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
// and type inference systems.
CanonicalizeOpnd(Name);
this->SSAName = Name;
this->BaseAddr = FirstAddrMinusOne;
this->DUChains.clear();
return;
}
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(op_t Name, ea_t FirstAddrMinusOne) {
if (o_reg == Name.type) {
// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
// and type inference systems.
CanonicalizeOpnd(Name);
this->SSAName = Name;
this->BaseAddr = FirstAddrMinusOne;
return;
}
// DEBUG dump.
clc5q
committed
void SMPDUChainArray::Dump(void) const {
size_t index;
for (index = 0; index < this->GetSize(); ++index) {
this->DUChains.at(index).Dump((int) index);
}
return;
}
// *****************************************************************
// Class SMPCompleteDUChains
// *****************************************************************
// DEBUG dump.
clc5q
committed
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;
clc5q
committed
assert(BitIndex <= this->BitLimit);
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;
clc5q
committed
this->BitLimit = Size;
if (0 != ExtraBits) {
}
else {
}
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;
clc5q
committed
assert(BitIndex <= this->BitLimit);
this->STARSBits[ByteIndex] |= STARSBitMasks[BitNumber];
return;
}
void STARSBitSet::ResetBit(size_t BitIndex) {
size_t ByteIndex = BitIndex / 8;
size_t BitNumber = BitIndex % 8;
clc5q
committed
assert(BitIndex <= this->BitLimit);
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;
}
clc5q
committed
// Map system or library call name to FG info about its return value.
static map<string, struct FineGrainedInfo> ReturnRegisterTypeMap;
clc5q
committed
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
// 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;
}
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
// 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;