Skip to content

Commit

Permalink
Added PowerPC addr-taken pass
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandro Sanchez Bach committed Jun 14, 2017
1 parent 9f3bfc4 commit 07572ce
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 11 deletions.
76 changes: 68 additions & 8 deletions cfg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,73 @@ CFG::print_function_summaries(FILE *out)
}


void
CFG::mark_addrtaken(uint64_t addr)
{
BB *cc;

if (this->start2bb.count(addr)) {
cc = this->start2bb[addr];
if (!cc->addrtaken) {
cc->addrtaken = true;
verbose(3, "marking addrtaken bb@0x%016jx", cc->start);
}
}
}


void
CFG::analyze_addrtaken_ppc()
{
BB *bb;

/* Instructions can get reordered, so we emulate the ISA subset relevant for the patterns below,
* clearing the intermediate register values with with -1 if the result is irrelevant or undefined. */
int64_t registers[32];

for(auto &kv: this->start2bb) {
bb = kv.second;
for(auto &ins: bb->insns) {
if(ins.operands.size() < 2) {
continue;
}
/* Pattern #1 (32-bit)
* Load the address from its word halves. Following variants are supported:
* - Using addis/addi (gcc):
* lis rN, .L@ha
* addi rN, rN, L@l
* - Using addis/ori:
* lis rN, .L@ha
* ori rN, rN, .L@l */
if(ins.id == PPC_INS_LIS) {
int64_t dst = ins.operands[0].ppc_value.reg - PPC_REG_R0;
int64_t imm = ins.operands[1].ppc_value.imm;
assert(dst < 32);
registers[dst] = imm << 16;
}
else if(ins.id == PPC_INS_ADDI || ins.id == PPC_INS_ORI) {
int64_t lhs = ins.operands[1].ppc_value.reg - PPC_REG_R0;
int64_t rhs = ins.operands[2].ppc_value.imm;
assert(lhs < 32);
if (registers[lhs] != -1) {
mark_addrtaken(registers[lhs] | rhs);
}
}
else if(ins.operands[0].type == Operand::OP_TYPE_REG
&& ins.operands[0].ppc_value.reg >= PPC_REG_R0
&& ins.operands[0].ppc_value.reg <= PPC_REG_R31) {
int64_t dst = ins.operands[0].ppc_value.reg - PPC_REG_R0;
registers[dst] = -1;
}
}
}
}


void
CFG::analyze_addrtaken_x86()
{
BB *bb, *cc;
BB *bb;
Operand *op_src, *op_dst;

for(auto &kv: this->start2bb) {
Expand All @@ -50,13 +113,7 @@ CFG::analyze_addrtaken_x86()
op_src = &ins.operands[1];
if(((op_dst->type == Operand::OP_TYPE_REG) || (op_dst->type == Operand::OP_TYPE_MEM))
&& (op_src->type == Operand::OP_TYPE_IMM)) {
if(this->start2bb.count(op_src->x86_value.imm)) {
cc = this->start2bb[op_src->x86_value.imm];
if(!cc->addrtaken) {
cc->addrtaken = true;
verbose(3, "marking addrtaken bb@0x%016jx", cc->start);
}
}
mark_addrtaken(op_src->x86_value.imm);
}
}
}
Expand All @@ -69,6 +126,9 @@ CFG::analyze_addrtaken()
verbose(1, "starting address-taken analysis");

switch(this->binary->arch) {
case Binary::ARCH_PPC:
analyze_addrtaken_ppc();
break;
case Binary::ARCH_X86:
analyze_addrtaken_x86();
break;
Expand Down
6 changes: 6 additions & 0 deletions cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,17 @@ class CFG {
std::map<uint64_t, BB*> bad_bbs;

private:
/* pass: address-taken detection */
void mark_addrtaken (uint64_t addr);
void analyze_addrtaken_ppc ();
void analyze_addrtaken_x86 ();
void analyze_addrtaken ();

/* pass: switch detection */
void mark_jmptab_as_data (uint64_t start, uint64_t end);
void find_switches_x86 ();
void find_switches ();

void expand_function (Function *f, BB *bb);
void find_functions ();
void find_entry ();
Expand Down
1 change: 1 addition & 0 deletions disasm-ppc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ nucleus_disasm_bb_ppc(Binary *bin, DisasmSection *dis, BB *bb)
}

ins = &bb->insns.back();
ins->id = cs_ins->id;
ins->start = cs_ins->address;
ins->size = cs_ins->size;
ins->mnem = std::string(cs_ins->mnemonic);
Expand Down
2 changes: 1 addition & 1 deletion disasm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ nucleus_disasm_section(Binary *bin, DisasmSection *dis)
}
dis->BBs.push_back(BB(mutants[i]));
Q.push(&dis->BBs.back());
}
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions insn.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,14 @@ class Instruction {
INS_FLAG_NOP = 0x040
};

Instruction() : start(0), size(0), addr_size(0), target(0), flags(0), invalid(false), privileged(false), trap(false) {}
Instruction(const Instruction &i) : start(i.start), size(i.size), addr_size(i.addr_size), target(i.target), flags(i.flags),
Instruction() : id(0), start(0), size(0), addr_size(0), target(0), flags(0), invalid(false), privileged(false), trap(false) {}
Instruction(const Instruction &i) : id(i.id), start(i.start), size(i.size), addr_size(i.addr_size), target(i.target), flags(i.flags),
mnem(i.mnem), op_str(i.op_str), operands(i.operands), invalid(i.invalid), privileged(i.privileged), trap(i.trap) {}

void print (FILE *out);
Edge::EdgeType edge_type ();

unsigned int id;
uint64_t start;
uint8_t size;
uint8_t addr_size;
Expand Down

0 comments on commit 07572ce

Please sign in to comment.