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/armv7/thumb2_disasm/arm_pcode_parser/parse.py | |
| 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/armv7/thumb2_disasm/arm_pcode_parser/parse.py')
| -rw-r--r-- | arch/armv7/thumb2_disasm/arm_pcode_parser/parse.py | 469 |
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)) |
