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
@@ -0,0 +1,217 @@
1
+ import logging
2
+ import re
3
+
4
+ import networkx as nx
5
+
6
+ from .. import hinting
7
+ from . import analysis
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class DefUseGraph(nx.MultiDiGraph):
13
+ def add_def_use(self, def_node, use_node, def_info, use_info, color):
14
+ # logger.info(f"def use def_node={def_node} use_node={use_node}")
15
+ # logger.info(f" def_info={def_info}")
16
+ # logger.info(f" use_info={use_info}")
17
+ self.add_edges_from(
18
+ [
19
+ (
20
+ def_node,
21
+ use_node,
22
+ {"def_info": def_info, "use_info": use_info, "color": color},
23
+ )
24
+ ]
25
+ )
26
+
27
+
28
+ class ColorizerDefUse(analysis.Analysis):
29
+ name = "colorizer_def_use_graph"
30
+ description = "assemble a def use graph from colorizer summary hints"
31
+ version = "0.0.1"
32
+
33
+ def __init__(self, *args, **kwargs):
34
+ super().__init__(*args, **kwargs)
35
+ self.new_hints = []
36
+ self.not_new_hints = []
37
+ self.hinter.register(
38
+ hinting.DynamicRegisterValueSummaryHint, self.collect_hints
39
+ )
40
+ self.hinter.register(hinting.DynamicMemoryValueSummaryHint, self.collect_hints)
41
+
42
+ def collect_hints(self, hint: hinting.Hint):
43
+ if (
44
+ type(hint) is hinting.DynamicRegisterValueSummaryHint
45
+ or type(hint) is hinting.DynamicMemoryValueSummaryHint
46
+ ):
47
+ if hint.new:
48
+ self.new_hints.append(hint)
49
+ else:
50
+ self.not_new_hints.append(hint)
51
+
52
+ def run(self, machine):
53
+ self.du_graph = DefUseGraph()
54
+ color2genesis = {}
55
+
56
+ def hint_dv_info(hint):
57
+ if type(hint) is hinting.DynamicRegisterValueSummaryHint:
58
+ return {
59
+ "new": hint.new,
60
+ "count": hint.count,
61
+ "num_micro_executions": hint.num_micro_executions,
62
+ "type": "reg",
63
+ "is_read": hint.use,
64
+ "reg_name": hint.reg_name,
65
+ "color": hint.color,
66
+ }
67
+ elif type(hint) is hinting.DynamicMemoryValueSummaryHint:
68
+ return {
69
+ "new": hint.new,
70
+ "count": hint.count,
71
+ "num_micro_executions": hint.num_micro_executions,
72
+ "type": "mem",
73
+ "is_read": hint.use,
74
+ "base": hint.base,
75
+ "index": hint.index,
76
+ "scale": hint.scale,
77
+ "offset": hint.offset,
78
+ "color": hint.color,
79
+ }
80
+ else:
81
+ assert 1 == 0
82
+
83
+ for hint in self.new_hints:
84
+ # this is a new color so its either an input or a write of a computed value
85
+
86
+ # some sanity checking
87
+ assert "def" in hint.message
88
+ assert hint.color not in color2genesis
89
+ assert (hint.use and ("read" in hint.message)) or (
90
+ (not hint.use) and ("write" in hint.message)
91
+ )
92
+
93
+ self.du_graph.add_node(hint.pc)
94
+
95
+ dv_info = hint_dv_info(hint)
96
+
97
+ if hint.use:
98
+ # this is a read
99
+ # hallucinate a node representing the creation of that color
100
+ color_node = f"input color-{hint.color}"
101
+ assert dv_info["type"] == "reg" or dv_info["type"] == "mem"
102
+
103
+ if dv_info["type"] == "reg":
104
+ color_node = color_node + " " + dv_info["reg_name"]
105
+ if dv_info["type"] == "mem":
106
+ color_node = color_node + " *(" + dv_info["base"]
107
+ if dv_info["index"] != "None":
108
+ color_node += f"{dv_info['scale']}*{dv_info['index']}"
109
+ if dv_info["offset"] > 0:
110
+ color_node += f"{dv_info['offset']}"
111
+ color_node += ")"
112
+ color_node += "_init"
113
+ self.du_graph.add_node(color_node)
114
+ # record mapping from this color to its creation info
115
+ color2genesis[hint.color] = (color_node, dv_info)
116
+ # and an edge between that color node and this instruction
117
+ self.du_graph.add_def_use(
118
+ color_node, hint.pc, color_node, dv_info, hint.color
119
+ )
120
+ else:
121
+ # this is a write of a computed value
122
+ # record mapping from this color to its creation info
123
+ color2genesis[hint.color] = (hint.pc, dv_info)
124
+
125
+ for hint in self.not_new_hints:
126
+ # not a new color. so its a flow
127
+ self.du_graph.add_node(hint.pc)
128
+ # can't be a def
129
+ assert "def" not in hint.message
130
+ # we should never see !new && !use since that is just a value copy
131
+ # assert hint.use
132
+ if not hint.use:
133
+ pass
134
+ else:
135
+ dv_info = hint_dv_info(hint)
136
+ (def_node, def_info) = color2genesis[hint.color]
137
+ self.du_graph.add_def_use(
138
+ def_node, hint.pc, def_info, dv_info, hint.color
139
+ )
140
+
141
+ # hint out the def-use graph
142
+ self.hinter.send(
143
+ hinting.DefUseGraphHint(
144
+ graph=nx.node_link_data(self.du_graph, edges="links"),
145
+ message="concrete-summary-def-use-graph",
146
+ )
147
+ )
148
+
149
+ with open("colorizer_def_use.dot", "w") as dot:
150
+
151
+ def writeit(foo):
152
+ dot.write(foo + "\n")
153
+
154
+ writeit("digraph{")
155
+ writeit(" rankdir=LR")
156
+
157
+ node2nodeid = {}
158
+ for node in self.du_graph.nodes:
159
+ # 4461 is pc
160
+ # {"id": 4461},
161
+ # An input color rsp is register
162
+ # {"id": "input color-1 rsp_init"},
163
+ node_id = f"node_{len(node2nodeid)}"
164
+ if type(node) is int:
165
+ # nodeinfo = ("instruction", f"0x{node}")
166
+ writeit(f' {node_id} [label="0x{node:x}"]')
167
+ else:
168
+ assert type(node) is str
169
+ foo = re.search("input color-([0-9]+) (.*)_init", node)
170
+ assert foo is not None
171
+ (cns, reg) = foo.groups()
172
+ cn = int(cns)
173
+ # nodeinfo = ("input", (cn, reg))
174
+ writeit(f' {node_id} [color="blue", label="input({reg})"]')
175
+ node2nodeid[node] = node_id
176
+
177
+ di = nx.get_edge_attributes(self.du_graph, "def_info")
178
+ ui = nx.get_edge_attributes(self.du_graph, "use_info")
179
+ for e in self.du_graph.edges:
180
+ if type(di[e]) is str:
181
+ foo = re.search("color-([0-9]+) (.*)_init", di[e])
182
+ (cns, reg) = foo.groups()
183
+ cn = int(cns)
184
+ assert cn == ui[e]["color"]
185
+ else:
186
+ assert di[e]["color"] == ui[e]["color"]
187
+ (src, dst, k) = e
188
+ cn = ui[e]["color"]
189
+ tl = ""
190
+
191
+ def i2s(inf):
192
+ lab = ""
193
+ if "type" in inf:
194
+ if inf["type"] == "reg":
195
+ lab = inf["reg_name"]
196
+ if inf["type"] == "mem":
197
+ lab = "["
198
+ if inf["base"] != "None":
199
+ lab += inf["base"]
200
+ if inf["index"] != "None":
201
+ lab += f'+{inf["scale"]}*{inf["index"]}'
202
+ if inf["offset"] != 0:
203
+ lab += f'+{inf["offset"]:x}'
204
+ lab += "]"
205
+ return lab
206
+
207
+ hl = i2s(ui[e])
208
+ tl = i2s(di[e])
209
+
210
+ writeit(
211
+ f' {node2nodeid[src]} -> {node2nodeid[dst]} [label="{cn}",headlabel="{hl}",taillabel="{tl}"]'
212
+ )
213
+
214
+ writeit("}\n")
215
+
216
+ def get_graph(self):
217
+ return self.du_graph
@@ -1,100 +1,190 @@
1
- # mypy: ignore-errors
2
- import logging
3
-
4
- import networkx as nx
1
+ import sys
2
+ import typing
5
3
 
6
4
  from .. import hinting
7
5
  from . import analysis
8
6
 
9
- hinter = hinting.get_hinter(__name__)
10
- logger = logging.getLogger(__name__)
7
+ # goal here is to summarize across multiple micro execution if two
8
+ # hints map to the same key then they are in same equivalence class so
9
+ # we elide away things that will be specific to a run like micro exec
10
+ # number, color (actual dyn value), ptr addresses, etc.
11
11
 
12
12
 
13
- class DefUseGraph(nx.MultiDiGraph):
14
- def add_def_use(self, def_node, use_node, def_info, use_info, color):
15
- self.add_edges_from(
16
- [
17
- (
18
- def_node,
19
- use_node,
20
- {"def_info": def_info, "use_info": use_info, "color": color},
21
- )
22
- ]
13
+ def compute_dv_key(hint):
14
+ if type(hint) is hinting.DynamicRegisterValueHint:
15
+ return (
16
+ ("type", "reg"),
17
+ ("pc", hint.pc),
18
+ ("size", hint.size),
19
+ ("use", hint.use),
20
+ ("new", hint.new),
21
+ ("reg_name", hint.reg_name),
23
22
  )
23
+ elif type(hint) is hinting.DynamicMemoryValueHint:
24
+ return (
25
+ ("type", "mem"),
26
+ ("pc", hint.pc),
27
+ ("size", hint.size),
28
+ ("use", hint.use),
29
+ ("new", hint.new),
30
+ ("base", hint.base),
31
+ ("index", hint.index),
32
+ ("scale", hint.scale),
33
+ ("offset", hint.offset),
34
+ )
35
+ elif type(hint) is hinting.MemoryUnavailableHint:
36
+ return (
37
+ ("type", "mem_unavail"),
38
+ ("pc", hint.pc),
39
+ ("size", hint.size),
40
+ ("is_read", hint.is_read),
41
+ ("base", hint.base_reg_name),
42
+ ("index", hint.index_reg_name),
43
+ ("scale", hint.scale),
44
+ ("offset", hint.offset),
45
+ )
46
+ elif type(hint) is hinting.EmulationException:
47
+ return (("type", "emu_fail"), ("pc", hint.pc), ("exception", hint.exception))
24
48
 
25
-
26
- du_graph = DefUseGraph()
27
- color2nodeDv = {}
49
+ else:
50
+ # should never happen
51
+ assert (
52
+ (type(hint) is hinting.DynamicRegisterValueHint)
53
+ or (type(hint) is hinting.DynamicMemoryValueHint)
54
+ or (type(hint) is hinting.MemoryUnavailableHint)
55
+ or (type(hint) is hinting.EmulationException)
56
+ )
28
57
 
29
58
 
30
- class ColorizerSummary(analysis.Filter):
59
+ class ColorizerSummary(analysis.Analysis):
31
60
  name = "colorizer_summary"
32
- description = "summarized version of colorizer"
61
+ description = "collect and summarize colorizer output across micro executions"
33
62
  version = "0.0.1"
34
63
 
35
- @staticmethod
36
- def dynamic_value_summary(hint: hinting.Hint):
37
- # print(hint)
38
- # instr_node = hint.instruction
39
- # du_graph.add_node(instr_node)
40
- du_graph.add_node(hint.pc)
41
- if type(hint) is hinting.DynamicRegisterValueProbHint:
42
- dv_info = [
43
- ("prob", hint.prob),
44
- ("type", "reg"),
45
- ("reg_name", hint.reg_name),
46
- ]
47
- elif type(hint) is hinting.DynamicMemoryValueProbHint:
48
- dv_info = [
49
- ("prob", hint.prob),
50
- ("type", "mem"),
51
- ("base", hint.base),
52
- ("index", hint.index),
53
- ("scale", hint.scale),
54
- ("offset", hint.offset),
55
- ]
56
- else:
57
- assert 1 == 0
58
- if hint.new:
59
- # this is a new color so its either an input or a write of a computed value
60
- assert "def" in hint.message
61
- assert hint.color not in color2nodeDv
62
- if hint.use:
63
- assert "read" in hint.message
64
- # color2nodeDv[hint.color] = (instr_node, dv_info)
65
- color2nodeDv[hint.color] = (hint.pc, dv_info)
66
- else:
67
- assert "write" in hint.message
68
- color2nodeDv[hint.color] = (hint.pc, dv_info)
69
- # if its a read then
70
- # hallucinate a node representing the creation of that color
71
- if hint.use:
72
- color_node = f"input color-{hint.color}"
73
- du_graph.add_node(color_node)
74
- color2nodeDv[hint.color] = (color_node, None)
75
- # and an edge between that and this instruction
76
- du_graph.add_def_use(
77
- color_node, hint.pc, color_node, dv_info, hint.color
78
- )
79
- else:
80
- # not a new color. so its a flow
81
- assert "def" not in hint.message
82
- # we should never see new && !use since that is just a value copy
64
+ def __init__(self, *args, **kwargs):
65
+ super().__init__(*args, **kwargs)
66
+ self.hint_list = []
67
+ self.exec_ids = set([])
68
+ self.hinter.register(hinting.DynamicRegisterValueHint, self.collect_hints)
69
+ self.hinter.register(hinting.DynamicMemoryValueHint, self.collect_hints)
70
+ self.hinter.register(hinting.MemoryUnavailableHint, self.collect_hints)
71
+ self.hinter.register(hinting.EmulationException, self.collect_hints)
83
72
 
84
- # assert hint.use
85
- (def_node, def_dv_info) = color2nodeDv[hint.color]
86
- du_graph.add_def_use(def_node, hint.pc, def_dv_info, dv_info, hint.color)
73
+ def collect_hints(self, hint):
74
+ self.hint_list.append(hint)
75
+ self.exec_ids.add(hint.exec_id)
87
76
 
88
- def activate(self):
89
- # pdb.set_trace()
90
- print("activating colorizer_summary")
91
- self.listen(hinting.DynamicRegisterValueProbHint, self.dynamic_value_summary)
92
- self.listen(hinting.DynamicMemoryValueProbHint, self.dynamic_value_summary)
77
+ def run(self, machine):
78
+ # Establish true colors 1, 2, 3, ...
79
+ #
80
+ # The colors we have in hints are random initial reg or memory
81
+ # values or values computed from those. This means they don't
82
+ # correspond across micro-executions. We need them to do so if
83
+ # we are to summarize.
84
+ #
85
+ truecolors = set([])
86
+ dvh2truecolor = {}
87
+ color2truecolor = {}
88
+ for hint in self.hint_list:
89
+ if hasattr(hint, "color"):
90
+ if hint.new:
91
+ # This is a hint with a "new" color meaning the
92
+ # hint time is when the color was first
93
+ # observed. If we are trying to match up such new
94
+ # colors across micro executions, we do so by
95
+ # matching up the dv keys for them at this
96
+ # time of first observation.
97
+ dvk = compute_dv_key(hint)
98
+ dvh = hash(dvk) % ((sys.maxsize + 1) * 2)
99
+ if dvh not in dvh2truecolor:
100
+ # we need to establish a color for this dvh
101
+ next_color = 1 + len(truecolors)
102
+ truecolors.add(next_color)
103
+ dvh2truecolor[dvh] = next_color
104
+ # make sure to map every hint color to its true color
105
+ color2truecolor[hint.color] = dvh2truecolor[dvh]
106
+ else:
107
+ assert hint.color in color2truecolor
93
108
 
94
- def deactivate(self):
95
- # import pdb
96
- # pdb.set_trace()
109
+ # use compute_dv_key to put keys into equiv classes
110
+ # which works for both new and not-new hints
111
+ # start off by collecting set of all such classes
112
+ all_hint_keys = set([])
113
+ hk_exemplar = {}
114
+ for hint in self.hint_list:
115
+ hk = compute_dv_key(hint)
116
+ all_hint_keys.add(hk)
117
+ # keep one exemplar for each equivalence class
118
+ if hk not in hk_exemplar:
119
+ hk_exemplar[hk] = hint
97
120
 
98
- jsg = nx.node_link_data(du_graph)
99
- with open("dugraph.json", "w") as j:
100
- j.write(str(jsg))
121
+ hint_keys_sorted = sorted(list(all_hint_keys))
122
+
123
+ # given the equivalence classes established by `compute_dv_key`, determine
124
+ # which of those were observed in each micro-execution
125
+ hk_observed: typing.Dict[
126
+ int, typing.Set[typing.Tuple[int, bool, str, bool, str, str, str, int, int]]
127
+ ] = {}
128
+ for hint in self.hint_list:
129
+ if hint.exec_id not in hk_observed:
130
+ hk_observed[hint.exec_id] = set([])
131
+ # this hint key was observed in micro execution me
132
+ hk_observed[hint.exec_id].add(compute_dv_key(hint))
133
+
134
+ # get counts for hint across micro executions
135
+ hk_c = {}
136
+ for hk in hint_keys_sorted:
137
+ hk_c[hk] = 0
138
+ for exec_id in self.exec_ids:
139
+ for hk2 in hk_observed[exec_id]:
140
+ if hk == hk2:
141
+ hk_c[hk] += 1
142
+
143
+ for hk in hint_keys_sorted:
144
+ hint = hk_exemplar[hk]
145
+ if type(hint) is hinting.DynamicRegisterValueHint:
146
+ self.hinter.send(
147
+ hinting.DynamicRegisterValueSummaryHint(
148
+ pc=hint.pc,
149
+ reg_name=hint.reg_name,
150
+ color=color2truecolor[hint.color],
151
+ size=hint.size,
152
+ use=hint.use,
153
+ new=hint.new,
154
+ count=hk_c[hk],
155
+ num_micro_executions=len(self.exec_ids),
156
+ message=hint.message + "-summary",
157
+ )
158
+ )
159
+ if type(hint) is hinting.DynamicMemoryValueHint:
160
+ self.hinter.send(
161
+ hinting.DynamicMemoryValueSummaryHint(
162
+ pc=hint.pc,
163
+ size=hint.size,
164
+ base=hint.base,
165
+ index=hint.index,
166
+ scale=hint.scale,
167
+ offset=hint.offset,
168
+ color=color2truecolor[hint.color],
169
+ use=hint.use,
170
+ new=hint.new,
171
+ message=hint.message + "-summary",
172
+ count=hk_c[hk],
173
+ num_micro_executions=len(self.exec_ids),
174
+ )
175
+ )
176
+ if type(hint) is hinting.MemoryUnavailableHint:
177
+ self.hinter.send(
178
+ hinting.MemoryUnavailableSummaryHint(
179
+ is_read=hint.is_read,
180
+ size=hint.size,
181
+ base_reg_name=hint.base_reg_name,
182
+ index_reg_name=hint.index_reg_name,
183
+ offset=hint.offset,
184
+ scale=hint.bscale,
185
+ pc=hint.pc,
186
+ count=hk_c[hk],
187
+ num_micro_executions=len(self.exec_ids),
188
+ message=hint.message + "-summary",
189
+ )
190
+ )
@@ -19,7 +19,6 @@ from .hints import (
19
19
  )
20
20
 
21
21
  log = logging.getLogger(__name__)
22
- hinter = hinting.get_hinter(__name__)
23
22
 
24
23
  # Tell angr to be quiet please
25
24
  logging.getLogger("angr").setLevel(logging.WARNING)
@@ -121,7 +120,7 @@ class FieldDetectionMixin(underlays.AnalysisUnderlay):
121
120
  size=size,
122
121
  expr=str(expr),
123
122
  )
124
- hinter.info(hint)
123
+ self.hinter.self(hint)
125
124
  if self.halt_on_hint:
126
125
  raise PathTerminationSignal()
127
126
  else:
@@ -204,7 +203,7 @@ class FieldDetectionMixin(underlays.AnalysisUnderlay):
204
203
  start=start // 8,
205
204
  end=end // 8,
206
205
  )
207
- hinter.info(hint)
206
+ self.hinter.send(hint)
208
207
  if self.halt_on_hint:
209
208
  raise PathTerminationSignal()
210
209
  else:
@@ -226,7 +225,7 @@ class FieldDetectionMixin(underlays.AnalysisUnderlay):
226
225
  access="read",
227
226
  expr=str(expr),
228
227
  )
229
- hinter.info(hint)
228
+ self.hinter.send(hint)
230
229
  if self.halt_on_hint:
231
230
  raise PathTerminationSignal()
232
231
  else:
@@ -288,7 +287,7 @@ class FieldDetectionMixin(underlays.AnalysisUnderlay):
288
287
  end=end,
289
288
  expr=str(expr),
290
289
  )
291
- hinter.info(hint)
290
+ self.hinter.send(hint)
292
291
  bad = True
293
292
  if bad and good:
294
293
  log.error("Write was complete and partial; your labels overlap.")
@@ -317,7 +316,7 @@ class FieldDetectionMixin(underlays.AnalysisUnderlay):
317
316
  access="write",
318
317
  expr=str(expr),
319
318
  )
320
- hinter.info(hint)
319
+ self.hinter.send(hint)
321
320
  if self.halt_on_hint:
322
321
  raise PathTerminationSignal()
323
322
  else:
@@ -362,7 +361,7 @@ class FieldDetectionMixin(underlays.AnalysisUnderlay):
362
361
  size=val.get_size(),
363
362
  label=label,
364
363
  )
365
- hinter.info(hint)
364
+ self.hinter.send(hint)
366
365
 
367
366
  if label in fda.fda_labels:
368
367
  log.error(
@@ -420,7 +419,7 @@ class FieldDetectionMixin(underlays.AnalysisUnderlay):
420
419
  filt.deactivate()
421
420
 
422
421
 
423
- class FieldDetectionFilter(analyses.Filter):
422
+ class FieldDetectionFilter(analyses.Analysis):
424
423
  """Secondary field definition analysis.
425
424
 
426
425
  This picks up patterns that aren't noticeable from any
@@ -4,7 +4,7 @@ import typing
4
4
  from ... import hinting
5
5
 
6
6
 
7
- class ClaripySerializable(hinting.Serializable):
7
+ class ClaripySerializable(hinting.Hint):
8
8
  """Serializable wrapper that allows serializing claripy expressions in hints."""
9
9
 
10
10
  @classmethod
@@ -14,7 +14,7 @@ class MallocModel(state.models.Model):
14
14
  platform = platforms.Platform(
15
15
  platforms.Architecture.X86_64, platforms.Byteorder.LITTLE
16
16
  )
17
- abi = platforms.ABI.SYSTEMV
17
+ abi = platforms.ABI.NONE
18
18
 
19
19
  _arg1_for_arch = {
20
20
  platforms.Architecture.AARCH64: "x0",
@@ -201,7 +201,7 @@ class FreeModel(state.models.Model):
201
201
  platform = platforms.Platform(
202
202
  platforms.Architecture.X86_64, platforms.Byteorder.LITTLE
203
203
  )
204
- abi = platforms.ABI.SYSTEMV
204
+ abi = platforms.ABI.NONE
205
205
 
206
206
  def __init__(self, address: int):
207
207
  super().__init__(address)