summaryrefslogtreecommitdiff
path: root/arch/armv7/thumb2_disasm/arm_pcode_parser/parse.py
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/armv7/thumb2_disasm/arm_pcode_parser/parse.py
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/armv7/thumb2_disasm/arm_pcode_parser/parse.py')
-rw-r--r--arch/armv7/thumb2_disasm/arm_pcode_parser/parse.py469
1 files changed, 241 insertions, 228 deletions
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))