5252
5353
5454class ARMLoadRegisterHalfwordXData (ARMOpcodeXData ):
55+ """Data format:
56+ - variables:
57+ 0: vrt (lhs)
58+
59+ - expressions:
60+ 0: xrn
61+ 1: xrm
62+ 2: xmem (rhs)
63+ 3: xrmem (rhs, rewritten)
64+ 4: xaddr (address of rhs)
65+
66+ - c expressions:
67+ 0: cxrmem (rhs)
68+ 1: cxaddr (address of rhs)
69+ """
5570
5671 def __init__ (self , xdata : InstrXData ) -> None :
5772 ARMOpcodeXData .__init__ (self , xdata )
@@ -61,36 +76,79 @@ def vrt(self) -> "XVariable":
6176 return self .var (0 , "vrt" )
6277
6378 @property
64- def vmem (self ) -> "XVariable" :
65- return self .var (1 , "vmem" )
79+ def xrn (self ) -> "XXpr" :
80+ return self .xpr (0 , "xrn" )
81+
82+ @property
83+ def xrm (self ) -> "XXpr" :
84+ return self .xpr (1 , "xrm" )
6685
6786 @property
6887 def xmem (self ) -> "XXpr" :
6988 return self .xpr (2 , "xmem" )
7089
90+ @property
91+ def is_xmem_ok (self ) -> bool :
92+ return self .is_xpr_ok (2 )
93+
7194 @property
7295 def xrmem (self ) -> "XXpr" :
7396 return self .xpr (3 , "xrmem" )
7497
98+ @property
99+ def is_xrmem_ok (self ) -> bool :
100+ return self .is_xpr_ok (3 )
101+
102+ @property
103+ def cxrmem (self ) -> "XXpr" :
104+ return self .cxpr (0 , "cxrmem" )
105+
106+ @property
107+ def is_cxrmem_ok (self ) -> bool :
108+ return self .is_cxpr_ok (0 )
109+
75110 @property
76111 def xaddr (self ) -> "XXpr" :
77112 return self .xpr (4 , "xaddr" )
78113
79114 @property
80- def is_xrmem_unknown (self ) -> bool :
81- return self .xdata .xprs_r [3 ] is None
115+ def is_xaddr_ok (self ) -> bool :
116+ return self .is_xpr_ok (4 )
117+
118+ @property
119+ def xxaddr (self ) -> "XXpr" :
120+ return self .xpr (5 , "xxaddr" )
121+
122+ @property
123+ def is_xxaddr_ok (self ) -> bool :
124+ return self .is_xpr_ok (5 )
125+
126+ @property
127+ def cxaddr (self ) -> "XXpr" :
128+ return self .cxpr (1 , "cxaddr" )
82129
83130 @property
84- def is_address_known (self ) -> bool :
85- return self .xdata . xprs_r [ 4 ] is not None
131+ def is_cxaddr_ok (self ) -> bool :
132+ return self .is_cxpr_ok ( 1 )
86133
87134 @property
88135 def annotation (self ) -> str :
89136 wbu = self .writeback_update ()
90- if self .is_ok :
91- assignment = str (self .vrt ) + " := " + str (self .xrmem )
92- elif self .is_xrmem_unknown and self .is_address_known :
93- assignment = str (self .vrt ) + " := *(" + str (self .xaddr ) + ")"
137+ if self .is_cxrmem_ok :
138+ crhs = str (self .cxrmem )
139+ elif self .is_cxaddr_ok :
140+ crhs = "*(" + str (self .cxaddr ) + ")"
141+ else :
142+ crhs = "None"
143+ cx = " (C: " + crhs + ")"
144+ addr = str (self .xxaddr if self .is_xxaddr_ok else self .xaddr )
145+ caddr = str (self .cxaddr if self .is_cxaddr_ok else "None" )
146+ caddr = " (addr: " + addr + "; C: " + caddr + ")"
147+ if self .is_ok or self .is_xrmem_ok :
148+ assignment = str (self .vrt ) + " := " + str (self .xrmem ) + cx + caddr
149+ elif self .is_xaddr_ok :
150+ assignment = (
151+ str (self .vrt ) + " := *(" + str (self .xaddr ) + ")" + cx + caddr )
94152 else :
95153 assignment = "Error value"
96154 return self .add_instruction_condition (assignment ) + wbu
@@ -109,27 +167,14 @@ class ARMLoadRegisterHalfword(ARMOpcode):
109167 args[3]: index of memory location in armdictionary
110168 args[4]: is-wide (thumb)
111169
112- xdata format: a:vxxxxrrrdh
113- --------------------------
114- vars[0]: lhs
115- vars[1]: memory location expressed as a variable
116- xprs[0]: value in rn
117- xprs[1]: value in rm
118- xprs[2]: value in memory location
119- xprs[3]: value in memory location (simplified)
120- xprs[4]: address of memory location
170+ xdata format:
171+ -------------
121172 rdefs[0]: reaching definitions rn
122173 rdefs[1]: reaching definitions rm
123174 rdefs[2]: reaching definitions memory location
124175 rdefs[3..]: reaching definitions for memory value
125176 uses[0]: use of lhs
126177 useshigh[0]: use of lhs at high level
127-
128- optional:
129- vars[1]: lhs base register (if base update)
130-
131- xprs[.]: instruction condition (if has condition)
132- xprs[.]: new address for base register
133178 """
134179
135180 def __init__ (self , d : "ARMDictionary" , ixval : IndexedTableValue ) -> None :
@@ -149,13 +194,20 @@ def opargs(self) -> List[ARMOperand]:
149194 return [self .armd .arm_operand (self .args [i ]) for i in [0 , 1 , 2 , 3 ]]
150195
151196 def lhs (self , xdata : InstrXData ) -> List [XVariable ]:
152- return [xdata .vars [0 ]]
197+ xd = ARMLoadRegisterHalfwordXData (xdata )
198+ return [xd .vrt ]
153199
154200 def is_load_instruction (self , xdata : InstrXData ) -> bool :
155201 return True
156202
157203 def rhs (self , xdata : InstrXData ) -> List [XXpr ]:
158- return [xdata .xprs [1 ]]
204+ xd = ARMLoadRegisterHalfwordXData (xdata )
205+ if xd .is_xrmem_ok :
206+ return [xd .xrmem ]
207+ elif xd .is_xmem_ok :
208+ return [xd .xmem ]
209+ else :
210+ return []
159211
160212 def annotation (self , xdata : InstrXData ) -> str :
161213 return ARMLoadRegisterHalfwordXData (xdata ).annotation
@@ -189,38 +241,63 @@ def ast_prov(
189241
190242 # high-level assignment
191243
244+ def has_cast () -> bool :
245+ return (
246+ astree .has_register_variable_intro (iaddr )
247+ and astree .get_register_variable_intro (iaddr ).has_cast ())
248+
249+ lhs = xd .vrt
250+
192251 if xd .is_ok :
193- lhs = xd .vrt
194- rhs = xd .xrmem
195- xaddr = xd .xaddr
196- hl_lhs = XU .xvariable_to_ast_lval (lhs , xdata , iaddr , astree , rhs = rhs )
197- hl_rhs = XU .xxpr_to_ast_def_expr (
198- rhs , xdata , iaddr , astree , memaddr = xaddr , size = 2 )
252+ rhs = xd .cxrmem
253+ rhsval = None if has_cast () else xd .cxrmem
254+ hl_lhs = XU .xvariable_to_ast_lval (
255+ lhs , xdata , iaddr , astree , rhs = rhsval )
256+ hl_rhs = XU .xxpr_to_ast_def_expr (rhs , xdata , iaddr , astree )
257+
258+ elif xd .is_cxaddr_ok :
259+ cxaddr = xd .cxaddr
260+ hl_lhs = XU .xvariable_to_ast_lval (lhs , xdata , iaddr , astree )
261+ hl_rhs = XU .xmemory_dereference_lval_expr (
262+ cxaddr , xdata , iaddr , astree )
199263
200- elif xd .is_xrmem_unknown and xd . is_address_known :
264+ elif xd .is_xaddr_ok :
201265 xaddr = xd .xaddr
202- lhs = xd .vrt
203266 hl_lhs = XU .xvariable_to_ast_lval (lhs , xdata , iaddr , astree )
204267 hl_rhs = XU .xmemory_dereference_lval_expr (
205- xaddr , xdata , iaddr , astree , size = 2 )
268+ xaddr , xdata , iaddr , astree )
269+
270+ chklogger .logger .warning (
271+ "LDRH: Unable to use a C expression for rhs. Fall back to "
272+ + "native byte-based address: %s to form rhs %s at address %s" ,
273+ str (xaddr ), str (hl_rhs ), iaddr )
206274
207275 else :
208276 chklogger .logger .error (
209277 "LDRH: both memory value and address values are error values "
210278 + "at address %s: " , iaddr )
211- return ([], [])
279+ return ([], (ll_pre + [ll_assign ] + ll_post ))
280+
212281
213282 rdefs = xdata .reachingdefs
214283 defuses = xdata .defuses
215284 defuseshigh = xdata .defuseshigh
216285
286+ if has_cast ():
287+ lhstype = hl_lhs .ctype (astree .ctyper )
288+ if lhstype is not None :
289+ hl_rhs = astree .mk_cast_expr (lhstype , hl_rhs )
290+
217291 hl_assign = astree .mk_assign (
218292 hl_lhs ,
219293 hl_rhs ,
220294 iaddr = iaddr ,
221295 bytestring = bytestring ,
222296 annotations = annotations )
223297
298+ if has_cast ():
299+ astree .add_expose_instruction (hl_assign .instrid )
300+
224301 astree .add_instr_mapping (hl_assign , ll_assign )
225302 astree .add_instr_address (hl_assign , [iaddr ])
226303 astree .add_expr_mapping (hl_rhs , ll_rhs )
@@ -245,7 +322,7 @@ def ast_prov(
245322 ll_assigns : List [AST .ASTInstruction ] = [ll_assign , ll_addr_assign ]
246323
247324 basereg = xd .get_base_update_var ()
248- newaddr = xd .get_base_update_xpr ()
325+ newaddr = xd .get_base_update_cxpr ()
249326 hl_addr_lhs = XU .xvariable_to_ast_lval (basereg , xdata , iaddr , astree )
250327 hl_addr_rhs = XU .xxpr_to_ast_def_expr (newaddr , xdata , iaddr , astree )
251328
0 commit comments