summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorGalen Williamson <galen@vector35.com>2025-07-23 13:56:24 -0400
committerGalen Williamson <galen@vector35.com>2025-08-14 14:06:49 -0400
commitd6e13c753b30260b182cfe433e4e275244a4ab78 (patch)
treee5872f325dc26012646d999af94d937942ada0f8 /arch
parentce38990dae2d88d96793715d40544c7e5ece524d (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.cpp24
-rw-r--r--arch/armv7/thumb2_disasm/arm_pcode_parser/README.md7
-rwxr-xr-xarch/armv7/thumb2_disasm/arm_pcode_parser/codegencpp.py49
-rwxr-xr-xarch/armv7/thumb2_disasm/arm_pcode_parser/filter.py8
-rw-r--r--arch/armv7/thumb2_disasm/arm_pcode_parser/parse.py469
-rw-r--r--arch/armv7/thumb2_disasm/il_thumb2.cpp42
-rw-r--r--arch/armv7/thumb2_disasm/spec.cpp4
-rw-r--r--arch/armv7/thumb2_disasm/spec.txt2
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');