diff --git a/include/fxos/passes/cfg.h b/include/fxos/passes/cfg.h index 657778d..561e6c9 100644 --- a/include/fxos/passes/cfg.h +++ b/include/fxos/passes/cfg.h @@ -45,6 +45,7 @@ #define FXOS_PASSES_CFG_H #include +#include namespace FxOS { @@ -54,9 +55,20 @@ public: CfgPass(Disassembly &disasm); bool analyzeInstruction(uint32_t pc, Instruction &inst) override; - /* Explore a new function at the specified address. This is a wrapper - around [analyzeFunction()] that creates the function. */ + /* Explore a new function at the specified address. This method creates the + function if it doesn't exist yet, explores its CFG, and generates claims + over relevant parts of the binary. */ bool exploreFunction(uint32_t pc); + + /* Access the set of claims generated by the last call to + exploreFunctions(). */ + std::set resultClaims(); + +private: + /* Last explored function */ + uint32_t m_lastFunction; + /* Set of instructions in a function, used to generate new claims */ + std::set m_claimedInstructions; }; } /* namespace FxOS */ diff --git a/lib/passes/cfg.cpp b/lib/passes/cfg.cpp index 23af3c6..16faee8 100644 --- a/lib/passes/cfg.cpp +++ b/lib/passes/cfg.cpp @@ -13,7 +13,7 @@ namespace FxOS { CfgPass::CfgPass(Disassembly &disasm): - InstructionPass(disasm) + InstructionPass(disasm), m_claimedInstructions {} { this->setAllowDiscovery(true); } @@ -27,6 +27,8 @@ bool CfgPass::analyzeInstruction(uint32_t pc, Instruction &i) return false; } + m_claimedInstructions.insert(pc); + /* Compute the jump target for jump instructions. This is easy because they are all trivially computable. (...If they are not we dub them "terminal" to avoid the computation!) */ @@ -93,6 +95,9 @@ bool CfgPass::analyzeInstruction(uint32_t pc, Instruction &i) bool CfgPass::exploreFunction(uint32_t pc) { + m_lastFunction = pc; + m_claimedInstructions.clear(); + if(!m_disasm.hasFunctionAt(pc)) { // TODO: Have proper function creation methods in Disassembly Function func = { .address=pc, .callTargets={} }; @@ -102,4 +107,34 @@ bool CfgPass::exploreFunction(uint32_t pc) return this->analyzeFunction(pc); } +std::set CfgPass::resultClaims() +{ + Claim base; + base.address = 0xffffffff; + base.size = 0; + base.type = Claim::Function; + base.owner = m_lastFunction; + + std::set set; + Claim c = base; + + for(uint32_t pc: m_claimedInstructions) { + if(pc == c.address + c.size) { + c.size += 2; + } + else { + if(c.size > 0) + set.insert(c); + c = base; + c.address = pc; + c.size = 2; + } + } + + if(c.size > 0) + set.insert(c); + + return set; +} + } /* namespace FxOS */ diff --git a/shell/a.cpp b/shell/a.cpp index 21281f9..51b0d5d 100644 --- a/shell/a.cpp +++ b/shell/a.cpp @@ -246,9 +246,11 @@ static void ad_disassemble_all(VirtualSpace &space, errors++; if(!force) return; } - else successes++; - - /* TODO: Get subfunction addresses here */ + else { + for(Claim const &c: cfg_pass.resultClaims()) + space.disasm.addExclusiveClaim(c); + successes++; + } } timer.stop(); printf("\n"); @@ -283,6 +285,9 @@ static void ad_disassemble_all(VirtualSpace &space, printf("Successfully analyzed %d functions (%d errors)\n", successes, errors); + + /* TODO: Get subfunction addresses by abstract interpretation and keep + going recursively */ } static std::vector parse_ad(Session &session, Parser &parser)