diff --git a/chb/arm/opcodes/ARMBitFieldInsert.py b/chb/arm/opcodes/ARMBitFieldInsert.py index 812de7a5..8698a62a 100644 --- a/chb/arm/opcodes/ARMBitFieldInsert.py +++ b/chb/arm/opcodes/ARMBitFieldInsert.py @@ -53,8 +53,18 @@ class ARMBitFieldInsertXData(ARMOpcodeXData): """BFI """ - def __init__(self, xdata: InstrXData) -> None: + def __init__(self, xdata: InstrXData, lsb: int, width: int) -> None: ARMOpcodeXData.__init__(self, xdata) + self._lsb = lsb + self._width = width + + @property + def lsb(self) -> int: + return self._lsb + + @property + def width(self) -> int: + return self._width @property def vrd(self) -> "XVariable": @@ -68,6 +78,23 @@ def xrd(self) -> "XXpr": def xrn(self) -> "XXpr": return self.xpr(1, "xrn") + @property + def annotation(self) -> str: + lhs = str(self.vrd) + rhs1 = str(self.xrd) + rhs2 = str(self.xrn) + assign = ( + lhs + + " := bit-field-insert(" + + rhs1 + + ", " + + rhs2 + + ", lsb:" + + str(self.lsb) + + ", width:" + + str(self.width)) + return self.add_instruction_condition(assign) + @armregistry.register_tag("BFI", ARMOpcode) class ARMBitFieldInsert(ARMOpcode): @@ -123,30 +150,8 @@ def width(self) -> int: return self.args[2] def annotation(self, xdata: InstrXData) -> str: - xd = ARMBitFieldInsertXData(xdata) - if xd.is_ok: - lhs = str(xd.vrd) - rhs1 = str(xd.xrd) - rhs2 = str(xd.xrn) - assignment = ( - lhs - + " := bit-field-insert(" - + rhs1 - + ", " - + rhs2 - + ", lsb:" - + str(self.lsb) - + ", width:" - + str(self.width)) - if xdata.has_unknown_instruction_condition(): - return "if ? then " + assignment - elif xdata.has_instruction_condition(): - c = str(xdata.xprs[1]) - return "if " + c + " then " + assignment - else: - return assignment - else: - return "Error value" + xd = ARMBitFieldInsertXData(xdata, self.lsb, self.width) + return xd.annotation def ast_prov( self, @@ -168,9 +173,11 @@ def ast_prov( return ([], [nopinstr]) - lhs = xdata.vars[0] - rhs1 = xdata.xprs[0] - rhs2 = xdata.xprs[1] + xd = ARMBitFieldInsertXData(xdata, self.lsb, self.width) + + lhs = xd.vrd + rhs1 = xd.xrd + rhs2 = xd.xrn rdefs = xdata.reachingdefs defuses = xdata.defuses defuseshigh = xdata.defuseshigh diff --git a/chb/arm/opcodes/ARMByteReversePackedHalfword.py b/chb/arm/opcodes/ARMByteReversePackedHalfword.py index 5961e762..de412416 100644 --- a/chb/arm/opcodes/ARMByteReversePackedHalfword.py +++ b/chb/arm/opcodes/ARMByteReversePackedHalfword.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,7 @@ from chb.app.InstrXData import InstrXData from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand from chb.ast.ARMIntrinsics import ARMIntrinsics @@ -44,6 +44,37 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMByteReversePackedHalfwordXData(ARMOpcodeXData): + """REV16 """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vrd(self) -> "XVariable": + return self.var(0, "vrd") + + @property + def xrm(self) -> "XXpr": + return self.xpr(0, "xrm") + + @property + def xxrm(self) -> "XXpr": + return self.xpr(1, "xxrm") + + @property + def annotation(self) -> str: + if self.is_ok: + lhs = str(self.vrd) + rhs = str(self.xxrm) + assign = lhs + " := __rev16(" + str(rhs) + ") intrinsic" + return self.add_instruction_condition(assign) + else: + return "REV16: error" @armregistry.register_tag("REV16", ARMOpcode) @@ -89,16 +120,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(i) for i in self.args[:-1]] def annotation(self, xdata: InstrXData) -> str: - lhs = str(xdata.vars[0]) - rhs = str(xdata.xprs[1]) - assignment = lhs + " := __rev16(" + str(rhs) + ") intrinsic" - if xdata.has_unknown_instruction_condition(): - return "if ? then " + assignment - elif xdata.has_instruction_condition(): - c = str(xdata.xprs[1]) - return "if " + c + " then " + assignment - else: - return assignment + xd = ARMByteReversePackedHalfwordXData(xdata) + return xd.annotation # -------------------------------------------------------------------------- # Operation diff --git a/chb/arm/opcodes/ARMMove.py b/chb/arm/opcodes/ARMMove.py index df3c3e9e..a32016a4 100644 --- a/chb/arm/opcodes/ARMMove.py +++ b/chb/arm/opcodes/ARMMove.py @@ -92,6 +92,10 @@ def is_cresult_ok(self) -> bool: @property def annotation(self) -> str: + if self.xdata.instruction_is_subsumed(): + return "subsumed by " + self.xdata.subsumed_by() + if self.xdata.instruction_subsumes(): + return "subsumes " + ", ".join(self.xdata.subsumes()) cx = " (C: " + (str(self.cresult) if self.is_cresult_ok else "None") + ")" rhs = str(self.result) if self.is_result_ok else str(self.xrm) assignment = str(self.vrd) + " := " + rhs + cx diff --git a/chb/arm/opcodes/ARMSignedBitFieldExtract.py b/chb/arm/opcodes/ARMSignedBitFieldExtract.py index 5fa7eb0f..1ed86573 100644 --- a/chb/arm/opcodes/ARMSignedBitFieldExtract.py +++ b/chb/arm/opcodes/ARMSignedBitFieldExtract.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2022 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -25,20 +25,50 @@ # SOFTWARE. # ------------------------------------------------------------------------------ -from typing import List, TYPE_CHECKING +from typing import List, Tuple, TYPE_CHECKING from chb.app.InstrXData import InstrXData from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand import chb.util.fileutil as UF - from chb.util.IndexedTable import IndexedTableValue +from chb.util.loggingutil import chklogger if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XXpr + + +class ARMSignedBitFieldExtractXData(ARMOpcodeXData): + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vrd(self) -> "XVariable": + return self.var(0, "vrd") + + @property + def xrn(self) -> "XXpr": + return self.xpr(0, "xrn") + + @property + def xxrn(self) -> "XXpr": + return self.xpr(1, "xxrn") + + @property + def result_simplified(self) -> str: + return simplify_result( + self.xdata.args[1], self.xdata.args[2], self.xrn, self.xxrn) + + @property + def annotation(self) -> str: + assignment = str(self.vrd) + " := " + self.result_simplified + return self.add_instruction_condition(assignment) @armregistry.register_tag("SBFX", ARMOpcode) @@ -64,15 +94,8 @@ def operands(self) -> List[ARMOperand]: return [self.armd.arm_operand(i) for i in self.args] def annotation(self, xdata: InstrXData) -> str: - """xdata format: a:vxx . - - vars[0]: lhs - xprs[0]: rhs1 - xprs[1]: value to be stored (syntactic) - """ - - lhs = str(xdata.vars[0]) - result = xdata.xprs[0] - rresult = xdata.xprs[1] - xresult = simplify_result(xdata.args[1], xdata.args[2], result, rresult) - return lhs + " := " + xresult + xd = ARMSignedBitFieldExtractXData(xdata) + if xd.is_ok: + return xd.annotation + else: + return "Error value" diff --git a/chb/arm/opcodes/ARMSignedExtendHalfword.py b/chb/arm/opcodes/ARMSignedExtendHalfword.py index c43add16..be02beae 100644 --- a/chb/arm/opcodes/ARMSignedExtendHalfword.py +++ b/chb/arm/opcodes/ARMSignedExtendHalfword.py @@ -77,6 +77,9 @@ def annotation(self, xdata: InstrXData) -> str: xprs[1]: rhs (simplified) """ + ''' lhs = str(xdata.vars[0]) result = str(xdata.xprs[1]) return lhs + " := " + result + ''' + return "pending" diff --git a/chb/arm/opcodes/ARMUnsignedExtendAddByte.py b/chb/arm/opcodes/ARMUnsignedExtendAddByte.py index 34044cc1..420d49a6 100644 --- a/chb/arm/opcodes/ARMUnsignedExtendAddByte.py +++ b/chb/arm/opcodes/ARMUnsignedExtendAddByte.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,7 @@ from chb.app.InstrXData import InstrXData from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand import chb.util.fileutil as UF @@ -39,6 +39,43 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMUnsignedExtendAddByteXData(ARMOpcodeXData): + """ + Data format: + - variables: + 0: vrd + + - expressions: + 0: xrn + 1: xrm + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vrd(self) -> "XVariable": + return self.var(0, "vrd") + + @property + def xrn(self) -> "XXpr": + return self.xpr(0, "xrn") + + @property + def xrm(self) -> "XXpr": + return self.xpr(1, "xrm") + + @property + def annotation(self) -> str: + lhs = str(self.vrd) + rhs1 = str(self.xrn) + rhs2 = str(self.xrm) + assign = lhs + " := extend_add_byte(" + rhs1 + ", " + rhs2 + ")" + return self.add_instruction_condition(assign) @armregistry.register_tag("UXTAB", ARMOpcode) @@ -65,14 +102,5 @@ def operands(self) -> List[ARMOperand]: return [self.armd.arm_operand(self.args[i]) for i in [0, 1, 2]] def annotation(self, xdata: InstrXData) -> str: - """xdata format a:vxx . - - vars[0]: lhs - xprs[0]: rhs1 - xprs[1]: rhs2 - """ - - lhs = str(xdata.vars[0]) - op1 = str(xdata.xprs[0]) - op2 = str(xdata.xprs[1]) - return lhs + ":= extend_add_byte(" + op1 + ", " + op2 + ")" + xd = ARMUnsignedExtendAddByteXData(xdata) + return xd.annotation diff --git a/chb/arm/opcodes/ARMVCompare.py b/chb/arm/opcodes/ARMVCompare.py index 417aa932..ddc84f7a 100644 --- a/chb/arm/opcodes/ARMVCompare.py +++ b/chb/arm/opcodes/ARMVCompare.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,7 @@ from chb.app.InstrXData import InstrXData from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand import chb.ast.ASTNode as AST @@ -45,6 +45,52 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XXpr + + +class ARMVCompareXData(ARMOpcodeXData): + """ + Data format: + - variables + 0: v_fpsrc + + - expressions + 0: xsrc1 + 1: xsrc2 + 2: rxsrc1 + 3: rxsrc2 + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def v_fpsrc(self) -> "XVariable": + return self.var(0, "v_fpsrc") + + @property + def xsrc1(self) -> "XXpr": + return self.xpr(0, "xsrc1") + + @property + def xsrc2(self) -> "XXpr": + return self.xpr(1, "xsrc2") + + @property + def rxsrc1(self) -> "XXpr": + return self.xpr(2, "rxsrc1") + + @property + def rxsrc2(self) -> "XXpr": + return self.xpr(3, "rxsrc2") + + @property + def annotation(self) -> str: + rhs1 = str(self.rxsrc1) + rhs2 = str(self.rxsrc2) + comparison = "compare " + rhs1 + " and " + rhs2 + return self.add_instruction_condition(comparison) @armregistry.register_tag("VCMPE", ARMOpcode) @@ -98,10 +144,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(self.args[i]) for i in [2, 3, 4]] def annotation(self, xdata: InstrXData) -> str: - rhs1 = str(xdata.xprs[2]) - rhs2 = str(xdata.xprs[3]) - comparison = "compare " + rhs1 + " and " + rhs2 - return comparison + xd = ARMVCompareXData(xdata) + return xd.annotation def ast_prov( self, diff --git a/chb/arm/opcodes/ARMVDivide.py b/chb/arm/opcodes/ARMVDivide.py index 811d3018..34e6fa7e 100644 --- a/chb/arm/opcodes/ARMVDivide.py +++ b/chb/arm/opcodes/ARMVDivide.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -33,7 +33,7 @@ from chb.astinterface.ASTInterface import ASTInterface from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand import chb.invariants.XXprUtil as XU @@ -45,6 +45,53 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMVDivideXData(ARMOpcodeXData): + """ + Data format: + - variables: + 0: vdst + + - expressions: + 0: xsrc1 + 1: xsrc2 + 2: rxsrc1 + 3: rxsrc2 + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vdst(self) -> "XVariable": + return self.var(0, "vdst") + + @property + def xsrc1(self) -> "XXpr": + return self.xpr(0, "xsrc1") + + @property + def xsrc2(self) -> "XXpr": + return self.xpr(1, "xsrc2") + + @property + def rxsrc1(self) -> "XXpr": + return self.xpr(2, "rxsrc1") + + @property + def rxsrc2(self) -> "XXpr": + return self.xpr(3, "rxsrc2") + + @property + def annotation(self) -> str: + lhs = str(self.vdst) + rhs1 = str(self.rxsrc1) + rhs2 = str(self.rxsrc2) + assign = lhs + " := " + rhs1 + " / " + rhs2 + return self.add_instruction_condition(assign) @armregistry.register_tag("VDIV", ARMOpcode) @@ -86,12 +133,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(self.args[i]) for i in [1, 2, 3]] def annotation(self, xdata: InstrXData) -> str: - return ( - str(xdata.vars[0]) - + " := " - + str(xdata.xprs[2]) - + " / " - + str(xdata.xprs[3])) + xd = ARMVDivideXData(xdata) + return xd.annotation def ast_prov( self, diff --git a/chb/arm/opcodes/ARMVLoadRegister.py b/chb/arm/opcodes/ARMVLoadRegister.py index 59a672c1..9e07f389 100644 --- a/chb/arm/opcodes/ARMVLoadRegister.py +++ b/chb/arm/opcodes/ARMVLoadRegister.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,7 @@ from chb.app.InstrXData import InstrXData from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand import chb.ast.ASTNode as AST @@ -45,6 +45,90 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XXpr + + +class ARMVLoadRegisterXData(ARMOpcodeXData): + """ + Data format: + - variables + 0: vvd + 1: vmem + + - expressions: + 0: xmem + 1: rxmem + 2: xbase + 3: rxbase + 4: xaddr + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vvd(self) -> "XVariable": + return self.var(0, "vvd") + + @property + def is_vvd_ok(self) -> bool: + return self.is_var_ok(0) + + @property + def vmem(self) -> "XVariable": + return self.var(1, "vmem") + + @property + def is_vmem_ok(self) -> bool: + return self.is_var_ok(1) + + @property + def xmem(self) -> "XXpr": + return self.xpr(0, "xmem") + + @property + def is_xmem_ok(self) -> bool: + return self.is_xpr_ok(0) + + @property + def rxmem(self) -> "XXpr": + return self.xpr(1, "rxmem") + + @property + def is_rxmem_ok(self) -> bool: + return self.is_xpr_ok(1) + + @property + def xbase(self) -> "XXpr": + return self.xpr(2, "xbase") + + @property + def is_xbase_ok(self) -> bool: + return self.is_xpr_ok(2) + + @property + def rxbase(self) -> "XXpr": + return self.xpr(3, "rxbase") + + @property + def is_rxbase_ok(self) -> bool: + return self.is_xpr_ok(3) + + @property + def xaddr(self) -> "XXpr": + return self.xpr(4, "xaddr") + + @property + def is_xaddr_ok(self) -> bool: + return self.is_xpr_ok(4) + + @property + def annotation(self) -> str: + lhs = str(self.vvd) if self.is_vvd_ok else "?" + rhs = str(self.rxmem) if self.is_rxmem_ok else "?" + assign = lhs + " := " + rhs + return self.add_instruction_condition(assign) @armregistry.register_tag("VLDR", ARMOpcode) @@ -90,16 +174,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(self.args[i]) for i in [0, 1, 2]] def annotation(self, xdata: InstrXData) -> str: - lhs = str(xdata.vars[0]) - rhs = str(xdata.xprs[1]) - assignment = lhs + " := " + rhs - if xdata.has_unknown_instruction_condition(): - return "if ? then " + assignment - elif xdata.has_instruction_condition(): - c = str(xdata.xprs[1]) - return "if " + c + " then " + assignment - else: - return assignment + xd = ARMVLoadRegisterXData(xdata) + return xd.annotation def ast_prov( self, diff --git a/chb/arm/opcodes/ARMVStoreRegister.py b/chb/arm/opcodes/ARMVStoreRegister.py index b67dce4d..3bf414ae 100644 --- a/chb/arm/opcodes/ARMVStoreRegister.py +++ b/chb/arm/opcodes/ARMVStoreRegister.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,7 @@ from chb.app.InstrXData import InstrXData from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand import chb.ast.ASTNode as AST @@ -45,6 +45,61 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMVStoreRegisterXData(ARMOpcodeXData): + """ + Data format: + - variables + 0: vmem + + - expressions: + 0: xsrc + 1: rxsrc + 2: xbase + 3: rxbase + 4: xaddr + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vmem(self) -> "XVariable": + return self.var(0, "vmem") + + @property + def is_vmem_ok(self) -> bool: + return self.is_var_ok(0) + + @property + def xsrc(self) -> "XXpr": + return self.xpr(0, "xsrc") + + @property + def rxsrc(self) -> "XXpr": + return self.xpr(1, "rxsrc") + + @property + def xbase(self) -> "XXpr": + return self.xpr(2, "xbase") + + @property + def rxbase(self) -> "XXpr": + return self.xpr(3, "rxbase") + + @property + def xaddr(self) -> "XXpr": + return self.xpr(4, "xaddr") + + @property + def annotation(self) -> str: + lhs = str(self.vmem) + rhs = str(self.rxsrc) + assign = lhs + " := " + rhs + return self.add_instruction_condition(assign) @armregistry.register_tag("VSTR", ARMOpcode) @@ -86,16 +141,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(self.args[i]) for i in [0, 1, 2]] def annotation(self, xdata: InstrXData) -> str: - lhs = str(xdata.vars[0]) - rhs = str(xdata.xprs[1]) - assignment = lhs + " := " + rhs - if xdata.has_unknown_instruction_condition(): - return "if ? then " + assignment - elif xdata.has_instruction_condition(): - c = str(xdata.xprs[1]) - return "if " + c + " then " + assignment - else: - return assignment + xd = ARMVStoreRegisterXData(xdata) + return xd.annotation def ast_prov( self, diff --git a/chb/arm/opcodes/ARMVectorConvert.py b/chb/arm/opcodes/ARMVectorConvert.py index ad0adda0..88a811d5 100644 --- a/chb/arm/opcodes/ARMVectorConvert.py +++ b/chb/arm/opcodes/ARMVectorConvert.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -33,7 +33,7 @@ from chb.astinterface.ASTInterface import ASTInterface from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand import chb.invariants.XXprUtil as XU @@ -45,6 +45,42 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMVectorConvertXData(ARMOpcodeXData): + """ + Data format: + - variables: + 0: vdst + + - expressions: + 0: xsrc + 1: rxsrc + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vdst(self) -> "XVariable": + return self.var(0, "vdst") + + @property + def xsrc(self) -> "XXpr": + return self.xpr(0, "xsrc") + + @property + def rxsrc(self) -> "XXpr": + return self.xpr(1, "rxsrc") + + @property + def annotation(self) -> str: + lhs = str(self.vdst) + rhs = str(self.rxsrc) + assign = lhs + " := " + rhs + return self.add_instruction_condition(assign) @armregistry.register_tag("VCVTR", ARMOpcode) @@ -116,16 +152,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(self.args[i]) for i in [4, 5]] def annotation(self, xdata: InstrXData) -> str: - """xdata format: a:vxx . - - vars[0]: lhs - xprs[0]: rhs - xprs[1]: rhs rewritten - """ - - lhs = str(xdata.vars[0]) - rhs = str(xdata.xprs[1]) - return lhs + " := " + rhs + xd = ARMVectorConvertXData(xdata) + return xd.annotation def ast_prov( self, diff --git a/chb/arm/opcodes/ARMVectorDuplicate.py b/chb/arm/opcodes/ARMVectorDuplicate.py index 9e4f1c33..124a06fd 100644 --- a/chb/arm/opcodes/ARMVectorDuplicate.py +++ b/chb/arm/opcodes/ARMVectorDuplicate.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,7 @@ from chb.app.InstrXData import InstrXData from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand import chb.util.fileutil as UF @@ -40,6 +40,40 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMVectorDuplicateXData(ARMOpcodeXData): + """ + Data format: + - variables + 0: vdst + + - expressions: + 0: src + 1: rsrc + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vdst(self) -> "XVariable": + return self.var(0, "vdst") + + @property + def src(self) -> "XXpr": + return self.xpr(0, "src") + + @property + def rsrc(self) -> "XXpr": + return self.xpr(1, "rsrc") + + @property + def annotation(self) -> str: + assign = "duplicate(" + str(self.rsrc) + ")" + return self.add_instruction_condition(assign) @armregistry.register_tag("VDUP", ARMOpcode) @@ -81,11 +115,5 @@ def vfp_datatype(self) -> "ARMVfpDatatype": return self.armd.arm_vfp_datatype(self.args[0]) def annotation(self, xdata: InstrXData) -> str: - """xdata format: a:xx . - - xprs[0]: rhs - xprs[1]: rhs rewritten - """ - - rhs = str(xdata.xprs[1]) - return "duplicate(" + rhs + ")" + xd = ARMVectorDuplicateXData(xdata) + return xd.annotation diff --git a/chb/arm/opcodes/ARMVectorMoveDDS.py b/chb/arm/opcodes/ARMVectorMoveDDS.py index bd4a911b..47ed1b6a 100644 --- a/chb/arm/opcodes/ARMVectorMoveDDS.py +++ b/chb/arm/opcodes/ARMVectorMoveDDS.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -35,7 +35,7 @@ from chb.astinterface.ASTInterface import ASTInterface from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand from chb.invariants.XXpr import XprConstant @@ -48,6 +48,53 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMVectorMoveDDSXData(ARMOpcodeXData): + """ + Data format: + - variables: + 0: vdst1 + 1: vdst2 + 2: vddst + + - expressions: + 0: xsrc + 1: rxsrc + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vdst1(self) -> "XVariable": + return self.var(0, "vdst1") + + @property + def vdst2(self) -> "XVariable": + return self.var(1, "vdst2") + + @property + def vddst(self) -> "XVariable": + return self.var(2, "vddst") + + @property + def xsrc(self) -> "XXpr": + return self.xpr(0, "xsrc") + + @property + def rxsrc(self) -> "XXpr": + return self.xpr(1, "rxsrc") + + @property + def annotation(self) -> str: + lhs1 = str(self.vdst1) + lhs2 = str(self.vdst2) + rhs = str(self.rxsrc) + assign = "(" + lhs1 + ", " + lhs2 + ") := " + rhs + return self.add_instruction_condition(assign) @armregistry.register_tag("VMOVDDS", ARMOpcode) @@ -104,10 +151,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(i) for i in self.args] def annotation(self, xdata: InstrXData) -> str: - lhs1 = str(xdata.vars[0]) - lhs2 = str(xdata.vars[1]) - rhs = str(xdata.xprs[1]) - return "(" + lhs1 + ", " + lhs2 + ") := " + rhs + xd = ARMVectorMoveDDSXData(xdata) + return xd.annotation def ast_prov( self, diff --git a/chb/arm/opcodes/ARMVectorMoveDDSS.py b/chb/arm/opcodes/ARMVectorMoveDDSS.py index 4f3b18ca..97485194 100644 --- a/chb/arm/opcodes/ARMVectorMoveDDSS.py +++ b/chb/arm/opcodes/ARMVectorMoveDDSS.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -35,7 +35,7 @@ from chb.astinterface.ASTInterface import ASTInterface from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand from chb.invariants.XXpr import XprConstant @@ -47,7 +47,75 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary - from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMVectorMoveDDSSXData(ARMOpcodeXData): + """ + Data format: + - variables: + 0: vdst1 + 1: vdst2 + 2: vddst + + - expressions: + 0: xsrc1 + 1: xsrc2 + 2: xssrc + 3: rxsrc1 + 4: rxsrc2 + 5: rxssrc + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vdst1(self) -> "XVariable": + return self.var(0, "vdst1") + + @property + def vdst2(self) -> "XVariable": + return self.var(1, "vdst2") + + @property + def vdddst(self) -> "XVariable": + return self.var(2, "vddst") + + @property + def xsrc1(self) -> "XXpr": + return self.xpr(0, "xsrc1") + + @property + def xsrc2(self) -> "XXpr": + return self.xpr(1, "xsrc2") + + @property + def xssrc(self) -> "XXpr": + return self.xpr(2, "xssrc") + + @property + def rxsrc1(self) -> "XXpr": + return self.xpr(3, "rxsrc1") + + @property + def rxsrc2(self) -> "XXpr": + return self.xpr(4, "rxsrc2") + + @property + def rxssrc(self) -> "XXpr": + return self.xpr(5, "rxssrc") + + @property + def annotation(self) -> str: + lhs1 = str(self.vdst1) + lhs2 = str(self.vdst2) + rhs1 = str(self.rxssrc) + rhs2 = str(self.rxsrc2) + assign = lhs1 + " := " + rhs1 + "; " + lhs2 + " := " + rhs2 + return self.add_instruction_condition(assign) @armregistry.register_tag("VMOVDDSS", ARMOpcode) @@ -97,7 +165,7 @@ def mnemonic_extension(self) -> str: @property def vfp_datatype(self) -> "ARMVfpDatatype": - return self.armd.arm_vfp_datatype(self.args[0]) + return self.armd.arm_vfp_datatype(self.args[0]) @property def operands(self) -> List[ARMOperand]: @@ -108,11 +176,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(i) for i in self.args] def annotation(self, xdata: InstrXData) -> str: - lhs1 = str(xdata.vars[0]) - lhs2 = str(xdata.vars[1]) - rhs1 = str(xdata.xprs[2]) - rhs2 = str(xdata.xprs[3]) - return (lhs1 + " := " + rhs1 + "; " + lhs2 + " := " + rhs2) + xd = ARMVectorMoveDDSSXData(xdata) + return xd.annotation def ast_prov( self, diff --git a/chb/arm/opcodes/ARMVectorMoveDS.py b/chb/arm/opcodes/ARMVectorMoveDS.py index f23abfe1..4d69b9d9 100644 --- a/chb/arm/opcodes/ARMVectorMoveDS.py +++ b/chb/arm/opcodes/ARMVectorMoveDS.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2024 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -35,7 +35,7 @@ from chb.astinterface.ASTInterface import ASTInterface from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand from chb.invariants.XXpr import XXpr, XprConstant @@ -49,6 +49,35 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMVectorMoveDSXData(ARMOpcodeXData): + """ + Data format: + - variables: + 0: vdst + + - expressions: + 0: xsrc + 1: rxsrc + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vdst(self) -> "XVariable": + return self.var(0, "vdst") + + @property + def xsrc(self) -> "XXpr": + return self.xpr(0, "xsrc") + + @property + def rxsrc(self) -> "XXpr": + return self.xpr(1, "rxsrc") @armregistry.register_tag("VMOVDS", ARMOpcode) @@ -138,8 +167,9 @@ def _unpack_imm64(self, x: XXpr) -> float: return struct.unpack('d', b8)[0] def annotation(self, xdata: InstrXData) -> str: - rhs = xdata.xprs[1] - lhs = xdata.vars[0] + xd = ARMVectorMoveDSXData(xdata) + rhs = xd.rxsrc + lhs = xd.vdst if rhs.is_int_constant and str(lhs).startswith("S"): f = self._unpack_imm32(rhs) return str(lhs) + " := #" + str(f) @@ -147,7 +177,7 @@ def annotation(self, xdata: InstrXData) -> str: d = self._unpack_imm64(rhs) return str(lhs) + " := #" + str(d) else: - return str(xdata.vars[0]) + " := " + str(xdata.xprs[1]) + return str(lhs) + " := " + str(rhs) def ast_prov( self, diff --git a/chb/arm/opcodes/ARMVectorMoveDSS.py b/chb/arm/opcodes/ARMVectorMoveDSS.py index bc236950..3fa5f6cb 100644 --- a/chb/arm/opcodes/ARMVectorMoveDSS.py +++ b/chb/arm/opcodes/ARMVectorMoveDSS.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -35,7 +35,7 @@ from chb.astinterface.ASTInterface import ASTInterface from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand from chb.invariants.XXpr import XprConstant @@ -48,6 +48,63 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMVectorMoveDSSXData(ARMOpcodeXData): + """ + Data format: + - variables: + 0: vdst + + - expressions: + 0: xsrc1 + 1: xsrc2 + 2: xssrc + 3: rxsrc1 + 4: rxsrc2 + 5: rxssrc + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vdst(self) -> "XVariable": + return self.var(0, "vdst") + + @property + def xsrc1(self) -> "XXpr": + return self.xpr(0, "xsrc1") + + @property + def xsrc2(self) -> "XXpr": + return self.xpr(1, "xsrc2") + + @property + def xssrc(self) -> "XXpr": + return self.xpr(2, "xssrc") + + @property + def rxsrc1(self) -> "XXpr": + return self.xpr(3, "rxsrc1") + + @property + def rxsrc2(self) -> "XXpr": + return self.xpr(4, "rxsrc2") + + @property + def rxssrc(self) -> "XXpr": + return self.xpr(5, "rxssrc") + + @property + def annotation(self) -> str: + lhs = str(self.vdst) + rhs1 = str(self.rxssrc) + rhs2 = str(self.rxsrc2) + assign = lhs + " := " + rhs1 + ":" + rhs2 + return self.add_instruction_condition(assign) @armregistry.register_tag("VMOVDSS", ARMOpcode) @@ -92,7 +149,7 @@ def mnemonic_extension(self) -> str: @property def vfp_datatype(self) -> "ARMVfpDatatype": - return self.armd.arm_vfp_datatype(self.args[0]) + return self.armd.arm_vfp_datatype(self.args[0]) @property def operands(self) -> List[ARMOperand]: @@ -103,10 +160,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(i) for i in self.args] def annotation(self, xdata: InstrXData) -> str: - lhs = str(xdata.vars[0]) - rhs1 = str(xdata.xprs[2]) - rhs2 = str(xdata.xprs[3]) - return (lhs + " := " + rhs1 + ":" + rhs2) + xd = ARMVectorMoveDSSXData(xdata) + return xd.annotation def ast_prov( self, diff --git a/chb/arm/opcodes/ARMVectorSubtract.py b/chb/arm/opcodes/ARMVectorSubtract.py index ec3ad0ee..d97dce1a 100644 --- a/chb/arm/opcodes/ARMVectorSubtract.py +++ b/chb/arm/opcodes/ARMVectorSubtract.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2023 Aarno Labs LLC +# Copyright (c) 2021-2025 Aarno Labs LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -33,7 +33,7 @@ from chb.astinterface.ASTInterface import ASTInterface from chb.arm.ARMDictionaryRecord import armregistry -from chb.arm.ARMOpcode import ARMOpcode, simplify_result +from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result from chb.arm.ARMOperand import ARMOperand import chb.invariants.XXprUtil as XU @@ -45,6 +45,63 @@ if TYPE_CHECKING: from chb.arm.ARMDictionary import ARMDictionary from chb.arm.ARMVfpDatatype import ARMVfpDatatype + from chb.invariants.XVariable import XVariable + from chb.invariants.XXpr import XprCompound, XprConstant, XXpr + + +class ARMVectorSubtractXData(ARMOpcodeXData): + """ + Data format: + - variables: + 0: vdst + + - expressions: + 0: xsrc1 + 1: xsrc2 + 2: xdst + 3: rxsrc1 + 4: rxsrc2 + 5: rxdst + """ + + def __init__(self, xdata: InstrXData) -> None: + ARMOpcodeXData.__init__(self, xdata) + + @property + def vdst(self) -> "XVariable": + return self.var(0, "vdst") + + @property + def xsrc1(self) -> "XXpr": + return self.xpr(0, "xsrc1") + + @property + def xsrc2(self) -> "XXpr": + return self.xpr(1, "xsrc2") + + @property + def xdst(self) -> "XXpr": + return self.xpr(2, "xdst") + + @property + def rxsrc1(self) -> "XXpr": + return self.xpr(3, "rxsrc1") + + @property + def rxsrc2(self) -> "XXpr": + return self.xpr(4, "rxsrc2") + + @property + def rxdst(self) -> "XXpr": + return self.xpr(5, "rxdst") + + @property + def annotation(self) -> str: + lhs = str(self.vdst) + rhs1 = str(self.rxsrc1) + rhs2 = str(self.rxsrc2) + assign = lhs + " := " + rhs1 + " - " + rhs2 + return self.add_instruction_condition(assign) @armregistry.register_tag("VSUB", ARMOpcode) @@ -96,11 +153,8 @@ def opargs(self) -> List[ARMOperand]: return [self.armd.arm_operand(self.args[i]) for i in [1, 2, 3]] def annotation(self, xdata: InstrXData) -> str: - lhs = str(xdata.vars[0]) - rhs1 = str(xdata.xprs[3]) - rhs2 = str(xdata.xprs[4]) - rhsd = str(xdata.xprs[5]) - return lhs + " := " + rhs1 + " - " + rhs2 + xd = ARMVectorSubtractXData(xdata) + return xd.annotation def ast_prov( self, @@ -111,10 +165,11 @@ def ast_prov( List[AST.ASTInstruction], List[AST.ASTInstruction]]: annotations: List[str] = [iaddr, "VSUB"] + xd = ARMVectorSubtractXData(xdata) - lhs = xdata.vars[0] - rhs1 = xdata.xprs[3] - rhs2 = xdata.xprs[4] + lhs = xd.vdst + rhs1 = xd.rxsrc1 + rhs2 = xd.rxsrc2 rdefs = xdata.reachingdefs defuses = xdata.defuses defuseshigh = xdata.defuseshigh diff --git a/chb/bctypes/BCFiles.py b/chb/bctypes/BCFiles.py index 772ed4dd..90d8866c 100644 --- a/chb/bctypes/BCFiles.py +++ b/chb/bctypes/BCFiles.py @@ -26,7 +26,7 @@ # ------------------------------------------------------------------------------ """Contains all global types in a CIL file.""" -from typing import Any, cast, Dict, List, Optional, TYPE_CHECKING +from typing import Any, cast, Dict, List, Optional, Tuple, TYPE_CHECKING import xml.etree.ElementTree as ET @@ -55,6 +55,7 @@ def __init__(self, app: "AppAccess", xnode: ET.Element) -> None: self._gvardecls: List[BCVarInfo] = [] self._gvardefs: List[BCVarInfo] = [] self._functions: Dict[str, BCFunctionDefinition] = {} + self._srcmap: List[Tuple[str, int, str, str]] = [] self.initialize(xnode) @property @@ -102,6 +103,10 @@ def gvardefs(self) -> List[BCVarInfo]: def globalvars(self) -> List[BCVarInfo]: return self._gvardefs + self._gvardecls + @property + def srcmap(self) -> List[Tuple[str, int, str, str]]: + return self._srcmap + @property def functions(self) -> Dict[str, BCFunctionDefinition]: return self._functions @@ -149,6 +154,7 @@ def initialize(self, xnode: ET.Element) -> None: self.initialize_vardefs(xnode.find("varinfos")) self.initialize_vardecls(xnode.find("varinfodecls")) self.initialize_functions(xnode.find("ifuns")) + self.initialize_srcmap(xnode.find("srcmap")) def initialize_compinfos(self, tnode: Optional[ET.Element]) -> None: if tnode: @@ -209,6 +215,18 @@ def initialize_functions(self, tnode: Optional[ET.Element]) -> None: self._functions[svinfo.vname] = BCFunctionDefinition( self, svinfo.vname, xfundef) + def initialize_srcmap(self, tnode: Optional[ET.Element]) -> None: + if tnode is not None: + for x in tnode.findall("srcloc"): + vix = x.get("vix") + lnr = x.get("lnr") + ixfn = x.get("ixfn") + binloc = x.get("binloc") + if vix and lnr and ixfn and binloc: + srcvinfo = self.bcd.varinfo(int(vix)) + srcfile = self.bcd.string(int(ixfn)) + self._srcmap.append((srcfile, int(lnr), srcvinfo.vname, binloc)) + def __str__(self) -> str: lines: List[str] = [] lines.append("\n".join(str(t) for t in self.gtypes)) diff --git a/chb/cmdline/chkx b/chb/cmdline/chkx index ec4507e6..3424947d 100755 --- a/chb/cmdline/chkx +++ b/chb/cmdline/chkx @@ -584,6 +584,11 @@ def parse() -> argparse.Namespace: ddatamd5s.add_argument("xname", help="name of executable") ddatamd5s.set_defaults(func=UCC.ddata_md5s) + # -- ddata srcmap -- + ddatasrcmap = ddataparsers.add_parser("srcmap") + ddatasrcmap.add_argument("xname", help="name of executable") + ddatasrcmap.set_defaults(func=UCC.ddata_srcmap) + # ----------------------------------------------------------------- results -- resultscmd = subparsers.add_parser('results') resultscmd.set_defaults(func=resultscommand) diff --git a/chb/cmdline/commandutil.py b/chb/cmdline/commandutil.py index e179cb1e..3bfede7a 100644 --- a/chb/cmdline/commandutil.py +++ b/chb/cmdline/commandutil.py @@ -2561,3 +2561,34 @@ def ddata_md5s(args: argparse.Namespace) -> NoReturn: print(md5 + ": " + str(count)) exit(0) + + +def ddata_srcmap(args: argparse.Namespace) -> NoReturn: + + # arguments + xname: str = str(args.xname) + + try: + (path, xfile) = get_path_filename(xname) + except UF.CHBError as e: + print(str(e.wrap())) + exit(1) + + xinfo = XI.XInfo() + xinfo.load(path, xfile) + + app = get_app(path, xfile, xinfo) + srcmap = app.bcfiles.srcmap + + result: Dict[str, Dict[int, Tuple[str, str]]] = {} + + for (fname, linenr, vname, binloc) in srcmap: + result.setdefault(fname, {}) + result[fname][linenr] = (vname, binloc) + + for fname in result: + print(fname) + for (linenr, (vname, binloc)) in sorted(result[fname].items()): + print(str(linenr).rjust(6) + ": " + binloc.rjust(10) + " " + vname) + + exit(0) diff --git a/chb/cmdline/reportcmds.py b/chb/cmdline/reportcmds.py index e65a88da..ff74d11e 100644 --- a/chb/cmdline/reportcmds.py +++ b/chb/cmdline/reportcmds.py @@ -1149,11 +1149,11 @@ def consider(faddr: str): # heuristics, which (for now) means shared object stubs. if calltgt.is_so_target: opcode = instr.opcode # type: ignore - if "MIPS" in repr(opcode): # ugly but concise! + if app.is_mips: # No support (or need?) for MIPS just yet continue optgt = opcode.opargs[0] - tgtname = cast(StubTarget, calltgt).stub.name + tgtname = cast("StubTarget", calltgt).stub.name if optgt.is_absolute: tgtaddr = optgt.opkind.address.get_hex() consider_pair(tgtaddr, tgtname) diff --git a/chb/mips/opcodes/MIPSMovF.py b/chb/mips/opcodes/MIPSMovF.py new file mode 100644 index 00000000..0784992d --- /dev/null +++ b/chb/mips/opcodes/MIPSMovF.py @@ -0,0 +1,56 @@ +# ------------------------------------------------------------------------------ +# CodeHawk Binary Analyzer +# Author: Henny Sipma +# ------------------------------------------------------------------------------ +# The MIT License (MIT) +# +# Copyright (c) 2025 Aarno Labs LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# ------------------------------------------------------------------------------ + +from typing import cast, List, Sequence, TYPE_CHECKING + +from chb.app.InstrXData import InstrXData + +from chb.mips.MIPSDictionaryRecord import mipsregistry +from chb.mips.MIPSOpcode import MIPSOpcode, simplify_result +from chb.mips.MIPSOperand import MIPSOperand + +from chb.util.IndexedTable import IndexedTableValue + +if TYPE_CHECKING: + from chb.mips.MIPSDictionary import MIPSDictionary + + +@mipsregistry.register_tag("movf", MIPSOpcode) +class MIPSMovF(MIPSOpcode): + + def __init__( + self, + mipsd: "MIPSDictionary", + ixval: IndexedTableValue) -> None: + MIPSOpcode.__init__(self, mipsd, ixval) + + @property + def operands(self) -> Sequence[MIPSOperand]: + return [self.mipsd.mips_operand(i) for i in self.args[1:]] + + def annotation(self, xdata: InstrXData) -> str: + return "pending" diff --git a/chb/mips/opcodes/MIPSMovT.py b/chb/mips/opcodes/MIPSMovT.py new file mode 100644 index 00000000..541153c1 --- /dev/null +++ b/chb/mips/opcodes/MIPSMovT.py @@ -0,0 +1,56 @@ +# ------------------------------------------------------------------------------ +# CodeHawk Binary Analyzer +# Author: Henny Sipma +# ------------------------------------------------------------------------------ +# The MIT License (MIT) +# +# Copyright (c) 2025 Aarno Labs LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# ------------------------------------------------------------------------------ + +from typing import cast, List, Sequence, TYPE_CHECKING + +from chb.app.InstrXData import InstrXData + +from chb.mips.MIPSDictionaryRecord import mipsregistry +from chb.mips.MIPSOpcode import MIPSOpcode, simplify_result +from chb.mips.MIPSOperand import MIPSOperand + +from chb.util.IndexedTable import IndexedTableValue + +if TYPE_CHECKING: + from chb.mips.MIPSDictionary import MIPSDictionary + + +@mipsregistry.register_tag("movt", MIPSOpcode) +class MIPSMovT(MIPSOpcode): + + def __init__( + self, + mipsd: "MIPSDictionary", + ixval: IndexedTableValue) -> None: + MIPSOpcode.__init__(self, mipsd, ixval) + + @property + def operands(self) -> Sequence[MIPSOperand]: + return [self.mipsd.mips_operand(i) for i in self.args[1:]] + + def annotation(self, xdata: InstrXData) -> str: + return "pending"