ida-xtensa
ida-xtensa copied to clipboard
ida7.0
Some modifies for ida 7.0.
#
# IDAPython Xtensa processor module
# https://github.com/themadinventor/ida-xtensa
#
# Copyright (C) 2014 Fredrik Ahlberg
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301 USA.
# v0.1 - changes by tinhead
# bug fix for 'l8ui','l16si','l16ui','l32i','s8i','s16i' and 's32i' size and shift
# bug fix for 'rsr.epc2','rsr.epc3' detection
# 'ill' added, normally one can work without
# 'rsr.epc4','rsr.epc5','rsr.epc6','rsr.epc7' added
#
# v0.2 - changes by tinhead
# bug fix for 'addmi' size
# bug fix for 'movi' size
# bug fix for 'l32r' with offset >= 0
# note: movi.n and addi with values higher than 127 looks bit wired in compare to
# xt-objdump, better would be something like 'ret.value = 0x80 - ret.value'
import copy
try:
from idaapi import *
except ImportError:
class processor_t(object):
pass
dt_byte = dt_word = dt_dword = None
PR_SEGS = PR_DEFSEG32 = PR_RNAMESOK = PR_ADJSEGS = PRN_HEX = PR_USE32 = 0
ASH_HEXF3 = ASD_DECF0 = ASO_OCTF1 = ASB_BINF3 = AS_NOTAB = AS_ASCIIC = AS_ASCIIZ = 0
CF_CALL = CF_JUMP = CF_STOP = 0
o_void = o_reg = o_imm = o_displ = o_near = None
class Operand:
REG = 0
IMM = 1
MEM = 2
RELA = 3
RELAL = 4
RELU = 5
MEM_INDEX = 6
def __init__(self, type, size, rshift, size2 = 0, rshift2 = 0, signext = False, vshift = 0, off = 0, xlate = None, dt = dt_byte, regbase = None):
self.type = type
self.size = size
self.rshift = rshift
self.size2 = size2
self.rshift2 = rshift2
self.signext = signext or (self.type in (Operand.RELA, Operand.RELAL, Operand.MEM))
self.vshift = vshift
self.off = off
self.xlate = xlate
self.dt = dt
self.regbase = regbase
def bitfield(self, op, size, rshift):
val = (op >> rshift) & (0xffffffff >> (32 - size))
return val
def parse(self, ret, op, cmd = None):
val = self.bitfield(op, self.size, self.rshift)
if self.size2:
val |= ((op >> self.rshift2) & (0xffffffff >> (32-self.size2))) << self.size
if self.signext and (val & (1 << (self.size+self.size2-1))):
val = -((~val)&((1 << (self.size+self.size2-1))-1))-1
val <<= self.vshift
val += self.off
if self.xlate:
val = self.xlate(val)
ret.dtyp = self.dt
if self.type == Operand.REG:
ret.type = o_reg
ret.reg = val if val < 16 else 16
elif self.type == Operand.IMM:
ret.type = o_imm
ret.value = val
elif self.type == Operand.MEM:
ret.type = o_mem
ret.addr = (cmd.ea+3+(val<<2))&0xfffffffc if val < 0 else (((cmd.ea+3+(val<<2))-0x40000)&0xfffffffc)
elif self.type == Operand.MEM_INDEX:
ret.type = o_displ
ret.phrase = self.bitfield(op, *self.regbase)
ret.addr = val
elif self.type in (Operand.RELA, Operand.RELAL):
ret.type = o_near
ret.addr = val + cmd.ea + 4 if self.type == Operand.RELA else ((cmd.ea&0xfffffffc)+4+(val<<2))
elif self.type == Operand.RELU:
ret.type = o_near
ret.addr = val + cmd.ea + 4
else:
raise ValueError("unhandled operand type");
# These magic lookup tables are defined in table 3-17 and 3-18 (p.41-42) in
# Xtensa Instruction Set Architecture Reference Manual
def b4const(val):
lut = (-1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256)
return lut[val]
def b4constu(val):
lut = (32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256)
return lut[val]
def movi_n(val):
return val if val & 0x60 != 0x60 else -(0x20 - val & 0x1f)
def addin(val):
return val if val else -1
def shimm(val):
return 32-val
class Instr(object):
fmt_NONE = (3, ())
fmt_NNONE = (2, ())
fmt_RRR = (3, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 8), Operand(Operand.REG, 4, 4)))
fmt_RRR_extui = (3, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 4), Operand(Operand.IMM, 4, 8, 1, 16), Operand(Operand.IMM, 4, 20, off=1)))
fmt_RRR_sext = (3, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 4, 4, off=7)))
fmt_RRR_1imm = (3, (Operand(Operand.IMM, 4, 8),))
fmt_RRR_2imm = (3, (Operand(Operand.IMM, 4, 8), Operand(Operand.IMM, 4, 4)))
fmt_RRR_immr = (3, (Operand(Operand.REG, 4, 4), Operand(Operand.IMM, 4, 8)))
fmt_RRR_2r = (3, (Operand(Operand.REG, 4, 4), Operand(Operand.REG, 4, 8)))
fmt_RRR_2rr = (3, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 4)))
fmt_RRR_sll = (3, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 8)))
fmt_RRR_slli = (3, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 4, 4, 1, 20, xlate=shimm)))
fmt_RRR_srai = (3, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 4), Operand(Operand.IMM, 4, 8, 1, 20)))
fmt_RRR_sh = (3, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 4), Operand(Operand.IMM, 4, 8)))
fmt_RRR_ssa = (3, (Operand(Operand.REG, 4, 8),))
fmt_RRR_ssai = (3, (Operand(Operand.IMM, 4, 8, 1, 4),))
fmt_RRI8 = (3, (Operand(Operand.REG, 4, 4), Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 8, 16, signext = True)))
fmt_RRI8_addmi = (3, (Operand(Operand.REG, 4, 4), Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 8, 16, signext = True, vshift=8, dt=dt_dword)))
fmt_RRI8_i12 = (3, (Operand(Operand.REG, 4, 4), Operand(Operand.IMM, 8, 16, 4, 8, dt=dt_word)))
fmt_RRI8_disp = (3, (Operand(Operand.REG, 4, 4), Operand(Operand.MEM_INDEX, 8, 16, vshift=0, regbase=(4, 8))))
fmt_RRI8_disp16 = (3, (Operand(Operand.REG, 4, 4), Operand(Operand.MEM_INDEX, 8, 16, vshift=1, dt=dt_word, regbase=(4, 8))))
fmt_RRI8_disp32 = (3, (Operand(Operand.REG, 4, 4), Operand(Operand.MEM_INDEX, 8, 16, vshift=2, dt=dt_dword, regbase=(4, 8))))
fmt_RRI8_b = (3, (Operand(Operand.REG, 4, 8), Operand(Operand.REG, 4, 4), Operand(Operand.RELA, 8, 16)))
fmt_RRI8_bb = (3, (Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 4, 4, 1, 12), Operand(Operand.RELA, 8, 16)))
fmt_RI16 = (3, (Operand(Operand.REG, 4, 4), Operand(Operand.MEM, 16, 8, dt=dt_dword)))
fmt_BRI8 = (3, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 8), Operand(Operand.RELA, 8, 16)))
fmt_BRI8_imm = (3, (Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 4, 12, xlate = b4const), Operand(Operand.RELA, 8, 16)))
fmt_BRI8_immu = (3, (Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 4, 12, xlate = b4constu), Operand(Operand.RELA, 8, 16)))
fmt_BRI12 = (3, (Operand(Operand.REG, 4, 8), Operand(Operand.RELA, 12, 12)))
fmt_RI12S3 = (3, (Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 12, 12, vshift=3)))
fmt_CALL = (3, (Operand(Operand.RELA, 18, 6),))
fmt_CALL_sh = (3, (Operand(Operand.RELAL, 18, 6),))
fmt_CALLX = (3, (Operand(Operand.REG, 4, 8),))
fmt_RSR = (3, (Operand(Operand.IMM, 8, 8), Operand(Operand.REG, 4, 4)))
fmt_RSR_spec = (3, (Operand(Operand.REG, 4, 4),))
fmt_RRRN = (2, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 8), Operand(Operand.REG, 4, 4)))
fmt_RRRN_addi = (2, (Operand(Operand.REG, 4, 12), Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 4, 4, xlate=addin)))
fmt_RRRN_2r = (2, (Operand(Operand.REG, 4, 4), Operand(Operand.REG, 4, 8)))
fmt_RRRN_disp = (2, (Operand(Operand.REG, 4, 4), Operand(Operand.MEM_INDEX, 4, 12, vshift=2, regbase=(4, 8))))
fmt_RI6 = (2, (Operand(Operand.REG, 4, 8), Operand(Operand.RELU, 4, 12, 2, 4)))
fmt_RI7 = (2, (Operand(Operand.REG, 4, 8), Operand(Operand.IMM, 4, 12, 3, 4, xlate=movi_n)))
def __init__(self, name, opcode, mask, fmt, flags = 0):
self.name = name
self.opcode = opcode
self.mask = mask
(self.size, self.fmt) = fmt
self.flags = flags
def match(self, op):
return (op & self.mask) == self.opcode
def parseOperands(self, operands, op, cmd = None):
for ret, fmt in zip(operands, self.fmt):
fmt.parse(ret, op, cmd)
def __str__(self):
return "<Instr %s %x/%x>" % (self.name, self.opcode, self.mask)
class XtensaProcessor(processor_t):
id = 0x8000 + 1990
flag = PR_SEGS | PR_DEFSEG32 | PR_RNAMESOK | PR_ADJSEGS | PRN_HEX | PR_USE32
cnbits = 8
dnbits = 8
psnames = ["xtensa"]
plnames = ["Tensilica Xtensa"]
segreg_size = 0
tbyte_size = 0
instruc_start = 0
assembler = {
"flag": ASH_HEXF3 | ASD_DECF0 | ASO_OCTF1 | ASB_BINF3 | AS_NOTAB
| AS_ASCIIC | AS_ASCIIZ,
"uflag": 0,
"name": "GNU assembler",
"origin": ".org",
"end": "end",
"cmnt": ";",
"ascsep": '"',
"accsep": "'",
"esccodes": "\"'",
"a_ascii": ".ascii",
"a_byte": ".byte",
"a_word": ".short",
"a_dword": ".int",
"a_bss": "dfs %s",
"a_seg": "seg",
"a_curip": ".",
"a_public": "",
"a_weak": "",
"a_extrn": ".extrn",
"a_comdef": "",
"a_align": ".align",
"lbrace": "(",
"rbrace": ")",
"a_mod": "%",
"a_band": "&",
"a_bor": "|",
"a_xor": "^",
"a_bnot": "~",
"a_shl": "<<",
"a_shr": ">>",
"a_sizeof_fmt": "size %s",
}
ops = (
("abs", 0x600100, 0xff0f0f, Instr.fmt_RRR_2rr ),
("add", 0x800000, 0xff000f, Instr.fmt_RRR ),
("addi", 0x00c002, 0x00f00f, Instr.fmt_RRI8 ),
("addmi", 0x00d002, 0x00f00f, Instr.fmt_RRI8_addmi ),
("addx2", 0x900000, 0xff000f, Instr.fmt_RRR ),
("addx4", 0xa00000, 0xff000f, Instr.fmt_RRR ),
("addx8", 0xb00000, 0xff000f, Instr.fmt_RRR ),
("and", 0x100000, 0xff000f, Instr.fmt_RRR ),
("ball", 0x004007, 0x00f00f, Instr.fmt_RRI8_b ),
("bany", 0x008007, 0x00f00f, Instr.fmt_RRI8_b ),
("bbc", 0x005007, 0x00f00f, Instr.fmt_RRI8_b ),
("bbs", 0x00d007, 0x00f00f, Instr.fmt_RRI8_b ),
("bbci", 0x006007, 0x00e00f, Instr.fmt_RRI8_bb ),
("bbsi", 0x00e007, 0x00e00f, Instr.fmt_RRI8_bb ),
("beq", 0x001007, 0x00f00f, Instr.fmt_RRI8_b ),
("beqi", 0x000026, 0x0000ff, Instr.fmt_BRI8_imm ), # was RRI8
("beqz", 0x000016, 0x0000ff, Instr.fmt_BRI12 ),
("bge", 0x00a007, 0x00f00f, Instr.fmt_RRI8_b ),
("bgei", 0x0000e6, 0x0000ff, Instr.fmt_BRI8_imm ),
("bgeu", 0x00b007, 0x00f00f, Instr.fmt_RRI8_b ),
("bgeui", 0x0000f6, 0x0000ff, Instr.fmt_BRI8_immu ),
("bgez", 0x0000d6, 0x0000ff, Instr.fmt_BRI12 ),
("blt", 0x002007, 0x00f00f, Instr.fmt_RRI8_b ),
("blti", 0x0000a6, 0x0000ff, Instr.fmt_BRI8_imm ),
("bltu", 0x003007, 0x00f00f, Instr.fmt_RRI8_b ),
("bltui", 0x0000b6, 0x0000ff, Instr.fmt_BRI8_immu ),
("bltz", 0x000096, 0x0000ff, Instr.fmt_BRI12 ),
("bnall", 0x00c007, 0x00f00f, Instr.fmt_RRI8_b ),
("bnone", 0x000007, 0x00f00f, Instr.fmt_RRI8_b ),
("bne", 0x009007, 0x00f00f, Instr.fmt_RRI8_b ),
("bnei", 0x000066, 0x0000ff, Instr.fmt_BRI8_imm ),
("bnez", 0x000056, 0x0000ff, Instr.fmt_BRI12 ),
("break", 0x004000, 0xfff00f, Instr.fmt_RRR_2imm ),
("call0", 0x000005, 0x00003f, Instr.fmt_CALL_sh, CF_CALL ),
("call4", 0x000015, 0x00003f, Instr.fmt_CALL_sh, CF_CALL ),
("call8", 0x000025, 0x00003f, Instr.fmt_CALL_sh, CF_CALL ),
("call12", 0x000035, 0x00003f, Instr.fmt_CALL_sh, CF_CALL ),
("callx0", 0x0000c0, 0xfff0ff, Instr.fmt_CALLX, CF_CALL | CF_JUMP ),
("callx4", 0x0000d0, 0xfff0ff, Instr.fmt_CALLX, CF_CALL | CF_JUMP ),
("callx8", 0x0000e0, 0xfff0ff, Instr.fmt_CALLX, CF_CALL | CF_JUMP ),
("callx12",0x0000f0, 0xfff0ff, Instr.fmt_CALLX, CF_CALL | CF_JUMP ),
("dsync", 0x002030, 0xffffff, Instr.fmt_NONE ),
("entry", 0x000036, 0x0000ff, Instr.fmt_RI12S3 ),
("esync", 0x002020, 0xffffff, Instr.fmt_NONE ),
("extui", 0x040000, 0x0e000f, Instr.fmt_RRR_extui ),
("extw", 0x0020d0, 0xffffff, Instr.fmt_NONE ),
("isync", 0x002000, 0xffffff, Instr.fmt_NONE ),
# ("ill", 0x000000, 0xffffff, Instr.fmt_NONE ), # normally one not need this
("j", 0x000006, 0x00003f, Instr.fmt_CALL, CF_STOP ),
("jx", 0x0000a0, 0xfff0ff, Instr.fmt_CALLX, CF_STOP | CF_JUMP ),
("l8ui", 0x000002, 0x00f00f, Instr.fmt_RRI8_disp ),
("l16si", 0x009002, 0x00f00f, Instr.fmt_RRI8_disp16 ),
("l16ui", 0x001002, 0x00f00f, Instr.fmt_RRI8_disp16 ),
("l32i", 0x002002, 0x00f00f, Instr.fmt_RRI8_disp32 ),
("l32r", 0x000001, 0x00000f, Instr.fmt_RI16 ),
("memw", 0x0020c0, 0xffffff, Instr.fmt_NONE ),
("moveqz", 0x830000, 0xff000f, Instr.fmt_RRR ),
("movgez", 0xb30000, 0xff000f, Instr.fmt_RRR ),
("movi", 0x00a002, 0x00f00f, Instr.fmt_RRI8_i12 ),
("movltz", 0xa30000, 0xff000f, Instr.fmt_RRR ),
("movnez", 0x930000, 0xff000f, Instr.fmt_RRR ),
("mul16s", 0xd10000, 0xff000f, Instr.fmt_RRR ),
("mul16u", 0xc10000, 0xff000f, Instr.fmt_RRR ),
("mull", 0x820000, 0xff000f, Instr.fmt_RRR ),
("muluh", 0xa20000, 0xff000f, Instr.fmt_RRR ),
("neg", 0x600000, 0xff0f0f, Instr.fmt_RRR_2rr ),
("nsa", 0x40e000, 0xfff00f, Instr.fmt_RRR_2r ),
("nsau", 0x40f000, 0xfff00f, Instr.fmt_RRR_2r ),
("nop", 0x0020f0, 0xffffff, Instr.fmt_NONE ),
("or", 0x200000, 0xff000f, Instr.fmt_RRR ),
("ret", 0x000080, 0xffffff, Instr.fmt_NONE, CF_STOP ),
("retw.n", 0x00f01d, 0x00ffff, Instr.fmt_NNONE, CF_STOP ),
("rfe", 0x003000, 0xffffff, Instr.fmt_NONE, CF_STOP ),
("rfi", 0x003010, 0xfff0ff, Instr.fmt_RRR_1imm, CF_STOP ),
("rsil", 0x006000, 0xfff00f, Instr.fmt_RRR_immr ),
("rsr.prid", 0x03eb00, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.epc1", 0x03b100, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.epc2", 0x03b200, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.epc3", 0x03b300, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.epc4", 0x03b400, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.epc5", 0x03b500, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.epc6", 0x03b600, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.epc7", 0x03b700, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.ps", 0x03e600, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.exccause", 0x03e800, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.ccount", 0x03e400, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.excvaddr", 0x03ee00, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.depc", 0x03c000, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.prid", 0x03eb00, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.ccompare0", 0x03f000, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.interrupt", 0x03e200, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.intenable", 0x03e400, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.sar", 0x030300, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr.ddr", 0x036800, 0xffff0f, Instr.fmt_RSR_spec ),
("rsr", 0x030000, 0xff000f, Instr.fmt_RSR ),
("rsync", 0x002010, 0xffffff, Instr.fmt_NONE ),
("s8i", 0x004002, 0x00f00f, Instr.fmt_RRI8_disp ),
("s16i", 0x005002, 0x00f00f, Instr.fmt_RRI8_disp16 ),
("s32i", 0x006002, 0x00f00f, Instr.fmt_RRI8_disp32 ),
("sext", 0x230000, 0xff000f, Instr.fmt_RRR_sext ),
("sll", 0xa10000, 0xff00ff, Instr.fmt_RRR_sll ),
("slli", 0x010000, 0xef000f, Instr.fmt_RRR_slli ),
("sra", 0xb10000, 0xff0f0f, Instr.fmt_RRR_2rr ),
("srai", 0x210000, 0xef000f, Instr.fmt_RRR_srai ),
("src", 0x810000, 0xff000f, Instr.fmt_RRR ),
("srl", 0x910000, 0xff0f0f, Instr.fmt_RRR_2rr ),
("srli", 0x410000, 0xff000f, Instr.fmt_RRR_sh ),
("ssa8b", 0x403000, 0xfff0ff, Instr.fmt_RRR_ssa ),
("ssa8l", 0x402000, 0xfff0ff, Instr.fmt_RRR_ssa ),
("ssai", 0x404000, 0xfff0ef, Instr.fmt_RRR_ssai ),
("ssl", 0x401000, 0xfff0ff, Instr.fmt_RRR_ssa ),
("ssr", 0x400000, 0xfff0ff, Instr.fmt_RRR_ssa ),
("sub", 0xc00000, 0xff000f, Instr.fmt_RRR ),
("subx2", 0xd00000, 0xff000f, Instr.fmt_RRR ),
("subx4", 0xe00000, 0xff000f, Instr.fmt_RRR ),
("subx8", 0xf00000, 0xff000f, Instr.fmt_RRR ),
("waiti", 0x007000, 0xfff0ff, Instr.fmt_RRR_1imm ),
("wdtlb", 0x50e000, 0xfff00f, Instr.fmt_RRR_2r ),
("witlb", 0x506000, 0xfff00f, Instr.fmt_RRR_2r ),
("wsr.intenable", 0x13e400, 0xffff0f, Instr.fmt_RSR_spec ),
("wsr.litbase", 0x130500, 0xffff0f, Instr.fmt_RSR_spec ),
("wsr.vecbase", 0x13e700, 0xffff0f, Instr.fmt_RSR_spec ),
("wsr.ps", 0x13e600, 0xffff0f, Instr.fmt_RSR_spec ),
("wsr.epc1", 0x13b100, 0xffff0f, Instr.fmt_RSR_spec ),
("wsr.ccompare0", 0x13f000, 0xffff0f, Instr.fmt_RSR_spec ),
("wsr.intclear", 0x13e300, 0xffff0f, Instr.fmt_RSR_spec ),
("wsr.sar", 0x130300, 0xffff0f, Instr.fmt_RSR_spec ),
("wsr", 0x130000, 0xff000f, Instr.fmt_RSR ),
("xor", 0x300000, 0xff000f, Instr.fmt_RRR ),
("xsr", 0x610000, 0xff000f, Instr.fmt_RSR ),
("add.n", 0x000a, 0x000f, Instr.fmt_RRRN ),
("addi.n", 0x000b, 0x000f, Instr.fmt_RRRN_addi ),
("beqz.n", 0x008c, 0x00cf, Instr.fmt_RI6 ),
("bnez.n", 0x00cc, 0x00cf, Instr.fmt_RI6 ),
("mov.n", 0x000d, 0xf00f, Instr.fmt_RRRN_2r ),
("break.n", 0xf02d, 0xf0ff, Instr.fmt_RRRN ),
("ret.n", 0xf00d, 0xffff, Instr.fmt_NNONE, CF_STOP ),
("l32i.n", 0x0008, 0x000f, Instr.fmt_RRRN_disp ),
("movi.n", 0x000c, 0x008f, Instr.fmt_RI7 ),
("nop.n", 0xf03d, 0xffff, Instr.fmt_NNONE ),
("s32i.n", 0x0009, 0x000f, Instr.fmt_RRRN_disp ),
)
def __init__(self):
processor_t.__init__(self)
self._init_instructions()
self._init_registers()
def _add_instruction(self, instr):
self.instrs_list.append(instr)
def _init_instructions(self):
self.instrs_list = []
self.short_insts = []
self.long_insts = []
for o in self.ops:
instr = Instr(*o)
self._add_instruction(instr)
if instr.size == 2:
self.short_insts.append(instr)
else:
self.long_insts.append(instr)
self.instruc = [{ "name": i.name, "feature": i.flags } for i in self.instrs_list]
self.instruc_end = len(self.instruc)
self.instrs = {}
for instr in self.instrs_list:
self.instrs[instr.name] = instr
self.instrs_ids = {}
for i, instr in enumerate(self.instrs_list):
self.instrs_ids[instr.name] = i
instr.id = i
def _init_registers(self):
self.reg_names = ["a%d" % d for d in range(16)]
self.reg_names += ["pc", "sar", "CS", "DS"]
self.reg_ids = {}
for i, reg in enumerate(self.reg_names):
self.reg_ids[reg] = i
self.reg_first_sreg = self.reg_code_sreg = self.reg_ids["CS"]
self.reg_last_sreg = self.reg_data_sreg = self.reg_ids["DS"]
def _pull_op_byte(self, insn):
ea = insn.ea + insn.size
byte = get_wide_byte(ea)
insn.size += 1
return byte
def _find_instr(self, insn):
op = self._pull_op_byte(insn)
op |= self._pull_op_byte(insn) << 8
for instr in self.short_insts:
if instr.match(op):
return instr, op
op |= self._pull_op_byte(insn) << 16
for instr in self.long_insts:
if instr.match(op):
return instr, op
return None, op
def notify_ana(self, insn):
instr, op = self._find_instr(insn)
if not instr:
return 0
insn.itype = instr.id
operands = [insn[i] for i in xrange(1, 6)]
for o in operands:
o.type = o_void
instr.parseOperands(operands, op, insn)
return insn.size
def emu(self, insn):
for i in xrange(1, 6):
op = insn[i]
if op.type == o_void:
break
elif op.type == o_mem:
insn.create_op_data(op.addr, 0, op.dtyp)
insn.add_dref(op.addr, 0, dr_R)
elif op.type == o_near:
features = insn.get_canon_feature()
if features & CF_CALL:
fl = fl_CN
else:
fl = fl_JN
insn.add_cref(op.addr, 0, fl)
feature = insn.get_canon_feature()
if feature & CF_JUMP:
remember_problem(Q_jumps, insn.ea)
if not feature & CF_STOP:
insn.add_cref(insn.ea + insn.size, 0, fl_F)
return True
notify_emu = emu
def outop(self, ctx, op):
if op.type == o_reg:
ctx.out_register(self.reg_names[op.reg])
elif op.type == o_imm:
instr = self.instrs_list[ctx.insn.itype]
if instr.name in ("extui", "bbci", "bbsi", "slli", "srli", "srai", "ssai"):
# bit numbers/shifts are always decimal
ctx.out_long(op.value, 10)
else:
ctx.out_value(op, OOFW_IMM)
elif op.type in (o_near, o_mem):
ok = ctx.out_name_expr(op, op.addr, BADADDR)
if not ok:
ctx.out_tagon(COLOR_ERROR)
ctx.out_long(op.addr, 16)
ctx.out_tagoff(COLOR_ERROR)
remember_problem(Q_noName, ctx.insn.ea)
elif op.type == o_displ:
ctx.out_register(self.reg_names[op.phrase])
ctx.out_line(", ")
ctx.out_value(op, OOF_ADDR)
else:
return False
return True
notify_out_operand = outop
def out_mnem(self, ctx):
ctx.out_mnem(15, "")
def notify_out_insn(self, ctx):
ctx.out_mnemonic()
for i in xrange(1, 6):
if ctx.insn[i].type == o_void:
break
if i > 0:
ctx.out_symbol(',')
ctx.out_char(' ')
ctx.out_one_operand(i)
ctx.set_gen_cmt()
ctx.flush_outbuf()
def PROCESSOR_ENTRY():
return XtensaProcessor()
if __name__ == "__main__":
class DummyProcessor(XtensaProcessor):
def __init__(self, b):
XtensaProcessor.__init__(self)
self.b = b
def _pull_op_byte(self):
return self.b.pop(0)
def disasm(b):
dp = DummyProcessor([ord(ch) for ch in b])
instr, op = dp._find_instr()
assert instr
class cmd(object):
ea = 1234
instr.operands = []
for operand in instr.fmt:
o = copy.copy(operand)
operand.parse(o, op, cmd)
instr.operands.append(o)
return instr
assert disasm("\x36\x61\x00").name == "entry"
assert disasm("\xd0\x04\x00").name == "callx4"
assert disasm("\xe0\x08\x00").name == "callx8"
assert disasm("\xf0\x00\x00").name == "callx12"
assert disasm("\x1d\xf0").name == "retw.n"
assert disasm("\x55\xa2\x28").name == "call4"
assert disasm("\xe5\xc7\x01").name == "call8"
assert disasm("\x75\x0c\xa9").name == "call12"
assert disasm("\x00\xbb\x23").name == "sext"
assert disasm("\x20\xba\xa2").name == "muluh"
assert disasm("\x2c\x08").name == "movi.n"
assert disasm("\x2c\x08").operands[0].reg == 8
assert disasm("\x2c\x08").operands[1].value == 32
assert disasm("\x1c\x68").operands[1].value == 22
assert disasm("\x4c\x00").operands[1].value == 64
assert disasm("\x6c\x11").operands[1].value == -31
谢谢 @Yangff
I cannot this processor type to populate in IDA7.0. I have copied the file to the plugins folder, but as this is my first time working with the software, I am not sure what other steps I need to take.
Is anyone will to explain what else needs to be done, or if this is just not working in version 7.0?
I cannot this processor type to populate in IDA7.0. I have copied the file to the plugins folder, but as this is my first time working with the software, I am not sure what other steps I need to take.
Is anyone will to explain what else needs to be done, or if this is just not working in version 7.0?
You should put it under You_IDA_PATH\procs
instead of plugins folder
Still got an error: missing call back of notify_emu. I load the binaries directly into ida and choose the xtensa processor. Are there any other steps that I have missed? My ida version is 7.0.
When i install this script, I got other issue.
Processor module script failed to initialize.
File: /Applications/IDA Pro 7.0/ida.app/Contents/MacOS/procs/xtensa.py
Assembler field 'flag' is missing or incorrectly defined
Anybody knows how to solve that ?
@Yangff can you know what type of that error ?
Ok, i solved. Just remove AS_ASCIIZ in flag properties change:
"flag": ASH_HEXF3 | ASD_DECF0 | ASO_OCTF1 | ASB_BINF3 | AS_NOTAB
| AS_ASCIIC | AS_ASCIIZ,
to
"flag": ASH_HEXF3 | ASD_DECF0 | ASO_OCTF1 | ASB_BINF3 | AS_NOTAB
| AS_ASCIIC ,
IDA7.0 -- the plugin can not decompile .a file, are there any other steps that I have missed?
i found a error
File "C:/Program Files/IDA 7.7/procs\xtensa.py", line 214, in XtensaProcessor "flag": ASH_HEXF3 | ASD_DECF0 | ASO_OCTF1 | ASB_BINF3 | AS_NOTAB NameError: name 'AS_NOTAB' is not defined