support for mova, and more responsible OS creation

This commit is contained in:
Lephenixnoir 2020-02-29 11:22:26 +01:00
parent ea44c1ffa1
commit c1c1be2d2c
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
12 changed files with 85 additions and 35 deletions

View File

@ -22,7 +22,10 @@ int disassembly(Library &library, Target &target, char const *ref,
/* Observe the target only if it has an OS mapped */
std::unique_ptr<OS> os;
if(target.covers(MemoryRegion::ROM)) os = std::make_unique<OS>(target);
try {
os = std::make_unique<OS>(target);
}
catch(std::exception &) {}
/* Parameters inside the ref */
uint32_t address = -1;
@ -142,6 +145,7 @@ int disassembly(Library &library, Target &target, char const *ref,
p.promote_syscall = PrintPass::Promote;
p.promote_syscallname = PrintPass::Append;
p.promote_symbol = PrintPass::Append;
p.promote_pcaddr_loc = PrintPass::Promote;
p.run();
}

View File

@ -49,6 +49,8 @@ public:
int promote_syscallname;
/* Promote an integer to a symbol */
int promote_symbol;
/* In a mova, promote "pc+<disp>" to the computed address */
int promote_pcaddr_loc;
/* TODO: More print pass parameters */
@ -73,6 +75,7 @@ private:
void syscall(ConcreteInstructionArg const &);
void syscallname(ConcreteInstructionArg const &);
void symbol(ConcreteInstructionArg const &);
void pcaddrloc(ConcreteInstructionArg const &);
};
} /* namespace FxOS */

View File

@ -113,6 +113,9 @@ public:
return m_target;
}
/* List of passes that have run so far */
std::set<std::string> passes;
private:
/* Underlying target */
Target &m_target;
@ -127,7 +130,7 @@ private:
class DisassemblyPass
{
public:
DisassemblyPass(Disassembly &disasm);
DisassemblyPass(Disassembly &disasm, std::string name="");
/* Analyze a single instruction, probably updating the annotations and
the state of the pass itself. */
@ -156,13 +159,16 @@ private:
/* Visited blocks */
std::set<uint32_t> m_seen;
/* Name of pass */
std::string m_name;
};
/* A disassembly pass that observes each instruction independently */
class InstructionDisassemblyPass: public DisassemblyPass
{
public:
InstructionDisassemblyPass(Disassembly &disasm);
InstructionDisassemblyPass(Disassembly &disasm, std::string name="");
/* Runs the pass from the first instruction currently loaded, all the
way down to the bottom, as if always using enqueue_next(). */

View File

@ -70,6 +70,7 @@ struct Argument
ArrayDeref, /* @(r0,rn) or @(r0,gbr) */
PcRel, /* @(disp,pc) with 4-alignment correction */
PcJump, /* pc+disp */
PcAddr, /* pc+disp with special delayed slot semantics */
Imm, /* #imm */
};
@ -84,7 +85,7 @@ struct Argument
CpuRegister base;
/* Index register. Valid for ArrayDeref */
CpuRegister index;
/* Displacement in bytes. Valid for StructDeref, PcRel and PcJump */
/* Displacement in bytes. For StructDeref, PcRel, PcJump, and PcAddr */
int disp;
/* Operation size. Generally a multiplier for disp */
int opsize;
@ -102,6 +103,7 @@ Argument Argument_StructDeref(int disp, int opsize, CpuRegister base);
Argument Argument_ArrayDeref(CpuRegister index, CpuRegister base);
Argument Argument_PcRel(int disp, int opsize);
Argument Argument_PcJump(int disp);
Argument Argument_PcAddr(int disp);
Argument Argument_Imm(int imm);
/* Assembler instruction */

View File

@ -45,7 +45,7 @@ ConcreteInstruction::ConcreteInstruction(Instruction const &inst):
//---
Disassembly::Disassembly(Target &target):
m_target {target}, m_instructions {}
passes {}, m_target {target}, m_instructions {}
{
}
@ -106,8 +106,8 @@ ConcreteInstruction &Disassembly::readins(uint32_t pc)
// Base pass
//---
DisassemblyPass::DisassemblyPass(Disassembly &disasm):
m_disasm(disasm)
DisassemblyPass::DisassemblyPass(Disassembly &disasm, std::string name):
m_disasm(disasm), m_name(name)
{
}
@ -171,14 +171,16 @@ void DisassemblyPass::run(uint32_t entry_pc)
m_seen.insert(pc);
}
if(m_name != "") m_disasm.passes.insert(m_name);
}
//---
// Base instruction-level pass
//---
InstructionDisassemblyPass::InstructionDisassemblyPass(Disassembly &disasm):
DisassemblyPass(disasm)
InstructionDisassemblyPass::InstructionDisassemblyPass(Disassembly &disasm,
std::string name): DisassemblyPass(disasm, name)
{
}

View File

@ -142,6 +142,14 @@ Argument Argument_PcJump(int disp)
return arg;
}
Argument Argument_PcAddr(int disp)
{
Argument arg;
arg.kind = Argument::PcAddr;
arg.disp = disp;
return arg;
}
Argument Argument_Imm(int imm)
{
Argument arg;
@ -172,6 +180,8 @@ std::string Argument::str() const
return format("@(%d,pc)", disp);
case Argument::PcJump:
return format("pc+%d", disp);
case Argument::PcAddr:
return format("pc+%u", disp);
case Argument::Imm:
return format("#%d", imm);
default:

View File

@ -27,7 +27,12 @@ void Library::explore(std::string path)
fs::recursive_directory_iterator it(path);
for(auto &file: it)
{
if(!fs::is_directory(file)) load(file.path());
if(!fs::is_directory(file)) try {
load(file.path());
}
catch(FxOS::SyntaxError &e) {
log(ERR "%s", e.str());
}
}
}
catch(fs::filesystem_error &e)
@ -63,13 +68,8 @@ void Library::load(std::string path)
if(type == "assembly")
{
try {
int total = load_asm(file, offset, line);
m_asmtables.push_back(std::make_pair(h["name"],total));
}
catch(FxOS::SyntaxError &e) {
log(ERR "%s", e.str());
}
int total = load_asm(file, offset, line);
m_asmtables.push_back(std::make_pair(h["name"],total));
}
else if(type == "target")
{
@ -79,22 +79,12 @@ void Library::load(std::string path)
return;
}
try {
m_targets[h["name"]] = load_target(file, offset, line);
}
catch(FxOS::SyntaxError &e) {
log(ERR "%s", e.str());
}
m_targets[h["name"]] = load_target(file, offset, line);
}
else if(type == "symbols")
{
try {
SymbolTable st = load_symbols(file, offset, line);
m_symtables.push_back(st);
}
catch(FxOS::SyntaxError &e) {
log(ERR "%s", e.str());
}
SymbolTable st = load_symbols(file, offset, line);
m_symtables.push_back(st);
}
else
{

View File

@ -22,6 +22,8 @@ enum Token {
SR, PR, GBR, VBR, DBR, SSR, SPC, SGR, MACH, MACL,
/* PC-relative jumps and displacements (with 4-alignment correction) */
JUMP8, JUMP12, AT_DPC,
/* PC-relative address access (without memory access) */
DPC,
/* Immediate operands */
IMM,
/* Memory access with post-increment and pre-decrement */
@ -83,6 +85,7 @@ space [ \t]+
"rm" { return RM; }
"jump8" { return JUMP8; }
"jump12" { return JUMP12; }
"pc+disp" { return DPC; }
"@(disp,"[ ]*"pc)" { return AT_DPC; }
"@rn" { return AT_RN; }
"@rm" { return AT_RM; }
@ -208,6 +211,7 @@ static Argument make_arg(int token, int opsize, int m, int n, int d, int i)
case MACL: return Argument_Reg(Reg::MACL);
case JUMP8: return Argument_PcJump(d8 * 2);
case JUMP12: return Argument_PcJump(d12 * 2);
case DPC: return Argument_PcAddr(d * 4);
case IMM: return Argument_Imm(i8);
case AT_RN: return Argument_Deref(Rn);
case AT_RM: return Argument_Deref(Rm);

View File

@ -13,7 +13,7 @@ using namespace FxOS::Log;
namespace FxOS {
CfgPass::CfgPass(Disassembly &disasm):
DisassemblyPass(disasm)
DisassemblyPass(disasm, "cfg")
{
}

View File

@ -7,7 +7,7 @@
namespace FxOS {
PcrelPass::PcrelPass(Disassembly &disasm):
InstructionDisassemblyPass(disasm)
InstructionDisassemblyPass(disasm, "pcrel")
{
}
@ -45,6 +45,19 @@ void PcrelPass::analyze(uint32_t pc, ConcreteInstruction &ci)
ca.value = DataValue(IntegerType::u32);
ca.value.write(0, 4, addr);
}
else if(a.kind == Argument::PcAddr
&& m_disasm.passes.count("cfg"))
{
uint32_t addr = (pc & ~3) + 4 + a.disp;
/* SH3 manual says that the semantics of mova change in
a delay slot. GNU as: "yeah but sorry they don't" */
// if(ci.delayslot) addr = (ci.jmptarget&~3) + 4 + a.disp;
ca.location = RelConstDomain().constant(addr);
ca.value = DataValue(IntegerType::u32);
ca.value.write(0, 4, addr);
}
}
}

View File

@ -11,14 +11,16 @@ namespace FxOS {
PrintPass::PrintPass(Disassembly &disasm,
std::vector<SymbolTable> const &symtables):
InstructionDisassemblyPass(disasm), m_symtables(symtables)
InstructionDisassemblyPass(disasm, "print"), m_symtables(symtables)
{
/* Default parameters: all 0 */
/* Use an OS observer to describe syscalls in header lines */
Target &t = disasm.target();
if(t.covers(MemoryRegion::ROM))
try {
m_os = std::make_unique<OS>(t);
}
catch(std::exception &) {}
}
void PrintPass::analyze(uint32_t pc, ConcreteInstruction &ci)
@ -70,6 +72,12 @@ void PrintPass::analyze(uint32_t pc, ConcreteInstruction &ci)
pcrelloc(arg);
queue_flush();
}
else if(a.kind == Argument::PcAddr)
{
queue(a.str());
pcaddrloc(arg);
queue_flush();
}
else
{
queue(a.str());
@ -173,4 +181,12 @@ void PrintPass::symbol(ConcreteInstructionArg const &arg)
queue(*maybe_name, promote_symbol==Promote);
}
void PrintPass::pcaddrloc(ConcreteInstructionArg const &arg)
{
if(!RelConstDomain().is_constant(arg.location)) return;
if(promote_pcaddr_loc == Never) return;
queue(format("<%s>", arg.location.str()), promote_pcaddr_loc==Promote);
}
} /* namespace FxOS */

View File

@ -7,7 +7,7 @@
namespace FxOS {
SyscallPass::SyscallPass(Disassembly &disasm, OS *os):
InstructionDisassemblyPass(disasm), m_os(os)
InstructionDisassemblyPass(disasm, "syscall"), m_os(os)
{
}