|
24 | 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
25 | 25 | # SOFTWARE. |
26 | 26 | # ------------------------------------------------------------------------------ |
| 27 | +import xml.etree.ElementTree as ET |
27 | 28 |
|
28 | 29 | from typing import cast, Dict, List, Optional, Set, TYPE_CHECKING |
29 | 30 |
|
30 | 31 | import chb.bctypes.TypeConstraint as TC |
31 | 32 |
|
| 33 | +import chb.util.fileutil as UF |
| 34 | + |
32 | 35 | if TYPE_CHECKING: |
33 | 36 | from chb.app.AppAccess import AppAccess |
34 | 37 |
|
@@ -231,18 +234,96 @@ def __str__(self) -> str: |
231 | 234 | return "\n".join(lines) |
232 | 235 |
|
233 | 236 |
|
| 237 | +class TypingRule: |
| 238 | + |
| 239 | + def __init__(self, tcstore: "TypeConstraintStore", xr: ET.Element) -> None: |
| 240 | + self._tcstore = tcstore |
| 241 | + self._xr = xr |
| 242 | + |
| 243 | + @property |
| 244 | + def tcstore(self) -> "TypeConstraintStore": |
| 245 | + return self._tcstore |
| 246 | + |
| 247 | + @property |
| 248 | + def app(self) -> "AppAccess": |
| 249 | + return self.tcstore.app |
| 250 | + |
| 251 | + @property |
| 252 | + def iaddr(self) -> str: |
| 253 | + return self._xr.get("loc", "0x0") |
| 254 | + |
| 255 | + @property |
| 256 | + def rulename(self) -> str: |
| 257 | + return self._xr.get("rule", "?") |
| 258 | + |
| 259 | + @property |
| 260 | + def typeconstraint(self) -> TC.TypeConstraint: |
| 261 | + ix = self._xr.get("tc-ix") |
| 262 | + if ix is not None: |
| 263 | + return self.app.tcdictionary.type_constraint(int(ix)) |
| 264 | + else: |
| 265 | + raise UF.CHBError("Type constraint without tc index") |
| 266 | + |
| 267 | + def __str__(self) -> str: |
| 268 | + ix = self._xr.get("tc-ix") |
| 269 | + return self.rulename + " " + str(ix) + ":" + str(self.typeconstraint) |
| 270 | + |
| 271 | + |
234 | 272 | class TypeConstraintStore: |
| 273 | + """Global store for type constraints. |
| 274 | +
|
| 275 | + Note: The use of this object is currently somewhat conflicted. It was |
| 276 | + originally intended for global use, to recover function signatures for |
| 277 | + an entire binary. More recently, however, it has been mainly used to |
| 278 | + perform type construction for all local variables (registers and stack) |
| 279 | + within individual functions to support lifting. This latest use in its |
| 280 | + present form does not scale to an entire binary. For now the scaling |
| 281 | + issue is solved by resetting the store after each function, which |
| 282 | + essentially means that the store, when saved, only holds the constraints |
| 283 | + for a single function (the latest processed). |
| 284 | + """ |
235 | 285 |
|
236 | 286 | def __init__(self, app: "AppAccess") -> None: |
237 | 287 | self._app = app |
238 | 288 | self._constraints: Optional[List[TC.TypeConstraint]] = None |
239 | 289 | self._functionconstraints: Dict[str, FunctionTypeConstraints] = {} |
240 | 290 | self._functionregconstraints: Dict[str, FunctionRegisterConstraints] = {} |
| 291 | + self._rules_applied: Optional[Dict[str, Dict[str, List[TypingRule]]]] = None |
241 | 292 |
|
242 | 293 | @property |
243 | 294 | def app(self) -> "AppAccess": |
244 | 295 | return self._app |
245 | 296 |
|
| 297 | + @property |
| 298 | + def rules_applied(self) -> Dict[str, Dict[str, List[TypingRule]]]: |
| 299 | + if self._rules_applied is None: |
| 300 | + self._rules_applied = {} |
| 301 | + tcstore = UF.get_typeconstraint_store_xnode( |
| 302 | + self.app.path, self.app.filename) |
| 303 | + if tcstore is not None: |
| 304 | + rules = tcstore.find("rules-applied") |
| 305 | + if rules is not None: |
| 306 | + for xf in rules.findall("function"): |
| 307 | + faddr = xf.get("faddr", "0x0") |
| 308 | + self._rules_applied[faddr] = {} |
| 309 | + for xr in xf.findall("rule"): |
| 310 | + rule = TypingRule(self, xr) |
| 311 | + self._rules_applied[faddr].setdefault(rule.iaddr, []) |
| 312 | + self._rules_applied[faddr][rule.iaddr].append(rule) |
| 313 | + |
| 314 | + return self._rules_applied |
| 315 | + |
| 316 | + def rules_applied_to_instruction( |
| 317 | + self, faddr: str, iaddr: str) -> List[TypingRule]: |
| 318 | + result: List[TypingRule] = [] |
| 319 | + if faddr in self.rules_applied: |
| 320 | + if iaddr in self.rules_applied[faddr]: |
| 321 | + for r in self.rules_applied[faddr][iaddr]: |
| 322 | + if r.typeconstraint.is_var_constraint: |
| 323 | + continue |
| 324 | + result.append(r) |
| 325 | + return result |
| 326 | + |
246 | 327 | @property |
247 | 328 | def constraints(self) -> List[TC.TypeConstraint]: |
248 | 329 | if self._constraints is None: |
|
0 commit comments