Squashed 'external/capstone/' content from commit e46f64fa

git-subtree-dir: external/capstone
git-subtree-split: e46f64fadb351e9ecd05264fab26f2772feb0994
This commit is contained in:
2026-05-11 11:55:07 +02:00
commit 802798ce3c
3968 changed files with 2967598 additions and 0 deletions
@@ -0,0 +1,144 @@
# Copyright © 2022 Rot127 <unisono@quyllur.org>
# SPDX-License-Identifier: BSD-3
import logging as log
import re
from tree_sitter import Node
from autosync.cpptranslator.patches.Helper import (
get_MCInst_var_name,
get_text,
template_param_list_to_dict,
)
from autosync.cpptranslator.patches.Patch import Patch
class AddCSDetail(Patch):
"""
Adds calls to `<ARCH>_add_cs_detail_<n>()` for printOperand functions in <ARCH>InstPrinter.c
Patch void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNo, SStream *O) {...}
to void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNo, SStream *O) {
<ARCH>_add_cs_detail_<n>(MI, ARM_OP_GROUP_ThumbLdrLabelOperand, ...);
...
}
"""
# TODO Simply checking for the passed types would be so much nicer.
# Parameter lists of printOperand() functions we need to add `<ARCH>_add_cs_detail_<n>()` to.
# Spaces are removed, so we only need to check the letters.
valid_param_lists = [
b"(MCInst*MI,unsignedOpNum,SStream*O)", # Default printOperand parameters.
b"(MCInst*MI,unsignedOpNo,SStream*O)", # ARM - printComplexRotationOp / PPC default
b"(MCInst*MI,intopNum,SStream *O)", # Mips - printMemOperandEA and others
b"(SStream*O,ARM_AM::ShiftOpcShOpc,unsignedShImm,boolgetUseMarkup())", # ARM - printRegImmShift
b"(MCInst*MI,unsignedOpNo,SStream*O,constchar*Modifier)", # PPC - printPredicateOperand
b"(MCInst*MI,uint64_tAddress,unsignedOpNo,SStream*O)", # PPC - printBranchOperand
b"(MCInst*MI,intOpNum,SStream*O)", # SystemZ
b"(MCInst*MI,intOpNum,SStream*O)", # Xtensa printOperand parameters.
b"(MCInst*MI,intOpNum,SStream*OS)", # Xtensa printOperand parameters.
b"(MCInst*MI,intopNum,SStream*O)", # Sparc printOperand parameters.
]
def __init__(self, priority: int, arch: str):
super().__init__(priority)
self.arch = arch
def get_search_pattern(self) -> str:
return (
"(function_definition"
" (_)+"
" (function_declarator"
' ((identifier) @fcn_id (#match? @fcn_id "print.*"))'
" ((parameter_list) @p_list)"
" )"
" (compound_statement) @comp_stmt"
") @print_op"
)
def get_main_capture_name(self) -> str:
return "print_op"
def get_patch(
self, captures: list[tuple[Node, str]], src: bytes, **kwargs
) -> bytes:
fcn_def: Node = captures[0][0]
params = captures[2][0]
params = get_text(src, params.start_byte, params.end_byte)
if re.sub(b"[\n \t]", b"", params) not in self.valid_param_lists:
return get_text(src, fcn_def.start_byte, fcn_def.end_byte)
fcn_id = captures[1][0]
fcn_id = get_text(src, fcn_id.start_byte, fcn_id.end_byte)
add_cs_detail = self.get_add_cs_detail(src, fcn_def, fcn_id, params)
comp = captures[3][0]
comp = get_text(src, comp.start_byte, comp.end_byte)
return (
b"static inline void "
+ fcn_id
+ params
+ b"{ "
+ add_cs_detail
+ comp.strip(b"{")
)
def get_add_cs_detail(
self, src: bytes, fcn_def: Node, fcn_id: bytes, params: bytes
) -> bytes:
op_group_enum = (
self.arch.encode("utf8") + b"_OP_GROUP_" + fcn_id[5:]
) # Remove "print" from function id
is_template = fcn_def.prev_sibling.type == "template_parameter_list"
if b"OpNum" in params:
op_num_var_name = b"OpNum"
elif b"OpNo" in params:
op_num_var_name = b"OpNo"
elif b"opNum" in params:
op_num_var_name = b"opNum"
else:
raise ValueError("OpNum parameter could not be identified.")
if not is_template and op_num_var_name in params:
# Standard printOperand() parameters
mcinst_var = get_MCInst_var_name(src, fcn_def)
return (
f"{self.arch}_add_cs_detail_0(".encode()
+ mcinst_var
+ b", "
+ op_group_enum
+ b", "
+ op_num_var_name
+ b");"
)
elif op_group_enum == b"ARM_OP_GROUP_RegImmShift":
return (
f"{self.arch}_add_cs_detail_2(MI, ".encode()
+ op_group_enum
+ b", ShOpc, ShImm);"
)
elif is_template and op_num_var_name in params:
mcinst_var = get_MCInst_var_name(src, fcn_def)
templ_p = template_param_list_to_dict(fcn_def.prev_sibling)
cs_args = b""
for tp in templ_p:
op_group_enum = (
b"CONCAT(" + op_group_enum + b", " + tp["identifier"] + b")"
)
cs_args += b", " + tp["identifier"]
return (
f"{self.arch}_add_cs_detail_{len(templ_p)}(".encode()
+ mcinst_var
+ b", "
+ op_group_enum
+ b", "
+ op_num_var_name
+ b" "
+ cs_args
+ b");"
)
log.fatal(f"Case {op_group_enum} not handled.")
exit(1)