smallworld-re 1.0.2__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.
Files changed (306) hide show
  1. smallworld/analyses/__init__.py +8 -0
  2. smallworld/analyses/analysis.py +8 -67
  3. smallworld/analyses/code_coverage.py +1 -2
  4. smallworld/analyses/colorizer.py +301 -534
  5. smallworld/analyses/colorizer_def_use.py +217 -0
  6. smallworld/analyses/colorizer_summary.py +173 -83
  7. smallworld/analyses/field_detection/field_analysis.py +7 -8
  8. smallworld/analyses/field_detection/hints.py +1 -1
  9. smallworld/analyses/field_detection/malloc.py +2 -2
  10. smallworld/analyses/trace_execution.py +160 -0
  11. smallworld/analyses/trace_execution_types.py +42 -0
  12. smallworld/analyses/unstable/angr/divergence.py +1 -2
  13. smallworld/analyses/unstable/angr/model.py +5 -6
  14. smallworld/analyses/unstable/angr_nwbt.py +3 -4
  15. smallworld/analyses/unstable/code_coverage.py +2 -3
  16. smallworld/analyses/unstable/code_reachable.py +2 -3
  17. smallworld/analyses/unstable/control_flow_tracer.py +2 -3
  18. smallworld/analyses/unstable/pointer_finder.py +2 -3
  19. smallworld/analyses/unstable/utils/tui.py +71 -0
  20. smallworld/emulators/__init__.py +3 -1
  21. smallworld/emulators/angr/angr.py +30 -9
  22. smallworld/emulators/angr/machdefs/__init__.py +2 -0
  23. smallworld/emulators/angr/machdefs/aarch64.py +1 -1
  24. smallworld/emulators/angr/machdefs/amd64.py +0 -4
  25. smallworld/emulators/angr/machdefs/arm.py +0 -2
  26. smallworld/emulators/angr/machdefs/i386.py +0 -2
  27. smallworld/emulators/angr/machdefs/loongarch.py +340 -0
  28. smallworld/emulators/angr/machdefs/machdef.py +1 -8
  29. smallworld/emulators/angr/machdefs/mips.py +0 -2
  30. smallworld/emulators/angr/machdefs/mips64.py +0 -2
  31. smallworld/emulators/angr/machdefs/ppc.py +1 -2
  32. smallworld/emulators/angr/machdefs/riscv.py +8 -10
  33. smallworld/emulators/angr/machdefs/xtensa.py +7 -4
  34. smallworld/emulators/emulator.py +22 -0
  35. smallworld/emulators/ghidra/__init__.py +37 -0
  36. smallworld/emulators/ghidra/ghidra.py +513 -0
  37. smallworld/emulators/ghidra/machdefs/__init__.py +31 -0
  38. smallworld/emulators/ghidra/machdefs/aarch64.py +289 -0
  39. smallworld/emulators/ghidra/machdefs/amd64.py +185 -0
  40. smallworld/emulators/ghidra/machdefs/arm.py +370 -0
  41. smallworld/emulators/ghidra/machdefs/i386.py +109 -0
  42. smallworld/emulators/ghidra/machdefs/loongarch.py +162 -0
  43. smallworld/emulators/ghidra/machdefs/machdef.py +81 -0
  44. smallworld/emulators/ghidra/machdefs/mips.py +163 -0
  45. smallworld/emulators/ghidra/machdefs/mips64.py +186 -0
  46. smallworld/emulators/ghidra/machdefs/ppc.py +98 -0
  47. smallworld/emulators/ghidra/machdefs/riscv.py +208 -0
  48. smallworld/emulators/ghidra/machdefs/xtensa.py +21 -0
  49. smallworld/emulators/ghidra/typing.py +28 -0
  50. smallworld/emulators/hookable.py +18 -4
  51. smallworld/emulators/panda/machdefs/__init__.py +2 -2
  52. smallworld/emulators/panda/machdefs/aarch64.py +186 -11
  53. smallworld/emulators/panda/machdefs/amd64.py +103 -11
  54. smallworld/emulators/panda/machdefs/arm.py +216 -20
  55. smallworld/emulators/panda/machdefs/i386.py +30 -7
  56. smallworld/emulators/panda/machdefs/machdef.py +9 -16
  57. smallworld/emulators/panda/machdefs/mips.py +49 -5
  58. smallworld/emulators/panda/machdefs/mips64.py +57 -5
  59. smallworld/emulators/panda/machdefs/ppc.py +38 -13
  60. smallworld/emulators/panda/panda.py +146 -44
  61. smallworld/emulators/unicorn/__init__.py +2 -0
  62. smallworld/emulators/unicorn/machdefs/aarch64.py +253 -264
  63. smallworld/emulators/unicorn/machdefs/amd64.py +254 -259
  64. smallworld/emulators/unicorn/machdefs/arm.py +200 -212
  65. smallworld/emulators/unicorn/machdefs/i386.py +84 -90
  66. smallworld/emulators/unicorn/machdefs/machdef.py +2 -23
  67. smallworld/emulators/unicorn/machdefs/mips.py +127 -135
  68. smallworld/emulators/unicorn/unicorn.py +52 -13
  69. smallworld/helpers.py +4 -19
  70. smallworld/hinting/hinting.py +22 -192
  71. smallworld/hinting/hints.py +50 -18
  72. smallworld/instructions/bsid.py +8 -8
  73. smallworld/logging.py +4 -2
  74. smallworld/platforms/__init__.py +12 -0
  75. smallworld/platforms/defs/__init__.py +36 -0
  76. smallworld/platforms/defs/aarch64.py +450 -0
  77. smallworld/platforms/defs/amd64.py +463 -0
  78. smallworld/platforms/defs/arm.py +519 -0
  79. smallworld/platforms/defs/i386.py +258 -0
  80. smallworld/platforms/defs/loongarch.py +270 -0
  81. smallworld/platforms/defs/mips.py +321 -0
  82. smallworld/platforms/defs/mips64.py +313 -0
  83. smallworld/platforms/defs/platformdef.py +97 -0
  84. smallworld/platforms/defs/powerpc.py +259 -0
  85. smallworld/platforms/defs/riscv.py +257 -0
  86. smallworld/platforms/defs/xtensa.py +96 -0
  87. smallworld/{platforms.py → platforms/platforms.py} +3 -0
  88. smallworld/state/cpus/__init__.py +2 -0
  89. smallworld/state/cpus/aarch64.py +0 -9
  90. smallworld/state/cpus/amd64.py +6 -28
  91. smallworld/state/cpus/arm.py +0 -11
  92. smallworld/state/cpus/cpu.py +0 -11
  93. smallworld/state/cpus/i386.py +0 -7
  94. smallworld/state/cpus/loongarch.py +299 -0
  95. smallworld/state/cpus/mips.py +4 -47
  96. smallworld/state/cpus/mips64.py +18 -58
  97. smallworld/state/cpus/powerpc.py +2 -9
  98. smallworld/state/cpus/riscv.py +1 -11
  99. smallworld/state/cpus/xtensa.py +0 -5
  100. smallworld/state/memory/code.py +44 -2
  101. smallworld/state/memory/elf/__init__.py +5 -1
  102. smallworld/state/memory/elf/coredump/__init__.py +3 -0
  103. smallworld/state/memory/elf/coredump/coredump.py +46 -0
  104. smallworld/state/memory/elf/coredump/prstatus/__init__.py +27 -0
  105. smallworld/state/memory/elf/coredump/prstatus/aarch64.py +46 -0
  106. smallworld/state/memory/elf/coredump/prstatus/amd64.py +40 -0
  107. smallworld/state/memory/elf/coredump/prstatus/arm.py +53 -0
  108. smallworld/state/memory/elf/coredump/prstatus/i386.py +30 -0
  109. smallworld/state/memory/elf/coredump/prstatus/mips.py +55 -0
  110. smallworld/state/memory/elf/coredump/prstatus/mips64.py +57 -0
  111. smallworld/state/memory/elf/coredump/prstatus/ppc.py +82 -0
  112. smallworld/state/memory/elf/coredump/prstatus/prstatus.py +129 -0
  113. smallworld/state/memory/elf/elf.py +225 -61
  114. smallworld/state/memory/elf/register_state.py +36 -0
  115. smallworld/state/memory/elf/rela/__init__.py +2 -0
  116. smallworld/state/memory/elf/rela/aarch64.py +3 -1
  117. smallworld/state/memory/elf/rela/amd64.py +4 -2
  118. smallworld/state/memory/elf/rela/arm.py +4 -2
  119. smallworld/state/memory/elf/rela/i386.py +4 -2
  120. smallworld/state/memory/elf/rela/loongarch.py +32 -0
  121. smallworld/state/memory/elf/rela/mips.py +39 -18
  122. smallworld/state/memory/elf/rela/ppc.py +31 -14
  123. smallworld/state/memory/elf/structs.py +3 -0
  124. smallworld/state/memory/heap.py +2 -2
  125. smallworld/state/memory/memory.py +18 -0
  126. smallworld/state/memory/pe/__init__.py +3 -0
  127. smallworld/state/memory/pe/pe.py +361 -0
  128. smallworld/state/memory/pe/structs.py +60 -0
  129. smallworld/state/memory/stack/__init__.py +2 -0
  130. smallworld/state/memory/stack/loongarch.py +26 -0
  131. smallworld/state/models/__init__.py +29 -2
  132. smallworld/state/models/aarch64/__init__.py +1 -0
  133. smallworld/state/models/aarch64/systemv/__init__.py +6 -0
  134. smallworld/state/models/aarch64/systemv/c99/__init__.py +12 -0
  135. smallworld/state/models/aarch64/systemv/c99/signal.py +16 -0
  136. smallworld/state/models/aarch64/systemv/c99/stdio.py +265 -0
  137. smallworld/state/models/aarch64/systemv/c99/stdlib.py +169 -0
  138. smallworld/state/models/aarch64/systemv/c99/string.py +139 -0
  139. smallworld/state/models/aarch64/systemv/c99/time.py +61 -0
  140. smallworld/state/models/aarch64/systemv/posix/__init__.py +6 -0
  141. smallworld/state/models/aarch64/systemv/posix/libgen.py +16 -0
  142. smallworld/state/models/aarch64/systemv/posix/signal.py +157 -0
  143. smallworld/state/models/aarch64/systemv/systemv.py +80 -0
  144. smallworld/state/models/amd64/__init__.py +1 -0
  145. smallworld/state/models/amd64/systemv/__init__.py +6 -0
  146. smallworld/state/models/amd64/systemv/c99/__init__.py +12 -0
  147. smallworld/state/models/amd64/systemv/c99/signal.py +16 -0
  148. smallworld/state/models/amd64/systemv/c99/stdio.py +265 -0
  149. smallworld/state/models/amd64/systemv/c99/stdlib.py +169 -0
  150. smallworld/state/models/amd64/systemv/c99/string.py +139 -0
  151. smallworld/state/models/amd64/systemv/c99/time.py +61 -0
  152. smallworld/state/models/amd64/systemv/posix/__init__.py +6 -0
  153. smallworld/state/models/amd64/systemv/posix/libgen.py +16 -0
  154. smallworld/state/models/amd64/systemv/posix/signal.py +157 -0
  155. smallworld/state/models/amd64/systemv/systemv.py +78 -0
  156. smallworld/state/models/armel/__init__.py +1 -0
  157. smallworld/state/models/armel/systemv/__init__.py +6 -0
  158. smallworld/state/models/armel/systemv/c99/__init__.py +12 -0
  159. smallworld/state/models/armel/systemv/c99/signal.py +16 -0
  160. smallworld/state/models/armel/systemv/c99/stdio.py +265 -0
  161. smallworld/state/models/armel/systemv/c99/stdlib.py +169 -0
  162. smallworld/state/models/armel/systemv/c99/string.py +139 -0
  163. smallworld/state/models/armel/systemv/c99/time.py +61 -0
  164. smallworld/state/models/armel/systemv/posix/__init__.py +6 -0
  165. smallworld/state/models/armel/systemv/posix/libgen.py +16 -0
  166. smallworld/state/models/armel/systemv/posix/signal.py +157 -0
  167. smallworld/state/models/armel/systemv/systemv.py +82 -0
  168. smallworld/state/models/armhf/__init__.py +1 -0
  169. smallworld/state/models/armhf/systemv/__init__.py +6 -0
  170. smallworld/state/models/armhf/systemv/c99/__init__.py +12 -0
  171. smallworld/state/models/armhf/systemv/c99/signal.py +16 -0
  172. smallworld/state/models/armhf/systemv/c99/stdio.py +265 -0
  173. smallworld/state/models/armhf/systemv/c99/stdlib.py +169 -0
  174. smallworld/state/models/armhf/systemv/c99/string.py +139 -0
  175. smallworld/state/models/armhf/systemv/c99/time.py +61 -0
  176. smallworld/state/models/armhf/systemv/posix/__init__.py +6 -0
  177. smallworld/state/models/armhf/systemv/posix/libgen.py +16 -0
  178. smallworld/state/models/armhf/systemv/posix/signal.py +157 -0
  179. smallworld/state/models/armhf/systemv/systemv.py +77 -0
  180. smallworld/state/models/c99/__init__.py +12 -0
  181. smallworld/state/models/c99/fmt_print.py +915 -0
  182. smallworld/state/models/c99/fmt_scan.py +864 -0
  183. smallworld/state/models/c99/math.py +362 -0
  184. smallworld/state/models/c99/signal.py +71 -0
  185. smallworld/state/models/c99/stdio.py +1305 -0
  186. smallworld/state/models/c99/stdlib.py +595 -0
  187. smallworld/state/models/c99/string.py +674 -0
  188. smallworld/state/models/c99/time.py +340 -0
  189. smallworld/state/models/c99/utils.py +89 -0
  190. smallworld/state/models/cstd.py +759 -0
  191. smallworld/state/models/errno.py +581 -0
  192. smallworld/state/models/filedesc.py +515 -0
  193. smallworld/state/models/i386/__init__.py +1 -0
  194. smallworld/state/models/i386/systemv/__init__.py +6 -0
  195. smallworld/state/models/i386/systemv/c99/__init__.py +12 -0
  196. smallworld/state/models/i386/systemv/c99/signal.py +16 -0
  197. smallworld/state/models/i386/systemv/c99/stdio.py +265 -0
  198. smallworld/state/models/i386/systemv/c99/stdlib.py +169 -0
  199. smallworld/state/models/i386/systemv/c99/string.py +139 -0
  200. smallworld/state/models/i386/systemv/c99/time.py +61 -0
  201. smallworld/state/models/i386/systemv/posix/__init__.py +6 -0
  202. smallworld/state/models/i386/systemv/posix/libgen.py +16 -0
  203. smallworld/state/models/i386/systemv/posix/signal.py +157 -0
  204. smallworld/state/models/i386/systemv/systemv.py +71 -0
  205. smallworld/state/models/loongarch64/__init__.py +1 -0
  206. smallworld/state/models/loongarch64/systemv/__init__.py +6 -0
  207. smallworld/state/models/loongarch64/systemv/c99/__init__.py +12 -0
  208. smallworld/state/models/loongarch64/systemv/c99/signal.py +16 -0
  209. smallworld/state/models/loongarch64/systemv/c99/stdio.py +265 -0
  210. smallworld/state/models/loongarch64/systemv/c99/stdlib.py +169 -0
  211. smallworld/state/models/loongarch64/systemv/c99/string.py +139 -0
  212. smallworld/state/models/loongarch64/systemv/c99/time.py +61 -0
  213. smallworld/state/models/loongarch64/systemv/posix/__init__.py +6 -0
  214. smallworld/state/models/loongarch64/systemv/posix/libgen.py +16 -0
  215. smallworld/state/models/loongarch64/systemv/posix/signal.py +157 -0
  216. smallworld/state/models/loongarch64/systemv/systemv.py +83 -0
  217. smallworld/state/models/mips/__init__.py +1 -0
  218. smallworld/state/models/mips/systemv/__init__.py +6 -0
  219. smallworld/state/models/mips/systemv/c99/__init__.py +12 -0
  220. smallworld/state/models/mips/systemv/c99/signal.py +16 -0
  221. smallworld/state/models/mips/systemv/c99/stdio.py +265 -0
  222. smallworld/state/models/mips/systemv/c99/stdlib.py +169 -0
  223. smallworld/state/models/mips/systemv/c99/string.py +139 -0
  224. smallworld/state/models/mips/systemv/c99/time.py +61 -0
  225. smallworld/state/models/mips/systemv/posix/__init__.py +6 -0
  226. smallworld/state/models/mips/systemv/posix/libgen.py +16 -0
  227. smallworld/state/models/mips/systemv/posix/signal.py +157 -0
  228. smallworld/state/models/mips/systemv/systemv.py +78 -0
  229. smallworld/state/models/mips64/__init__.py +1 -0
  230. smallworld/state/models/mips64/systemv/__init__.py +6 -0
  231. smallworld/state/models/mips64/systemv/c99/__init__.py +12 -0
  232. smallworld/state/models/mips64/systemv/c99/signal.py +16 -0
  233. smallworld/state/models/mips64/systemv/c99/stdio.py +265 -0
  234. smallworld/state/models/mips64/systemv/c99/stdlib.py +169 -0
  235. smallworld/state/models/mips64/systemv/c99/string.py +139 -0
  236. smallworld/state/models/mips64/systemv/c99/time.py +61 -0
  237. smallworld/state/models/mips64/systemv/posix/__init__.py +6 -0
  238. smallworld/state/models/mips64/systemv/posix/libgen.py +16 -0
  239. smallworld/state/models/mips64/systemv/posix/signal.py +157 -0
  240. smallworld/state/models/mips64/systemv/systemv.py +98 -0
  241. smallworld/state/models/mips64el/__init__.py +1 -0
  242. smallworld/state/models/mips64el/systemv/__init__.py +6 -0
  243. smallworld/state/models/mips64el/systemv/c99/__init__.py +12 -0
  244. smallworld/state/models/mips64el/systemv/c99/signal.py +16 -0
  245. smallworld/state/models/mips64el/systemv/c99/stdio.py +265 -0
  246. smallworld/state/models/mips64el/systemv/c99/stdlib.py +169 -0
  247. smallworld/state/models/mips64el/systemv/c99/string.py +139 -0
  248. smallworld/state/models/mips64el/systemv/c99/time.py +61 -0
  249. smallworld/state/models/mips64el/systemv/posix/__init__.py +6 -0
  250. smallworld/state/models/mips64el/systemv/posix/libgen.py +16 -0
  251. smallworld/state/models/mips64el/systemv/posix/signal.py +157 -0
  252. smallworld/state/models/mips64el/systemv/systemv.py +96 -0
  253. smallworld/state/models/mipsel/__init__.py +1 -0
  254. smallworld/state/models/mipsel/systemv/__init__.py +6 -0
  255. smallworld/state/models/mipsel/systemv/c99/__init__.py +12 -0
  256. smallworld/state/models/mipsel/systemv/c99/signal.py +16 -0
  257. smallworld/state/models/mipsel/systemv/c99/stdio.py +265 -0
  258. smallworld/state/models/mipsel/systemv/c99/stdlib.py +169 -0
  259. smallworld/state/models/mipsel/systemv/c99/string.py +139 -0
  260. smallworld/state/models/mipsel/systemv/c99/time.py +61 -0
  261. smallworld/state/models/mipsel/systemv/posix/__init__.py +6 -0
  262. smallworld/state/models/mipsel/systemv/posix/libgen.py +16 -0
  263. smallworld/state/models/mipsel/systemv/posix/signal.py +157 -0
  264. smallworld/state/models/mipsel/systemv/systemv.py +78 -0
  265. smallworld/state/models/model.py +27 -2
  266. smallworld/state/models/posix/__init__.py +6 -0
  267. smallworld/state/models/posix/libgen.py +123 -0
  268. smallworld/state/models/posix/signal.py +690 -0
  269. smallworld/state/models/powerpc/__init__.py +1 -0
  270. smallworld/state/models/powerpc/systemv/__init__.py +6 -0
  271. smallworld/state/models/powerpc/systemv/c99/__init__.py +12 -0
  272. smallworld/state/models/powerpc/systemv/c99/signal.py +16 -0
  273. smallworld/state/models/powerpc/systemv/c99/stdio.py +265 -0
  274. smallworld/state/models/powerpc/systemv/c99/stdlib.py +169 -0
  275. smallworld/state/models/powerpc/systemv/c99/string.py +139 -0
  276. smallworld/state/models/powerpc/systemv/c99/time.py +61 -0
  277. smallworld/state/models/powerpc/systemv/posix/__init__.py +6 -0
  278. smallworld/state/models/powerpc/systemv/posix/libgen.py +16 -0
  279. smallworld/state/models/powerpc/systemv/posix/signal.py +157 -0
  280. smallworld/state/models/powerpc/systemv/systemv.py +93 -0
  281. smallworld/state/models/riscv64/__init__.py +1 -0
  282. smallworld/state/models/riscv64/systemv/__init__.py +6 -0
  283. smallworld/state/models/riscv64/systemv/c99/__init__.py +12 -0
  284. smallworld/state/models/riscv64/systemv/c99/signal.py +16 -0
  285. smallworld/state/models/riscv64/systemv/c99/stdio.py +265 -0
  286. smallworld/state/models/riscv64/systemv/c99/stdlib.py +169 -0
  287. smallworld/state/models/riscv64/systemv/c99/string.py +139 -0
  288. smallworld/state/models/riscv64/systemv/c99/time.py +61 -0
  289. smallworld/state/models/riscv64/systemv/posix/__init__.py +6 -0
  290. smallworld/state/models/riscv64/systemv/posix/libgen.py +16 -0
  291. smallworld/state/models/riscv64/systemv/posix/signal.py +157 -0
  292. smallworld/state/models/riscv64/systemv/systemv.py +85 -0
  293. smallworld/state/state.py +65 -24
  294. smallworld/state/unstable/elf.py +16 -31
  295. smallworld/utils.py +6 -1
  296. {smallworld_re-1.0.2.dist-info → smallworld_re-2.0.0.dist-info}/METADATA +76 -43
  297. smallworld_re-2.0.0.dist-info/RECORD +374 -0
  298. {smallworld_re-1.0.2.dist-info → smallworld_re-2.0.0.dist-info}/WHEEL +1 -1
  299. smallworld/state/models/x86/__init__.py +0 -2
  300. smallworld/state/models/x86/microsoftcdecl.py +0 -35
  301. smallworld/state/models/x86/systemv.py +0 -240
  302. smallworld_re-1.0.2.dist-info/RECORD +0 -166
  303. /smallworld/state/models/{posix.py → _posix.py} +0 -0
  304. {smallworld_re-1.0.2.dist-info → smallworld_re-2.0.0.dist-info}/entry_points.txt +0 -0
  305. {smallworld_re-1.0.2.dist-info → smallworld_re-2.0.0.dist-info/licenses}/LICENSE.txt +0 -0
  306. {smallworld_re-1.0.2.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
- print("Panda: setting up state")
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
- print("\ton_insn: exit")
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
- print("\ton_insn: run")
131
+ logger.debug("\ton_insn: run")
131
132
  elif self.state == PandaEmulator.ThreadState.STEP:
132
133
  # stop and wait for me
133
- print("\ton_insn: step")
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
- print("\ton_insn: block")
138
+ logger.debug("\ton_insn: block")
138
139
 
139
- print(f"Panda: on_insn: {hex(pc)}, {self.state}")
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
- print(f"Panda: {pc} out of bounds")
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
- cb(self.manager)
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
- cb(self.manager)
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
- raise exceptions.ConfigurationError(
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
- print(f"\t{self.manager.current_instruction()}")
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
- print(f"Panda: on_block: {tb}, {self.state}")
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
- print(f"\ton_read: {addr}")
274
+ logger.debug(f"\ton_read: {addr}")
251
275
  orig_data = self.panda.virtual_memory_read(self.manager.cpu, addr, size)
252
- if self.manager.all_reads_hook:
253
- val = self.manager.all_reads_hook(
254
- self.manager, addr, size, orig_data
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
- if val:
257
- self.manager.write_memory(addr, val)
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
- print(f"\ton_write: {hex(addr)}")
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
- if self.manager.all_writes_hook:
271
- self.manager.all_writes_hook(self.manager, addr, size, byte_val)
272
-
273
- if cb := self.manager.is_memory_write_hooked(addr):
274
- cb(self.manager, addr, size, byte_val)
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
- print(f"\ton_interrupt: {intno}")
279
- # First if all interrupts are hooked, run that function
280
- if self.manager.all_interrupts_hook:
281
- self.manager.all_interrupts_hook(self.manager)
282
- # Then run interrupt specific function
283
- if cb := self.manager.is_interrupt_hooked(intno):
284
- cb(self.manager)
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
- print(
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
- print("Signaling main to run")
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
- # Signal that we are done and to run main
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.machdef.cs_arch, self.panda_thread.machdef.cs_mode
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
- print("Main signaling panda to run")
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
- print(f"Step: reading register {pc}")
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",