Skip to content

RAnal SLEIGH plugin - #120

Merged
thestr4ng3r merged 48 commits into
rizinorg:masterfrom
FXTi:sleigh_anal
Sep 2, 2020
Merged

RAnal SLEIGH plugin#120
thestr4ng3r merged 48 commits into
rizinorg:masterfrom
FXTi:sleigh_anal

Conversation

@FXTi

@FXTi FXTi commented Jun 20, 2020

Copy link
Copy Markdown
Contributor

Detailed description

  • Improve pdgsd result in RCore plugin.
  • Port SleighInstructionPrototype from Ghidra's JAVA codebase to identify instruction's control flow type from underlying Constructor.
  • Implement as-much-as-possible P-code to ESIL translation.
  • Implement pattern-match on P-codes to identify type of single instruction.
  • Improve processor and compiler spec file parse to extract reg info.
  • Add pdga command to RCore plugin to enable this plugin.
  • Enable plugin's compilation option as default.

Test plan

Has been tested on 8 cases in r2-testbins. Test cases will be added in next pr.

@FXTi

FXTi commented Jun 28, 2020

Copy link
Copy Markdown
Contributor Author

How to label a bunch of P-codes generated from one single processor instruction.

For example, SAR RSI,0x3 should be labeled as R_ANAL_OP_TYPE_SAR.

But in P-codes, it's :

0x00000725: SAR RSI,0x3
    (unique,0xa420,4) = INT_AND 0x3, 0x3f
    (unique,0xa430,8) = COPY RSI
    RSI = INT_SRIGHT RSI, (unique,0xa420,4)
    (unique,0x2aa0,1) = INT_NOTEQUAL (unique,0xa420,4), 0x0
    (unique,0x2ab0,4) = INT_SUB (unique,0xa420,4), 0x1
    (unique,0x2ac0,8) = INT_SRIGHT (unique,0xa430,8), (unique,0x2ab0,4)
    (unique,0x2ad0,8) = INT_AND (unique,0x2ac0,8), 0x1
    (unique,0x2af0,1) = INT_NOTEQUAL (unique,0x2ad0,8), 0x0
    (unique,0x2b00,1) = BOOL_NEGATE (unique,0x2aa0,1)
    (unique,0x2b10,1) = INT_AND (unique,0x2b00,1), CF
    (unique,0x2b20,1) = INT_AND (unique,0x2aa0,1), (unique,0x2af0,1)
    CF = INT_OR (unique,0x2b10,1), (unique,0x2b20,1)
    (unique,0x2b50,1) = INT_EQUAL (unique,0xa420,4), 0x1
    (unique,0x2b60,1) = BOOL_NEGATE (unique,0x2b50,1)
    OF = INT_AND (unique,0x2b60,1), OF
    (unique,0x2590,1) = INT_NOTEQUAL (unique,0xa420,4), 0x0
    (unique,0x25b0,1) = INT_SLESS RSI, 0x0
    (unique,0x25c0,1) = BOOL_NEGATE (unique,0x2590,1)
    (unique,0x25d0,1) = INT_AND (unique,0x25c0,1), SF
    (unique,0x25e0,1) = INT_AND (unique,0x2590,1), (unique,0x25b0,1)
    SF = INT_OR (unique,0x25d0,1), (unique,0x25e0,1)
    (unique,0x2610,1) = INT_EQUAL RSI, 0x0
    (unique,0x2620,1) = BOOL_NEGATE (unique,0x2590,1)
    (unique,0x2630,1) = INT_AND (unique,0x2620,1), ZF
    (unique,0x2640,1) = INT_AND (unique,0x2590,1), (unique,0x2610,1)
    ZF = INT_OR (unique,0x2630,1), (unique,0x2640,1)
    (unique,0x2660,1) = POPCOUNT RSI
    PF = INT_AND (unique,0x2660,1), 0x1

My solution here is:

  1. Get operands from disas result, which is RSI and 0x3
  2. filter register name from result above, which is RSI
  3. Use register name to filter out the P-codes containing register name in operands, which are:
  2     (unique,0xa430,8) = COPY RSI
  3     RSI = INT_SRIGHT RSI, (unique,0xa420,4)
  4     (unique,0x25b0,1) = INT_SLESS RSI, 0x0
  5     (unique,0x2610,1) = INT_EQUAL RSI, 0x0
  6     (unique,0x2660,1) = POPCOUNT RSI
  1. Use only operator from result above, which are: COPY INT_SRIGHT INT_SLESS INT_EQUAL POPCOUNT
  2. label those P-code operators and take the one matters most. which is INT_SRIGHT -> R_ANAL_OP_TYPE_SAR

@FXTi

FXTi commented Jun 28, 2020

Copy link
Copy Markdown
Contributor Author
  • What is the exact info that you get in Java-Ghidra about a single instruction? Maybe they already have more than just pcode somewhere, either coming from sleigh directly or derived from pcode.

About pcode info getting from SLEIGH, there're Architecture::inst, which is built in Architecture::buildInstructions. By calling TypeOp::registerInstructions, it actually set opflags and behave. And all these info is used by Emulate system. There's also PcodeEmitCache to export pcode from SLEIGH for Emulate system. But I think this could be equal usage but much heavier than my impl. I just need to do the pair, filter, and sort work.

  • What analysis/filtering operations are already provided by the decompiler/sleigh library? Perhaps you can use some kind of data flow analysis/filtering to mask the ops you want.

It's mainly data flow analysis, I think it doesn't fit.

@thestr4ng3r

Copy link
Copy Markdown
Member
  • What is the exact info that you get in Java-Ghidra about a single instruction? Maybe they already have more than just pcode somewhere, either coming from sleigh directly or derived from pcode.

About pcode info getting from SLEIGH, there're Architecture::inst, which is built in Architecture::buildInstructions. By calling TypeOp::registerInstructions, it actually set opflags and behave. And all these info is used by Emulate system. There's also PcodeEmitCache to export pcode from SLEIGH for Emulate system. But I think this could be equal usage but much heavier than my impl. I just need to do the pair, filter, and sort work.

As far as I can tell, TypeOp are the pcode ops, not the real instructions. What I meant is what exactly do you get for e.g. a single x86 instruction aside from pcode. Also, did you check in Java yet?

@XVilka

XVilka commented Jul 22, 2020

Copy link
Copy Markdown
Member

@trufae @ret2libc by the way, please take a look when you have time and if you have any suggestions/complaints - write it here.

Comment thread src/anal_ghidra.cpp
Comment thread src/anal_ghidra.cpp
Comment thread src/SleighInstruction.h Outdated
@FXTi

FXTi commented Aug 4, 2020

Copy link
Copy Markdown
Contributor Author

2020-08-05_02-54

Benefit from reading oneInstruction(), core_ghidra's P-code display is improved again.

The rest work is to label instructions' type. And ESIL.

@FXTi

FXTi commented Aug 7, 2020

Copy link
Copy Markdown
Contributor Author

The current issue is: hard to describe behaviour of R_ANAL_OP_TYPE_XXX across multi-arch

Still take SAR instruction as example, I've implemented p-code filter function, and also consider middle variables, since middle variables can hold value from desired registers.

About middle variables:

  • It's casual to split one side affect of instruction into multiple P-code, and that introduce some variables holds middle value.
  • SLEIGH use unique varnode for that.
  • Those unique varnode will hold middle value and participate in later computation.

For example:

0x0000105c: PUSH EAX
    (unique,0x12f0,4) = COPY EAX
    ESP = INT_SUB ESP, 0x4
    (unique,0x12f0,4) = STORE [ESP]

It's obvious that middle variables(unique varnodes) is necessary for analysis.

Let's continue on original topic:

Raw P-code:

0x000011a3: SAR ESI,0xfd
    (unique,0x7900,4) = INT_AND 0xfd, 0x1f
    (unique,0x7910,4) = COPY ESI
    ESI = INT_SRIGHT ESI, (unique,0x7900,4)
    (unique,0x2060,1) = INT_NOTEQUAL (unique,0x7900,4), 0x0
    (unique,0x2070,4) = INT_SUB (unique,0x7900,4), 0x1
    (unique,0x2080,4) = INT_SRIGHT (unique,0x7910,4), (unique,0x2070,4)
    (unique,0x2090,4) = INT_AND (unique,0x2080,4), 0x1
    (unique,0x20b0,1) = INT_NOTEQUAL (unique,0x2090,4), 0x0
    (unique,0x20c0,1) = BOOL_NEGATE (unique,0x2060,1)
    (unique,0x20d0,1) = INT_AND (unique,0x20c0,1), CF
    (unique,0x20e0,1) = INT_AND (unique,0x2060,1), (unique,0x20b0,1)
    CF = INT_OR (unique,0x20d0,1), (unique,0x20e0,1)
    (unique,0x2110,1) = INT_EQUAL (unique,0x7900,4), 0x1
    (unique,0x2120,1) = BOOL_NEGATE (unique,0x2110,1)
    OF = INT_AND (unique,0x2120,1), OF
    (unique,0x1b50,1) = INT_NOTEQUAL (unique,0x7900,4), 0x0
    (unique,0x1b70,1) = INT_SLESS ESI, 0x0
    (unique,0x1b80,1) = BOOL_NEGATE (unique,0x1b50,1)
    (unique,0x1b90,1) = INT_AND (unique,0x1b80,1), SF
    (unique,0x1ba0,1) = INT_AND (unique,0x1b50,1), (unique,0x1b70,1)
    SF = INT_OR (unique,0x1b90,1), (unique,0x1ba0,1)
    (unique,0x1bd0,1) = INT_EQUAL ESI, 0x0
    (unique,0x1be0,1) = BOOL_NEGATE (unique,0x1b50,1)
    (unique,0x1bf0,1) = INT_AND (unique,0x1be0,1), ZF
    (unique,0x1c00,1) = INT_AND (unique,0x1b50,1), (unique,0x1bd0,1)
    ZF = INT_OR (unique,0x1bf0,1), (unique,0x1c00,1)
    (unique,0x1c20,1) = POPCOUNT ESI
    PF = INT_AND (unique,0x1c20,1), 0x1

Filtered P-code:

0x11a3: ESI = INT_SRIGHT ESI unique(7900, 4)
0x11a3: unique(2080, 4) = INT_SRIGHT unique(7910, 4) unique(2070, 4)
0x11a3: unique(2090, 4) = INT_AND unique(2080, 4) 1
0x11a3: unique(20b0, 1) = INT_NOTEQUAL unique(2090, 4) 0
0x11a3: unique(20e0, 1) = INT_AND unique(2060, 1) unique(20b0, 1)
0x11a3: CF = INT_OR unique(20d0, 1) unique(20e0, 1)
0x11a3: unique(1b70, 1) = INT_SLESS ESI 0
0x11a3: unique(1ba0, 1) = INT_AND unique(1b50, 1) unique(1b70, 1)
0x11a3: SF = INT_OR unique(1b90, 1) unique(1ba0, 1)
0x11a3: unique(1bd0, 1) = INT_EQUAL ESI 0
0x11a3: unique(1c00, 1) = INT_AND unique(1b50, 1) unique(1bd0, 1)
0x11a3: ZF = INT_OR unique(1bf0, 1) unique(1c00, 1)
0x11a3: unique(1c20, 1) = POPCOUNT ESI
0x11a3: PF = INT_AND unique(1c20, 1) 1
0x11a3: unique(7910, 4) = COPY ESI

The filtered P-code is enough to know this instruction is doing INT_SRIGHT. But if we want to fill RAnal data structure like other RAnal plugins do:

	case R_ANAL_OP_TYPE_SAR:
		CREATE_SRC_DST (op);
		set_src_dst (a->reg, op->dst, handle, insn, 0);
		set_src_dst (a->reg, op->src[0], handle, insn, 1);
		set_src_dst (a->reg, op->src[1], handle, insn, 2);
		set_src_dst (a->reg, op->src[2], handle, insn, 3);

It will require forward and backward lookup on complete P-codes to trace what unique varnodes originally are: a register, an address or a const value? Since I add data flow tracing on unique varnodes, I think of a new way to do identity work: model behaviour of R_ANAL_OP_TYPE_XXX across multi-arch and match complete P-codes with this pattern.

Still take SAR as example:

SAR is applied on one victim register, doing signed right shift on victim register, and store back into victim register

And that can be translate into three constraints:

  • P-codes must contain INT_SRIGHT
  • the input0 varnode of INT_SRIGHT should be register or unique varnode generated from operation on register(input0 is varnode input being shifted)
  • the output varnode of INT_SRIGHT should be shifted register or unique varnode which will be stored in shifted register

If all three constraints matches, we can say this instruction is R_ANAL_OP_TYPE_SAR.
But I don't know (how related RAnal data structure should be filled) and how accurate this solution will provide. Most importantly, whether my constraints are correct across multi-arches?

Moreover, I think ESIL is relatively easier to translate from P-code than structure filling. So, can I just provide accurate P-code and ignore related data structure?(Just label instructions) WIll radare2 extract necessary info from ESIL?

@XVilka

XVilka commented Aug 7, 2020

Copy link
Copy Markdown
Member

A lot of radare2 analysis steps requires this RAnalOp information rather than pure ESIL. Thus the plain P-code to ESIL translation wouldn't be enough. I suggest to make the plugin to fill some kind of hashtable to precompute these references, on the stage of initializing the analysis.

@wargio

wargio commented Aug 7, 2020

Copy link
Copy Markdown
Member

I agree with @XVilka i do not expect to have SLEIGH handling perfectly the analysis data that is given to RAnal.

I would also suggest to precompute and stay away from ESIL linked analysis.

Maybe you can try with a simplified view of the issue (you know, to start) and then try to patch things out; is not the best solution, but since the problem is quite complex, i would start this way.

@FXTi

FXTi commented Aug 10, 2020

Copy link
Copy Markdown
Contributor Author

P-code list for your reference: https://ghidra.re/courses/languages/html/pcodedescription.html

R_ANAL_OP_TYPE_MOV = 9, /* register move */

Pattern:

  • Has COPY or STORE
  • Input and output come from registers appear in assembly

Example:

0x00001191: MOV EBP,ESP
    EBP = COPY ESP
0x00001194: MOV dword ptr [EBP + -0x4],0x0
    (unique,0x3a0,4) = INT_ADD EBP, 0xfffffffc
    (unique,0xf40,4) = COPY 0x0
    (unique,0xf40,4) = STORE [(unique,0x3a0,4)]
0x0000119b: MOV dword ptr [EAX + -0x64],EAX
    (unique,0x3a0,4) = INT_ADD EAX, 0xffffff9c
    (unique,0xf30,4) = COPY EAX
    (unique,0xf30,4) = STORE [(unique,0x3a0,4)]

R_ANAL_OP_TYPE_CMOV = 9 | R_ANAL_OP_TYPE_COND, /* conditional move */

Pattern:

  • Has COPY or STORE
  • Input and output come from registers appear in assembly
  • Has CBRANCH above it jumps to next instruction or jumps to this COPY or STORE pcode

Example:

0x000011a1: CMOVL ECX,dword ptr [0x3]
    (unique,0x1090,1) = INT_NOTEQUAL OF, SF
    (unique,0x3aa0,1) = BOOL_NEGATE (unique,0x1090,1)
    CBRANCH dword_ptr(0x000011a8), (unique,0x3aa0,1)
    ECX = COPY dword_ptr(0x00000003)

R_ANAL_OP_TYPE_TRAP = 10, /* it's a trap! */

No, there's no trap in raw pcode

R_ANAL_OP_TYPE_SWI = 11, /* syscall, software interrupt */

Pattern:

  • Has CALLOTHER

Attention:
It's recognize as COMPUTED_CALL due to CALLIND. Do I need to specify this is R_ANAL_OP_TYPE_SWI?

Example:

0x000011a8: INT 0x80
    (unique,0x5370,4) = CALLOTHER 0x10, 0x80
    CALLIND (unique,0x5370,4)

0x00400114: syscall 
    CALLOTHER 0x3, 0x0

R_ANAL_OP_TYPE_CSWI = 11 | R_ANAL_OP_TYPE_COND, /* syscall, software interrupt */

Pattern:

  • Has CALLOTHER ans CBRANCH

Attention:
As above.

R_ANAL_OP_TYPE_UPUSH = 12, /* unknown push of data into stack */

Pattern:

  • Has STROE
  • Output of STORE is or comes from stack_reg

Example:

0x00001190: PUSH EBP
    (unique,0x12f0,4) = COPY EBP
    ESP = INT_SUB ESP, 0x4
    (unique,0x12f0,4) = STORE [ESP]

R_ANAL_OP_TYPE_RPUSH = R_ANAL_OP_TYPE_UPUSH | R_ANAL_OP_TYPE_REG, /* push register */

Pattern:

  • Has STROE
  • Output of STORE is or comes from stack_reg
  • Input of STORE is or comes from a register appearing in assembly

Example:

0x00001190: PUSH EBP
    (unique,0x12f0,4) = COPY EBP
    ESP = INT_SUB ESP, 0x4
    (unique,0x12f0,4) = STORE [ESP]

R_ANAL_OP_TYPE_PUSH = 13, /* push value into stack */

Pattern:

  • Has STROE
  • Output of STORE is or comes from stack_reg
  • Input of STORE isn't a register
  • Input of STORE doesn't come from a register

Example:

0x00001190: PUSH EBP
    (unique,0x12f0,4) = COPY EBP
    ESP = INT_SUB ESP, 0x4
    (unique,0x12f0,4) = STORE [ESP]

R_ANAL_OP_TYPE_POP = 14, /* pop value from stack to register */

Pattern:

  • Has LOAD
  • Input of LOAD is or comes from stack_reg
  • Output of LOAD is or comes from register appearing in assembly

Example:

0x000011af: POP EBP
    EBP = LOAD [ESP]
    ESP = INT_ADD ESP, 0x4

R_ANAL_OP_TYPE_CMP = 15, /* compare something */

Pattern:

  • Has INT_SUB
  • Two inputs of INT_SUB is a register or comes from register appearing in assembly
  • Output of key pcode is one input of INT_EQUAL or INT_LESS or INT_NOTEQUAL or INT_LESSEQUAL or INT_SLESS or INT_SLESSEQUAL

Attention:
Is INT_ADD and INT_SUB to include all situations?

Example:

0x0000120b: CMP EBX,EAX
    CF = INT_LESS EBX, EAX
    OF = INT_SBORROW EBX, EAX
    (unique,0x3c00,4) = INT_SUB EBX, EAX
    SF = INT_SLESS (unique,0x3c00,4), 0x0
    ZF = INT_EQUAL (unique,0x3c00,4), 0x0
    (unique,0x1b20,1) = POPCOUNT (unique,0x3c00,4)
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_ACMP = 16, /* compare via and */

Pattern:

  • Has INT_AND
  • Two inputs of INT_AND is a register or comes from register appearing in assembly
  • Output of key pcode is one input of INT_EQUAL or INT_LESS or INT_NOTEQUAL or INT_LESSEQUAL or INT_SLESS or INT_SLESSEQUAL

Attention:
As above.

Example:

0x0000120b: TEST EBX,EAX
    CF = COPY 0x0
    OF = COPY 0x0
    (unique,0x83c0,4) = INT_AND EBX, EAX
    SF = INT_SLESS (unique,0x83c0,4), 0x0
    ZF = INT_EQUAL (unique,0x83c0,4), 0x0
    (unique,0x1b20,1) = POPCOUNT (unique,0x83c0,4)
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_ADD = 17,

Pattern:

  • Has INT_ADD
  • Input of INT_ADD is a register or comes from register appearing in assembly
  • Output of INT_ADD is a register or comes from register appearing in assembly

Example:

0x000011f4: ADD EBX,0x2e0c
    CF = INT_CARRY EBX, 0x2e0c
    OF = INT_SCARRY EBX, 0x2e0c
    EBX = INT_ADD EBX, 0x2e0c
    SF = INT_SLESS EBX, 0x0
    ZF = INT_EQUAL EBX, 0x0
    (unique,0x1b20,1) = POPCOUNT EBX
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_SUB = 18,

Pattern:

  • Has INT_ADD
  • Input of INT_ADD is a register or comes from register appearing in assembly
  • Output of INT_ADD is a register or comes from register appearing in assembly

Example:

0x000011ec: SUB ESP,0x10
    CF = INT_LESS ESP, 0x10
    OF = INT_SBORROW ESP, 0x10
    ESP = INT_SUB ESP, 0x10
    SF = INT_SLESS ESP, 0x0
    ZF = INT_EQUAL ESP, 0x0
    (unique,0x1b20,1) = POPCOUNT ESP
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_IO = 19,

Attention:
Just pretend this does not exist.

Example:

0x00001198: IN AL, 0x7f
    AL = CALLOTHER 0x1, 0x7f

R_ANAL_OP_TYPE_MUL = 20,

Pattern:

  • Has INT_MULT
  • Input of INT_MULT is a register or comes from register appearing in assembly
  • Output of INT_MULT is a register or comes from register appearing in assembly

Example:

0x0000120b: IMUL EDX
    (unique,0x4e80,8) = INT_SEXT EAX
    (unique,0x4e90,8) = INT_SEXT EDX
    (unique,0x4eb0,8) = INT_MULT (unique,0x4e80,8), (unique,0x4e90,8)
    EDX = SUBPIECE (unique,0x4eb0,8), 0x4
    EAX = SUBPIECE (unique,0x4eb0,8), 0x0
    (unique,0x1c80,1) = INT_NOTEQUAL EDX, 0x0
    (unique,0x1c90,4) = INT_2COMP 0x1
    (unique,0x1ca0,1) = INT_NOTEQUAL EDX, (unique,0x1c90,4)
    CF = INT_AND (unique,0x1c80,1), (unique,0x1ca0,1)
    OF = COPY CF

R_ANAL_OP_TYPE_DIV = 21,

Pattern:

  • Has INT_DIV
  • Input of INT_DIV is a register or comes from register appearing in assembly
  • Output of INT_DIV is a register or comes from register appearing in assembly

Example:

0x00001209: DIV EDX
    (unique,0x45c0,8) = INT_ZEXT EDX
    (unique,0x45d0,8) = INT_ZEXT EDX
    (unique,0x45e0,8) = INT_LEFT (unique,0x45d0,8), 0x20
    (unique,0x45f0,8) = INT_ZEXT EAX
    (unique,0x4610,8) = INT_OR (unique,0x45e0,8), (unique,0x45f0,8)
    (unique,0x4630,8) = INT_DIV (unique,0x4610,8), (unique,0x45c0,8)
    EAX = SUBPIECE (unique,0x4630,8), 0x0
    (unique,0x4660,8) = INT_REM (unique,0x4610,8), (unique,0x45c0,8)
    EDX = SUBPIECE (unique,0x4660,8), 0x0

R_ANAL_OP_TYPE_SHR = 22,

Pattern:

  • Has INT_RIGHT
  • Input of INT_RIGHT is a register or comes from register appearing in assembly
  • Output of INT_RIGHT is a register or comes from register appearing in assembly

Example:

0x00001208: SHR EAX,1
    (unique,0xf50,1) = COPY 0x1
    (unique,0x80c0,4) = INT_AND EAX, 0x1
    CF = INT_NOTEQUAL (unique,0x80c0,4), 0x0
    OF = COPY 0x0
    EAX = INT_RIGHT EAX, 0x1
    SF = INT_SLESS EAX, 0x0
    ZF = INT_EQUAL EAX, 0x0
    (unique,0x1b20,1) = POPCOUNT EAX
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_SHL = 23,

Pattern:

  • Has INT_LEFT
  • Input of INT_RIGHT is a register or comes from register appearing in assembly
  • Output of INT_RIGHT is a register or comes from register appearing in assembly

Example:

0x0000120a: SHL EAX,1
    (unique,0xf50,1) = COPY 0x1
    CF = INT_SLESS EAX, 0x0
    EAX = INT_LEFT EAX, 0x1
    (unique,0x7b50,1) = INT_SLESS EAX, 0x0
    OF = INT_XOR CF, (unique,0x7b50,1)
    SF = INT_SLESS EAX, 0x0
    ZF = INT_EQUAL EAX, 0x0
    (unique,0x1b20,1) = POPCOUNT EAX
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_SAL = 24,

Attention:
Isn't this equal to R_ANAL_OP_TYPE_SAL?

R_ANAL_OP_TYPE_SAR = 25,

Pattern:

  • Has INT_SRIGHT
  • Input of INT_SRIGHT is a register or comes from register appearing in assembly
  • Output of INT_SRIGHT is a register or comes from register appearing in assembly

Example:

0x08048430: SAR EBX,0x2
    (unique,0x7900,4) = INT_AND 0x2, 0x1f
    (unique,0x7910,4) = COPY EBX
    EBX = INT_SRIGHT EBX, (unique,0x7900,4)
    (unique,0x2060,1) = INT_NOTEQUAL (unique,0x7900,4), 0x0
    (unique,0x2070,4) = INT_SUB (unique,0x7900,4), 0x1
    (unique,0x2080,4) = INT_SRIGHT (unique,0x7910,4), (unique,0x2070,4)
    (unique,0x2090,4) = INT_AND (unique,0x2080,4), 0x1
    (unique,0x20b0,1) = INT_NOTEQUAL (unique,0x2090,4), 0x0
    (unique,0x20c0,1) = BOOL_NEGATE (unique,0x2060,1)
    (unique,0x20d0,1) = INT_AND (unique,0x20c0,1), CF
    (unique,0x20e0,1) = INT_AND (unique,0x2060,1), (unique,0x20b0,1)
    CF = INT_OR (unique,0x20d0,1), (unique,0x20e0,1)
    (unique,0x2110,1) = INT_EQUAL (unique,0x7900,4), 0x1
    (unique,0x2120,1) = BOOL_NEGATE (unique,0x2110,1)
    OF = INT_AND (unique,0x2120,1), OF
    (unique,0x1b50,1) = INT_NOTEQUAL (unique,0x7900,4), 0x0
    (unique,0x1b70,1) = INT_SLESS EBX, 0x0
    (unique,0x1b80,1) = BOOL_NEGATE (unique,0x1b50,1)
    (unique,0x1b90,1) = INT_AND (unique,0x1b80,1), SF
    (unique,0x1ba0,1) = INT_AND (unique,0x1b50,1), (unique,0x1b70,1)
    SF = INT_OR (unique,0x1b90,1), (unique,0x1ba0,1)
    (unique,0x1bd0,1) = INT_EQUAL EBX, 0x0
    (unique,0x1be0,1) = BOOL_NEGATE (unique,0x1b50,1)
    (unique,0x1bf0,1) = INT_AND (unique,0x1be0,1), ZF
    (unique,0x1c00,1) = INT_AND (unique,0x1b50,1), (unique,0x1bd0,1)
    ZF = INT_OR (unique,0x1bf0,1), (unique,0x1c00,1)
    (unique,0x1c20,1) = POPCOUNT EBX
    PF = INT_AND (unique,0x1c20,1), 0x1

R_ANAL_OP_TYPE_OR = 26,

Pattern:

  • Has INT_OR
  • Input of INT_OR is a register or comes from register appearing in assembly
  • Output of INT_OR is a register or comes from register appearing in assembly

Example:

0x00001208: OR ESP,dword ptr [0xfffffff0]
    CF = COPY 0x0
    OF = COPY 0x0
    ESP = INT_OR ESP, dword_ptr(0xfffffff0)
    SF = INT_SLESS ESP, 0x0
    ZF = INT_EQUAL ESP, 0x0
    (unique,0x1b20,1) = POPCOUNT ESP
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_AND = 27,

Pattern:

  • Has INT_AND
  • Input of INT_AND is a register or comes from register appearing in assembly
  • Output of INT_AND is a register or comes from register appearing in assembly

Example:

0x080483d5: AND ESP,0xfffffff0
    CF = COPY 0x0
    OF = COPY 0x0
    ESP = INT_AND ESP, 0xfffffff0
    SF = INT_SLESS ESP, 0x0
    ZF = INT_EQUAL ESP, 0x0
    (unique,0x1b20,1) = POPCOUNT ESP
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_XOR = 28,

Pattern:

  • Has INT_XOR
  • Input of INT_XOR is a register or comes from register appearing in assembly
  • Output of INT_XOR is a register or comes from register appearing in assembly

Example:

0x00001203: XOR EAX,EAX
    CF = COPY 0x0
    OF = COPY 0x0
    EAX = INT_XOR EAX, EAX
    SF = INT_SLESS EAX, 0x0
    ZF = INT_EQUAL EAX, 0x0
    (unique,0x1b20,1) = POPCOUNT EAX
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_NOR = 29,

Attention:
Sample binary file needed!

R_ANAL_OP_TYPE_NOT = 30,

Pattern:

  • Only has INT_NEGATE

Attention:
I guess its accuracy will be low.

Example:

0x00001208: NOT EAX
    EAX = INT_NEGATE EAX

R_ANAL_OP_TYPE_STORE = 31, /* store from register to memory */

Attention:
I don't know how to identify this from mov or others.

Example:

0x00001218: STOSD ES:EDI
    (unique,0xe90,4) = COPY EDI
    (unique,0xea0,4) = INT_ADD EDI, 0x4
    (unique,0xeb0,4) = INT_ZEXT DF
    (unique,0xec0,4) = INT_MULT 0x8, (unique,0xeb0,4)
    EDI = INT_SUB (unique,0xea0,4), (unique,0xec0,4)
    (unique,0xee0,4) = COPY EAX
    (unique,0xee0,4) = STORE [(unique,0xe90,4)]

R_ANAL_OP_TYPE_LOAD = 32, /* load from memory to register */

Attention:
I don't know how to identify this from mov or others.

Example:

0x00001218: LODSD ESI
    (unique,0xc20,4) = COPY ESI
    (unique,0xc30,4) = INT_ADD ESI, 0x4
    (unique,0xc40,4) = INT_ZEXT DF
    (unique,0xc50,4) = INT_MULT 0x8, (unique,0xc40,4)
    ESI = INT_SUB (unique,0xc30,4), (unique,0xc50,4)
    (unique,0xc70,4) = LOAD [(unique,0xc20,4)]
    EAX = COPY (unique,0xc70,4)

R_ANAL_OP_TYPE_LEA = 33, /* TODO add ulea */

Attention:
I don't know how to identify this.

Example:

0x00001129: LEA ESI,[ESI]
    ESI = COPY ESI

R_ANAL_OP_TYPE_LEAVE = 34,

Attention:
Recommend just ignore this. Is this acceptable?

Example:

0x000011ca: LEAVE 
    ESP = COPY EBP
    EBP = LOAD [ESP]
    ESP = INT_ADD ESP, 0x4

R_ANAL_OP_TYPE_ROR = 35,

Attention:
I don't think we can differ this from right shift itself.

Example:

0x00001210: ROR EAX,1
    (unique,0xf50,1) = COPY 0x1
    (unique,0x7500,4) = INT_AND EAX, 0x1
    CF = INT_NOTEQUAL (unique,0x7500,4), 0x0
    (unique,0x7520,4) = INT_RIGHT EAX, 0x1
    (unique,0x7530,4) = INT_ZEXT CF
    (unique,0x7540,4) = INT_LEFT (unique,0x7530,4), 0x1f
    EAX = INT_OR (unique,0x7520,4), (unique,0x7540,4)
    (unique,0x7560,4) = INT_AND EAX, 0x40000000
    (unique,0x7570,1) = INT_NOTEQUAL (unique,0x7560,4), 0x0
    (unique,0x7580,1) = INT_SLESS EAX, 0x0
    OF = INT_XOR (unique,0x7570,1), (unique,0x7580,1)

0x00001210: ROR EAX,0x5
    (unique,0x7610,4) = INT_AND 0x5, 0x1f
    (unique,0x7620,4) = INT_RIGHT EAX, (unique,0x7610,4)
    (unique,0x7630,4) = INT_SUB 0x20, (unique,0x7610,4)
    (unique,0x7640,4) = INT_LEFT EAX, (unique,0x7630,4)
    EAX = INT_OR (unique,0x7620,4), (unique,0x7640,4)
    (unique,0x1e00,1) = INT_NOTEQUAL (unique,0x7610,4), 0x0
    (unique,0x1e20,1) = INT_SLESS EAX, 0x0
    (unique,0x1e30,1) = BOOL_NEGATE (unique,0x1e00,1)
    (unique,0x1e40,1) = INT_AND (unique,0x1e30,1), CF
    (unique,0x1e50,1) = INT_AND (unique,0x1e00,1), (unique,0x1e20,1)
    CF = INT_OR (unique,0x1e40,1), (unique,0x1e50,1)
    (unique,0x1e80,1) = INT_EQUAL (unique,0x7610,4), 0x1
    (unique,0x1e90,1) = INT_SLESS EAX, 0x0
    (unique,0x1ea0,4) = INT_LEFT EAX, 0x1
    (unique,0x1eb0,1) = INT_SLESS (unique,0x1ea0,4), 0x0
    (unique,0x1ed0,1) = INT_XOR (unique,0x1e90,1), (unique,0x1eb0,1)
    (unique,0x1ee0,1) = BOOL_NEGATE (unique,0x1e80,1)
    (unique,0x1ef0,1) = INT_AND (unique,0x1ee0,1), OF
    (unique,0x1f00,1) = INT_AND (unique,0x1e80,1), (unique,0x1ed0,1)
    OF = INT_OR (unique,0x1ef0,1), (unique,0x1f00,1)

R_ANAL_OP_TYPE_ROL = 36,

Attention:
Like above.

Example:

0x00001213: ROL EAX,0x5
    (unique,0x7210,4) = INT_AND 0x5, 0x1f
    (unique,0x7220,4) = INT_LEFT EAX, (unique,0x7210,4)
    (unique,0x7230,4) = INT_SUB 0x20, (unique,0x7210,4)
    (unique,0x7240,4) = INT_RIGHT EAX, (unique,0x7230,4)
    EAX = INT_OR (unique,0x7220,4), (unique,0x7240,4)
    (unique,0x1ce0,1) = INT_NOTEQUAL (unique,0x7210,4), 0x0
    (unique,0x1cf0,4) = INT_AND EAX, 0x1
    (unique,0x1d10,1) = INT_NOTEQUAL (unique,0x1cf0,4), 0x0
    (unique,0x1d20,1) = BOOL_NEGATE (unique,0x1ce0,1)
    (unique,0x1d30,1) = INT_AND (unique,0x1d20,1), CF
    (unique,0x1d40,1) = INT_AND (unique,0x1ce0,1), (unique,0x1d10,1)
    CF = INT_OR (unique,0x1d30,1), (unique,0x1d40,1)
    (unique,0x1d70,1) = INT_EQUAL (unique,0x7210,4), 0x1
    (unique,0x1d80,1) = INT_SLESS EAX, 0x0
    (unique,0x1da0,1) = INT_XOR CF, (unique,0x1d80,1)
    (unique,0x1db0,1) = BOOL_NEGATE (unique,0x1d70,1)
    (unique,0x1dc0,1) = INT_AND (unique,0x1db0,1), OF
    (unique,0x1dd0,1) = INT_AND (unique,0x1d70,1), (unique,0x1da0,1)
    OF = INT_OR (unique,0x1dc0,1), (unique,0x1dd0,1)

R_ANAL_OP_TYPE_XCHG = 37,

  • Has COPY
  • Classic exchange procedure of two variables with a temporary variable

Example:

0x00001216: XCHG EAX,EBX
    (unique,0x84b0,4) = COPY EAX
    EAX = COPY EBX
    EBX = COPY (unique,0x84b0,4)

R_ANAL_OP_TYPE_MOD = 38,

Pattern:

  • Has INT_SREM or INT_REM

Attention:

  • Will this pattern accurate enough?
  • Unluckily, assembly need improvement. P-code result is right, v1 and v0 is dalvik's local variables.

Example:

0x0000021e: rem_int_2addr 0x1004,0x1000
    v1 = INT_SREM v1, v0

R_ANAL_OP_TYPE_SWITCH = 39,

Example:

0x0000021e: packed_switch 0x1004,0x55
    (unique,0x330,4) = INT_MULT 0x55, 0x2
    (unique,0x340,4) = INT_ADD 0x21e, (unique,0x330,4)
    (unique,0x350,4) = INT_ADD (unique,0x340,4), 0x2
    (unique,0x370,2) = LOAD [(unique,0x350,4)]
    (unique,0x390,4) = INT_ZEXT (unique,0x370,2)
    (unique,0x3a0,4) = INT_ADD 0x21e, (unique,0x330,4)
    (unique,0x3b0,4) = INT_ADD (unique,0x3a0,4), 0x2
    (unique,0x3c0,4) = INT_ADD (unique,0x3b0,4), 0x2
    (unique,0x3e0,4) = LOAD [(unique,0x3c0,4)]
    (unique,0x3f0,1) = INT_LESS v1, (unique,0x3e0,4)
    CBRANCH dword_ptr(0x00000224), (unique,0x3f0,1)
    (unique,0x400,4) = INT_ADD (unique,0x3e0,4), (unique,0x390,4)
    (unique,0x410,1) = INT_LESSEQUAL (unique,0x400,4), v1
    CBRANCH dword_ptr(0x00000224), (unique,0x410,1)
    (unique,0x420,4) = INT_ADD 0x21e, (unique,0x330,4)
    (unique,0x430,4) = INT_ADD (unique,0x420,4), 0x2
    (unique,0x440,4) = INT_ADD (unique,0x430,4), 0x2
    (unique,0x460,4) = INT_ADD (unique,0x440,4), 0x4
    (unique,0x480,4) = INT_SUB v1, (unique,0x3e0,4)
    (unique,0x490,4) = INT_MULT (unique,0x480,4), 0x4
    (unique,0x4a0,4) = INT_ADD (unique,0x460,4), (unique,0x490,4)
    (unique,0x4c0,4) = LOAD [(unique,0x4a0,4)]
    (unique,0x4d0,4) = INT_MULT (unique,0x4c0,4), 0x2
    (unique,0x4f0,4) = INT_ADD 0x21e, (unique,0x4d0,4)
    BRANCHIND (unique,0x4f0,4)

R_ANAL_OP_TYPE_CASE = 40,

No related pcode

R_ANAL_OP_TYPE_LENGTH = 41,

Example:

0x00000234: array_length 0x1008,0x1008
    v2 = CPOOLREF v2, 0x0, 0x6

R_ANAL_OP_TYPE_CAST = 42,

Pattern:

  • Has CAST

R_ANAL_OP_TYPE_NEW = 43,

Pattern:

  • Has NEW

R_ANAL_OP_TYPE_ABS = 44,

Pattern:

  • Has FLOAT_ABS

Example:

0x00001208: FABS 
    ST0 = FLOAT_ABS ST0

R_ANAL_OP_TYPE_CPL = 45, /* complement */

Attention:
Sample binary file needed!

R_ANAL_OP_TYPE_CRYPTO = 46,

Attention:
Sample binary file needed!

R_ANAL_OP_TYPE_SYNC = 47,

Attention:
Sample binary file needed!

@wargio

wargio commented Aug 12, 2020

Copy link
Copy Markdown
Member

It's recognize as COMPUTED_CALL due to CALLIND. Do I need to specify this is R_ANAL_OP_TYPE_SWI?

No, i do not think is needed.

Is INT_ADD and INT_SUB to include all situations?

A CMP is always a sub.

Isn't this equal to R_ANAL_OP_TYPE_SAL?

Hmm yes.

R_ANAL_OP_TYPE_LEAVE = 34,

Attention:
Recommend just ignore this. Is this acceptable?

Example:

0x000011ca: LEAVE 
    ESP = COPY EBP
    EBP = LOAD [ESP]
    ESP = INT_ADD ESP, 0x4

Yes, ignore it.

R_ANAL_OP_TYPE_MOD = 38,

Pattern:

* Has `INT_SREM` or `INT_REM`

Attention:

* Will this pattern accurate enough?

* Unluckily, assembly need improvement. P-code result is right, `v1` and `v0` is dalvik's local variables.

Example:

0x0000021e: rem_int_2addr 0x1004,0x1000
    v1 = INT_SREM v1, v0

Yes, R_ANAL_OP_TYPE_MOD is signed and unsigned, therefore is correct your assumption.

Attention:
Sample binary file needed!

Have you checked in r2r-bins repo?

@thestr4ng3r

Copy link
Copy Markdown
Member

Fantastic overview!

It's recognize as COMPUTED_CALL due to CALLIND. Do I need to specify this is R_ANAL_OP_TYPE_SWI?

No, i do not think is needed.

I think it is needes because syscalls are very different instructions from calls. Since you already identified that they always have this CALLOTHER, do you think it would be hard to differenciate them?

R_ANAL_OP_TYPE_STORE = 31, /* store from register to memory */

Attention:
I don't know how to identify this from mov or others.

Store always has the destination in memory. I think if you encounter that it makes more sense to mark it as store than as mov. So having mov to memory marked as store is better than having store marked as mov in my opinion.

Essentially movs to memory are semantically just stores with a different name.

R_ANAL_OP_TYPE_LOAD = 32, /* load from memory to register */

Attention:
I don't know how to identify this from mov or others.

Same here, better mark movs as loads than the other way around.

R_ANAL_OP_TYPE_LEA = 33, /* TODO add ulea */

Attention:
I don't know how to identify this.

lea is x86 specific and essentially just a computation with a different name. I don't think you have to recognize them.

R_ANAL_OP_TYPE_NOR = 29,

Attention:
Sample binary file needed!

radare2/test/bins/mach0/ppc-ls:

            0x00005758      7f7bd8f8       nor r27, r27, r27

(or r2 -appc -b32 -ecfg.bigendian=1 -c "wx 7f7bd8f8" -)

R_ANAL_OP_TYPE_CPL = 45, /* complement */

Attention:
Sample binary file needed!

R_ANAL_OP_TYPE_CRYPTO = 46,

r2 -apic -easm.cpu=pic18 -c "pd1@0x300002" ihex:///home/florian/dev/radare2/test/bins/pic18c/FreeRTOS-pic18c.hex

            0x00300002      181e           comf 0x18, 1, 0

or r2 -apic -easm.cpu=pic18 -c "wx 181e" -

However most plugins mark CPL instructions as NOT. Complement is just bitwise negation so having both seems redundant unless NOT is only meant for something like dst = !src where dst will be only 1 or 0 but that's not documented anywhere so I would just ignore CPL and mark all as NOT.

Attention:
Sample binary file needed!

R_ANAL_OP_TYPE_SYNC = 47,

Attention:
Sample binary file needed!

I didn't find a binary with this one, but got this by bruteforcing with random bytes:

r2 -aarm -b64 -c "wx df3b03d5" -

            0x00000000      df3b03d5       isb 0xb

@FXTi

FXTi commented Aug 12, 2020

Copy link
Copy Markdown
Contributor Author

P-code list for your reference: https://ghidra.re/courses/languages/html/pcodedescription.html

R_ANAL_OP_TYPE_MOV = 9, /* register move */

Pattern:

  • Has COPY
  • Input and output come from registers appear in assembly

Example:

0x00001191: MOV EBP,ESP
    EBP = COPY ESP
0x00001194: MOV dword ptr [EBP + -0x4],0x0
    (unique,0x3a0,4) = INT_ADD EBP, 0xfffffffc
    (unique,0xf40,4) = COPY 0x0
    (unique,0xf40,4) = STORE [(unique,0x3a0,4)]
0x0000119b: MOV dword ptr [EAX + -0x64],EAX
    (unique,0x3a0,4) = INT_ADD EAX, 0xffffff9c
    (unique,0xf30,4) = COPY EAX
    (unique,0xf30,4) = STORE [(unique,0x3a0,4)]

R_ANAL_OP_TYPE_CMOV = 9 | R_ANAL_OP_TYPE_COND, /* conditional move */

Pattern:

  • Has COPY
  • Input and output come from registers appear in assembly
  • Has CBRANCH above it jumps to next instruction or jumps to this COPY or STORE pcode

Example:

0x000011a1: CMOVL ECX,dword ptr [0x3]
    (unique,0x1090,1) = INT_NOTEQUAL OF, SF
    (unique,0x3aa0,1) = BOOL_NEGATE (unique,0x1090,1)
    CBRANCH dword_ptr(0x000011a8), (unique,0x3aa0,1)
    ECX = COPY dword_ptr(0x00000003)

R_ANAL_OP_TYPE_STORE = 31, /* store from register to memory */

Pattern:

  • Has STORE
  • Input come from registers appear in assembly
  • Output doesn't come from registers appear in assembly

Example:

0x00001218: STOSD ES:EDI
    (unique,0xe90,4) = COPY EDI
    (unique,0xea0,4) = INT_ADD EDI, 0x4
    (unique,0xeb0,4) = INT_ZEXT DF
    (unique,0xec0,4) = INT_MULT 0x8, (unique,0xeb0,4)
    EDI = INT_SUB (unique,0xea0,4), (unique,0xec0,4)
    (unique,0xee0,4) = COPY EAX
    (unique,0xee0,4) = STORE [(unique,0xe90,4)]

R_ANAL_OP_TYPE_LOAD = 32, /* load from memory to register */

Pattern:

  • Has STORE
  • Input doesn't come from registers appear in assembly
  • Output come from registers appear in assembly

Example:

0x00001218: LODSD ESI
    (unique,0xc20,4) = COPY ESI
    (unique,0xc30,4) = INT_ADD ESI, 0x4
    (unique,0xc40,4) = INT_ZEXT DF
    (unique,0xc50,4) = INT_MULT 0x8, (unique,0xc40,4)
    ESI = INT_SUB (unique,0xc30,4), (unique,0xc50,4)
    (unique,0xc70,4) = LOAD [(unique,0xc20,4)]
    EAX = COPY (unique,0xc70,4)

R_ANAL_OP_TYPE_TRAP = 10, /* it's a trap! */

No, there's no trap in raw pcode

R_ANAL_OP_TYPE_SWI = 11, /* syscall, software interrupt */

Pattern:

  • Has CALLOTHER

Attention:
This kind has higher priority than flow type analysis. Should specify this as R_ANAL_OP_TYPE_SWI first.
Because it's recognize as COMPUTED_CALL due to CALLIND

Example:

0x000011a8: INT 0x80
    (unique,0x5370,4) = CALLOTHER 0x10, 0x80
    CALLIND (unique,0x5370,4)

0x00400114: syscall 
    CALLOTHER 0x3, 0x0

R_ANAL_OP_TYPE_CSWI = 11 | R_ANAL_OP_TYPE_COND, /* syscall, software interrupt */

Pattern:

  • Has CALLOTHER and CBRANCH

Attention:
As above.

R_ANAL_OP_TYPE_UPUSH = 12, /* unknown push of data into stack */

Pattern:

  • Has STROE
  • Output of STORE is or comes from stack_reg

Example:

0x00001190: PUSH EBP
    (unique,0x12f0,4) = COPY EBP
    ESP = INT_SUB ESP, 0x4
    (unique,0x12f0,4) = STORE [ESP]

R_ANAL_OP_TYPE_RPUSH = R_ANAL_OP_TYPE_UPUSH | R_ANAL_OP_TYPE_REG, /* push register */

Pattern:

  • Has STROE
  • Output of STORE is or comes from stack_reg
  • Input of STORE is or comes from a register appearing in assembly

Example:

0x00001190: PUSH EBP
    (unique,0x12f0,4) = COPY EBP
    ESP = INT_SUB ESP, 0x4
    (unique,0x12f0,4) = STORE [ESP]

R_ANAL_OP_TYPE_PUSH = 13, /* push value into stack */

Pattern:

  • Has STROE
  • Output of STORE is or comes from stack_reg
  • Input of STORE isn't a register
  • Input of STORE doesn't come from a register

Example:

0x00001190: PUSH EBP
    (unique,0x12f0,4) = COPY EBP
    ESP = INT_SUB ESP, 0x4
    (unique,0x12f0,4) = STORE [ESP]

R_ANAL_OP_TYPE_POP = 14, /* pop value from stack to register */

Pattern:

  • Has LOAD
  • Input of LOAD is or comes from stack_reg
  • Output of LOAD is or comes from register appearing in assembly

Example:

0x000011af: POP EBP
    EBP = LOAD [ESP]
    ESP = INT_ADD ESP, 0x4

R_ANAL_OP_TYPE_CMP = 15, /* compare something */

Pattern:

  • Has INT_SUB
  • Two inputs of INT_SUB is a register or comes from register appearing in assembly
  • Output of key pcode is one input of INT_EQUAL or INT_LESS or INT_NOTEQUAL or INT_LESSEQUAL or INT_SLESS or INT_SLESSEQUAL

Example:

0x0000120b: CMP EBX,EAX
    CF = INT_LESS EBX, EAX
    OF = INT_SBORROW EBX, EAX
    (unique,0x3c00,4) = INT_SUB EBX, EAX
    SF = INT_SLESS (unique,0x3c00,4), 0x0
    ZF = INT_EQUAL (unique,0x3c00,4), 0x0
    (unique,0x1b20,1) = POPCOUNT (unique,0x3c00,4)
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_ACMP = 16, /* compare via and */

Pattern:

  • Has INT_AND
  • Two inputs of INT_AND is a register or comes from register appearing in assembly
  • Output of key pcode is one input of INT_EQUAL or INT_LESS or INT_NOTEQUAL or INT_LESSEQUAL or INT_SLESS or INT_SLESSEQUAL

Example:

0x0000120b: TEST EBX,EAX
    CF = COPY 0x0
    OF = COPY 0x0
    (unique,0x83c0,4) = INT_AND EBX, EAX
    SF = INT_SLESS (unique,0x83c0,4), 0x0
    ZF = INT_EQUAL (unique,0x83c0,4), 0x0
    (unique,0x1b20,1) = POPCOUNT (unique,0x83c0,4)
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_ADD = 17,

Pattern:

  • Has INT_ADD
  • Input of INT_ADD is a register or comes from register appearing in assembly
  • Output of INT_ADD is a register or comes from register appearing in assembly

Example:

0x000011f4: ADD EBX,0x2e0c
    CF = INT_CARRY EBX, 0x2e0c
    OF = INT_SCARRY EBX, 0x2e0c
    EBX = INT_ADD EBX, 0x2e0c
    SF = INT_SLESS EBX, 0x0
    ZF = INT_EQUAL EBX, 0x0
    (unique,0x1b20,1) = POPCOUNT EBX
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_SUB = 18,

Pattern:

  • Has INT_ADD
  • Input of INT_ADD is a register or comes from register appearing in assembly
  • Output of INT_ADD is a register or comes from register appearing in assembly

Example:

0x000011ec: SUB ESP,0x10
    CF = INT_LESS ESP, 0x10
    OF = INT_SBORROW ESP, 0x10
    ESP = INT_SUB ESP, 0x10
    SF = INT_SLESS ESP, 0x0
    ZF = INT_EQUAL ESP, 0x0
    (unique,0x1b20,1) = POPCOUNT ESP
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_IO = 19,

Attention:
I think this could be regarded as a syscall. So ignore this.

Example:

0x00001198: IN AL, 0x7f
    AL = CALLOTHER 0x1, 0x7f

R_ANAL_OP_TYPE_MUL = 20,

Pattern:

  • Has INT_MULT
  • Input of INT_MULT is a register or comes from register appearing in assembly
  • Output of INT_MULT is a register or comes from register appearing in assembly

Example:

0x0000120b: IMUL EDX
    (unique,0x4e80,8) = INT_SEXT EAX
    (unique,0x4e90,8) = INT_SEXT EDX
    (unique,0x4eb0,8) = INT_MULT (unique,0x4e80,8), (unique,0x4e90,8)
    EDX = SUBPIECE (unique,0x4eb0,8), 0x4
    EAX = SUBPIECE (unique,0x4eb0,8), 0x0
    (unique,0x1c80,1) = INT_NOTEQUAL EDX, 0x0
    (unique,0x1c90,4) = INT_2COMP 0x1
    (unique,0x1ca0,1) = INT_NOTEQUAL EDX, (unique,0x1c90,4)
    CF = INT_AND (unique,0x1c80,1), (unique,0x1ca0,1)
    OF = COPY CF

R_ANAL_OP_TYPE_DIV = 21,

Pattern:

  • Has INT_DIV
  • Input of INT_DIV is a register or comes from register appearing in assembly
  • Output of INT_DIV is a register or comes from register appearing in assembly

Example:

0x00001209: DIV EDX
    (unique,0x45c0,8) = INT_ZEXT EDX
    (unique,0x45d0,8) = INT_ZEXT EDX
    (unique,0x45e0,8) = INT_LEFT (unique,0x45d0,8), 0x20
    (unique,0x45f0,8) = INT_ZEXT EAX
    (unique,0x4610,8) = INT_OR (unique,0x45e0,8), (unique,0x45f0,8)
    (unique,0x4630,8) = INT_DIV (unique,0x4610,8), (unique,0x45c0,8)
    EAX = SUBPIECE (unique,0x4630,8), 0x0
    (unique,0x4660,8) = INT_REM (unique,0x4610,8), (unique,0x45c0,8)
    EDX = SUBPIECE (unique,0x4660,8), 0x0

R_ANAL_OP_TYPE_SHR = 22,

Pattern:

  • Has INT_RIGHT
  • Input of INT_RIGHT is a register or comes from register appearing in assembly
  • Output of INT_RIGHT is a register or comes from register appearing in assembly

Example:

0x00001208: SHR EAX,1
    (unique,0xf50,1) = COPY 0x1
    (unique,0x80c0,4) = INT_AND EAX, 0x1
    CF = INT_NOTEQUAL (unique,0x80c0,4), 0x0
    OF = COPY 0x0
    EAX = INT_RIGHT EAX, 0x1
    SF = INT_SLESS EAX, 0x0
    ZF = INT_EQUAL EAX, 0x0
    (unique,0x1b20,1) = POPCOUNT EAX
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_SHL = 23,

Pattern:

  • Has INT_LEFT
  • Input of INT_RIGHT is a register or comes from register appearing in assembly
  • Output of INT_RIGHT is a register or comes from register appearing in assembly

Example:

0x0000120a: SHL EAX,1
    (unique,0xf50,1) = COPY 0x1
    CF = INT_SLESS EAX, 0x0
    EAX = INT_LEFT EAX, 0x1
    (unique,0x7b50,1) = INT_SLESS EAX, 0x0
    OF = INT_XOR CF, (unique,0x7b50,1)
    SF = INT_SLESS EAX, 0x0
    ZF = INT_EQUAL EAX, 0x0
    (unique,0x1b20,1) = POPCOUNT EAX
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_SAL = 24,

Attention:
Isn't this equal to R_ANAL_OP_TYPE_SHL?

R_ANAL_OP_TYPE_SAR = 25,

Pattern:

  • Has INT_SRIGHT
  • Input of INT_SRIGHT is a register or comes from register appearing in assembly
  • Output of INT_SRIGHT is a register or comes from register appearing in assembly

Example:

0x08048430: SAR EBX,0x2
    (unique,0x7900,4) = INT_AND 0x2, 0x1f
    (unique,0x7910,4) = COPY EBX
    EBX = INT_SRIGHT EBX, (unique,0x7900,4)
    (unique,0x2060,1) = INT_NOTEQUAL (unique,0x7900,4), 0x0
    (unique,0x2070,4) = INT_SUB (unique,0x7900,4), 0x1
    (unique,0x2080,4) = INT_SRIGHT (unique,0x7910,4), (unique,0x2070,4)
    (unique,0x2090,4) = INT_AND (unique,0x2080,4), 0x1
    (unique,0x20b0,1) = INT_NOTEQUAL (unique,0x2090,4), 0x0
    (unique,0x20c0,1) = BOOL_NEGATE (unique,0x2060,1)
    (unique,0x20d0,1) = INT_AND (unique,0x20c0,1), CF
    (unique,0x20e0,1) = INT_AND (unique,0x2060,1), (unique,0x20b0,1)
    CF = INT_OR (unique,0x20d0,1), (unique,0x20e0,1)
    (unique,0x2110,1) = INT_EQUAL (unique,0x7900,4), 0x1
    (unique,0x2120,1) = BOOL_NEGATE (unique,0x2110,1)
    OF = INT_AND (unique,0x2120,1), OF
    (unique,0x1b50,1) = INT_NOTEQUAL (unique,0x7900,4), 0x0
    (unique,0x1b70,1) = INT_SLESS EBX, 0x0
    (unique,0x1b80,1) = BOOL_NEGATE (unique,0x1b50,1)
    (unique,0x1b90,1) = INT_AND (unique,0x1b80,1), SF
    (unique,0x1ba0,1) = INT_AND (unique,0x1b50,1), (unique,0x1b70,1)
    SF = INT_OR (unique,0x1b90,1), (unique,0x1ba0,1)
    (unique,0x1bd0,1) = INT_EQUAL EBX, 0x0
    (unique,0x1be0,1) = BOOL_NEGATE (unique,0x1b50,1)
    (unique,0x1bf0,1) = INT_AND (unique,0x1be0,1), ZF
    (unique,0x1c00,1) = INT_AND (unique,0x1b50,1), (unique,0x1bd0,1)
    ZF = INT_OR (unique,0x1bf0,1), (unique,0x1c00,1)
    (unique,0x1c20,1) = POPCOUNT EBX
    PF = INT_AND (unique,0x1c20,1), 0x1

R_ANAL_OP_TYPE_OR = 26,

Pattern:

  • Has INT_OR
  • Input of INT_OR is a register or comes from register appearing in assembly
  • Output of INT_OR is a register or comes from register appearing in assembly

Example:

0x00001208: OR ESP,dword ptr [0xfffffff0]
    CF = COPY 0x0
    OF = COPY 0x0
    ESP = INT_OR ESP, dword_ptr(0xfffffff0)
    SF = INT_SLESS ESP, 0x0
    ZF = INT_EQUAL ESP, 0x0
    (unique,0x1b20,1) = POPCOUNT ESP
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_AND = 27,

Pattern:

  • Has INT_AND
  • Input of INT_AND is a register or comes from register appearing in assembly
  • Output of INT_AND is a register or comes from register appearing in assembly

Example:

0x080483d5: AND ESP,0xfffffff0
    CF = COPY 0x0
    OF = COPY 0x0
    ESP = INT_AND ESP, 0xfffffff0
    SF = INT_SLESS ESP, 0x0
    ZF = INT_EQUAL ESP, 0x0
    (unique,0x1b20,1) = POPCOUNT ESP
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_XOR = 28,

Pattern:

  • Has INT_XOR
  • Input of INT_XOR is a register or comes from register appearing in assembly
  • Output of INT_XOR is a register or comes from register appearing in assembly

Example:

0x00001203: XOR EAX,EAX
    CF = COPY 0x0
    OF = COPY 0x0
    EAX = INT_XOR EAX, EAX
    SF = INT_SLESS EAX, 0x0
    ZF = INT_EQUAL EAX, 0x0
    (unique,0x1b20,1) = POPCOUNT EAX
    PF = INT_AND (unique,0x1b20,1), 0x1

R_ANAL_OP_TYPE_NOR = 29,

Pattern:

  • Has INT_OR and INT_NEGATE
  • Input of INT_OR is a register or comes from register appearing in assembly
  • Output of INT_OR is a unique varnodedata
  • Output of INT_OR is input of INT_NEGATE
  • Output of INT_NEGATE is a register or comes from register appearing in assembly

Example:

0x00005758: nor r27,r27,r27
    (unique,0x69e0,4) = INT_OR r27, r27
    r27 = INT_NEGATE (unique,0x69e0,4)

R_ANAL_OP_TYPE_NOT = 30,

Pattern:

  • has INT_NEGATE
  • Input of INT_XOR is a register or comes from register appearing in assembly
  • Output of INT_XOR is a register or comes from register appearing in assembly

Attention:
I guess its accuracy will be low.

Example:

0x00001208: NOT EAX
    EAX = INT_NEGATE EAX

R_ANAL_OP_TYPE_LEA = 33, /* TODO add ulea */

Attention:
Just ignore this.

Example:

0x00001129: LEA ESI,[ESI]
    ESI = COPY ESI

R_ANAL_OP_TYPE_LEAVE = 34,

Attention:
Just ignore this.

Example:

0x000011ca: LEAVE 
    ESP = COPY EBP
    EBP = LOAD [ESP]
    ESP = INT_ADD ESP, 0x4

R_ANAL_OP_TYPE_ROR = 35,

Attention:
I don't think we can differ this from right shift itself.

Example:

0x00001210: ROR EAX,1
    (unique,0xf50,1) = COPY 0x1
    (unique,0x7500,4) = INT_AND EAX, 0x1
    CF = INT_NOTEQUAL (unique,0x7500,4), 0x0
    (unique,0x7520,4) = INT_RIGHT EAX, 0x1
    (unique,0x7530,4) = INT_ZEXT CF
    (unique,0x7540,4) = INT_LEFT (unique,0x7530,4), 0x1f
    EAX = INT_OR (unique,0x7520,4), (unique,0x7540,4)
    (unique,0x7560,4) = INT_AND EAX, 0x40000000
    (unique,0x7570,1) = INT_NOTEQUAL (unique,0x7560,4), 0x0
    (unique,0x7580,1) = INT_SLESS EAX, 0x0
    OF = INT_XOR (unique,0x7570,1), (unique,0x7580,1)

0x00001210: ROR EAX,0x5
    (unique,0x7610,4) = INT_AND 0x5, 0x1f
    (unique,0x7620,4) = INT_RIGHT EAX, (unique,0x7610,4)
    (unique,0x7630,4) = INT_SUB 0x20, (unique,0x7610,4)
    (unique,0x7640,4) = INT_LEFT EAX, (unique,0x7630,4)
    EAX = INT_OR (unique,0x7620,4), (unique,0x7640,4)
    (unique,0x1e00,1) = INT_NOTEQUAL (unique,0x7610,4), 0x0
    (unique,0x1e20,1) = INT_SLESS EAX, 0x0
    (unique,0x1e30,1) = BOOL_NEGATE (unique,0x1e00,1)
    (unique,0x1e40,1) = INT_AND (unique,0x1e30,1), CF
    (unique,0x1e50,1) = INT_AND (unique,0x1e00,1), (unique,0x1e20,1)
    CF = INT_OR (unique,0x1e40,1), (unique,0x1e50,1)
    (unique,0x1e80,1) = INT_EQUAL (unique,0x7610,4), 0x1
    (unique,0x1e90,1) = INT_SLESS EAX, 0x0
    (unique,0x1ea0,4) = INT_LEFT EAX, 0x1
    (unique,0x1eb0,1) = INT_SLESS (unique,0x1ea0,4), 0x0
    (unique,0x1ed0,1) = INT_XOR (unique,0x1e90,1), (unique,0x1eb0,1)
    (unique,0x1ee0,1) = BOOL_NEGATE (unique,0x1e80,1)
    (unique,0x1ef0,1) = INT_AND (unique,0x1ee0,1), OF
    (unique,0x1f00,1) = INT_AND (unique,0x1e80,1), (unique,0x1ed0,1)
    OF = INT_OR (unique,0x1ef0,1), (unique,0x1f00,1)

R_ANAL_OP_TYPE_ROL = 36,

Attention:
Like above.

Example:

0x00001213: ROL EAX,0x5
    (unique,0x7210,4) = INT_AND 0x5, 0x1f
    (unique,0x7220,4) = INT_LEFT EAX, (unique,0x7210,4)
    (unique,0x7230,4) = INT_SUB 0x20, (unique,0x7210,4)
    (unique,0x7240,4) = INT_RIGHT EAX, (unique,0x7230,4)
    EAX = INT_OR (unique,0x7220,4), (unique,0x7240,4)
    (unique,0x1ce0,1) = INT_NOTEQUAL (unique,0x7210,4), 0x0
    (unique,0x1cf0,4) = INT_AND EAX, 0x1
    (unique,0x1d10,1) = INT_NOTEQUAL (unique,0x1cf0,4), 0x0
    (unique,0x1d20,1) = BOOL_NEGATE (unique,0x1ce0,1)
    (unique,0x1d30,1) = INT_AND (unique,0x1d20,1), CF
    (unique,0x1d40,1) = INT_AND (unique,0x1ce0,1), (unique,0x1d10,1)
    CF = INT_OR (unique,0x1d30,1), (unique,0x1d40,1)
    (unique,0x1d70,1) = INT_EQUAL (unique,0x7210,4), 0x1
    (unique,0x1d80,1) = INT_SLESS EAX, 0x0
    (unique,0x1da0,1) = INT_XOR CF, (unique,0x1d80,1)
    (unique,0x1db0,1) = BOOL_NEGATE (unique,0x1d70,1)
    (unique,0x1dc0,1) = INT_AND (unique,0x1db0,1), OF
    (unique,0x1dd0,1) = INT_AND (unique,0x1d70,1), (unique,0x1da0,1)
    OF = INT_OR (unique,0x1dc0,1), (unique,0x1dd0,1)

R_ANAL_OP_TYPE_XCHG = 37,

  • Has COPY
  • Classic exchange procedure of two variables with a temporary variable

Example:

0x00001216: XCHG EAX,EBX
    (unique,0x84b0,4) = COPY EAX
    EAX = COPY EBX
    EBX = COPY (unique,0x84b0,4)

R_ANAL_OP_TYPE_MOD = 38,

Pattern:

  • Has INT_SREM or INT_REM

Attention:

  • Unluckily, assembly need improvement. P-code result is right, v1 and v0 is dalvik's local variables.

Example:

0x0000021e: rem_int_2addr 0x1004,0x1000
    v1 = INT_SREM v1, v0

R_ANAL_OP_TYPE_SWITCH = 39,

Example:

0x0000021e: packed_switch 0x1004,0x55
    (unique,0x330,4) = INT_MULT 0x55, 0x2
    (unique,0x340,4) = INT_ADD 0x21e, (unique,0x330,4)
    (unique,0x350,4) = INT_ADD (unique,0x340,4), 0x2
    (unique,0x370,2) = LOAD [(unique,0x350,4)]
    (unique,0x390,4) = INT_ZEXT (unique,0x370,2)
    (unique,0x3a0,4) = INT_ADD 0x21e, (unique,0x330,4)
    (unique,0x3b0,4) = INT_ADD (unique,0x3a0,4), 0x2
    (unique,0x3c0,4) = INT_ADD (unique,0x3b0,4), 0x2
    (unique,0x3e0,4) = LOAD [(unique,0x3c0,4)]
    (unique,0x3f0,1) = INT_LESS v1, (unique,0x3e0,4)
    CBRANCH dword_ptr(0x00000224), (unique,0x3f0,1)
    (unique,0x400,4) = INT_ADD (unique,0x3e0,4), (unique,0x390,4)
    (unique,0x410,1) = INT_LESSEQUAL (unique,0x400,4), v1
    CBRANCH dword_ptr(0x00000224), (unique,0x410,1)
    (unique,0x420,4) = INT_ADD 0x21e, (unique,0x330,4)
    (unique,0x430,4) = INT_ADD (unique,0x420,4), 0x2
    (unique,0x440,4) = INT_ADD (unique,0x430,4), 0x2
    (unique,0x460,4) = INT_ADD (unique,0x440,4), 0x4
    (unique,0x480,4) = INT_SUB v1, (unique,0x3e0,4)
    (unique,0x490,4) = INT_MULT (unique,0x480,4), 0x4
    (unique,0x4a0,4) = INT_ADD (unique,0x460,4), (unique,0x490,4)
    (unique,0x4c0,4) = LOAD [(unique,0x4a0,4)]
    (unique,0x4d0,4) = INT_MULT (unique,0x4c0,4), 0x2
    (unique,0x4f0,4) = INT_ADD 0x21e, (unique,0x4d0,4)
    BRANCHIND (unique,0x4f0,4)

R_ANAL_OP_TYPE_CASE = 40,

No related pcode

R_ANAL_OP_TYPE_LENGTH = 41,

Example:

0x00000234: array_length 0x1008,0x1008
    v2 = CPOOLREF v2, 0x0, 0x6

R_ANAL_OP_TYPE_CAST = 42,

Pattern:

  • Has CAST

R_ANAL_OP_TYPE_NEW = 43,

Pattern:

  • Has NEW

R_ANAL_OP_TYPE_ABS = 44,

Pattern:

  • Has FLOAT_ABS

Example:

0x00001208: FABS 
    ST0 = FLOAT_ABS ST0

R_ANAL_OP_TYPE_CPL = 45, /* complement */

Attention:
Just merge this situation into R_ANAL_OP_TYPE_NOT

Example:

0x00300002      comf 0x18, 1, 0
            unique(11e0, 1) = INT_NEGATE 18
            18 = COPY unique(11e0, 1)
            N = INT_SLESS unique(11e0, 1) 0
            Z = INT_EQUAL unique(11e0, 1) 0

R_ANAL_OP_TYPE_CRYPTO = 46,

Attention:
Just ignore this. Merge this into syscall

R_ANAL_OP_TYPE_SYNC = 47,

Attention:
Just ignore this. Merge this into syscall

@XVilka XVilka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are failing existing tests for r2ghidra:
https://travis-ci.com/github/radareorg/r2ghidra-dec/builds/179469587#L2399

[XX] /home/travis/build/radareorg/r2ghidra-dec/test/db/extras/asm_ghidra MIPS_LE_32
radare2 -escr.utf8=0 -escr.color=0 -escr.interactive=0 -N -Qc 'e asm.arch=r2ghidra
e asm.cpu=MIPS:LE:32:default:gcc
pd 50
' r2-testbins/elf/jni/jniO0-mips
-- stdout
@@ -1,59 +0,0 @@
-            ;-- entry0:
-            ;-- entry.fini0:
-            ;-- section..text:
-            ;-- .text:
-            ;-- _ftext:
-            ;-- __on_dlclose:
-            0x00000450      02001c3c       lui gp, 0x2                 ; [09] -r-x section size 480 named .text
-            0x00000454      b08b9c27       addiu gp, gp, -0x7450
-            0x00000458      21e09903       addu gp, gp, t9
-            0x0000045c      3480998f       lw t9, -0x7fcc(gp)
...
-- stderr
terminate called after throwing an instance of 'LowlevelError'
-- exit status: -1

@wargio

wargio commented Aug 13, 2020

Copy link
Copy Markdown
Member

Fantastic overview!

It's recognize as COMPUTED_CALL due to CALLIND. Do I need to specify this is R_ANAL_OP_TYPE_SWI?

No, i do not think is needed.

I think it is needes because syscalls are very different instructions from calls. Since you already identified that they always have this CALLOTHER, do you think it would be hard to differenciate them?

I do agree but my issue is more what for sleigh converts that interrupt to.

@FXTi

FXTi commented Aug 13, 2020

Copy link
Copy Markdown
Contributor Author

@wargio About CALLOTHER, it's actually SLEIGH's "custom op" like ESIL.
SLEIGH read userop from config. So it's basically any op which can not fit in existing P-code ecosystem, like CRYPTO or SYNC type in r2.
I think it's acceptable to classify them as syscall.
It's like extra function provided by system through interrupt.

@FXTi FXTi changed the title [WIP] RAnal SLEIGH plugin RAnal SLEIGH plugin Aug 23, 2020
@FXTi
FXTi marked this pull request as ready for review August 23, 2020 13:41
@FXTi

FXTi commented Aug 23, 2020

Copy link
Copy Markdown
Contributor Author

Now, all new features are complete. You can begin review, and I will fix bugs. I guess there will be tons of bugs...

Btw, this need even more tests than asm_ghidra. So if you have any idea to generate tests case fast, plz leave comments!

@thestr4ng3r @XVilka @wargio

Comment thread src/SleighAsm.cpp
Comment thread src/SleighAsm.cpp Outdated
Comment thread src/SleighAsm.cpp
Comment thread src/SleighAsm.h Outdated
Comment thread src/SleighAsm.h Outdated
Comment thread src/SleighInstruction.h Outdated
Comment thread src/SleighInstruction.h Outdated
Comment thread src/anal_ghidra.cpp Outdated
static char *get_reg_profile(RAnal *anal)
{
if(!strcmp(anal->cpu, "x86"))
return nullptr;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid unnecessary initialization when radare just try to guess what arch current binary is.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So "x86" in this case is because it's the default arch that r2 sets before knowing it from the binary? This could be problematic because the default arch in r2 is dependent on the host architecture, i.e. if you work on a raspberry pi or something, it would be "arm".
In any case, I think this needs at least a comment so it is clear why this check is there.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please add a comment.

Comment thread src/anal_ghidra.cpp Outdated
@thestr4ng3r

Copy link
Copy Markdown
Member

Seems to crash currently, depending on the used sleigh id:
20200824_22h41m28s_grim

@FXTi

FXTi commented Aug 25, 2020

Copy link
Copy Markdown
Contributor Author

@thestr4ng3r This is quite interesting: if you specify asm.cpu first, everything will be fine.
Also I' ve fixed some bugs.

@FXTi

FXTi commented Aug 29, 2020

Copy link
Copy Markdown
Contributor Author
  • Still problem in FP to mem, mem to FP
    (Because I'm not familiar with low level mem mechanism of Radare2)
[0x00000000]> e asm.arch=x86
[0x00000000]> e asm.bits=32
[0x00000000]> pdga
[0x00000000]> "ae 7,0x0,=[8]"
[0x00000000]> "ae 0x0,[8]"
0x7
[0x00000000]> "ae 7,I2F,0x0,=[8]"
[0x00000000]> "ae 0x0,[8]"
0x401c000000000000
[0x00000000]> "ae 7,I2F,512,=[8]"
[0x00000000]> "ae 512,[8]"
0x401c000000000000
[0x00000000]> "ae 7,I2F,512+8,=[8]"
[0x00000000]> "ae 512+16,[8]"
0x401c000000000000
[0x00000000]> "ae 512+32,[8]"
0x401c000000000000
[0x00000000]> 
  • SleighInstructionPrototype takes too much time and memory
    Already open a issue

  • SLEIGH support for Dex is poor
    Will do in next month

  • Test case needed
    Will to with memory optimization

FXTi added 4 commits August 30, 2020 18:21
* Add MEM to & Mem from path to CPUI_LOAD in ESIL
* Add BP and SN hard coded generation process

@thestr4ng3r thestr4ng3r left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should have some specific testing for the whole pattern-matching. What I would imagine are tests that write specific instructions (without a binary) and then do ao to print the instruction info.
Something like this:

e asm.arch=r2ghidra
e asm.cpu=x86:...
wx 31ed
ao
?e --
wx ...
ao
...

Normally you would write one r2r test for each of these ops, but since sleigh always takes so long to initialize I think one test with ?e -- between the instructions should be ok.

If you add one such check for each of the instruction types in your overview here: #120 (comment) (excluding the more exotic stuff we ignored), then I think we might be good to merge.

Comment thread src/anal_ghidra.cpp
if(arch.size() < 3)
throw LowlevelError("append_hardcoded_regs: Unexpected arch name.");

switch(arch[0] | arch[1] << 8 | arch[2] << 16)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you have to optimize the switch on the string this hard. As the nicest solution I would recommend to do something like here:
https://github.com/radareorg/r2ghidra-dec/blob/8e576eeadc211de4ac8d8c759cc368fa48cdfa99/src/ArchMap.cpp#L67-L79
Maybe you can even re-use the Mapper classes there if you move them to the header and replace RCore * here by a template parameter:
https://github.com/radareorg/r2ghidra-dec/blob/8e576eeadc211de4ac8d8c759cc368fa48cdfa99/src/ArchMap.cpp#L10-L14

But alternatively, a simple if/else would work too if you don't want to over-engineer it too much.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it should not fail completely if the arch is not known. You should still be able to use the plugin at least with unrecognized BP and SN.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will save this for next pr. Since current map is got from existing RAnal plugin source code, I think their result is not good enough. There must be something missing. I prepare to redo this in the future.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with both. Yes no need to optimize that and no need to make a new commit to address this now.

Comment thread src/anal_ghidra.cpp Outdated
static char *get_reg_profile(RAnal *anal)
{
if(!strcmp(anal->cpu, "x86"))
return nullptr;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So "x86" in this case is because it's the default arch that r2 sets before knowing it from the binary? This could be problematic because the default arch in r2 is dependent on the host architecture, i.e. if you work on a raspberry pi or something, it would be "arm".
In any case, I think this needs at least a comment so it is clear why this check is there.

Comment thread src/core_ghidra.cpp Outdated
Comment thread src/anal_ghidra.cpp Outdated

@XVilka XVilka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets merge this, further improvements can be done as a separate pull requests.

Comment thread src/SleighInstruction.cpp
Comment thread src/anal_ghidra.cpp
if(arch.size() < 3)
throw LowlevelError("append_hardcoded_regs: Unexpected arch name.");

switch(arch[0] | arch[1] << 8 | arch[2] << 16)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with both. Yes no need to optimize that and no need to make a new commit to address this now.

Comment thread src/anal_ghidra.cpp Outdated
static char *get_reg_profile(RAnal *anal)
{
if(!strcmp(anal->cpu, "x86"))
return nullptr;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please add a comment.

Comment thread src/anal_ghidra.cpp
case 128:
if(regset->arena->size - off - 1 >= 0)
{
memcpy(&ret, regset->arena->bytes + off, sizeof(long double));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think using long double is a good idea.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all compilers supports 64+ bits regs. I suggest to limit this to x64 via ifdef endif

Comment thread src/anal_ghidra.cpp
return ret;
}

static bool esil_set_double(RReg *reg, RRegItem *item, long double value)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same this

@thestr4ng3r
thestr4ng3r merged commit e083b18 into rizinorg:master Sep 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants