fxos/lib/analysis.cpp

147 lines
3.9 KiB
C++

//---------------------------------------------------------------------------//
// 1100101 |_ mov #0, r4 __ //
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
// |_ base# + offset |_| /_\_\___/__/ //
//---------------------------------------------------------------------------//
#include <fxos/analysis.h>
#include <cassert>
namespace FxOS {
void ProgramState::setFunctionInit()
{
// TODO: Analysis: Set symbolic parameters at function entry
for(int i = 0; i < 16; i++)
m_regs[i] = RelConstDomain().top();
}
void ProgramState::setBottom()
{
for(int i = 0; i < 16; i++)
m_regs[i] = RelConstDomain().bottom();
}
void ProgramState::applyDiff(ProgramStateDiff const &diff)
{
RelConstDomain RCD;
int t = diff.target();
if(t == static_cast<int>(ProgramStateDiff::Target::None)) {
/* Nothing */
}
else if(t == static_cast<int>(ProgramStateDiff::Target::Unknown)) {
for(int i = 0; i < 16; i++)
m_regs[i] = RCD.top();
}
else {
assert((unsigned)t < 16 && "invalid register target");
m_regs[t] = diff.value();
}
}
void ProgramState::joinWith(ProgramState const &other)
{
RelConstDomain RCD;
for(int i = 0; i < 16; i++) {
m_regs[i] = RCD.join(m_regs[i], other.getRegister(i));
}
}
bool ProgramState::le(ProgramState const &other) const
{
RelConstDomain RCD;
for(int i = 0; i < 16; i++) {
if(!RCD.le(m_regs[i], other.getRegister(i)))
return false;
}
return true;
}
/* Information stored for each block during the fixpoint iteration */
struct BlockStates
{
ProgramState entry;
std::vector<ProgramStateDiff> diffs;
ProgramState exit;
ProgramState nextEntry;
};
static ProgramStateDiff interpretInstruction(
Instruction const &ins, ProgramState const &PS)
{
}
static void interpretBlock(BasicBlock const &bb, BlockStates &states)
{
ProgramState PS(states.entry);
states.diffs.clear();
for(Instruction const &i: bb) {
ProgramStateDiff diff = interpretInstruction(i, PS);
states.diffs.push_back(diff);
PS.applyDiff(diff);
}
states.exit = PS;
}
std::unique_ptr<StaticFunctionAnalysis> analyzeFunction(Function const &f)
{
std::vector<BlockStates> VBS;
/* Initialize all blocks' entry states */
for(uint i = 0; i < f.blockCount(); i++) {
BlockStates BS;
if(i == 0)
BS.entry.setFunctionInit();
else
BS.entry.setBottom();
VBS.push_back(BS);
}
/* The naive iteration strategy */
while(true) {
/* Interpret all blocks on their current states */
for(uint i = 0; i < f.blockCount(); i++)
interpretBlock(f.basicBlockByIndex(i), VBS[i]);
/* Compute the next entry state for each block */
for(uint i = 0; i < f.blockCount(); i++) {
BasicBlock const &bb = f.basicBlockByIndex(i);
VBS[i].nextEntry.setBottom();
for(auto succ: bb.successors())
VBS[i].nextEntry.joinWith(VBS[succ.blockIndex()].exit);
}
/* Determine whether a fixpoint has been reached yet */
bool pfp = std::all_of(VBS.begin(), VBS.end(),
[](BlockStates &BS) { return BS.nextEntry.le(BS.entry); });
if(pfp)
break;
/* Switch to next state */
for(uint i = 0; i < f.blockCount(); i++)
VBS[i].entry = VBS[i].nextEntry;
}
auto an = std::make_unique<StaticFunctionAnalysis>();
for(uint i = 0; i < f.blockCount(); i++) {
StaticFunctionAnalysis::Block B;
B.entry = VBS[i].entry;
B.diffs = std::move(VBS[i].diffs);
an->blocks.push_back(std::move(B));
}
return an;
}
// TODO_need_bb_successors;
} /* namespace FxOS */