fxos/lib/passes/pcrel.cpp

60 lines
1.2 KiB
C++

//---
// fxos.passes.pcrel: Resolution of PC-relative addresses
//---
#include <fxos/disasm-passes/pcrel.h>
namespace FxOS {
PcrelPass::PcrelPass(Disassembly &disasm):
DisassemblyPass(disasm)
{
}
void PcrelPass::analyze(uint32_t pc, ConcreteInstruction &ci)
{
Instruction const &i = ci.inst;
for(size_t n = 0; n < i.args.size(); n++)
{
Argument const &a = i.args[n];
ConcreteInstructionArg &ca = ci.args[n];
if(a.kind == Argument::PcRel)
{
uint32_t addr = (pc & ~(a.opsize - 1)) + 4 + a.disp;
ca.location = RelConstDomain().constant(addr);
/* Also compute the value. This is sign-extended from
16-bit with mov.w. There is no mov.b for this
instruction. */
Target &t = m_disasm.target();
uint32_t v;
switch(i.opsize)
{
case 2:
v = t.read_i16(addr);
break;
case 4:
v = t.read_i32(addr);
break;
default:
throw std::runtime_error("Wrong pcrel opsize");
}
ca.value = DataValue(IntegerType::u32);
ca.value.write(0,4,v);
}
else if(a.kind == Argument::PcJump)
{
uint32_t addr = pc + 4 + a.disp;
ca.location = RelConstDomain().constant(addr);
}
}
enqueue_unseen_successors(pc, ci);
}
} /* namespace FxOS */