Function detection: drop normalized address space

We used to have a normalized address space formed only functions,
skipping all the holes. This was employed to identify "skipping
jumps". However, this method was ineffective, and we changed the
definition of skipping jump as a jump skipping over CFEPs that are
highly likely to be actual functions.

This commit removes the leftovers of the normalized address space
computation, which was also the cause of a bug in function detection.
This commit is contained in:
Alessandro Di Federico
2017-01-23 22:53:53 +01:00
parent 6b91aeb9a2
commit c3fbcf31aa
+25 -50
View File
@@ -111,7 +111,7 @@ private:
void initPostDispatcherIt();
void collectFunctionCalls();
void collectReturnInstructions();
void initNormalizedAddressSpace();
void registerBasicBlockAddressRanges();
interval_set findCoverage(BasicBlock *BB);
// CFEP related methods
@@ -188,7 +188,6 @@ private:
std::map<BasicBlock *, SmallVector<CFEPRelation, 2>> Relations;
OnceQueue<BasicBlock *> CFEPWorkList;
interval_set Callees;
interval_set NormalizedReadInterval;
std::map<BasicBlock *, std::vector<BasicBlock *>> Functions;
};
@@ -274,54 +273,28 @@ void FBD::collectReturnInstructions() {
}
}
/// \brief Address space normalization
/// Assign the lowest address to 0 and skip any holes in the translated
/// address space.
void FBD::initNormalizedAddressSpace() {
// Sort all the basic blocks by their starting address
std::map<uint64_t, std::pair<BasicBlock *, uint64_t>> SortedPCs;
/// \brief Register for each basic block the range of addresses it covers
void FBD::registerBasicBlockAddressRanges() {
// Register the range of addresses covered by each basic block
for (User *U : F.getParent()->getFunction("newpc")->users()) {
auto *Call = dyn_cast<CallInst>(U);
if (Call == nullptr)
continue;
BasicBlock *BB = Call->getParent();
uint64_t Address = getLimitedValue(Call->getOperand(0));
uint64_t Size = getLimitedValue(Call->getOperand(1));
assert(Address > 0 && Size > 0);
SortedPCs[Address] = { Call->getParent(), Size };
}
// Assign addresses in the normalized address space
uint64_t CurrentAddress = 0;
for (auto &P : SortedPCs) {
BasicBlock *BB = P.second.first;
uint64_t Size = P.second.second;
uint64_t StartAddress = P.first;
uint64_t EndAddress = StartAddress + Size;
interval_set VirtualInterval;
VirtualInterval += interval::right_open(StartAddress, EndAddress);
// Move the read range into the normalized address space and merge the
// result into NormalizedReadInterval
interval_set ReadInterval = JTM->readRange() & VirtualInterval;
for (auto Interval : ReadInterval) {
uint64_t Lower = (Interval.lower() - StartAddress) + CurrentAddress;
uint64_t Upper = Lower + Interval.upper() - Interval.lower();
NormalizedReadInterval += interval::right_open(Lower, Upper);
}
// Associate each basic block with its interval in the normalized address
// space
Coverage[BB] += interval::right_open(CurrentAddress, CurrentAddress + Size);
CurrentAddress += Size;
Coverage[BB] += interval::right_open(Address, Address + Size);
}
}
interval_set FBD::findCoverage(BasicBlock *BB) {
auto It = Coverage.find(BB);
if (It != Coverage.end())
if (It != Coverage.end()) {
return It->second;
}
OnceQueue<BasicBlock *> WorkList;
WorkList.insert(BB);
@@ -330,8 +303,9 @@ interval_set FBD::findCoverage(BasicBlock *BB) {
BB = WorkList.pop();
It = Coverage.find(BB);
if (It != Coverage.end())
if (It != Coverage.end()) {
return It->second;
}
for (BasicBlock *Predecessor : predecessors(BB))
if (JTM->isTranslatedBB(Predecessor))
@@ -359,7 +333,10 @@ void FBD::collectInitialCFEPSet() {
if (JT.hasReason(JumpTargetManager::Callee)) {
registerCFEP(CFEPHead, Callee);
assert(Coverage.find(CFEPHead) != Coverage.end());
Callees += Coverage[CFEPHead];
Insert = true;
}
@@ -385,8 +362,6 @@ void FBD::cfepProcessPhase1() {
while (!CFEPWorkList.empty()) {
BasicBlock *CFEP = CFEPWorkList.pop();
interval_set Covered;
// Find all the basic block it can reach
OnceQueue<BasicBlock *> WorkList;
WorkList.insert(CFEP);
@@ -394,8 +369,6 @@ void FBD::cfepProcessPhase1() {
while (!WorkList.empty()) {
BasicBlock *RelatedBB = WorkList.pop();
Covered += Coverage[RelatedBB];
auto FCIt = FunctionCalls.find(RelatedBB->getTerminator());
if (FCIt != FunctionCalls.end()) {
// This basic block ends with a function call, proceed with the return
@@ -431,18 +404,22 @@ void FBD::cfepProcessPhase1() {
if (FunctionCalls.count(T) != 0 || Returns.count(T) != 0)
continue;
uint64_t StartAddress = findCoverage(BB).begin()->lower();
interval_set StartAddressRange = findCoverage(BB);
uint64_t StartAddress = StartAddressRange.begin()->lower();
assert(StartAddress != 0);
for (BasicBlock *S : successors(BB)) {
if (!JTM->isTranslatedBB(S) || Coverage.count(S) == 0)
continue;
interval_set &BBInterval = Coverage[S];
assert(Coverage.find(S) != Coverage.end());
interval_set &DestinationAddressRange = Coverage[S];
// TODO: why this?
if (BBInterval.size() == 0)
if (DestinationAddressRange.size() == 0)
continue;
uint64_t DestinationAddress = BBInterval.begin()->lower();
uint64_t DestinationAddress = DestinationAddressRange.begin()->lower();
interval_set JumpInterval;
if (StartAddress <= DestinationAddress)
@@ -450,8 +427,8 @@ void FBD::cfepProcessPhase1() {
else
JumpInterval += interval::closed(DestinationAddress, StartAddress);
JumpInterval -= Covered;
JumpInterval -= NormalizedReadInterval;
JumpInterval -= StartAddressRange;
JumpInterval -= DestinationAddressRange;
JumpInterval &= Callees;
uint64_t Distance = JumpInterval.size();
@@ -480,8 +457,6 @@ void FBD::filterCFEPs() {
bool Keep = C.hasReason(Callee);
bool AddressTaken = C.hasReason(GlobalData) || C.hasReason(InCode);
// if (getBasicBlockPC(Head) == 0x18a70)
// dbg << "here\n";
if (!Keep && AddressTaken) {
Keep = true;
// Check no relation of Jump type and 0-distance exist
@@ -609,7 +584,7 @@ map<BasicBlock *, vector<BasicBlock *>> FBD::run() {
JTM->noReturn().computeKillerSet(CallPredecessors, Returns);
JTM->setCFGForm(JumpTargetManager::SemanticPreservingCFG);
initNormalizedAddressSpace();
registerBasicBlockAddressRanges();
collectInitialCFEPSet();