smallworld-re 1.0.3__py3-none-any.whl → 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smallworld/analyses/__init__.py +8 -0
- smallworld/analyses/analysis.py +8 -67
- smallworld/analyses/code_coverage.py +1 -2
- smallworld/analyses/colorizer.py +301 -534
- smallworld/analyses/colorizer_def_use.py +217 -0
- smallworld/analyses/colorizer_summary.py +173 -83
- smallworld/analyses/field_detection/field_analysis.py +7 -8
- smallworld/analyses/field_detection/hints.py +1 -1
- smallworld/analyses/field_detection/malloc.py +2 -2
- smallworld/analyses/trace_execution.py +160 -0
- smallworld/analyses/trace_execution_types.py +42 -0
- smallworld/analyses/unstable/angr/divergence.py +1 -2
- smallworld/analyses/unstable/angr/model.py +5 -6
- smallworld/analyses/unstable/angr_nwbt.py +3 -4
- smallworld/analyses/unstable/code_coverage.py +2 -3
- smallworld/analyses/unstable/code_reachable.py +2 -3
- smallworld/analyses/unstable/control_flow_tracer.py +2 -3
- smallworld/analyses/unstable/pointer_finder.py +2 -3
- smallworld/analyses/unstable/utils/tui.py +71 -0
- smallworld/emulators/__init__.py +3 -1
- smallworld/emulators/angr/angr.py +30 -9
- smallworld/emulators/angr/machdefs/__init__.py +2 -0
- smallworld/emulators/angr/machdefs/aarch64.py +1 -1
- smallworld/emulators/angr/machdefs/amd64.py +0 -4
- smallworld/emulators/angr/machdefs/arm.py +0 -2
- smallworld/emulators/angr/machdefs/i386.py +0 -2
- smallworld/emulators/angr/machdefs/loongarch.py +340 -0
- smallworld/emulators/angr/machdefs/machdef.py +1 -8
- smallworld/emulators/angr/machdefs/mips.py +0 -2
- smallworld/emulators/angr/machdefs/mips64.py +0 -2
- smallworld/emulators/angr/machdefs/ppc.py +1 -2
- smallworld/emulators/angr/machdefs/riscv.py +8 -10
- smallworld/emulators/angr/machdefs/xtensa.py +7 -4
- smallworld/emulators/emulator.py +22 -0
- smallworld/emulators/ghidra/__init__.py +37 -0
- smallworld/emulators/ghidra/ghidra.py +513 -0
- smallworld/emulators/ghidra/machdefs/__init__.py +31 -0
- smallworld/emulators/ghidra/machdefs/aarch64.py +289 -0
- smallworld/emulators/ghidra/machdefs/amd64.py +185 -0
- smallworld/emulators/ghidra/machdefs/arm.py +370 -0
- smallworld/emulators/ghidra/machdefs/i386.py +109 -0
- smallworld/emulators/ghidra/machdefs/loongarch.py +162 -0
- smallworld/emulators/ghidra/machdefs/machdef.py +81 -0
- smallworld/emulators/ghidra/machdefs/mips.py +163 -0
- smallworld/emulators/ghidra/machdefs/mips64.py +186 -0
- smallworld/emulators/ghidra/machdefs/ppc.py +98 -0
- smallworld/emulators/ghidra/machdefs/riscv.py +208 -0
- smallworld/emulators/ghidra/machdefs/xtensa.py +21 -0
- smallworld/emulators/ghidra/typing.py +28 -0
- smallworld/emulators/hookable.py +18 -4
- smallworld/emulators/panda/machdefs/__init__.py +2 -2
- smallworld/emulators/panda/machdefs/aarch64.py +186 -11
- smallworld/emulators/panda/machdefs/amd64.py +103 -11
- smallworld/emulators/panda/machdefs/arm.py +216 -20
- smallworld/emulators/panda/machdefs/i386.py +30 -7
- smallworld/emulators/panda/machdefs/machdef.py +9 -16
- smallworld/emulators/panda/machdefs/mips.py +49 -5
- smallworld/emulators/panda/machdefs/mips64.py +57 -5
- smallworld/emulators/panda/machdefs/ppc.py +38 -13
- smallworld/emulators/panda/panda.py +146 -44
- smallworld/emulators/unicorn/__init__.py +2 -0
- smallworld/emulators/unicorn/machdefs/aarch64.py +253 -264
- smallworld/emulators/unicorn/machdefs/amd64.py +254 -259
- smallworld/emulators/unicorn/machdefs/arm.py +200 -212
- smallworld/emulators/unicorn/machdefs/i386.py +84 -90
- smallworld/emulators/unicorn/machdefs/machdef.py +2 -23
- smallworld/emulators/unicorn/machdefs/mips.py +127 -135
- smallworld/emulators/unicorn/unicorn.py +52 -13
- smallworld/helpers.py +4 -19
- smallworld/hinting/hinting.py +22 -192
- smallworld/hinting/hints.py +50 -18
- smallworld/instructions/bsid.py +8 -8
- smallworld/logging.py +4 -2
- smallworld/platforms/__init__.py +12 -0
- smallworld/platforms/defs/__init__.py +36 -0
- smallworld/platforms/defs/aarch64.py +450 -0
- smallworld/platforms/defs/amd64.py +463 -0
- smallworld/platforms/defs/arm.py +519 -0
- smallworld/platforms/defs/i386.py +258 -0
- smallworld/platforms/defs/loongarch.py +270 -0
- smallworld/platforms/defs/mips.py +321 -0
- smallworld/platforms/defs/mips64.py +313 -0
- smallworld/platforms/defs/platformdef.py +97 -0
- smallworld/platforms/defs/powerpc.py +259 -0
- smallworld/platforms/defs/riscv.py +257 -0
- smallworld/platforms/defs/xtensa.py +96 -0
- smallworld/{platforms.py → platforms/platforms.py} +3 -0
- smallworld/state/cpus/__init__.py +2 -0
- smallworld/state/cpus/aarch64.py +0 -9
- smallworld/state/cpus/amd64.py +6 -28
- smallworld/state/cpus/arm.py +0 -11
- smallworld/state/cpus/cpu.py +0 -11
- smallworld/state/cpus/i386.py +0 -7
- smallworld/state/cpus/loongarch.py +299 -0
- smallworld/state/cpus/mips.py +4 -47
- smallworld/state/cpus/mips64.py +18 -58
- smallworld/state/cpus/powerpc.py +2 -9
- smallworld/state/cpus/riscv.py +1 -11
- smallworld/state/cpus/xtensa.py +0 -5
- smallworld/state/memory/code.py +38 -2
- smallworld/state/memory/elf/__init__.py +5 -1
- smallworld/state/memory/elf/coredump/__init__.py +3 -0
- smallworld/state/memory/elf/coredump/coredump.py +46 -0
- smallworld/state/memory/elf/coredump/prstatus/__init__.py +27 -0
- smallworld/state/memory/elf/coredump/prstatus/aarch64.py +46 -0
- smallworld/state/memory/elf/coredump/prstatus/amd64.py +40 -0
- smallworld/state/memory/elf/coredump/prstatus/arm.py +53 -0
- smallworld/state/memory/elf/coredump/prstatus/i386.py +30 -0
- smallworld/state/memory/elf/coredump/prstatus/mips.py +55 -0
- smallworld/state/memory/elf/coredump/prstatus/mips64.py +57 -0
- smallworld/state/memory/elf/coredump/prstatus/ppc.py +82 -0
- smallworld/state/memory/elf/coredump/prstatus/prstatus.py +129 -0
- smallworld/state/memory/elf/elf.py +211 -57
- smallworld/state/memory/elf/register_state.py +36 -0
- smallworld/state/memory/elf/rela/__init__.py +2 -0
- smallworld/state/memory/elf/rela/aarch64.py +3 -1
- smallworld/state/memory/elf/rela/amd64.py +4 -2
- smallworld/state/memory/elf/rela/arm.py +4 -2
- smallworld/state/memory/elf/rela/i386.py +4 -2
- smallworld/state/memory/elf/rela/loongarch.py +32 -0
- smallworld/state/memory/elf/rela/mips.py +39 -18
- smallworld/state/memory/elf/rela/ppc.py +31 -14
- smallworld/state/memory/elf/structs.py +3 -0
- smallworld/state/memory/heap.py +2 -2
- smallworld/state/memory/memory.py +18 -0
- smallworld/state/memory/pe/__init__.py +3 -0
- smallworld/state/memory/pe/pe.py +361 -0
- smallworld/state/memory/pe/structs.py +60 -0
- smallworld/state/memory/stack/__init__.py +2 -0
- smallworld/state/memory/stack/loongarch.py +26 -0
- smallworld/state/models/__init__.py +29 -2
- smallworld/state/models/aarch64/__init__.py +1 -0
- smallworld/state/models/aarch64/systemv/__init__.py +6 -0
- smallworld/state/models/aarch64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/aarch64/systemv/c99/signal.py +16 -0
- smallworld/state/models/aarch64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/aarch64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/aarch64/systemv/c99/string.py +139 -0
- smallworld/state/models/aarch64/systemv/c99/time.py +61 -0
- smallworld/state/models/aarch64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/aarch64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/aarch64/systemv/posix/signal.py +157 -0
- smallworld/state/models/aarch64/systemv/systemv.py +80 -0
- smallworld/state/models/amd64/__init__.py +1 -0
- smallworld/state/models/amd64/systemv/__init__.py +6 -0
- smallworld/state/models/amd64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/amd64/systemv/c99/signal.py +16 -0
- smallworld/state/models/amd64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/amd64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/amd64/systemv/c99/string.py +139 -0
- smallworld/state/models/amd64/systemv/c99/time.py +61 -0
- smallworld/state/models/amd64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/amd64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/amd64/systemv/posix/signal.py +157 -0
- smallworld/state/models/amd64/systemv/systemv.py +78 -0
- smallworld/state/models/armel/__init__.py +1 -0
- smallworld/state/models/armel/systemv/__init__.py +6 -0
- smallworld/state/models/armel/systemv/c99/__init__.py +12 -0
- smallworld/state/models/armel/systemv/c99/signal.py +16 -0
- smallworld/state/models/armel/systemv/c99/stdio.py +265 -0
- smallworld/state/models/armel/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/armel/systemv/c99/string.py +139 -0
- smallworld/state/models/armel/systemv/c99/time.py +61 -0
- smallworld/state/models/armel/systemv/posix/__init__.py +6 -0
- smallworld/state/models/armel/systemv/posix/libgen.py +16 -0
- smallworld/state/models/armel/systemv/posix/signal.py +157 -0
- smallworld/state/models/armel/systemv/systemv.py +82 -0
- smallworld/state/models/armhf/__init__.py +1 -0
- smallworld/state/models/armhf/systemv/__init__.py +6 -0
- smallworld/state/models/armhf/systemv/c99/__init__.py +12 -0
- smallworld/state/models/armhf/systemv/c99/signal.py +16 -0
- smallworld/state/models/armhf/systemv/c99/stdio.py +265 -0
- smallworld/state/models/armhf/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/armhf/systemv/c99/string.py +139 -0
- smallworld/state/models/armhf/systemv/c99/time.py +61 -0
- smallworld/state/models/armhf/systemv/posix/__init__.py +6 -0
- smallworld/state/models/armhf/systemv/posix/libgen.py +16 -0
- smallworld/state/models/armhf/systemv/posix/signal.py +157 -0
- smallworld/state/models/armhf/systemv/systemv.py +77 -0
- smallworld/state/models/c99/__init__.py +12 -0
- smallworld/state/models/c99/fmt_print.py +915 -0
- smallworld/state/models/c99/fmt_scan.py +864 -0
- smallworld/state/models/c99/math.py +362 -0
- smallworld/state/models/c99/signal.py +71 -0
- smallworld/state/models/c99/stdio.py +1305 -0
- smallworld/state/models/c99/stdlib.py +595 -0
- smallworld/state/models/c99/string.py +674 -0
- smallworld/state/models/c99/time.py +340 -0
- smallworld/state/models/c99/utils.py +89 -0
- smallworld/state/models/cstd.py +759 -0
- smallworld/state/models/errno.py +581 -0
- smallworld/state/models/filedesc.py +515 -0
- smallworld/state/models/i386/__init__.py +1 -0
- smallworld/state/models/i386/systemv/__init__.py +6 -0
- smallworld/state/models/i386/systemv/c99/__init__.py +12 -0
- smallworld/state/models/i386/systemv/c99/signal.py +16 -0
- smallworld/state/models/i386/systemv/c99/stdio.py +265 -0
- smallworld/state/models/i386/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/i386/systemv/c99/string.py +139 -0
- smallworld/state/models/i386/systemv/c99/time.py +61 -0
- smallworld/state/models/i386/systemv/posix/__init__.py +6 -0
- smallworld/state/models/i386/systemv/posix/libgen.py +16 -0
- smallworld/state/models/i386/systemv/posix/signal.py +157 -0
- smallworld/state/models/i386/systemv/systemv.py +71 -0
- smallworld/state/models/loongarch64/__init__.py +1 -0
- smallworld/state/models/loongarch64/systemv/__init__.py +6 -0
- smallworld/state/models/loongarch64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/loongarch64/systemv/c99/signal.py +16 -0
- smallworld/state/models/loongarch64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/loongarch64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/loongarch64/systemv/c99/string.py +139 -0
- smallworld/state/models/loongarch64/systemv/c99/time.py +61 -0
- smallworld/state/models/loongarch64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/loongarch64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/loongarch64/systemv/posix/signal.py +157 -0
- smallworld/state/models/loongarch64/systemv/systemv.py +83 -0
- smallworld/state/models/mips/__init__.py +1 -0
- smallworld/state/models/mips/systemv/__init__.py +6 -0
- smallworld/state/models/mips/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mips/systemv/c99/signal.py +16 -0
- smallworld/state/models/mips/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mips/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mips/systemv/c99/string.py +139 -0
- smallworld/state/models/mips/systemv/c99/time.py +61 -0
- smallworld/state/models/mips/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mips/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mips/systemv/posix/signal.py +157 -0
- smallworld/state/models/mips/systemv/systemv.py +78 -0
- smallworld/state/models/mips64/__init__.py +1 -0
- smallworld/state/models/mips64/systemv/__init__.py +6 -0
- smallworld/state/models/mips64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mips64/systemv/c99/signal.py +16 -0
- smallworld/state/models/mips64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mips64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mips64/systemv/c99/string.py +139 -0
- smallworld/state/models/mips64/systemv/c99/time.py +61 -0
- smallworld/state/models/mips64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mips64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mips64/systemv/posix/signal.py +157 -0
- smallworld/state/models/mips64/systemv/systemv.py +98 -0
- smallworld/state/models/mips64el/__init__.py +1 -0
- smallworld/state/models/mips64el/systemv/__init__.py +6 -0
- smallworld/state/models/mips64el/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mips64el/systemv/c99/signal.py +16 -0
- smallworld/state/models/mips64el/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mips64el/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mips64el/systemv/c99/string.py +139 -0
- smallworld/state/models/mips64el/systemv/c99/time.py +61 -0
- smallworld/state/models/mips64el/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mips64el/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mips64el/systemv/posix/signal.py +157 -0
- smallworld/state/models/mips64el/systemv/systemv.py +96 -0
- smallworld/state/models/mipsel/__init__.py +1 -0
- smallworld/state/models/mipsel/systemv/__init__.py +6 -0
- smallworld/state/models/mipsel/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mipsel/systemv/c99/signal.py +16 -0
- smallworld/state/models/mipsel/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mipsel/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mipsel/systemv/c99/string.py +139 -0
- smallworld/state/models/mipsel/systemv/c99/time.py +61 -0
- smallworld/state/models/mipsel/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mipsel/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mipsel/systemv/posix/signal.py +157 -0
- smallworld/state/models/mipsel/systemv/systemv.py +78 -0
- smallworld/state/models/model.py +27 -2
- smallworld/state/models/posix/__init__.py +6 -0
- smallworld/state/models/posix/libgen.py +123 -0
- smallworld/state/models/posix/signal.py +690 -0
- smallworld/state/models/powerpc/__init__.py +1 -0
- smallworld/state/models/powerpc/systemv/__init__.py +6 -0
- smallworld/state/models/powerpc/systemv/c99/__init__.py +12 -0
- smallworld/state/models/powerpc/systemv/c99/signal.py +16 -0
- smallworld/state/models/powerpc/systemv/c99/stdio.py +265 -0
- smallworld/state/models/powerpc/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/powerpc/systemv/c99/string.py +139 -0
- smallworld/state/models/powerpc/systemv/c99/time.py +61 -0
- smallworld/state/models/powerpc/systemv/posix/__init__.py +6 -0
- smallworld/state/models/powerpc/systemv/posix/libgen.py +16 -0
- smallworld/state/models/powerpc/systemv/posix/signal.py +157 -0
- smallworld/state/models/powerpc/systemv/systemv.py +93 -0
- smallworld/state/models/riscv64/__init__.py +1 -0
- smallworld/state/models/riscv64/systemv/__init__.py +6 -0
- smallworld/state/models/riscv64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/riscv64/systemv/c99/signal.py +16 -0
- smallworld/state/models/riscv64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/riscv64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/riscv64/systemv/c99/string.py +139 -0
- smallworld/state/models/riscv64/systemv/c99/time.py +61 -0
- smallworld/state/models/riscv64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/riscv64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/riscv64/systemv/posix/signal.py +157 -0
- smallworld/state/models/riscv64/systemv/systemv.py +85 -0
- smallworld/state/state.py +65 -24
- smallworld/state/unstable/elf.py +16 -31
- smallworld/utils.py +6 -1
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/METADATA +74 -42
- smallworld_re-2.0.0.dist-info/RECORD +374 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/WHEEL +1 -1
- smallworld/state/models/x86/__init__.py +0 -2
- smallworld/state/models/x86/microsoftcdecl.py +0 -35
- smallworld/state/models/x86/systemv.py +0 -240
- smallworld_re-1.0.3.dist-info/RECORD +0 -166
- /smallworld/state/models/{posix.py → _posix.py} +0 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/entry_points.txt +0 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/licenses/LICENSE.txt +0 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/top_level.txt +0 -0
@@ -68,6 +68,7 @@ class PandaEmulator(
|
|
68
68
|
def __init__(self, manager, thread_state):
|
69
69
|
super().__init__(daemon=True)
|
70
70
|
self.manager = manager
|
71
|
+
self.platdef = platforms.PlatformDef.for_platform(self.manager.platform)
|
71
72
|
self.machdef = PandaMachineDef.for_platform(self.manager.platform)
|
72
73
|
self.state = thread_state
|
73
74
|
self.panda = None
|
@@ -104,7 +105,7 @@ class PandaEmulator(
|
|
104
105
|
|
105
106
|
@self.panda.cb_after_machine_init
|
106
107
|
def setup(cpu):
|
107
|
-
|
108
|
+
logger.debug("Panda: setting up state")
|
108
109
|
self.setup_state(cpu)
|
109
110
|
self.signal_and_wait()
|
110
111
|
|
@@ -122,27 +123,27 @@ class PandaEmulator(
|
|
122
123
|
|
123
124
|
if pc in self.manager._exit_points:
|
124
125
|
# stay here until i say die
|
125
|
-
|
126
|
+
logger.debug("\ton_insn: exit")
|
126
127
|
self.state = PandaEmulator.ThreadState.EXIT
|
127
128
|
self.signal_and_wait()
|
128
129
|
elif self.state == PandaEmulator.ThreadState.RUN:
|
129
130
|
# keep going until the end
|
130
|
-
|
131
|
+
logger.debug("\ton_insn: run")
|
131
132
|
elif self.state == PandaEmulator.ThreadState.STEP:
|
132
133
|
# stop and wait for me
|
133
|
-
|
134
|
+
logger.debug("\ton_insn: step")
|
134
135
|
self.signal_and_wait()
|
135
136
|
elif self.state == PandaEmulator.ThreadState.BLOCK:
|
136
137
|
# keep going until the end
|
137
|
-
|
138
|
+
logger.debug("\ton_insn: block")
|
138
139
|
|
139
|
-
|
140
|
+
logger.debug(f"Panda: on_insn: {hex(pc)}, {self.state}")
|
140
141
|
# Check if our pc is in bounds; if not stop
|
141
142
|
if (
|
142
143
|
not self.manager._bounds.is_empty()
|
143
144
|
and not self.manager._bounds.contains_value(pc)
|
144
145
|
):
|
145
|
-
|
146
|
+
logger.debug(f"Panda: {pc} out of bounds")
|
146
147
|
self.state = PandaEmulator.ThreadState.EXIT
|
147
148
|
self.signal_and_wait()
|
148
149
|
|
@@ -151,10 +152,31 @@ class PandaEmulator(
|
|
151
152
|
self.manager.all_instructions_hook(self.manager)
|
152
153
|
|
153
154
|
if cb := self.manager.is_instruction_hooked(pc):
|
154
|
-
|
155
|
+
try:
|
156
|
+
cb(self.manager)
|
157
|
+
except exceptions.EmulationStop:
|
158
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
159
|
+
self.signal_and_wait()
|
160
|
+
except Exception as e:
|
161
|
+
logger.exception(
|
162
|
+
f"Exception running instruction hook at {pc:x}"
|
163
|
+
)
|
164
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
165
|
+
self.signal_and_wait(exception=e)
|
155
166
|
|
156
167
|
if cb := self.manager.is_function_hooked(pc):
|
157
|
-
|
168
|
+
try:
|
169
|
+
logger.info(f"Calling function callback at {hex(pc)}")
|
170
|
+
cb(self.manager)
|
171
|
+
logger.info(f"Completed function callback at {hex(pc)}")
|
172
|
+
except exceptions.EmulationStop:
|
173
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
174
|
+
self.signal_and_wait()
|
175
|
+
except Exception as e:
|
176
|
+
logger.exception(f"Exception running function hook at {pc:x}")
|
177
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
178
|
+
self.signal_and_wait(exception=e)
|
179
|
+
|
158
180
|
# Mimic a platform-specific "return" instruction.
|
159
181
|
if (
|
160
182
|
self.manager.platform.architecture
|
@@ -209,9 +231,11 @@ class PandaEmulator(
|
|
209
231
|
# mips32 and mips64: branch to register 'ra'
|
210
232
|
ret = self.manager.read_register("ra")
|
211
233
|
else:
|
212
|
-
|
234
|
+
logger.error(
|
213
235
|
"Don't know how to return for {self.manager.platform.architecture}"
|
214
236
|
)
|
237
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
238
|
+
self.signal_and_wait()
|
215
239
|
|
216
240
|
self.manager.write_register("pc", ret)
|
217
241
|
|
@@ -227,7 +251,7 @@ class PandaEmulator(
|
|
227
251
|
if not self.manager.current_instruction():
|
228
252
|
# report error if function hooking is enabled?
|
229
253
|
pass
|
230
|
-
|
254
|
+
logger.debug(f"\t{self.manager.current_instruction()}")
|
231
255
|
self.hook_return = pc + self.manager.current_instruction().size
|
232
256
|
|
233
257
|
return True
|
@@ -240,63 +264,100 @@ class PandaEmulator(
|
|
240
264
|
self.state == PandaEmulator.ThreadState.BLOCK
|
241
265
|
or self.state == PandaEmulator.ThreadState.SETUP
|
242
266
|
):
|
243
|
-
|
267
|
+
logger.debug(f"Panda: on_block: {tb}, {self.state}")
|
244
268
|
# We need to pause on the next block and wait
|
245
269
|
self.signal_and_wait()
|
246
270
|
|
247
271
|
# Used for hooking mem reads
|
248
272
|
@self.panda.cb_virt_mem_before_read(enabled=True)
|
249
273
|
def on_read(cpu, pc, addr, size):
|
250
|
-
|
274
|
+
logger.debug(f"\ton_read: {addr}")
|
251
275
|
orig_data = self.panda.virtual_memory_read(self.manager.cpu, addr, size)
|
252
|
-
|
253
|
-
|
254
|
-
self.manager
|
276
|
+
try:
|
277
|
+
if self.manager.all_reads_hook:
|
278
|
+
val = self.manager.all_reads_hook(
|
279
|
+
self.manager, addr, size, orig_data
|
280
|
+
)
|
281
|
+
if val:
|
282
|
+
self.manager.write_memory(addr, val)
|
283
|
+
orig_data = val
|
284
|
+
if cb := self.manager.is_memory_read_hooked(addr, size):
|
285
|
+
val = cb(self.manager, addr, size, orig_data)
|
286
|
+
if val:
|
287
|
+
self.manager.write_memory(addr, val)
|
288
|
+
except exceptions.EmulationStop:
|
289
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
290
|
+
self.signal_and_wait()
|
291
|
+
except Exception as e:
|
292
|
+
logger.exception(
|
293
|
+
"Exception running read hook at {pc:x}, from {addr:x}"
|
255
294
|
)
|
256
|
-
|
257
|
-
|
258
|
-
orig_data = val
|
259
|
-
if cb := self.manager.is_memory_read_hooked(addr):
|
260
|
-
val = cb(self.manager, addr, size, orig_data)
|
261
|
-
if val:
|
262
|
-
self.manager.write_memory(addr, val)
|
295
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
296
|
+
self.signal_and_wait(exception=e)
|
263
297
|
|
264
298
|
# Used for hooking mem writes
|
265
299
|
@self.panda.cb_virt_mem_before_write(enabled=True)
|
266
300
|
def on_write(cpu, pc, addr, size, buf):
|
267
|
-
|
301
|
+
logger.debug(f"\ton_write: {hex(addr)}")
|
268
302
|
byte_val = bytes([buf[i] for i in range(size)])
|
303
|
+
try:
|
304
|
+
if self.manager.all_writes_hook:
|
305
|
+
self.manager.all_writes_hook(self.manager, addr, size, byte_val)
|
269
306
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
307
|
+
if cb := self.manager.is_memory_write_hooked(addr, size):
|
308
|
+
cb(self.manager, addr, size, byte_val)
|
309
|
+
except exceptions.EmulationStop:
|
310
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
311
|
+
self.signal_and_wait()
|
312
|
+
except Exception as e:
|
313
|
+
logger.exception(
|
314
|
+
"Exception running read hook at {pc:x}, from {addr:x}"
|
315
|
+
)
|
316
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
317
|
+
self.signal_and_wait(exception=e)
|
275
318
|
|
276
319
|
@self.panda.cb_before_handle_interrupt(enabled=True)
|
277
320
|
def on_interrupt(cpu, intno):
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
self.manager.all_interrupts_hook
|
282
|
-
|
283
|
-
|
284
|
-
cb
|
321
|
+
logger.debug(f"\ton_interrupt: {intno}")
|
322
|
+
try:
|
323
|
+
# First if all interrupts are hooked, run that function
|
324
|
+
if self.manager.all_interrupts_hook:
|
325
|
+
self.manager.all_interrupts_hook(self.manager)
|
326
|
+
# Then run interrupt specific function
|
327
|
+
if cb := self.manager.is_interrupt_hooked(intno):
|
328
|
+
cb(self.manager)
|
329
|
+
except exceptions.EmulationStop:
|
330
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
331
|
+
self.signal_and_wait()
|
332
|
+
except Exception as e:
|
333
|
+
logger.exception("Exception running interrupt hook for {intno}")
|
334
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
335
|
+
self.signal_and_wait(exception=e)
|
285
336
|
|
286
337
|
@self.panda.cb_before_handle_exception(enabled=True)
|
287
338
|
def on_exception(cpu, exception_index):
|
288
|
-
|
339
|
+
logger.error(
|
289
340
|
f"Panda for help: you are hitting an exception at {exception_index}."
|
290
341
|
)
|
342
|
+
self.state = PandaEmulator.ThreadState.EXIT
|
343
|
+
# Generate an exception so we exit ungracefully
|
344
|
+
try:
|
345
|
+
raise exceptions.EmulationError(
|
346
|
+
f"Panda exception {exception_index}"
|
347
|
+
)
|
348
|
+
except exceptions.EmulationError as e:
|
349
|
+
self.signal_and_wait(exception=e)
|
291
350
|
|
292
351
|
self.panda.run()
|
293
352
|
|
294
353
|
# This is a blocking call for this thread
|
295
|
-
def signal_and_wait(self):
|
296
|
-
|
354
|
+
def signal_and_wait(self, exception: typing.Optional[Exception] = None):
|
355
|
+
logger.debug("Signaling main to run")
|
297
356
|
with self.manager.condition:
|
298
|
-
#
|
357
|
+
# Save an exception if someone wanted to raise one
|
358
|
+
self.manager.exception = exception
|
299
359
|
|
360
|
+
# Signal that we are done and to run main
|
300
361
|
self.manager.run_main = True
|
301
362
|
self.manager.condition.notify()
|
302
363
|
|
@@ -320,6 +381,7 @@ class PandaEmulator(
|
|
320
381
|
self.condition = threading.Condition()
|
321
382
|
self.run_panda = False
|
322
383
|
self.run_main = False
|
384
|
+
self.exception: typing.Optional[Exception] = None
|
323
385
|
|
324
386
|
# Thread communication variables
|
325
387
|
self.cpu = None
|
@@ -329,7 +391,8 @@ class PandaEmulator(
|
|
329
391
|
self.panda_thread.start()
|
330
392
|
|
331
393
|
self.disassembler = capstone.Cs(
|
332
|
-
self.panda_thread.
|
394
|
+
self.panda_thread.platdef.capstone_arch,
|
395
|
+
self.panda_thread.platdef.capstone_mode,
|
333
396
|
)
|
334
397
|
self.disassembler.detail = True
|
335
398
|
|
@@ -463,7 +526,42 @@ class PandaEmulator(
|
|
463
526
|
logger.error("This strays into reserved MMIO memory; please don't.")
|
464
527
|
raise exceptions.EmulationError("Write to MIPS64 MMIO space")
|
465
528
|
|
466
|
-
self.panda_thread.panda.physical_memory_write(address, content)
|
529
|
+
# self.panda_thread.panda.physical_memory_write(address, content)
|
530
|
+
|
531
|
+
# NOTE: Panda does not handle writing across segment boundaries gracefully
|
532
|
+
#
|
533
|
+
# If you map 0x1000 - 0x2000, and then map 0x2000 - 0x3000,
|
534
|
+
# writing to 0x1000 - 0x3000 will probably segfault the emulator.
|
535
|
+
#
|
536
|
+
# This is because QEMU may put adjacent guest memory segments
|
537
|
+
# in non-adjacent host memory.
|
538
|
+
# Panda only performs the guest-to-host address translation
|
539
|
+
# on the initial address; it doesn't check
|
540
|
+
# that all requested blocks are in the same segment.
|
541
|
+
|
542
|
+
offset = 0
|
543
|
+
size = len(content)
|
544
|
+
|
545
|
+
# NOTE: This algorithm takes advantage of the fact that Python slices
|
546
|
+
# can return fewer than the requested number of bytes if the upper bound
|
547
|
+
# is past the end of the list being sliced.
|
548
|
+
if address % self.PAGE_SIZE != 0:
|
549
|
+
block_size = address % self.PAGE_SIZE
|
550
|
+
self.panda_thread.panda.physical_memory_write(
|
551
|
+
address, content[0:block_size]
|
552
|
+
)
|
553
|
+
|
554
|
+
offset += block_size
|
555
|
+
size -= block_size
|
556
|
+
|
557
|
+
while size > 0:
|
558
|
+
block_address = address + offset
|
559
|
+
self.panda_thread.panda.physical_memory_write(
|
560
|
+
block_address, content[offset : offset + self.PAGE_SIZE]
|
561
|
+
)
|
562
|
+
|
563
|
+
offset += self.PAGE_SIZE
|
564
|
+
size -= self.PAGE_SIZE
|
467
565
|
|
468
566
|
logger.debug(f"wrote {len(content)} bytes to 0x{address:x}")
|
469
567
|
|
@@ -514,7 +612,7 @@ class PandaEmulator(
|
|
514
612
|
logger.info("emulation complete")
|
515
613
|
|
516
614
|
def signal_and_wait(self) -> None:
|
517
|
-
|
615
|
+
logger.debug("Main signaling panda to run")
|
518
616
|
with self.condition:
|
519
617
|
# Signal that we are done and to run panda
|
520
618
|
self.run_panda = True
|
@@ -527,6 +625,10 @@ class PandaEmulator(
|
|
527
625
|
# Clear the event for the next iteration
|
528
626
|
self.run_main = False
|
529
627
|
|
628
|
+
# If we had an exception, raise it
|
629
|
+
if self.exception is not None:
|
630
|
+
raise self.exception
|
631
|
+
|
530
632
|
def step_block(self) -> None:
|
531
633
|
self.check()
|
532
634
|
if self.panda_thread.state == self.ThreadState.SETUP:
|
@@ -558,7 +660,7 @@ class PandaEmulator(
|
|
558
660
|
self.panda_thread.state = self.ThreadState.STEP
|
559
661
|
|
560
662
|
pc = self.pc
|
561
|
-
|
663
|
+
logger.debug(f"Step: reading register {pc}")
|
562
664
|
|
563
665
|
code = self.read_memory(pc, 15) # longest possible instruction
|
564
666
|
if code is None:
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from .unicorn import (
|
2
|
+
UnicornEmulationError,
|
2
3
|
UnicornEmulationExecutionError,
|
3
4
|
UnicornEmulationMemoryReadError,
|
4
5
|
UnicornEmulationMemoryWriteError,
|
@@ -7,6 +8,7 @@ from .unicorn import (
|
|
7
8
|
|
8
9
|
__all__ = [
|
9
10
|
"UnicornEmulator",
|
11
|
+
"UnicornEmulationError",
|
10
12
|
"UnicornEmulationMemoryReadError",
|
11
13
|
"UnicornEmulationMemoryWriteError",
|
12
14
|
"UnicornEmulationExecutionError",
|