summaryrefslogtreecommitdiff
path: root/arch/powerpc/assembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/assembler.cpp')
-rw-r--r--arch/powerpc/assembler.cpp195
1 files changed, 175 insertions, 20 deletions
diff --git a/arch/powerpc/assembler.cpp b/arch/powerpc/assembler.cpp
index bafc0686..845b1ecb 100644
--- a/arch/powerpc/assembler.cpp
+++ b/arch/powerpc/assembler.cpp
@@ -20,9 +20,17 @@ using namespace std;
/* capstone stuff */
#include "capstone/capstone.h"
+#include "disassembler.h"
-//#define MYLOG printf
+#define DEBUG 0
+#if DEBUG
+#define MYLOG printf
+#else
#define MYLOG(...) while(0);
+#endif
+
+
+// #define ENABLE_CAPSTONE
#include "assembler.h"
@@ -1252,10 +1260,14 @@ map<string, info> lookup = {
{"rlwinm GPR , GPR , NUM , NUM , NUM",{0x54000000,0x03FFFFFE}}, // 010101xxxxxxxxxxxxxxxxxxxxxxxxx0 rlwinm r0, r0, 0, 0, 0
{"rlwinm . GPR , GPR , NUM , NUM , NUM",{0x54000001,0x03FFFFFE}}, // 010101xxxxxxxxxxxxxxxxxxxxxxxxx1 rlwinm. r0, r0, 0, 0, 0
{ "slwi GPR , GPR , NUM",{0x5400003E,0x03FFF83E}}, // 010101xxxxxxxxxxxxxxx00000xxxxx0 slwi r0, r0, 0
-{ "rotlwi . GPR , GPR , NUM",{0x5400003F,0x03FFF800}}, // 010101xxxxxxxxxxxxxxx00000111111 rotlwi. r0, r0, 0
+{ "clrrwi GPR , GPR , NUM",{0x54000000,0x03FF003E}}, // 010101xxxxxxxxxx0000000000xxxxx0 clrrwi r0, r0, 1
+{ "clrrwi . GPR , GPR , NUM",{0x54000001,0x03FF003F}}, // 010101xxxxxxxxxx0000000000xxxxx0 clrrwi. r0, r0, 1
{ "clrlwi GPR , GPR , NUM",{0x5400007E,0x03FF07C0}}, // 010101xxxxxxxxxx00000xxxxx111110 clrlwi r0, r0, 1
{ "clrlwi . GPR , GPR , NUM",{0x5400007F,0x03FF07C0}}, // 010101xxxxxxxxxx00000xxxxx111111 clrlwi. r0, r0, 1
{ "rotlwi GPR , GPR , NUM",{0x5400083E,0x03FFF800}}, // 010101xxxxxxxxxxxxxxx00000111110 rotlwi r0, r0, 1
+{ "rotlwi . GPR , GPR , NUM",{0x5400083F,0x03FFF800}}, // 010101xxxxxxxxxxxxxxx00000111111 rotlwi. r0, r0, 1
+{ "rotrwi GPR , GPR , NUM",{0x5400083E,0x03FFF800}}, // 010101xxxxxxxxxxxxxxx00000111110 rotrwi r0, r0, 1
+{ "rotrwi . GPR , GPR , NUM",{0x5400003F,0x03FFF800}}, // 010101xxxxxxxxxxxxxxx00000111111 rotrwi. r0, r0, 0
{ "srwi GPR , GPR , NUM",{0x54000FFE,0x03FFFFC0}}, // 010101xxxxxxxxxxxxxxxxxxxx111110 srwi r0, r0, 0x1f
{ "rlwnm GPR , GPR , GPR , NUM , NUM",{0x5C000000,0x03FFFFFE}}, // 010111xxxxxxxxxxxxxxxxxxxxxxxxx0 rlwnm r0, r0, r0, 0, 0
{"rlwnm . GPR , GPR , GPR , NUM , NUM",{0x5C000001,0x03FFFFFE}}, // 010111xxxxxxxxxxxxxxxxxxxxxxxxx1 rlwnm. r0, r0, r0, 0, 0
@@ -1271,8 +1283,20 @@ map<string, info> lookup = {
{ "andis . GPR , GPR , NUM",{0x74000000,0x03FFFFFF}}, // 011101xxxxxxxxxxxxxxxxxxxxxxxxxx andis. r0, r0, 0
{ "rotldi GPR , GPR , NUM",{0x78000000,0x03FFF802}}, // 011110xxxxxxxxxxxxxxx000000000x0 rotldi r0, r0, 0
{ "rotldi . GPR , GPR , NUM",{0x78000001,0x03FFF802}}, // 011110xxxxxxxxxxxxxxx000000000x1 rotldi. r0, r0, 0
+{ "rotrdi GPR , GPR , NUM",{0x78000000,0x03FFF802}}, // 011110xxxxxxxxxxxxxxx000000000x0 rotrdi r0, r0, 0
+{ "rotrdi . GPR , GPR , NUM",{0x78000001,0x03FFF802}}, // 011110xxxxxxxxxxxxxxx000000000x1 rotrdi. r0, r0, 0
+
+{ "extrdi . GPR , GPR , NUM , NUM",{0x78000023,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx000x1 rldicl. r0, r0, 0x20, 0x20
+
+// clrrdi r1, r1, 0x5 782106a4 // 011110'00001'00001'00000'110101'00100
+// // 000000'11111'11111'00000'111111'00000
+{ "clrrdi GPR , GPR , NUM",{0x78000004,0x03FF07E0}}, // 011110'xxxxx'xxxxx'00000'xxxxxx'00100 clrrdi r0, r0, 0x20
+{ "clrrdi . GPR , GPR , NUM",{0x78000005,0x03FF07E0}}, // 011110xxxxxxxxxx00000xxxxxx00101 clrrdi. r0, r0, 0x20
+{ "extldi GPR , GPR , NUM , NUM",{0x78000004,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx001x0 extldi r0, r0, 1, 0
+{ "extldi . GPR , GPR , NUM , NUM",{0x78000005,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx001x1 extldi. r0, r0, 1, 0
{ "rldicr GPR , GPR , NUM , NUM",{0x78000004,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx001x0 rldicr r0, r0, 0, 0
{ "rldicr . GPR , GPR , NUM , NUM",{0x78000005,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx001x1 rldicr. r0, r0, 0, 0
+
{ "rldic GPR , GPR , NUM , NUM",{0x78000008,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx010x0 rldic r0, r0, 0, 0
{ "rldic . GPR , GPR , NUM , NUM",{0x78000009,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx010x1 rldic. r0, r0, 0, 0
{ "rldimi GPR , GPR , NUM , NUM",{0x7800000C,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx011x0 rldimi r0, r0, 0, 0
@@ -1281,13 +1305,20 @@ map<string, info> lookup = {
{ "rotld . GPR , GPR , GPR",{0x78000011,0x03FFF800}}, // 011110xxxxxxxxxxxxxxx00000010001 rotld. r0, r0, r0
{ "rldcr GPR , GPR , GPR , NUM",{0x78000012,0x03FFFFE0}}, // 011110xxxxxxxxxxxxxxxxxxxxx10010 rldcr r0, r0, r0, 0
{ "rldcr . GPR , GPR , GPR , NUM",{0x78000013,0x03FFFFE0}}, // 011110xxxxxxxxxxxxxxxxxxxxx10011 rldcr. r0, r0, r0, 0
+
{ "clrldi GPR , GPR , NUM",{0x78000020,0x03FF07E0}}, // 011110xxxxxxxxxx00000xxxxxx00000 clrldi r0, r0, 0x20
{ "clrldi . GPR , GPR , NUM",{0x78000021,0x03FF07E0}}, // 011110xxxxxxxxxx00000xxxxxx00001 clrldi. r0, r0, 0x20
+{ "extrdi GPR , GPR , NUM , NUM",{0x78000022,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx000x0 extrdi r0, r0, 1, 0x20
+{ "extrdi . GPR , GPR , NUM , NUM",{0x78000023,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx000x1 extrdi. r0, r0, 1, 0x20
{ "rldicl GPR , GPR , NUM , NUM",{0x78000022,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx000x0 rldicl r0, r0, 0x20, 0x20
{ "rldicl . GPR , GPR , NUM , NUM",{0x78000023,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx000x1 rldicl. r0, r0, 0x20, 0x20
+
{ "rldcl GPR , GPR , GPR , NUM",{0x78000030,0x03FFFFE0}}, // 011110xxxxxxxxxxxxxxxxxxxxx10000 rldcl r0, r0, r0, 0x20
{ "rldcl . GPR , GPR , GPR , NUM",{0x78000031,0x03FFFFE0}}, // 011110xxxxxxxxxxxxxxxxxxxxx10001 rldcl. r0, r0, r0, 0x20
{ "sldi GPR , GPR , NUM",{0x780007C6,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx001x0 sldi r0, r0, 0x20
+{ "srdi GPR , GPR , NUM",{0x780007C4,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx000x0 srdi r0, r0, 0x20
+{ "sldi . GPR , GPR , NUM",{0x780007C7,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx001x0 sldi. r0, r0, 0x20
+{ "srdi . GPR , GPR , NUM",{0x780007C5,0x03FFFFE2}}, // 011110xxxxxxxxxxxxxxxxxxxxx000x0 srdi. r0, r0, 0x20
{ "cmpw GPR , GPR",{0x7C000000,0x001FF800}}, // 01111100000xxxxxxxxxx00000000000 cmpw r0, r0
{ "tw NUM , GPR , GPR",{0x7C000008,0x03FFF800}}, // 011111xxxxxxxxxxxxxxx00000001000 tw 0, r0, r0
{ "lvsl VREG , NUM , GPR",{0x7C00000C,0x03E0F800}}, // 011111xxxxx00000xxxxx00000001100 lvsl v0, 0, r0
@@ -2160,8 +2191,16 @@ const char *cs_err_to_string(cs_err e)
}
}
+int disasm_binja(uint8_t *data, uint32_t addr, string& result, string& err)
+{
+ return disassemble(data, addr, result);
+}
+
int disasm_capstone(uint8_t *data, uint32_t addr, string& result, string& err)
{
+#ifndef ENABLE_CAPSTONE
+ return -1;
+#endif
int rc = -1;
static bool init = false;
@@ -2218,18 +2257,20 @@ int disasm_capstone(uint8_t *data, uint32_t addr, string& result, string& err)
/* instruction tokenizing */
/*****************************************************************************/
-#define TT_GPR 1
-#define TT_VREG 2
-#define TT_FLAG 3
-#define TT_CREG 4
-#define TT_VSREG 5
-#define TT_FREG 6
-#define TT_NUM 7
-#define TT_PUNC 8
-#define TT_OPC 9
-
+enum t_type
+{
+ TT_GPR = 1,
+ TT_VREG = 2,
+ TT_FLAG = 3,
+ TT_CREG = 4,
+ TT_VSREG = 5,
+ TT_FREG = 6,
+ TT_NUM = 7,
+ TT_PUNC = 8,
+ TT_OPC = 9,
+};
struct token {
- int type;
+ t_type type;
uint32_t ival;
string sval;
};
@@ -2380,6 +2421,7 @@ void tokens_print(vector<token>& tokens)
case TT_FREG:
case TT_VSREG:
case TT_NUM:
+ case TT_FLAG:
printf("%s: %d\n", token_type_tostr(t.type), t.ival);
break;
case TT_PUNC:
@@ -2449,6 +2491,7 @@ float fitness(vector<token> dst, vector<token> src) {
float score(vector<token> baseline, uint32_t newcomer, uint32_t addr)
{
+ // return 0;
vector<token> toks_child;
string err;
string src;
@@ -2471,6 +2514,86 @@ float score(vector<token> baseline, uint32_t newcomer, uint32_t addr)
return fitness(baseline, toks_child);
}
+float score_binja(vector<token> baseline, uint32_t newcomer, uint32_t addr)
+{
+ vector<token> toks_child;
+ string err;
+ string src;
+
+ if(disasm_binja((uint8_t *)&newcomer, addr, src, err))
+ return -1;
+
+ /* compare mnemonics before doing more work */
+ string mnem = baseline[0].sval;
+ if(src.compare(0, mnem.size(), mnem) != 0) {
+ // A few special case equivalences that it can't figure out on its own
+ if (mnem == "rotrdi" && src.compare(0, 6, "rotldi") == 0)
+ {
+ if (tokenize("rotrdi" + src.substr(6), toks_child, err))
+ return 0;
+ toks_child.back().ival = 64 - toks_child.back().ival;
+ }
+ else if (mnem == "rldicl" && src.compare(0, 6, "rotldi") == 0)
+ {
+ if (tokenize("rldicl" + src.substr(6), toks_child, err))
+ return 0;
+ toks_child.push_back({TT_PUNC, 0, ","});
+ toks_child.push_back({TT_NUM, 0, ""});
+ }
+ else if (mnem == "rldcl" && src.compare(0, 5, "rotld") == 0)
+ {
+ if (tokenize("rldcl" + src.substr(5), toks_child, err))
+ return 0;
+ toks_child.push_back({TT_PUNC, 0, ","});
+ toks_child.push_back({TT_NUM, 0, ""});
+ }
+ else if (mnem == "rlwinm")
+ {
+ if (src.compare(0, 6, "clrrwi") == 0)
+ {
+ if (tokenize("rlwinm" + src.substr(6), toks_child, err))
+ return 0;
+ uint32_t me = toks_child.back().ival;
+ toks_child.back().ival = 0;
+ toks_child.push_back({TT_PUNC, 0, ","});
+ toks_child.push_back({TT_NUM, 0, ""});
+ toks_child.push_back({TT_PUNC, 0, ","});
+ toks_child.push_back({TT_NUM, 31 - me, ""});
+ }
+ else if (src.compare(0, 6, "clrlwi") == 0)
+ {
+ if (tokenize("rlwinm" + src.substr(6), toks_child, err))
+ return 0;
+ uint32_t mb = toks_child.back().ival;
+ toks_child.back().ival = 0;
+ toks_child.push_back({TT_PUNC, 0, ","});
+ toks_child.push_back({TT_NUM, mb, ""});
+ toks_child.push_back({TT_PUNC, 0, ","});
+ toks_child.push_back({TT_NUM, 31, ""});
+ }
+ else if (src.compare(0, 6, "rotlwi") == 0)
+ {
+ if (tokenize("rlwinm" + src.substr(6), toks_child, err))
+ return 0;
+ toks_child.push_back({TT_PUNC, 0, ","});
+ toks_child.push_back({TT_NUM, 0, ""});
+ toks_child.push_back({TT_PUNC, 0, ","});
+ toks_child.push_back({TT_NUM, 31, ""});
+ }
+ }
+ else
+ return 0;
+ }
+
+ /* mnemonics are the same, tokenize now... */
+ if(toks_child.size() == 0 && tokenize(src, toks_child, err)) {
+ printf("ERROR: %s\n", err.c_str());
+ return 0;
+ }
+
+ return fitness(baseline, toks_child);
+}
+
struct match {
uint32_t src_hi, src_lo; // source bit range
uint32_t dst_hi, dst_lo; // destination bit range
@@ -2512,12 +2635,15 @@ uint32_t enforce_bit_match(uint32_t inp, unsigned bit, vector<match> matches)
// seed: the seed value that may need the special case
// insword: instruction word
// bit: last bit changed
-uint32_t special_handling(uint32_t seed, uint32_t insword, int bit)
+uint32_t special_handling(uint32_t seed, uint32_t insword, int bit, vector<token> baseline)
{
switch(seed) {
/* sldi is extended mnemonic for rldicr (when mask = 63-shift) and hops
to it or other extended mnemonics easily */
case 0x780007C6:
+ // case 0x780007C4:
+ case 0x780007C7:
+ // case 0x780007C5:
/* if shift field changed, update mask */
if(bit==1 || (bit>=11 && bit<=15)) {
uint32_t shift = ((insword>>1)&1) | ((insword>>10)&0x3E);
@@ -2532,6 +2658,24 @@ uint32_t special_handling(uint32_t seed, uint32_t insword, int bit)
}
/* neither field updated */
return insword;
+ // case 0x780007C6:
+ case 0x780007C4:
+ // case 0x780007C7:
+ case 0x780007C5:
+ /* if shift field changed, update mask */
+ if(bit==1 || (bit>=11 && bit<=15)) {
+ uint32_t shift = ((insword>>1)&1) | ((insword>>10)&0x3E);
+ uint32_t mask = 64-shift;
+ return (insword&0xFFFFF81F) | (mask<<5);
+ }
+ /* if mask field changed, update shift */
+ if(bit>=5 && bit<=10) {
+ uint32_t mask = (insword>>5)&0x3F;
+ uint32_t shift = 64-mask;
+ return (insword&0xFFFF07FD) | ((shift&0x3E)<<11) | ((shift&0x1)<<1);
+ }
+ /* neither field updated */
+ return insword;
case 0x54000FFE: // srwi
if(bit>=6 && bit<=10) {
@@ -2767,6 +2911,8 @@ bool fmt_match(string fmt, string str, vector<string>& result)
/*****************************************************************************/
#define FAILURES_LIMIT 10000
+
+
int assemble_single(string src, uint32_t addr, uint8_t *result, string& err,
int& failures)
{
@@ -2805,11 +2951,17 @@ int assemble_single(string src, uint32_t addr, uint8_t *result, string& err,
toks_src.back().ival = -toks_src.back().ival;
toks_src[0].sval = "addis";
}
+ else if(!strncmp("rotrwi", toks_src[0].sval.c_str(), 6) &&
+ toks_src.back().type == TT_NUM) {
+ toks_src.back().ival = 32-toks_src.back().ival;
+ toks_src[0].sval = "rotlwi";
+ }
/* start with the parent */
uint32_t parent = info.seed;
float init_score, top_score;
- init_score = top_score = score(toks_src, parent, addr);
+ init_score = top_score = max(score(toks_src, parent, addr),
+ score_binja(toks_src, parent, addr));
/* cache the xor masks */
int n_flips = 0;
@@ -2839,9 +2991,10 @@ int assemble_single(string src, uint32_t addr, uint8_t *result, string& err,
for(; b1i<n_flips; b1i = (b1i+1) % n_flips) {
uint32_t child = parent ^ flipper[b1i];
- child = special_handling(info.seed, child, flipper_idx[b1i]);
+ child = special_handling(info.seed, child, flipper_idx[b1i], toks_src);
- float s = score(toks_src, child, addr);
+ float s = max(score(toks_src, child, addr),
+ score_binja(toks_src, child, addr));
if(s > top_score) {
parent = child;
top_score = s;
@@ -2864,20 +3017,22 @@ int assemble_single(string src, uint32_t addr, uint8_t *result, string& err,
for(int i=0; i<n_flips; ++i) {
if(rand()%2) {
parent ^= flipper[i];
- parent = special_handling(info.seed, parent, flipper_idx[i]);
+ parent = special_handling(info.seed, parent, flipper_idx[i], toks_src);
}
}
-
- top_score = score(toks_src, parent, addr);
+ top_score = max(score(toks_src, parent, addr),
+ score_binja(toks_src, parent, addr));
if(top_score >= init_score) {
MYLOG("perturbing the parent to: %08X (score:%f) (vs:%f)\n", parent, top_score, init_score);
break;
}
else {
+#if DEBUG
string tmp;
disasm_capstone((uint8_t *)&parent, addr, tmp, err);
MYLOG("%08X: %s perturb fail %f\n", parent, tmp.c_str(), top_score);
+#endif
failures++;
}