from ida_lines import COLOR_INSN, COLOR_MACRO
from ida_idp import CUSTOM_INSN_ITYPE, IDP_Hooks, ph_get_regnames, ph_get_id, PLFM_XTENSA, PLFM_RISCV
from ida_bytes import get_bytes
from ida_idaapi import plugin_t, PLUGIN_PROC, PLUGIN_HIDE, PLUGIN_SKIP, PLUGIN_KEEP
from ida_ua import o_displ, o_reg, o_imm, dt_dword, OOF_ADDR
from struct import unpack
import sys
import idaapi
from idaapi import *
import ida_pro
DEBUG_PLUGIN = True
NEWINSN_COLOR = COLOR_MACRO if DEBUG_PLUGIN else COLOR_INSN
class NewInstructionsx:
(NN_push,NN_pop,NN_jal16,NN_l_li,
) = range(CUSTOM_INSN_ITYPE, CUSTOM_INSN_ITYPE+4)
lst = {NN_push:"push",NN_pop:"popret",NN_jal16:"jal16",NN_l_li:"l.li"
}
#--------------------------------------------------------------------------
class xtensa_idp_hook_t(IDP_Hooks):
def __init__(self):
IDP_Hooks.__init__(self)
def decode_instruction(self, insn):
buf = get_bytes(insn.ea, 6)
if ( (buf[0]&0xF)==0x08 or (buf[0]&0xF)==0x04 ) and (buf[1]&0xF0)==0x80:
#print("0x%08X: %02X %02X" % (insn.ea, buf[0], buf[1],))
#push {ra,s0-s1},-64
if (buf[0]&0xF)==0x08:
insn.itype = NewInstructionsx.NN_push;
elif (buf[0]&0xF)==0x04:
insn.itype = NewInstructionsx.NN_pop;
insn.size = 2
insn.Op1.type = o_imm;
reg_num = (buf[0]>>4)&0xF;
insn.Op1.addr = reg_num;
if reg_num%4!=0x00:
reg_num = reg_num//4 + 1;
else:
reg_num = reg_num//4;
add_num = (buf[1]>>0)&0xF;
reg_num = (reg_num + add_num)*16;
if (buf[0]&0xF)==0x08:
insn.Op1.value = -reg_num;
elif (buf[0]&0xF)==0x04:
insn.Op1.value = reg_num;
print("insn.Op2.value = %X" % insn.Op1.value)
return True;
elif (buf[0]&0xFF) == 0x7B:
#06d05f7b
#6 3c 4 b 07b
#104 B6 3C
#16 3 0 8 f 7b
#E0 8962
insn.itype = NewInstructionsx.NN_jal16;
set_bit = (buf[2]>>4)&0x01;
reg = buf[1] & 0x0f;
if reg > 0x00:
reg_24_20 = reg -1;
else:
reg_24_20 = 0x10;
reg_19_16 = buf[2] & 0x0f;
reg_15_12 = (buf[1]>>0x04)&0x0f;
if set_bit == 0x00:
reg_11_08 = ((buf[3]>>0x04)&0x0f) & 0x07;
else:
reg_11_08 = ((buf[3]>>0x04)&0x0f) | 0x08;
reg_07_00 = buf[3]&0x0f;
reg_07_00 = (reg_07_00<<4) | ((buf[2]>>4)&0x0e);
reg = (reg_24_20<<20) | (reg_19_16<<16) | (reg_15_12<<12) | (reg_11_08<<8) | (reg_07_00<<0);
insn.size = 4
insn.Op1.type = o_imm;
print("reg1 = %X" % reg)
print("insn.ea = %X" % insn.ea)
reg = reg + (insn.ea&0x0fffff)
insn.Op1.value = reg;
print("reg2 = %X" % reg)
return True;
elif (buf[0]&0x7F) == 0x1f and (buf[1]&0xf0)==0x00:
#051f l.li a0
#0000 01010 00 11111
insn.itype = NewInstructionsx.NN_l_li;
lowest_bit = buf[0]>>7;
reg_4_1 = buf[1]&0x0f;
reg = (reg_4_1<<1) | lowest_bit;
insn.size = 6
insn.Op1.type = o_reg;
insn.Op1.value = reg;
print("reg21 = %d" % reg)
insn.Op2.type = o_imm;
reg = buf[5]<<24 | buf[4]<<16 | buf[3]<<8 | buf[2]<<0;
insn.Op2.value = reg;
print("reg22 = 0x%x" % reg)
return True;
return False;
def ev_ana_insn(self, insn):
return self.decode_instruction(insn)
def ev_out_mnem(self, outctx):
insntype = outctx.insn.itype
global NEWINSN_COLOR
if (insntype >= CUSTOM_INSN_ITYPE) and (insntype in NewInstructionsx.lst):
mnem = NewInstructionsx.lst[insntype]
outctx.out_tagon(NEWINSN_COLOR)
outctx.out_line(mnem)
outctx.out_tagoff(NEWINSN_COLOR)
#print("mnem = %s" % mnem)
# TODO: how can MNEM_width be determined programmatically?
MNEM_WIDTH = 12
width = max(1, MNEM_WIDTH - len(mnem))
outctx.out_line(' ' * width)
return True
return False
def ev_out_operand(self, outctx, op):
insn = outctx.insn
#print("CUSTOM_INSN_ITYPE = %x" % CUSTOM_INSN_ITYPE)
#print("NewInstructionsx.NN_quou = %x" % NewInstructionsx.NN_quou)
#print("NewInstructionsx.NN_muluh = %x" % NewInstructionsx.NN_muluh)
#print("NewInstructionsx.NN_ld_hu = %x" % NewInstructionsx.NN_ld_hu)
#print("NewInstructionsx.NN_ld_hu = ", NewInstructionsx.NN_ld_hu)
#print("NewInstructions.NN_st_h = %X" % NewInstructionsx.NN_st_h)
if insn.itype in [NewInstructionsx.NN_push, NewInstructionsx.NN_pop]:
#print("insn.itype = %X" % insn.itype)
#print("op.type = %X" % op.type)
#print("o_displ = %X" % o_displ)
#print("o_reg = %X" % o_reg)
#print("o_imm = %X" % o_imm)
if op.type == o_imm:
#print("o_displ = %X" % o_displ)
outctx.out_line(" {")
outctx.out_register(ph_get_regnames()[1])
reg_index = op.addr - 1;
if reg_index > 0:
outctx.out_line(', ');
outctx.out_register(ph_get_regnames()[8])
if reg_index > 2:
outctx.out_line('-');
outctx.out_register(ph_get_regnames()[18+reg_index-3])
elif reg_index==2:
outctx.out_line('-');
outctx.out_register(ph_get_regnames()[8+reg_index-1])
outctx.out_line('}, ');
outctx.out_value(op, OOFW_IMM |OOF_SIGNED |OOFS_NEEDSIGN|OOFW_32)
print("op.addr = %X" % op.addr)
print("op.value = %d" % op.value)
return True
if insn.itype in [NewInstructionsx.NN_jal16]:
#print("insn.itype = %X" % insn.itype)
#print("op.type = %X" % op.type)
#print("o_displ = %X" % o_displ)
#print("o_reg = %X" % o_reg)
#print("o_imm = %X" % o_imm)
if op.type == o_imm:
#outctx.out_long(op.value, 16)
outctx.out_value(op, OOFW_IMM | OOFW_32)
print("op.value = %X" % op.value)
print("op.addr = %X" % op.addr)
return True
if insn.itype in [NewInstructionsx.NN_l_li]:
#print("insn.itype = %X" % insn.itype)
#print("op.type = %X" % op.type)
#print("o_displ = %X" % o_displ)
#print("o_reg = %X" % o_reg)
#print("o_imm = %X" % o_imm)
if op.type == o_reg:
outctx.out_register(ph_get_regnames()[op.value])
return True
if op.type == o_imm:
#outctx.out_long(op.value, 16)
outctx.out_value(op, OOFW_IMM | OOFW_32)
print("op.value = %X" % op.value)
print("op.addr = %X" % op.addr)
return True
return False
#--------------------------------------------------------------------------
class XtensaESP(plugin_t):
flags = PLUGIN_PROC | PLUGIN_HIDE
comment = ""
wanted_hotkey = ""
help = "Adds support for additional Xtensa instructions"
wanted_name = "XtensaESP"
def __init__(self):
self.prochook = None
print ("%s initialized3." % XtensaESP.wanted_name)
def init(self):
#if ph_get_id() != PLFM_XTENSA:
if ph_get_id() != PLFM_RISCV:
print ("%s initialized1." % XtensaESP.wanted_name)
print ("PLFM_XTENSA = %d." % PLFM_XTENSA)
print ("ph_get_id() = %d." % ph_get_id())
return PLUGIN_SKIP
self.PTRSZ = 4 # Assume PTRSZ = 4 by default
self.prochook = xtensa_idp_hook_t()
self.prochook.hook()
print ("%s initialized2." % XtensaESP.wanted_name)
return PLUGIN_KEEP
def run(self, arg):
pass
def term(self):
if self.prochook:
self.prochook.unhook()
#--------------------------------------------------------------------------
def PLUGIN_ENTRY():
return XtensaESP()