diff options
| author | Galen Williamson <galen@vector35.com> | 2025-07-23 13:56:24 -0400 |
|---|---|---|
| committer | Galen Williamson <galen@vector35.com> | 2025-08-14 14:06:49 -0400 |
| commit | d6e13c753b30260b182cfe433e4e275244a4ab78 (patch) | |
| tree | e5872f325dc26012646d999af94d937942ada0f8 /arch | |
| parent | ce38990dae2d88d96793715d40544c7e5ece524d (diff) | |
[armv7/thumb2] Fix Lifting for PC-relative vldr instruction does not align PC when calculating address #6947
Updated thumb2 pcode parser used by disassembler generator to use Tatsu instead of deprecated Grako
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/armv7/il.cpp | 24 | ||||
| -rw-r--r-- | arch/armv7/thumb2_disasm/arm_pcode_parser/README.md | 7 | ||||
| -rwxr-xr-x | arch/armv7/thumb2_disasm/arm_pcode_parser/codegencpp.py | 49 | ||||
| -rwxr-xr-x | arch/armv7/thumb2_disasm/arm_pcode_parser/filter.py | 8 | ||||
| -rw-r--r-- | arch/armv7/thumb2_disasm/arm_pcode_parser/parse.py | 469 | ||||
| -rw-r--r-- | arch/armv7/thumb2_disasm/il_thumb2.cpp | 42 | ||||
| -rw-r--r-- | arch/armv7/thumb2_disasm/spec.cpp | 4 | ||||
| -rw-r--r-- | arch/armv7/thumb2_disasm/spec.txt | 2 |
8 files changed, 337 insertions, 268 deletions
diff --git a/arch/armv7/il.cpp b/arch/armv7/il.cpp index 7e5d4d90..de53689b 100644 --- a/arch/armv7/il.cpp +++ b/arch/armv7/il.cpp @@ -4933,6 +4933,30 @@ bool GetLowLevelILForArmInstruction(Architecture* arch, uint64_t addr, LowLevelI ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg, il.DivUnsigned(get_register_size(op2.reg), ReadRegisterOrPointer(il, op2, addr), ReadRegisterOrPointer(il, op3, addr)))); break; + case ARMV7_VCVT: + switch (instr.dataType) + { + case DT_S32: + case DT_U32: + switch (instr.dataType2) + { + case DT_F32: + case DT_F64: + // ConditionExecute(il, instr.cond, + // il.SetRegister(get_register_size(op1.reg), op1.reg, + // il.FloatToInt(4, il.Register(get_register_size(op2.reg), op2.reg)))); + ConditionExecute(il, instr.cond, + il.SetRegister(get_register_size(op1.reg), op1.reg, + il.FloatToInt(get_register_size(op1.reg), il.Register(get_register_size(op2.reg), op2.reg)))); + break; + default: + break; + } + break; + default: + break; + } + break; case ARMV7_VADD: if((instr.dataType != DT_F32) && (instr.dataType != DT_F64)) break; diff --git a/arch/armv7/thumb2_disasm/arm_pcode_parser/README.md b/arch/armv7/thumb2_disasm/arm_pcode_parser/README.md index c3adae56..7dcc5d15 100644 --- a/arch/armv7/thumb2_disasm/arm_pcode_parser/README.md +++ b/arch/armv7/thumb2_disasm/arm_pcode_parser/README.md @@ -4,7 +4,12 @@ translate the pseudocode for arm instructions (given in the docs) to target lang once the pcode is extracted, automatic generation of ultra-accurate disassemblers should become possible # how -use Grako parser generator, describe the language (pcode.ebnf) and write code generator (codegen.py) +~~use Grako parser generator, describe the language (pcode.ebnf) and write code generator (codegen.py)~~ +use Tatsu parser generator, describe the language (pcode.ebnf) and write code generator (codegen.py): + +``` +python3 -m tatsu --name pcode pcode.ebnf -o parse.py +``` # example input statement: diff --git a/arch/armv7/thumb2_disasm/arm_pcode_parser/codegencpp.py b/arch/armv7/thumb2_disasm/arm_pcode_parser/codegencpp.py index e66296b9..fff5bd05 100755 --- a/arch/armv7/thumb2_disasm/arm_pcode_parser/codegencpp.py +++ b/arch/armv7/thumb2_disasm/arm_pcode_parser/codegencpp.py @@ -3,8 +3,10 @@ import re import os import sys +from collections.abc import Sequence +from pprint import pformat -from parse import pcodeParser, pcodeSemantics +from parse import pcodeParser DEBUG = 0 @@ -12,6 +14,9 @@ DEBUG = 0 # misc utils ############################################################################### +def is_seq(x): + return type(x) not in [str, bytes] and isinstance(x, Sequence) + # convert "MOV (register)" text to the function that handles it # ->"mov_register" def convertHandlerName(name): @@ -43,10 +48,20 @@ def applyIndent(text, level=0): class BetterNode(object): def __init__(self, name, children=[], semicolon=False): self.name = name - self.children = children + if isinstance(children, filter): + self.children = list(children) + else: + self.children = children self.semicolon = semicolon + def __repr__(self): + if is_seq(self.children): + return 'BetterNode(%s)[%d]%s{\n %s\n}' % (self.name, len(self.children), ';' if self.semicolon else '', pformat(list(map(repr, self.children)), indent=4)) + else: + return 'BetterNode(%s)[%r]' % (self.name, self.children) + def gen(self, extra=''): + code = 'BOGUS' # leaf nodes (no possible descent) if self.name == 'ident': tmp = (self.children[0] + extra).replace('.', '_') @@ -64,8 +79,17 @@ class BetterNode(object): code = '\nreturn %s(req, res);' % self.children[0] self.semicolon = 0 else: - subCode = map(lambda x: x.gen(), self.children) - subCode = tuple(subCode) + + def c_gen(c): + if type(c) is str: + return c + elif is_seq(c): + c = tuple(map(c_gen, c)) + return c + else: + return ''.join(c.gen()) + + subCode = c_gen(self.children) # binary operations translate directly to C if self.name == 'xor': @@ -181,7 +205,7 @@ class BetterNode(object): if shamt: code = '((%s >> %d) & 1)' % (subCode[0], shamt) else: - code = '(%s & 1)' % subCode[0] + code = '(%s & 1)' % subCode[0] else: # there is a bit range to extract, [hi,lo] hi = int(subCode[1]) @@ -192,7 +216,6 @@ class BetterNode(object): code = '((%s >> %d) & 0x%X)' % (subCode[0], lo, 2**width-1) else: code = '(%s & 0x%X)' % (subCode[0], 2**width-1) - # if else elif self.name == 'if': if len(subCode) == 2: @@ -467,7 +490,7 @@ class PcodeSemantics(object): def expr0(self, ast): rv = None - if type(ast) == type([]): + if is_seq(ast): lookup = {'EOR':'xor', '+':'add', '-':'sub', '&&':'log_and', '||':'log_or' } @@ -493,7 +516,7 @@ class PcodeSemantics(object): def expr1(self, ast): rv = ast - if type(ast) == type([]): + if is_seq(ast): lookup = {'*':'mul', '/':'div', 'XOR':'xor', 'DIV':'div', '==':'equals', '!=':'not_equals', '<':'less_than', '>':'greater_than', '<<':'shl', '>>':'rshl', '>=':'greater_than_or_equals', '<=':'less_than_or_equals'} @@ -529,7 +552,7 @@ class PcodeSemantics(object): def expr3(self, ast): rv = 'BLUNDER' - if type(ast) == type([]): + if is_seq(ast): #print('ast is: ', ast) # empty closure, return original @@ -540,7 +563,7 @@ class PcodeSemantics(object): rv = BetterNode('group', [ast[1]]) elif ast[0] == '!': rv = BetterNode('log_not', [ast[1]]) - elif type(ast[1]==[]): + elif is_seq(ast[1]): closure = ast[1] assert closure[0][0] == ':' bn = BetterNode('concat', [ast[0], closure[0][1]]) @@ -657,7 +680,7 @@ class PcodeSemantics(object): if type(ast) == type(u'x'): funcName = ast[:-2] # function with arguments - elif type(ast) == type([]): + elif is_seq(ast): funcName = str(ast[0][:-1]) args = filter(lambda x: x!=',', ast[1:-1]) @@ -725,7 +748,7 @@ def genBlock(pcode, comments=True): (caseVar, indent) = (None, 0) for l in lines: - #print('line is: -%s-' % l) + # print('line is: -%s-' % l, file=sys.stderr) if l[0:5] == 'case ': m = re.match(r'^case (.*) of', l) result.append('/* pcode: %s */' % l.lstrip()) @@ -763,6 +786,8 @@ def genBlock(pcode, comments=True): result.append('}') (caseVar, indent) = (None, 0) code = gen(l) + # print(f'code is: -{code}-', file=sys.stderr) + result.append(code) return '\n'.join(result) diff --git a/arch/armv7/thumb2_disasm/arm_pcode_parser/filter.py b/arch/armv7/thumb2_disasm/arm_pcode_parser/filter.py index bd385d48..a19f39bb 100755 --- a/arch/armv7/thumb2_disasm/arm_pcode_parser/filter.py +++ b/arch/armv7/thumb2_disasm/arm_pcode_parser/filter.py @@ -10,20 +10,20 @@ import os import sys -print "filtering %s" % sys.argv[1] +print("filtering %s" % sys.argv[1]) fp = open(sys.argv[1],'rb') buf = fp.read() fp.close() len0 = len(buf) -print "file size before: %d\n" % len0 +print("file size before: %d\n" % len0) buf = buf.replace("\xe2\x80\x98", "'") buf = buf.replace("\xe2\x80\x99", "'") buf = buf.replace("\xe2\x80\x9C", '"') buf = buf.replace("\xe2\x80\x9D", '"') len1 = len(buf) -print "file size after: %d\n" % len1 -print "(%d stupid quotes replaced)" % ((len0-len1)/3) +print("file size after: %d\n" % len1) +print("(%d stupid quotes replaced)" % ((len0-len1)/3)) fp = open(sys.argv[1],'wb') fp.write(buf) diff --git a/arch/armv7/thumb2_disasm/arm_pcode_parser/parse.py b/arch/armv7/thumb2_disasm/arm_pcode_parser/parse.py index cd886f47..f9f9530b 100644 --- a/arch/armv7/thumb2_disasm/arm_pcode_parser/parse.py +++ b/arch/armv7/thumb2_disasm/arm_pcode_parser/parse.py @@ -1,89 +1,77 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- +#!/usr/bin/env python3 -# CAVEAT UTILITOR +# WARNING: CAVEAT UTILITOR # -# This file was automatically generated by Grako. +# This file was automatically generated by TatSu. # -# https://pypi.python.org/pypi/grako/ +# https://pypi.python.org/pypi/tatsu/ # -# Any changes you make to it will be overwritten the next time -# the file is generated. +# Any changes you make to it will be overwritten the next time +# the file is generated. +# ruff: noqa: C405, COM812, I001, F401, PLR1702, PLC2801, SIM117 -from __future__ import print_function, division, absolute_import, unicode_literals +import sys +from pathlib import Path -from grako.buffering import Buffer -from grako.parsing import graken, Parser -from grako.util import re, RE_FLAGS, generic_main # noqa +from tatsu.buffering import Buffer +from tatsu.parsing import Parser +from tatsu.parsing import tatsumasu +from tatsu.parsing import leftrec, nomemo, isname +from tatsu.infos import ParserConfig +from tatsu.util import re, generic_main -KEYWORDS = {} +KEYWORDS: set[str] = set() class pcodeBuffer(Buffer): - def __init__( - self, - text, - whitespace=None, - nameguard=None, - comments_re=None, - eol_comments_re=None, - ignorecase=None, - namechars='', - **kwargs - ): - super(pcodeBuffer, self).__init__( - text, - whitespace=whitespace, - nameguard=nameguard, - comments_re=comments_re, - eol_comments_re=eol_comments_re, - ignorecase=ignorecase, - namechars=namechars, - **kwargs + def __init__(self, text, /, config: ParserConfig | None = None, **settings): + config = ParserConfig.new( + config, + owner=self, + whitespace=None, + nameguard=None, + ignorecase=False, + namechars='', + parseinfo=False, + comments=None, + eol_comments=None, + keywords=KEYWORDS, + start='start', ) + config = config.replace(**settings) + + super().__init__(text, config=config) class pcodeParser(Parser): - def __init__( - self, - whitespace=None, - nameguard=None, - comments_re=None, - eol_comments_re=None, - ignorecase=None, - left_recursion=False, - parseinfo=True, - keywords=None, - namechars='', - buffer_class=pcodeBuffer, - **kwargs - ): - if keywords is None: - keywords = KEYWORDS - super(pcodeParser, self).__init__( - whitespace=whitespace, - nameguard=nameguard, - comments_re=comments_re, - eol_comments_re=eol_comments_re, - ignorecase=ignorecase, - left_recursion=left_recursion, - parseinfo=parseinfo, - keywords=keywords, - namechars=namechars, - buffer_class=buffer_class, - **kwargs + def __init__(self, /, config: ParserConfig | None = None, **settings): + config = ParserConfig.new( + config, + owner=self, + whitespace=None, + nameguard=None, + ignorecase=False, + namechars='', + parseinfo=False, + comments=None, + eol_comments=None, + keywords=KEYWORDS, + start='start', ) + config = config.replace(**settings) + + super().__init__(config=config) - @graken() + @tatsumasu() def _start_(self): self._statement_() with self._optional(): self._token(';') self._check_eof() - @graken() + @tatsumasu() def _statement_(self): with self._choice(): with self._option(): @@ -126,9 +114,15 @@ class pcodeParser(Parser): self._expr0_() self._token('=') self._expr0_() - self._error('expecting one of: NOP NOT_PERMITTED UNDEFINED UNPREDICTABLE nop') + self._error( + 'expecting one of: ' + "'(' 'NOP' 'NOT_PERMITTED' 'SEE'" + "'UNDEFINED' 'UNPREDICTABLE' 'if' 'nop'" + '<expr0> <expr1> <ident> <tuple>' + '[a-zA-Z][\\.\\w]*' + ) - @graken() + @tatsumasu() def _tuple_(self): self._token('(') with self._group(): @@ -137,9 +131,12 @@ class pcodeParser(Parser): self._token('-') with self._option(): self._expr0_() - self._error('expecting one of: -') + self._error( + 'expecting one of: ' + "'-' <expr0>" + ) - def block1(): + def block0(): self._token(',') with self._group(): with self._choice(): @@ -147,11 +144,14 @@ class pcodeParser(Parser): self._token('-') with self._option(): self._expr0_() - self._error('expecting one of: -') - self._positive_closure(block1) + self._error( + 'expecting one of: ' + "'-' <expr0>" + ) + self._positive_closure(block0) self._token(')') - @graken() + @tatsumasu() def _expr0_(self): with self._choice(): with self._option(): @@ -170,14 +170,20 @@ class pcodeParser(Parser): self._token('&&') with self._option(): self._token('||') - self._error('expecting one of: && + - EOR ||') + self._error( + 'expecting one of: ' + "'&&' '+' '-' 'EOR' '||'" + ) self._expr1_() self._positive_closure(block0) with self._option(): self._expr1_() - self._error('no available options') + self._error( + 'expecting one of: ' + '<expr1> <expr2>' + ) - @graken() + @tatsumasu() def _expr1_(self): with self._choice(): with self._option(): @@ -198,13 +204,16 @@ class pcodeParser(Parser): self._token('DIV') with self._option(): self._token('XOR') - self._error('expecting one of: * / << >> DIV XOR') + self._error( + 'expecting one of: ' + "'*' '/' '<<' '>>' 'DIV' 'XOR'" + ) self._expr2_() self._positive_closure(block0) with self._option(): self._expr2_() - def block2(): + def block1(): with self._group(): with self._choice(): with self._option(): @@ -219,23 +228,41 @@ class pcodeParser(Parser): self._token('<') with self._option(): self._token('>') - self._error('expecting one of: != < <= == > >=') + self._error( + 'expecting one of: ' + "'!=' '<' '<=' '==' '>' '>='" + ) self._expr2_() - self._positive_closure(block2) + self._positive_closure(block1) with self._option(): self._expr2_() - self._error('no available options') + self._error( + 'expecting one of: ' + '<expr2> <expr3> <func_call>' + ) - @graken() + @tatsumasu() def _expr2_(self): with self._choice(): with self._option(): self._func_call_() with self._option(): self._expr3_() - self._error('no available options') + self._error( + 'expecting one of: ' + "'!' '(' <advsimdexpandimm> <archversion>" + '<badreg> <bitcount> <bits>' + '<builtin_value> <consistent>' + '<currentinstrset> <decodeimmshift>' + '<expr3> <func_call> <ident> <initblock>' + '<issecure> <lastinitblock> <not>' + '<number> <signextend> <sliceable>' + '<thumbexpandimm> <thumbexpandimm_c>' + '<tuple> <uint> <vfpexpandimm>' + '<zeroextend> <zeros>' + ) - @graken() + @tatsumasu() def _expr3_(self): with self._choice(): with self._option(): @@ -251,9 +278,12 @@ class pcodeParser(Parser): self._number_() with self._option(): self._bits_() - self._error('no available options') + self._error( + 'expecting one of: ' + '<bits> <ident> <number>' + ) - def block1(): + def block0(): self._token(':') with self._group(): with self._choice(): @@ -263,8 +293,11 @@ class pcodeParser(Parser): self._number_() with self._option(): self._bits_() - self._error('no available options') - self._closure(block1) + self._error( + 'expecting one of: ' + '<bits> <ident> <number>' + ) + self._closure(block0) with self._option(): self._tuple_() with self._option(): @@ -274,25 +307,51 @@ class pcodeParser(Parser): with self._option(): self._token('!') self._expr0_() - self._error('no available options') + self._error( + 'expecting one of: ' + "'!' '(' 'ARM_GRP_ARM' 'ARM_GRP_CRC'" + "'ARM_GRP_CRYPT' 'ARM_GRP_DATABARRIER'" + "'ARM_GRP_DIVIDE' 'ARM_GRP_DPVFP'" + "'ARM_GRP_FPARMV8' 'ARM_GRP_FPVMLX'" + "'ARM_GRP_INVALID' 'ARM_GRP_JUMP'" + "'ARM_GRP_MCLASS' 'ARM_GRP_MULOPS'" + "'ARM_GRP_MULTPRO' 'ARM_GRP_NEON'" + "'ARM_GRP_NOTMCLASS' 'ARM_GRP_PREV8'" + "'ARM_GRP_T2EXTRACTPACK' 'ARM_GRP_THUMB'" + "'ARM_GRP_THUMB1ONLY' 'ARM_GRP_THUMB2'" + "'ARM_GRP_THUMB2DSP' 'ARM_GRP_TRUSTZONE'" + "'ARM_GRP_V4T' 'ARM_GRP_V5T'" + "'ARM_GRP_V5TE' 'ARM_GRP_V6'" + "'ARM_GRP_V6M' 'ARM_GRP_V6T2'" + "'ARM_GRP_V7' 'ARM_GRP_V8' 'ARM_GRP_VFP2'" + "'ARM_GRP_VFP3' 'ARM_GRP_VFP4' 'FALSE'" + "'InstrSet_ThumbEE' 'SRType_ASR'" + "'SRType_LSL' 'SRType_LSR' 'SRType_ROR'" + "'SRType_RRX' 'TRUE' 'Vd<' 'Vm<' 'Vn<'" + "'[01]+' 'align<' 'cc<' 'cmode<' 'cond<'" + "'imm6<' 'imm8<' 'imod<' 'index_align<'" + "'list<' 'mask<' 'registers<' <bits>" + '<builtin_value> <ident> <number>' + '<sliceable> <tuple> [a-zA-Z][\\.\\w]* \\d+' + ) - @graken() + @tatsumasu() def _number_(self): - self._pattern(r'\d+') + self._pattern('\\d+') - @graken() + @tatsumasu() def _bits_(self): - self._pattern(r"'[01]+'") + self._pattern("'[01]+'") - @graken() + @tatsumasu() def _ident_(self): - self._pattern(r'[a-zA-Z][\.\w]*') + self._pattern('[a-zA-Z][\\.\\w]*') - @graken() + @tatsumasu() def _whatever_(self): - self._pattern(r'.*') + self._pattern('.*') - @graken() + @tatsumasu() def _sliceable_(self): with self._choice(): with self._option(): @@ -363,9 +422,14 @@ class pcodeParser(Parser): self._token(':') self._number_() self._token('>') - self._error('no available options') + self._error( + 'expecting one of: ' + "'Vd<' 'Vm<' 'Vn<' 'align<' 'cc<'" + "'cmode<' 'imm6<' 'imm8<' 'imod<'" + "'index_align<' 'mask<'" + ) - @graken() + @tatsumasu() def _builtin_value_(self): with self._choice(): with self._option(): @@ -380,7 +444,10 @@ class pcodeParser(Parser): self._number_() with self._option(): self._ident_() - self._error('no available options') + self._error( + 'expecting one of: ' + '<ident> <number>' + ) self._token('>') with self._option(): self._token('list<') @@ -390,7 +457,10 @@ class pcodeParser(Parser): self._number_() with self._option(): self._ident_() - self._error('no available options') + self._error( + 'expecting one of: ' + '<ident> <number>' + ) self._token('>') with self._option(): self._token('cond<') @@ -480,9 +550,31 @@ class pcodeParser(Parser): self._token('ARM_GRP_DPVFP') with self._option(): self._token('ARM_GRP_V6M') - self._error('expecting one of: ARM_GRP_ARM ARM_GRP_CRC ARM_GRP_CRYPT ARM_GRP_DATABARRIER ARM_GRP_DIVIDE ARM_GRP_DPVFP ARM_GRP_FPARMV8 ARM_GRP_FPVMLX ARM_GRP_INVALID ARM_GRP_JUMP ARM_GRP_MCLASS ARM_GRP_MULOPS ARM_GRP_MULTPRO ARM_GRP_NEON ARM_GRP_NOTMCLASS ARM_GRP_PREV8 ARM_GRP_T2EXTRACTPACK ARM_GRP_THUMB ARM_GRP_THUMB1ONLY ARM_GRP_THUMB2 ARM_GRP_THUMB2DSP ARM_GRP_TRUSTZONE ARM_GRP_V4T ARM_GRP_V5T ARM_GRP_V5TE ARM_GRP_V6 ARM_GRP_V6M ARM_GRP_V6T2 ARM_GRP_V7 ARM_GRP_V8 ARM_GRP_VFP2 ARM_GRP_VFP3 ARM_GRP_VFP4 FALSE InstrSet_ThumbEE SRType_ASR SRType_LSL SRType_LSR SRType_ROR SRType_RRX TRUE') + self._error( + 'expecting one of: ' + "'ARM_GRP_ARM' 'ARM_GRP_CRC'" + "'ARM_GRP_CRYPT' 'ARM_GRP_DATABARRIER'" + "'ARM_GRP_DIVIDE' 'ARM_GRP_DPVFP'" + "'ARM_GRP_FPARMV8' 'ARM_GRP_FPVMLX'" + "'ARM_GRP_INVALID' 'ARM_GRP_JUMP'" + "'ARM_GRP_MCLASS' 'ARM_GRP_MULOPS'" + "'ARM_GRP_MULTPRO' 'ARM_GRP_NEON'" + "'ARM_GRP_NOTMCLASS' 'ARM_GRP_PREV8'" + "'ARM_GRP_T2EXTRACTPACK' 'ARM_GRP_THUMB'" + "'ARM_GRP_THUMB1ONLY' 'ARM_GRP_THUMB2'" + "'ARM_GRP_THUMB2DSP' 'ARM_GRP_TRUSTZONE'" + "'ARM_GRP_V4T' 'ARM_GRP_V5T'" + "'ARM_GRP_V5TE' 'ARM_GRP_V6'" + "'ARM_GRP_V6M' 'ARM_GRP_V6T2'" + "'ARM_GRP_V7' 'ARM_GRP_V8' 'ARM_GRP_VFP2'" + "'ARM_GRP_VFP3' 'ARM_GRP_VFP4' 'FALSE'" + "'InstrSet_ThumbEE' 'SRType_ASR'" + "'SRType_LSL' 'SRType_LSR' 'SRType_ROR'" + "'SRType_RRX' 'TRUE' 'cond<' 'list<'" + "'registers<'" + ) - @graken() + @tatsumasu() def _func_call_(self): with self._choice(): with self._option(): @@ -521,27 +613,44 @@ class pcodeParser(Parser): self._not_() with self._option(): self._issecure_() - self._error('no available options') + self._error( + 'expecting one of: ' + "'AdvSIMDExpandImm(' 'ArchVersion()'" + "'BadReg(' 'BitCount(' 'Consistent('" + "'CurrentInstrSet()' 'DecodeImmShift('" + "'InITBlock()' 'IsSecure()'" + "'LastInITBlock()' 'NOT(' 'SignExtend('" + "'ThumbExpandImm(' 'ThumbExpandImm_C('" + "'UInt(' 'VFPExpandImm(' 'ZeroExtend('" + "'Zeros(' <advsimdexpandimm>" + '<archversion> <badreg> <bitcount>' + '<consistent> <currentinstrset>' + '<decodeimmshift> <initblock> <issecure>' + '<lastinitblock> <not> <signextend>' + '<thumbexpandimm> <thumbexpandimm_c>' + '<uint> <vfpexpandimm> <zeroextend>' + '<zeros>' + ) - @graken() + @tatsumasu() def _bitcount_(self): self._token('BitCount(') self._expr0_() self._token(')') - @graken() + @tatsumasu() def _badreg_(self): self._token('BadReg(') self._expr0_() self._token(')') - @graken() + @tatsumasu() def _consistent_(self): self._token('Consistent(') self._expr0_() self._token(')') - @graken() + @tatsumasu() def _decodeimmshift_(self): self._token('DecodeImmShift(') self._expr0_() @@ -549,13 +658,13 @@ class pcodeParser(Parser): self._expr0_() self._token(')') - @graken() + @tatsumasu() def _thumbexpandimm_(self): self._token('ThumbExpandImm(') self._expr0_() self._token(')') - @graken() + @tatsumasu() def _thumbexpandimm_c_(self): self._token('ThumbExpandImm_C(') self._expr0_() @@ -563,7 +672,7 @@ class pcodeParser(Parser): self._expr0_() self._token(')') - @graken() + @tatsumasu() def _advsimdexpandimm_(self): self._token('AdvSIMDExpandImm(') self._expr0_() @@ -575,7 +684,7 @@ class pcodeParser(Parser): self._expr0_() self._token(')') - @graken() + @tatsumasu() def _vfpexpandimm_(self): self._token('VFPExpandImm(') self._expr0_() @@ -585,13 +694,13 @@ class pcodeParser(Parser): self._expr0_() self._token(')') - @graken() + @tatsumasu() def _uint_(self): self._token('UInt(') self._expr0_() self._token(')') - @graken() + @tatsumasu() def _zeroextend_(self): self._token('ZeroExtend(') self._expr0_() @@ -599,158 +708,62 @@ class pcodeParser(Parser): self._expr0_() self._token(')') - @graken() + @tatsumasu() def _zeros_(self): self._token('Zeros(') self._expr0_() self._token(')') - @graken() + @tatsumasu() def _initblock_(self): self._token('InITBlock()') - @graken() + @tatsumasu() def _lastinitblock_(self): self._token('LastInITBlock()') - @graken() + @tatsumasu() def _archversion_(self): self._token('ArchVersion()') - @graken() + @tatsumasu() def _currentinstrset_(self): self._token('CurrentInstrSet()') - @graken() + @tatsumasu() def _signextend_(self): self._token('SignExtend(') self._expr3_() self._token(', 32)') - @graken() + @tatsumasu() def _not_(self): self._token('NOT(') self._expr0_() self._token(')') - @graken() + @tatsumasu() def _issecure_(self): self._token('IsSecure()') -class pcodeSemantics(object): - def start(self, ast): - return ast - - def statement(self, ast): - return ast - - def tuple(self, ast): - return ast - - def expr0(self, ast): - return ast - - def expr1(self, ast): - return ast - - def expr2(self, ast): - return ast - - def expr3(self, ast): - return ast - - def number(self, ast): - return ast - - def bits(self, ast): - return ast - - def ident(self, ast): - return ast - - def whatever(self, ast): - return ast - - def sliceable(self, ast): - return ast - - def builtin_value(self, ast): - return ast - - def func_call(self, ast): - return ast - - def bitcount(self, ast): - return ast - - def badreg(self, ast): - return ast - - def consistent(self, ast): - return ast - - def decodeimmshift(self, ast): - return ast - - def thumbexpandimm(self, ast): - return ast - - def thumbexpandimm_c(self, ast): - return ast - - def advsimdexpandimm(self, ast): - return ast - - def vfpexpandimm(self, ast): - return ast - - def uint(self, ast): - return ast - - def zeroextend(self, ast): - return ast - - def zeros(self, ast): - return ast - - def initblock(self, ast): - return ast - - def lastinitblock(self, ast): - return ast - - def archversion(self, ast): - return ast - - def currentinstrset(self, ast): - return ast - - def signextend(self, ast): - return ast - - def not_(self, ast): - return ast - - def issecure(self, ast): - return ast - - -def main(filename, startrule, **kwargs): - with open(filename) as f: - text = f.read() +def main(filename, **kwargs): + if not filename or filename == '-': + text = sys.stdin.read() + else: + text = Path(filename).read_text() parser = pcodeParser() - return parser.parse(text, startrule, filename=filename, **kwargs) + return parser.parse( + text, + filename=filename, + **kwargs, + ) if __name__ == '__main__': import json - from grako.util import asjson + from tatsu.util import asjson ast = generic_main(main, pcodeParser, name='pcode') - print('AST:') - print(ast) - print() - print('JSON:') - print(json.dumps(asjson(ast), indent=2)) - print() + data = asjson(ast) + print(json.dumps(data, indent=2)) diff --git a/arch/armv7/thumb2_disasm/il_thumb2.cpp b/arch/armv7/thumb2_disasm/il_thumb2.cpp index 50f9b3ef..48dcf4ac 100644 --- a/arch/armv7/thumb2_disasm/il_thumb2.cpp +++ b/arch/armv7/thumb2_disasm/il_thumb2.cpp @@ -35,10 +35,10 @@ static uint32_t RegisterSizeFromPrefix(const char* prefix = "") return 4; } -static ExprId ReadRegister(LowLevelILFunction& il, decomp_result* instr, uint32_t reg, size_t size = 4, const char* prefix = "") +static ExprId ReadRegister(LowLevelILFunction& il, decomp_result* instr, uint32_t reg, size_t size = 4, const char* prefix = "", uint32_t align=0) { if (reg == armv7::REG_PC && strcmp(prefix, "") == 0) - return il.ConstPointer(size, instr->pc); + return il.ConstPointer(size, instr->pc & (align ? ~(align - 1) : ~0)); return il.Register(RegisterSizeFromPrefix(prefix), GetRegisterByIndex(reg, prefix)); } @@ -351,9 +351,9 @@ static ExprId ShiftedRegister(LowLevelILFunction& il, decomp_result* instr, uint } } - +#define ReadRegisterA(il, instr, reg, align) ReadRegister(il, instr, reg, 4, "", align) static ExprId GetMemoryAddress(LowLevelILFunction& il, decomp_result* instr, size_t operand, uint32_t size, - bool canWriteback = true) + bool canWriteback = true, uint32_t align=0) { uint32_t reg, second, t, n; switch (instr->format->operands[operand].type) @@ -367,19 +367,19 @@ static ExprId GetMemoryAddress(LowLevelILFunction& il, decomp_result* instr, siz second = instr->fields[instr->format->operands[operand].field1]; if (canWriteback && HasWriteback(instr, operand)) { - il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegister(il, instr, reg), il.Const(4, second)))); + il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegisterA(il, instr, reg, align), il.Const(4, second)))); return il.Register(4, reg); } - return il.Add(4, ReadRegister(il, instr, reg), il.Const(4, second)); + return il.Add(4, ReadRegisterA(il, instr, reg, align), il.Const(4, second)); case OPERAND_FORMAT_MEMORY_ONE_REG_NEG_IMM: reg = GetRegisterByIndex(instr->fields[instr->format->operands[operand].field0]); second = instr->fields[instr->format->operands[operand].field1]; if (canWriteback && HasWriteback(instr, operand)) { - il.AddInstruction(il.SetRegister(4, reg, il.Sub(4, ReadRegister(il, instr, reg), il.Const(4, second)))); + il.AddInstruction(il.SetRegister(4, reg, il.Sub(4, ReadRegisterA(il, instr, reg, align), il.Const(4, second)))); return il.Register(4, reg); } - return il.Sub(4, ReadRegister(il, instr, reg), il.Const(4, second)); + return il.Sub(4, ReadRegisterA(il, instr, reg, align), il.Const(4, second)); case OPERAND_FORMAT_MEMORY_ONE_REG_ADD_IMM: case OPERAND_FORMAT_MEMORY_ONE_REG_OPTIONAL_ADD_IMM: reg = GetRegisterByIndex(instr->fields[instr->format->operands[operand].field0]); @@ -387,23 +387,23 @@ static ExprId GetMemoryAddress(LowLevelILFunction& il, decomp_result* instr, siz if (canWriteback && HasWriteback(instr, operand)) { if (instr->fields[FIELD_add]) - il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegister(il, instr, reg), il.Const(4, second)))); + il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegisterA(il, instr, reg, align), il.Const(4, second)))); else - il.AddInstruction(il.SetRegister(4, reg, il.Sub(4, ReadRegister(il, instr, reg), il.Const(4, second)))); + il.AddInstruction(il.SetRegister(4, reg, il.Sub(4, ReadRegisterA(il, instr, reg, align), il.Const(4, second)))); return il.Register(4, reg); } if (instr->fields[FIELD_add]) - return il.Add(4, ReadRegister(il, instr, reg), il.Const(4, second)); - return il.Sub(4, ReadRegister(il, instr, reg), il.Const(4, second)); + return il.Add(4, ReadRegisterA(il, instr, reg, align), il.Const(4, second)); + return il.Sub(4, ReadRegisterA(il, instr, reg, align), il.Const(4, second)); case OPERAND_FORMAT_MEMORY_TWO_REG: reg = GetRegisterByIndex(instr->fields[instr->format->operands[operand].field0]); second = GetRegisterByIndex(instr->fields[instr->format->operands[operand].field1]); if (canWriteback && HasWriteback(instr, operand)) { - il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegister(il, instr, reg), il.Register(4, second)))); + il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegisterA(il, instr, reg, align), il.Register(4, second)))); return il.Register(4, reg); } - return il.Add(4, ReadRegister(il, instr, reg), il.Register(4, second)); + return il.Add(4, ReadRegisterA(il, instr, reg, align), il.Register(4, second)); case OPERAND_FORMAT_MEMORY_TWO_REG_SHIFT: reg = GetRegisterByIndex(instr->fields[instr->format->operands[operand].field0]); second = GetRegisterByIndex(instr->fields[instr->format->operands[operand].field1]); @@ -411,21 +411,21 @@ static ExprId GetMemoryAddress(LowLevelILFunction& il, decomp_result* instr, siz n = instr->fields[FIELD_shift_n]; if (canWriteback && HasWriteback(instr, operand)) { - il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegister(il, instr, reg), + il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegisterA(il, instr, reg, align), ShiftedRegister(il, instr, second, t, n)))); return il.Register(4, reg); } - return il.Add(4, ReadRegister(il, instr, reg), ShiftedRegister(il, instr, second, t, n)); + return il.Add(4, ReadRegisterA(il, instr, reg, align), ShiftedRegister(il, instr, second, t, n)); case OPERAND_FORMAT_MEMORY_TWO_REG_LSL_ONE: reg = GetRegisterByIndex(instr->fields[instr->format->operands[operand].field0]); second = GetRegisterByIndex(instr->fields[instr->format->operands[operand].field1]); if (canWriteback && HasWriteback(instr, operand)) { - il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegister(il, instr, reg), + il.AddInstruction(il.SetRegister(4, reg, il.Add(4, ReadRegisterA(il, instr, reg, align), il.ShiftLeft(4, ReadRegister(il, instr, second), il.Const(4, 1))))); return il.Register(4, reg); } - return il.Add(4, ReadRegister(il, instr, reg), il.ShiftLeft(4, ReadRegister(il, instr, second), il.Const(4, 1))); + return il.Add(4, ReadRegisterA(il, instr, reg, align), il.ShiftLeft(4, ReadRegister(il, instr, second), il.Const(4, 1))); case OPERAND_FORMAT_MEMORY_SP_IMM: case OPERAND_FORMAT_MEMORY_SP_OPTIONAL_IMM: second = instr->fields[instr->format->operands[operand].field0]; @@ -436,7 +436,7 @@ static ExprId GetMemoryAddress(LowLevelILFunction& il, decomp_result* instr, siz } return il.Add(4, il.Register(4, armv7::REG_SP), il.Const(4, second)); case OPERAND_FORMAT_MEMORY_PC: - return il.ConstPointer(4, instr->pc); + return il.ConstPointer(4, instr->pc & (align ? ~(align - 1) : ~0)); case OPERAND_FORMAT_LABEL: if (instr->fields[FIELD_add]) return il.ConstPointer(4, ALIGN4(instr->pc) + instr->fields[FIELD_imm32]); @@ -2053,7 +2053,9 @@ bool GetLowLevelILForNEONInstruction(Architecture* arch, LowLevelILFunction& il, } else { - il.AddInstruction(WriteILOperand(il, instr, 0, il.Load(regSize, GetMemoryAddress(il, instr, 1, 4)))); + il.AddInstruction(WriteILOperand(il, instr, 0, + il.Load(regSize, + GetMemoryAddress(il, instr, 1, 4, true, 4)))); } break; } diff --git a/arch/armv7/thumb2_disasm/spec.cpp b/arch/armv7/thumb2_disasm/spec.cpp index 89ee1807..f618eff7 100644 --- a/arch/armv7/thumb2_disasm/spec.cpp +++ b/arch/armv7/thumb2_disasm/spec.cpp @@ -34446,8 +34446,8 @@ int vcvt_float_int(struct decomp_request *req, struct decomp_result *res) /* pcode: dp_operation = (sz == 1) */ res->fields[FIELD_dp_operation] = ((res->fields[FIELD_sz]) == (1)); res->fields_mask[FIELD_dp_operation >> 6] |= 1LL << (FIELD_dp_operation & 63); - /* pcode: unsigned = (op == '0') */ - res->fields[FIELD_unsigned] = ((res->fields[FIELD_op]) == (0x0)); + /* pcode: unsigned = (opc3 == '0') */ + res->fields[FIELD_unsigned] = ((res->fields[FIELD_opc3]) == (0x0)); res->fields_mask[FIELD_unsigned >> 6] |= 1LL << (FIELD_unsigned & 63); /* pcode: m = UInt(Vm:M) */ res->fields[FIELD_m] = ((res->fields[FIELD_Vm]<<M_width)|(res->fields[FIELD_M])); diff --git a/arch/armv7/thumb2_disasm/spec.txt b/arch/armv7/thumb2_disasm/spec.txt index ebb5932d..eaffbfce 100644 --- a/arch/armv7/thumb2_disasm/spec.txt +++ b/arch/armv7/thumb2_disasm/spec.txt @@ -5526,7 +5526,7 @@ fmt VCVTR<c>.S32.F64 <Sd>,<Dm> extract32 1110,11101,D.1,11,1,opc1.1,opc2.1,opc3.1,Vd.4,101,sz.1,op.1,1,M.1,0,Vm.4 pcode_start to_integer = (opc1 == '1'); dp_operation = (sz == 1); -unsigned = (op == '0'); +unsigned = (opc3 == '0'); m = UInt(Vm:M); d = if dp_operation then UInt(D:Vd) else UInt(Vd:D); if (to_integer) then unsigned = (opc1 == '0'); |
