diff --git a/chb/app/CHVersion.py b/chb/app/CHVersion.py index deeff9ef..56071fe9 100644 --- a/chb/app/CHVersion.py +++ b/chb/app/CHVersion.py @@ -1 +1 @@ -chbversion: str = "0.3.0-20250821" +chbversion: str = "0.3.0-20250823" diff --git a/chb/app/GlobalMemoryMap.py b/chb/app/GlobalMemoryMap.py index ebef1d2a..f697c00c 100644 --- a/chb/app/GlobalMemoryMap.py +++ b/chb/app/GlobalMemoryMap.py @@ -206,6 +206,10 @@ def gtype(self) -> Optional["BCTyp"]: return self.mmap.bcdictionary.typ(int(tix)) return None + @property + def is_volatile(self) -> bool: + return self.gtype is not None and self.gtype.is_volatile + @property def size(self) -> Optional[int]: s = self._xnode.get("size", None) diff --git a/chb/arm/opcodes/ARMLoadRegisterHalfword.py b/chb/arm/opcodes/ARMLoadRegisterHalfword.py index cad1f962..f0ef1251 100644 --- a/chb/arm/opcodes/ARMLoadRegisterHalfword.py +++ b/chb/arm/opcodes/ARMLoadRegisterHalfword.py @@ -251,9 +251,8 @@ def has_cast() -> bool: if xd.is_ok: rhs = xd.cxrmem - rhsval = None if has_cast() else xd.cxrmem hl_lhs = XU.xvariable_to_ast_lval( - lhs, xdata, iaddr, astree, rhs=rhsval) + lhs, xdata, iaddr, astree, rhs=xd.cxrmem) hl_rhs = XU.xxpr_to_ast_def_expr(rhs, xdata, iaddr, astree) elif xd.is_cxaddr_ok: diff --git a/chb/bctypes/BCAttribute.py b/chb/bctypes/BCAttribute.py index 428461d9..a51f2ca4 100644 --- a/chb/bctypes/BCAttribute.py +++ b/chb/bctypes/BCAttribute.py @@ -53,6 +53,10 @@ def name(self) -> str: def params(self) -> List["BCAttrParam"]: return [self.bcd.attrparam(i) for i in self.args] + @property + def is_volatile(self) -> bool: + return self.name == "volatile" + def __str__(self) -> str: return self.name + "(" + ", ".join(str(p) for p in self.params) + ")" diff --git a/chb/bctypes/BCTyp.py b/chb/bctypes/BCTyp.py index bb056d91..77ad23b2 100644 --- a/chb/bctypes/BCTyp.py +++ b/chb/bctypes/BCTyp.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 @@ -191,6 +191,10 @@ def is_typedef(self) -> bool: def is_unknown(self) -> bool: return False + @property + def is_volatile(self) -> bool: + return any(a.is_volatile for a in self.attrs) + @property def attrs(self) -> List["BCAttribute"]: attrs = self.bcd.attributes(self.args[-1]) diff --git a/chb/cmdline/commandutil.py b/chb/cmdline/commandutil.py index cd1a10d9..c49da187 100644 --- a/chb/cmdline/commandutil.py +++ b/chb/cmdline/commandutil.py @@ -2534,11 +2534,16 @@ def ddata_gvars(args: argparse.Namespace) -> NoReturn: sgtype = str(gtype) else: sgtype = "" + if gloc.is_volatile: + vt = " (volatile)" + else: + vt = "" print(gloc.addr.rjust(8) + " " + gloc.name.ljust(60) + " " - + sgtype.ljust(20)) + + sgtype.ljust(20) + + vt) (count, coverage) = memmap.coverage() diff --git a/chb/invariants/VAssemblyVariable.py b/chb/invariants/VAssemblyVariable.py index 192c9985..64918aed 100644 --- a/chb/invariants/VAssemblyVariable.py +++ b/chb/invariants/VAssemblyVariable.py @@ -39,7 +39,7 @@ """ -from typing import Any, Dict, List, Sequence, Tuple, TYPE_CHECKING +from typing import Any, Dict, List, Optional, Sequence, Tuple, TYPE_CHECKING from chb.app.Register import Register @@ -96,6 +96,9 @@ def is_auxiliary_variable(self) -> bool: def is_global_variable(self) -> bool: return False + def get_global_variable_address(self) -> Optional[str]: + return None + @property def is_global_value(self) -> bool: return False @@ -297,6 +300,12 @@ def argument_index(self) -> int: "Assembly variable is not a stack argument: " + str(self)) + def get_global_variable_address(self) -> Optional[str]: + if self.is_global_variable: + if self.offset.is_constant_value_offset: + return hex(self.offset.offsetvalue()) + return None + def has_unknown_base(self) -> bool: return self.base.is_unknown @@ -417,6 +426,11 @@ def is_auxiliary_variable(self) -> bool: def is_global_value(self) -> bool: return self.auxvar.is_global_value + def get_global_variable_address(self) -> Optional[str]: + if self.is_global_value: + return self.auxvar.get_global_variable_address() + return None + @property def is_stack_base_address(self) -> bool: return self.auxvar.is_stack_base_address diff --git a/chb/invariants/VConstantValueVariable.py b/chb/invariants/VConstantValueVariable.py index c4999e0f..b8304667 100644 --- a/chb/invariants/VConstantValueVariable.py +++ b/chb/invariants/VConstantValueVariable.py @@ -128,6 +128,9 @@ def is_bridge_variable(self) -> bool: def is_global_value(self) -> bool: return False + def get_global_variable_address(self) -> Optional[str]: + return None + @property def is_function_return_value(self) -> bool: return False @@ -350,6 +353,11 @@ def is_global_value(self) -> bool: avar = self.variable.denotation return avar.is_memory_variable and avar.is_global_variable + def get_global_variable_address(self) -> Optional[str]: + if self.is_global_value: + return self.variable.denotation.get_global_variable_address() + return None + @property def is_argument_value(self) -> bool: avar = self.variable.denotation diff --git a/chb/invariants/XVariable.py b/chb/invariants/XVariable.py index 5c82ecea..f6e8ab7c 100644 --- a/chb/invariants/XVariable.py +++ b/chb/invariants/XVariable.py @@ -28,7 +28,7 @@ # ------------------------------------------------------------------------------ """Symbolic value, identified by name and sequence number""" -from typing import Any, cast, Dict, List, Tuple, TYPE_CHECKING +from typing import Any, cast, Dict, List, Optional, Tuple, TYPE_CHECKING from chb.app.Register import Register @@ -201,6 +201,11 @@ def is_global_variable(self) -> bool: return (self.has_denotation() and (self.denotation.is_global_variable or self.is_global_value)) + def get_global_variable_address(self) -> Optional[str]: + if self.is_global_variable: + return self.denotation.get_global_variable_address() + return None + @property def is_structured_var(self) -> bool: return (self.has_denotation() and self.denotation.is_structured_var) diff --git a/chb/invariants/XXpr.py b/chb/invariants/XXpr.py index 02a656e6..8326b542 100644 --- a/chb/invariants/XXpr.py +++ b/chb/invariants/XXpr.py @@ -149,6 +149,9 @@ def is_global_address(self) -> bool: def is_global_variable(self) -> bool: return False + def get_global_variable_address(self) -> Optional[str]: + return None + def is_int_const_value(self, n: int) -> bool: return False @@ -381,6 +384,9 @@ def is_structured_expr(self) -> bool: def is_global_variable(self) -> bool: return self.variable.is_global_variable + def get_global_variable_address(self) -> Optional[str]: + return self.variable.get_global_variable_address() + @property def is_function_return_value(self) -> bool: return (self.variable.has_denotation() diff --git a/chb/invariants/XXprUtil.py b/chb/invariants/XXprUtil.py index b10ba594..c9c8b926 100644 --- a/chb/invariants/XXprUtil.py +++ b/chb/invariants/XXprUtil.py @@ -1768,8 +1768,27 @@ def xvariable_to_ast_lval( to an ssa value, while a high-level register that is part of some rhs should be delegated to its reaching definitions, and thus should stay confined to functions dealing with rhs values. + + Note: another check should be added to this function as to whether the + rhs (if provided) is volatile. If so, it should not be used to propagate + that value. """ + if ( + astree.has_register_variable_intro(iaddr) + and astree.get_register_variable_intro(iaddr).has_cast()): + rhs = None + + if (rhs is not None and rhs.is_global_variable): + gaddr = rhs.get_global_variable_address() + if gaddr is not None: + gmemmap = xdata.app.globalmemorymap + if gaddr in gmemmap.locations: + gloc = gmemmap.get_location(gaddr) + if gloc is not None and gloc.gtype is not None: + if gloc.gtype.is_volatile: + rhs = None + # unknown memory value if xv.is_tmp or xv.has_unknown_memory_base(): if memaddr is not None: