Skip to content
Snippets Groups Projects
Commit ec396f1d authored by Jason Hiser's avatar Jason Hiser :tractor:
Browse files

revised cfg builder to build blocks for apparently unreachable code.

Former-commit-id: c04807a76e1358c5b454fb64dd19a13fde642fd0
parent 922f4696
No related branches found
No related tags found
No related merge requests found
...@@ -9,4 +9,4 @@ lib/ ...@@ -9,4 +9,4 @@ lib/
manifest.txt.config manifest.txt.config
tools/meds2pdb/meds2pdb tools/meds2pdb/meds2pdb
plugins_install/*.exe plugins_install/*.exe
*.swp
...@@ -53,8 +53,7 @@ class BasicBlock_t ...@@ -53,8 +53,7 @@ class BasicBlock_t
protected: protected:
void BuildBlock(Function_t* func, void BuildBlock( Instruction_t* insn,
Instruction_t* insn,
const std::map<Instruction_t*,BasicBlock_t*> &insn2block_map const std::map<Instruction_t*,BasicBlock_t*> &insn2block_map
); );
......
...@@ -26,24 +26,27 @@ class ControlFlowGraph_t ...@@ -26,24 +26,27 @@ class ControlFlowGraph_t
{ {
public: public:
ControlFlowGraph_t(Function_t* func); ControlFlowGraph_t(Function_t* func);
BasicBlock_t* GetEntry() const { return entry; } BasicBlock_t* GetEntry() const { return entry; }
Function_t* GetFunction() const { return function; } Function_t* GetFunction() const { return function; }
BasicBlockSet_t& GetBlocks() { return blocks; }
const BasicBlockSet_t& GetBlocks() const { return blocks; }
void dump(std::ostream &os=std::cout) const { os<<*this; } void dump(std::ostream &os=std::cout) const { os<<*this; }
protected: private:
// methods
void Build(Function_t *func); void Build(Function_t *func);
void alloc_blocks(const InstructionSet_t &starts, map<Instruction_t*,BasicBlock_t*>& insn2block_map);
void build_blocks(const map<Instruction_t*,BasicBlock_t*>& insn2block_map);
void find_unblocked_instructions(InstructionSet_t &starts, Function_t* func);
private: // data
std::set<BasicBlock_t*> blocks; BasicBlockSet_t blocks;
BasicBlock_t* entry; BasicBlock_t* entry;
Function_t* function; Function_t* function;
/* friends */ /* friends */
public: public:
friend std::ostream& operator<<(std::ostream& os, const ControlFlowGraph_t& cfg); friend std::ostream& operator<<(std::ostream& os, const ControlFlowGraph_t& cfg);
BasicBlockSet_t& GetBlocks() { return blocks; }
const BasicBlockSet_t& GetBlocks() const { return blocks; }
}; };
......
...@@ -37,11 +37,11 @@ BasicBlock_t::BasicBlock_t() ...@@ -37,11 +37,11 @@ BasicBlock_t::BasicBlock_t()
void BasicBlock_t::BuildBlock void BasicBlock_t::BuildBlock
( (
Function_t* func,
Instruction_t* insn, Instruction_t* insn,
const map<Instruction_t*,BasicBlock_t*> &insn2block_map const map<Instruction_t*,BasicBlock_t*> &insn2block_map
) )
{ {
const auto &func=insn->GetFunction();
assert(insn); assert(insn);
/* loop through the instructions for this block */ /* loop through the instructions for this block */
while(insn) while(insn)
...@@ -116,7 +116,7 @@ void BasicBlock_t::BuildBlock ...@@ -116,7 +116,7 @@ void BasicBlock_t::BuildBlock
break; break;
/* check for a fallthrough out of the function */ /* check for a fallthrough out of the function */
if(ft_insn && !is_in_container(func->GetInstructions(),ft_insn)) if(ft_insn && ft_insn->GetFunction() != func) // !is_in_container(func->GetInstructions(),ft_insn))
break; break;
......
...@@ -25,10 +25,12 @@ ...@@ -25,10 +25,12 @@
using namespace std; using namespace std;
using namespace libIRDB; using namespace libIRDB;
#define ALLOF(a) begin(a),end(a)
/* /*
* FindTargets - locate all possible instructions that are the target of a jump instruction * FindTargets - locate all possible instructions that are the target of a jump instruction
*/ */
static set<Instruction_t*> FindBlockStarts(Function_t* func) static InstructionSet_t FindBlockStarts(Function_t* func)
{ {
InstructionSet_t targets; InstructionSet_t targets;
...@@ -80,55 +82,86 @@ static set<Instruction_t*> FindBlockStarts(Function_t* func) ...@@ -80,55 +82,86 @@ static set<Instruction_t*> FindBlockStarts(Function_t* func)
return targets; return targets;
} }
ControlFlowGraph_t::ControlFlowGraph_t(Function_t* func) : ControlFlowGraph_t::ControlFlowGraph_t(Function_t* func) :
entry(NULL), function(func) entry(NULL), function(func)
{ {
Build(func); Build(func);
} }
void ControlFlowGraph_t::Build(Function_t* func)
{
set<Instruction_t*> starts=FindBlockStarts(func);
map<Instruction_t*,BasicBlock_t*> insn2block_map;
void ControlFlowGraph_t::alloc_blocks(const InstructionSet_t &starts, map<Instruction_t*,BasicBlock_t*>& insn2block_map)
{
/* create a basic block for each instruction that starts a block */ /* create a basic block for each instruction that starts a block */
for( set<Instruction_t*>::const_iterator it=starts.begin(); for(const auto &insn : starts)
it!=starts.end();
++it
)
{ {
Instruction_t* insn=*it; if(is_in_container(insn2block_map,insn)) // already allocated
BasicBlock_t* newblock=new BasicBlock_t; continue;
/* record the entry block */ auto newblock=new BasicBlock_t;
if(insn==func->GetEntryPoint())
entry=newblock;
assert( insn && newblock ); assert( insn && newblock );
blocks.insert(newblock); blocks.insert(newblock);
insn2block_map[insn]=newblock; insn2block_map[insn]=newblock;
} }
}
void ControlFlowGraph_t::build_blocks(const map<Instruction_t*,BasicBlock_t*>& insn2block_map)
{
/* Ask the basic block to set the fields for each block that need to be set */ /* Ask the basic block to set the fields for each block that need to be set */
for( map<Instruction_t*,BasicBlock_t*>::const_iterator it=insn2block_map.begin(); for(const auto &it : insn2block_map)
it!=insn2block_map.end();
++it
)
{ {
Instruction_t* insn=(*it).first; const auto insn=it.first;
BasicBlock_t* block=(*it).second; const auto block=it.second;
if(block->GetInstructions().size()>0) // already built
continue;
assert(insn && block); assert(insn && block);
block->BuildBlock(func, insn, insn2block_map); block->BuildBlock(insn, insn2block_map);
} }
}
void ControlFlowGraph_t::find_unblocked_instructions(InstructionSet_t &starts, Function_t* func)
{
auto mapped_instructions=InstructionSet_t();
auto missed_instructions=InstructionSet_t();
for(const auto block : GetBlocks())
mapped_instructions.insert(ALLOF(block->GetInstructions()));
auto my_inserter=inserter(missed_instructions,missed_instructions.end());
set_difference(ALLOF(func->GetInstructions()), ALLOF(mapped_instructions), my_inserter);
starts.insert(ALLOF(missed_instructions));
}
void ControlFlowGraph_t::Build(Function_t* func)
{
auto starts=FindBlockStarts(func);
auto insn2block_map=map<Instruction_t*,BasicBlock_t*> ();
alloc_blocks(starts, insn2block_map);
build_blocks(insn2block_map);
/* record the entry block */
entry=insn2block_map[func->GetEntryPoint()];
/* most functions are done now. */
/* however, if a function has a (direct) side entrance,
* some code may appear unreachable and not be placed in
* a block -- here, we detect that code and create a
* new basic block for every instruction, as any may have a side entrance
*/
/* note: side entrances may miss a block start */
/* in code that appears reachable from the entrance?! */
find_unblocked_instructions(starts, func);
alloc_blocks(starts, insn2block_map);
build_blocks(insn2block_map);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment