Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ida7.0 #12

Open
Yangff opened this issue Oct 23, 2017 · 13 comments
Open

ida7.0 #12

Yangff opened this issue Oct 23, 2017 · 13 comments

Comments

@Yangff
Copy link

Yangff commented Oct 23, 2017

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
@funte
Copy link

funte commented May 13, 2018

谢谢 @Yangff

@DeadEnded
Copy link

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?

@Yangff
Copy link
Author

Yangff commented Mar 29, 2019

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

@Annie983284450-1
Copy link

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.

@cuongnv
Copy link

cuongnv commented Aug 10, 2019

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 ?

@cuongnv
Copy link

cuongnv commented Aug 10, 2019

@Yangff can you know what type of that error ?

@cuongnv
Copy link

cuongnv commented Aug 10, 2019

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 ,

@hutuxiansheng
Copy link

IDA7.0 -- the plugin can not decompile .a file, are there any other steps that I have missed?

@nachisandro
Copy link

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

@jbalagiya
Copy link

jbalagiya commented Apr 5, 2024

i have same error anyown solve this problem sand me

@TakenTo
Copy link

TakenTo commented Jul 5, 2024

I also encountered the same bug, my software version is IDA_Pro_v8.3

1 similar comment
@TakenTo
Copy link

TakenTo commented Jul 5, 2024

I also encountered the same bug, my software version is IDA_Pro_v8.3

@omertheroot
Copy link

same here

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

No branches or pull requests

11 participants