Introduce support for dynamic functions

This commit is contained in:
Alessandro Di Federico
2021-10-15 18:46:50 +02:00
parent a023bfa7f5
commit 3a3eea0cf5
21 changed files with 764 additions and 290 deletions
+70 -29
View File
@@ -227,7 +227,53 @@ void commitToModel(GeneratedCodeBasicInfo &GCBI,
break;
case BranchType::InstructionLocalCFG:
EdgeType = FET::Invalid;
continue;
default:
break;
}
// Identify Source address
auto [Source, Size] = getPC(BB->getTerminator());
Source += Size;
revng_assert(Source.isValid());
// Identify Destination address
llvm::BasicBlock *JumpTargetBB = GCBI.getJumpTargetBlock(BB);
MetaAddress JumpTargetAddress = GCBI.getPCFromNewPC(JumpTargetBB);
model::BasicBlock &CurrentBlock = Function.CFG[JumpTargetAddress];
CurrentBlock.End = Source;
auto SuccessorsInserter = CurrentBlock.Successors.batch_insert();
llvm::BasicBlock *Successor = BB->getSingleSuccessor();
llvm::StringRef SymbolName;
MetaAddress Destination = MetaAddress::invalid();
if (Successor != nullptr)
Destination = getBasicBlockPC(Successor);
if (Destination.isValid()) {
revng_assert(not JumpTargetBB->empty());
auto *NewPCCall = getCallTo(&*Successor->begin(), "newpc");
revng_assert(NewPCCall != nullptr);
// Extract symbol name if any
auto *SymbolNameValue = NewPCCall->getArgOperand(4);
if (not isa<llvm::ConstantPointerNull>(SymbolNameValue)) {
llvm::Value *SymbolNameString = NewPCCall->getArgOperand(4);
SymbolName = extractFromConstantStringPtr(SymbolNameString);
revng_assert(SymbolName.size() != 0);
}
}
switch (Branch) {
case BranchType::Invalid:
case BranchType::FakeFunction:
case BranchType::RegularFunction:
case BranchType::NoReturnFunction:
case BranchType::UnhandledCall:
case BranchType::InstructionLocalCFG:
revng_abort();
break;
case BranchType::FunctionLocalCFG:
@@ -243,7 +289,10 @@ void commitToModel(GeneratedCodeBasicInfo &GCBI,
break;
case BranchType::HandledCall:
EdgeType = FET::FunctionCall;
if (SymbolName.size() > 0)
EdgeType = FET::IndirectCall;
else
EdgeType = FET::FunctionCall;
break;
case BranchType::IndirectCall:
@@ -275,21 +324,6 @@ void commitToModel(GeneratedCodeBasicInfo &GCBI,
break;
}
if (EdgeType == FET::Invalid)
continue;
// Identify Source address
auto [Source, Size] = getPC(BB->getTerminator());
Source += Size;
revng_assert(Source.isValid());
// Identify Destination address
llvm::BasicBlock *JumpTargetBB = GCBI.getJumpTargetBlock(BB);
MetaAddress JumpTargetAddress = GCBI.getPCFromNewPC(JumpTargetBB);
model::BasicBlock &CurrentBlock = Function.CFG[JumpTargetAddress];
CurrentBlock.End = Source;
auto SuccessorsInserter = CurrentBlock.Successors.batch_insert();
if (EdgeType == FET::DirectBranch) {
// Handle direct branch
auto Successors = GCBI.getSuccessors(BB);
@@ -304,21 +338,31 @@ void commitToModel(GeneratedCodeBasicInfo &GCBI,
SuccessorsInserter.insert(MakeEdge(Destination, EdgeType));
} else if (FunctionEdgeType::isCall(EdgeType)) {
// Handle call
llvm::BasicBlock *Successor = BB->getSingleSuccessor();
MetaAddress Destination = MetaAddress::invalid();
if (Successor != nullptr)
Destination = getBasicBlockPC(Successor);
// Record the edge in the CFG
auto TempEdge = MakeEdge(Destination, EdgeType);
const auto &Result = SuccessorsInserter.insert(TempEdge);
auto *Edge = llvm::cast<CallEdge>(Result.get());
if (Destination.isValid()) {
// If it's a direct call, inherit the prototype from the callee
model::Function &Callee = TheBinary.Functions.at(Destination);
Edge->Prototype = Callee.Prototype;
const auto IDF = TheBinary.ImportedDynamicFunctions;
bool IsDynamicCall = (not SymbolName.empty()
and IDF.count(SymbolName.str()) != 0);
if (IsDynamicCall) {
revng_assert(EdgeType == model::FunctionEdgeType::IndirectCall);
Edge->Destination = MetaAddress::invalid();
Edge->DynamicFunction = SymbolName.str();
Edge->Prototype = TheBinary.ImportedDynamicFunctions
.at(Edge->DynamicFunction)
.Prototype;
} else {
revng_assert(EdgeType == model::FunctionEdgeType::FunctionCall);
// If it's a direct call, inherit the prototype from the callee
model::Function &Callee = TheBinary.Functions.at(Destination);
Edge->Prototype = Callee.Prototype;
}
revng_assert(Edge->Prototype.isValid());
} else {
// It's an indirect call: forge a new prototype
auto NewType = makeType<RawFunctionType>();
@@ -370,9 +414,6 @@ void commitToModel(GeneratedCodeBasicInfo &GCBI,
} else {
// Handle other successors
llvm::BasicBlock *Successor = BB->getSingleSuccessor();
MetaAddress Destination = MetaAddress::invalid();
if (Successor != nullptr)
Destination = getBasicBlockPC(Successor);
// Record the edge in the CFG
SuccessorsInserter.insert(MakeEdge(Destination, EdgeType));