|
3 | 3 | import sys
|
4 | 4 | import traceback
|
5 | 5 | from enum import Enum
|
6 |
| -from typing import List, Union, NamedTuple |
| 6 | +from typing import List, Union, NamedTuple, Callable |
7 | 7 | import inspect
|
8 | 8 | from collections import OrderedDict
|
9 | 9 | from dataclasses import dataclass, field
|
@@ -323,6 +323,7 @@ def __init__(self, minidump_file, *, trace=False, quiet=False, thread_id=None, d
|
323 | 323 | self.exports = self._all_exports()
|
324 | 324 | self._exception = UnicornExceptionInfo()
|
325 | 325 | self._last_exception: Optional[UnicornExceptionInfo] = None
|
| 326 | + self._exception_hook: Optional[Callable[[ExceptionInfo], Optional[int]]] = None |
326 | 327 | if not self._quiet:
|
327 | 328 | print("Memory map:")
|
328 | 329 | self.print_memory()
|
@@ -912,10 +913,23 @@ def allocate(self, size, page_align=False):
|
912 | 913 | self.memory.commit(self.memory.align_page(ptr), self.memory.align_page(size))
|
913 | 914 | return ptr
|
914 | 915 |
|
| 916 | + def set_exception_hook(self, exception_hook: Optional[Callable[[ExceptionInfo], Optional[int]]]): |
| 917 | + previous_hook = self._exception_hook |
| 918 | + self._exception_hook = exception_hook |
| 919 | + return previous_hook |
| 920 | + |
915 | 921 | def handle_exception(self):
|
916 | 922 | assert not self._exception._handling
|
917 | 923 | self._exception._handling = True
|
918 | 924 |
|
| 925 | + if self._exception_hook is not None: |
| 926 | + hook_result = self._exception_hook(self._exception) |
| 927 | + if hook_result is not None: |
| 928 | + # Clear the pending exception |
| 929 | + self._last_exception = self._exception |
| 930 | + self._exception = UnicornExceptionInfo() |
| 931 | + return hook_result |
| 932 | + |
919 | 933 | if self._exception.type == ExceptionType.ContextSwitch:
|
920 | 934 | self.info(f"context switch, cip: {hex(self.regs.cip)}")
|
921 | 935 | # Clear the pending exception
|
|
0 commit comments