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.
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 +38 -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 +211 -57
  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.3.dist-info → smallworld_re-2.0.0.dist-info}/METADATA +74 -42
  297. smallworld_re-2.0.0.dist-info/RECORD +374 -0
  298. {smallworld_re-1.0.3.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.3.dist-info/RECORD +0 -166
  303. /smallworld/state/models/{posix.py → _posix.py} +0 -0
  304. {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/entry_points.txt +0 -0
  305. {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/licenses/LICENSE.txt +0 -0
  306. {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,82 @@
1
+ import typing
2
+
3
+ import lief
4
+
5
+ from ...... import platforms
6
+ from .prstatus import PrStatus
7
+
8
+
9
+ class PowerPC(PrStatus):
10
+ byteorder = platforms.Byteorder.BIG
11
+
12
+ @property
13
+ def register_coords(
14
+ self,
15
+ ) -> typing.List[typing.Tuple[typing.Optional[str], int, int]]:
16
+ return self._register_coords
17
+
18
+ def __init__(self, elf: lief.ELF.Binary, wordsize):
19
+ _register_list = [
20
+ "r0",
21
+ "r1",
22
+ "r2",
23
+ "r3",
24
+ "r4",
25
+ "r5",
26
+ "r6",
27
+ "r7",
28
+ "r8",
29
+ "r9",
30
+ "r10",
31
+ "r11",
32
+ "r12",
33
+ "r13",
34
+ "r14",
35
+ "r15",
36
+ "r16",
37
+ "r17",
38
+ "r18",
39
+ "r19",
40
+ "r20",
41
+ "r21",
42
+ "r22",
43
+ "r23",
44
+ "r24",
45
+ "r25",
46
+ "r26",
47
+ "r27",
48
+ "r28",
49
+ "r29",
50
+ "r30",
51
+ "r31",
52
+ "pc",
53
+ # No idea what these are, as it's not documented.
54
+ None,
55
+ None,
56
+ "ctr",
57
+ "lr",
58
+ ]
59
+ self._register_coords = [
60
+ (_register_list[i], i * wordsize, wordsize)
61
+ for i in range(0, len(_register_list))
62
+ ]
63
+ super().__init__(elf)
64
+
65
+
66
+ class PowerPC32(PowerPC):
67
+ architecture = platforms.Architecture.POWERPC32
68
+ pr_regs_off = 72
69
+ pr_regs_size = 192
70
+
71
+ def __init__(self, elf: lief.ELF.Binary):
72
+ super().__init__(elf, 4)
73
+
74
+
75
+ class PowerPC64(PowerPC):
76
+ architecture = platforms.Architecture.POWERPC64
77
+
78
+ pr_regs_off = 112
79
+ pr_regs_size = 384
80
+
81
+ def __init__(self, elf: lief.ELF.Binary):
82
+ super().__init__(elf, 8)
@@ -0,0 +1,129 @@
1
+ import abc
2
+ import typing
3
+
4
+ import lief
5
+
6
+ from ...... import exceptions, platforms, utils
7
+ from .....cpus import CPU
8
+ from .....state import FixedRegister
9
+
10
+
11
+ class PrStatus:
12
+ """Class for extracting process information from a core dump
13
+
14
+ The prstatus struct is arch-specific.
15
+ Lief can interpret them for a small number of architectures,
16
+ but definitely not all supported by SmallWorld.
17
+ """
18
+
19
+ @property
20
+ @abc.abstractmethod
21
+ def architecture(self) -> platforms.Architecture:
22
+ raise NotImplementedError()
23
+
24
+ @property
25
+ @abc.abstractmethod
26
+ def byteorder(self) -> platforms.Byteorder:
27
+ raise NotImplementedError()
28
+
29
+ def __init__(self, elf: lief.ELF.Binary):
30
+ assert elf.header.file_type == lief.ELF.E_TYPE.CORE
31
+
32
+ self.platform = platforms.Platform(self.architecture, self.byteorder)
33
+ self.platdef = platforms.PlatformDef.for_platform(self.platform)
34
+
35
+ self._registers: typing.Dict[str, int] = dict()
36
+
37
+ # Find the PrStatus note
38
+ prstatus: typing.Optional[lief.ELF.CorePrStatus] = None
39
+ for note in elf.notes:
40
+ if isinstance(note, lief.ELF.CorePrStatus):
41
+ prstatus = note
42
+ break
43
+
44
+ if prstatus is None:
45
+ # Didn't find one.
46
+ raise exceptions.ConfigurationError("ELF core file has no PrStatus note")
47
+
48
+ self._parse_prstatus(prstatus)
49
+
50
+ @property
51
+ @abc.abstractmethod
52
+ def pr_regs_off(self) -> int:
53
+ raise NotImplementedError()
54
+
55
+ @property
56
+ @abc.abstractmethod
57
+ def pr_regs_size(self) -> int:
58
+ raise NotImplementedError()
59
+
60
+ @property
61
+ def register_coords(
62
+ self,
63
+ ) -> typing.List[typing.Tuple[typing.Optional[str], int, int]]:
64
+ raise NotImplementedError()
65
+
66
+ def _parse_prstatus(self, prstatus: lief.ELF.CorePrStatus) -> None:
67
+ # Load the registers from prstatus.
68
+ #
69
+ # All prstatus structs have the same layout:
70
+ # a single field called 'pr_regs' that contains a list of registers.
71
+ # The only trick is knowng the offset of that field
72
+ # and the offset and size of each register within it.
73
+
74
+ # Get byteorder literals
75
+ byteorder: typing.Literal["little", "big"]
76
+ if self.byteorder is platforms.Byteorder.LITTLE:
77
+ byteorder = "little"
78
+ elif self.byteorder is platforms.Byteorder.BIG:
79
+ # NOTE: Core dumps generated on a little-endian machine appear to come out little-endian.
80
+ # This may be a problem in the future
81
+ byteorder = "little"
82
+ else:
83
+ raise exceptions.ConfigurationError(
84
+ f"Can't decode byteorder {self.byteorder}"
85
+ )
86
+
87
+ # Extract the raw bytes
88
+ data = prstatus.description.tobytes()
89
+
90
+ # Extract the registers from the struct
91
+ for name, reg_off, reg_size in self.register_coords:
92
+ if name is None:
93
+ # Register we don't handle, or padding.
94
+ continue
95
+ reg_start = self.pr_regs_off + reg_off
96
+ reg_end = self.pr_regs_off + reg_off + reg_size
97
+
98
+ reg_bytes = data[reg_start:reg_end]
99
+ if (
100
+ self.platdef.address_size == 8
101
+ and self.byteorder is platforms.Byteorder.BIG
102
+ ):
103
+ # 64-bit registers are somehow presented middle-endian
104
+ # I have no idea.
105
+ reg_bytes = reg_bytes[4:8] + reg_bytes[0:4]
106
+
107
+ self._registers[name] = int.from_bytes(reg_bytes, byteorder)
108
+
109
+ def populate_cpu(self, cpu: CPU) -> None:
110
+ for reg, value in self._registers.items():
111
+ if not hasattr(cpu, reg):
112
+ raise exceptions.ConfigurationError(
113
+ f"PrStatus register {reg} not in CPU for platform {self.platform}"
114
+ )
115
+ field = getattr(cpu, reg)
116
+ if not isinstance(field, FixedRegister):
117
+ field.set(value)
118
+
119
+ @classmethod
120
+ def for_platform(cls, platform: platforms.Platform, elf: lief.ELF.Binary):
121
+ try:
122
+ return utils.find_subclass(
123
+ cls,
124
+ lambda x: x.architecture == platform.architecture
125
+ and x.byteorder == platform.byteorder,
126
+ elf,
127
+ )
128
+ except Exception as e:
129
+ raise ValueError(f"No PrStatus class for {platform}") from e
@@ -4,7 +4,6 @@ import typing
4
4
  import lief
5
5
 
6
6
  from ....exceptions import ConfigurationError
7
- from ....hinting import Hint, get_hinter
8
7
  from ....platforms import Architecture, Byteorder, Platform
9
8
  from ....utils import RangeCollection
10
9
  from ...state import BytesValue
@@ -13,7 +12,6 @@ from .rela import ElfRelocator
13
12
  from .structs import ElfRela, ElfSymbol
14
13
 
15
14
  log = logging.getLogger(__name__)
16
- hinter = get_hinter(__name__)
17
15
 
18
16
  # ELF machine values
19
17
  # See /usr/include/elf.h for the complete list
@@ -26,6 +24,7 @@ EM_X86_64 = 62 # AMD/Intel x86-64
26
24
  EM_XTENSA = 94 # Xtensa
27
25
  EM_AARCH64 = 183 # ARM v9, or AARCH64
28
26
  EM_RISCV = 243 # RISC-V
27
+ EM_LOONGARCH = 258 # LoongArch
29
28
 
30
29
  # ARM-specific flag values
31
30
  EF_ARM_VFP_FLOAT = 0x400
@@ -99,10 +98,19 @@ class ElfExecutable(Executable):
99
98
  self._user_base = user_base
100
99
  self._file_base = 0
101
100
 
101
+ # Lief struct.
102
+ # We can't keep it around forever, since it's not copyable.
103
+ self._elf: typing.Optional[typing.Any] = None
104
+
105
+ # Initialize dynamic tag info
106
+ self._dtags: typing.Dict[int, int] = dict()
107
+
102
108
  # Initialize symbol info
103
- self._symbols: typing.List[ElfSymbol] = list()
109
+ self._dynamic_symbols: typing.List[ElfSymbol] = list()
110
+ self._static_symbols: typing.List[ElfSymbol] = list()
111
+ self._dynamic_relas: typing.List[ElfRela] = list()
112
+ self._static_relas: typing.List[ElfRela] = list()
104
113
  self._syms_by_name: typing.Dict[str, typing.List[ElfSymbol]] = dict()
105
- self._relas: typing.List[ElfRela] = list()
106
114
  self._relocator: typing.Optional[ElfRelocator] = None
107
115
 
108
116
  # Read the entire image out of the file.
@@ -121,6 +129,9 @@ class ElfExecutable(Executable):
121
129
  if elf is None:
122
130
  raise ConfigurationError("Failed parsing ELF")
123
131
 
132
+ # Save the lief struct
133
+ self._elf = elf
134
+
124
135
  # Extract the file header
125
136
  ehdr = elf.header
126
137
  if ehdr is None:
@@ -169,15 +180,13 @@ class ElfExecutable(Executable):
169
180
  elif phdr.type == PT_DYNAMIC:
170
181
  # Dynamic linking metadata.
171
182
  # This ELF needs dynamic linking
172
- hint = Hint(message="Program includes dynamic linking metadata")
173
- hinter.info(hint)
183
+ log.info("Program includes dynamic linking metadata")
174
184
  elif phdr.type == PT_INTERP:
175
185
  # Program interpreter
176
186
  # This completely changes how program loading works.
177
187
  # Whether you care is a different matter.
178
188
  interp = image[phdr.file_offset : phdr.file_offset + phdr.physical_size]
179
- hint = Hint(message=f"Program specifies interpreter {interp!r}")
180
- hinter.info(hint)
189
+ log.info(f"Program specifies interpreter {interp!r}")
181
190
  elif phdr.type == PT_NOTE:
182
191
  # Auxiliary information
183
192
  # Possibly useful for comparing machine/OS type.
@@ -189,8 +198,7 @@ class ElfExecutable(Executable):
189
198
  elif phdr.type == PT_TLS:
190
199
  # TLS Segment
191
200
  # Your analysis is about to get nasty :(
192
- hint = Hint(message="Program includes thread-local storage")
193
- hinter.info(hint)
201
+ log.info("Program includes thread-local storage")
194
202
  elif phdr.type == PT_GNU_EH_FRAME:
195
203
  # Exception handler frame.
196
204
  # GCC puts one of these in everything. Do we care?
@@ -198,13 +206,11 @@ class ElfExecutable(Executable):
198
206
  elif phdr.type == PT_GNU_STACK:
199
207
  # Stack executability
200
208
  # If this is missing, assume executable stack
201
- hint = Hint(message="Program specifies stack permissions")
202
- hinter.info(hint)
209
+ log.info("Program specifies stack permissions")
203
210
  elif phdr.type == PT_GNU_RELRO:
204
211
  # Read-only after relocation
205
212
  # Only the dynamic linker should write this data.
206
- hint = Hint(message="Program specifies RELRO data")
207
- hinter.info(hint)
213
+ log.info("Program specifies RELRO data")
208
214
  elif phdr.type == PT_GNU_PROPERTY:
209
215
  # GNU property segment
210
216
  # Contains extra metadata which I'm not sure anything uses
@@ -213,21 +219,18 @@ class ElfExecutable(Executable):
213
219
  # Unknown OS-specific program header
214
220
  # Either this is a weird ISA that extends the generic GNU ABI,
215
221
  # or this isn't a Linux ELF.
216
- hint = Hint(f"Unknown OS-specific program header: {phdr.type:08x}")
217
- hinter.warn(hint)
222
+ log.warn(f"Unknown OS-specific program header: {phdr.type:08x}")
218
223
  elif phdr.type >= PT_LOPROC and phdr.type <= PT_HIPROC:
219
224
  # Unknown machine-specific program header
220
225
  # This is probably a non-Intel ISA.
221
226
  # Most of these are harmless, serving to tell the RTLD
222
227
  # where to find machine-specific metadata
223
- hint = Hint(
228
+ log.warn(
224
229
  f"Unknown machine-specific program header: {phdr.type.value:08x}"
225
230
  )
226
- hinter.warn(hint)
227
231
  else:
228
232
  # Unknown program header outside the allowed custom ranges
229
- hint = Hint(f"Invalid program header: {phdr.type.value:08x}")
230
- hinter.warn(hint)
233
+ log.warn(f"Invalid program header: {phdr.type.value:08x}")
231
234
 
232
235
  # Compute the final total capacity
233
236
  for offset, value in self.items():
@@ -258,6 +261,9 @@ class ElfExecutable(Executable):
258
261
  # Or this is PowerPC64 and the entrypoint is gibberish
259
262
  self.entrypoint = None
260
263
 
264
+ # Organize dynamic tags
265
+ self._extract_dtags(elf)
266
+
261
267
  # Organize symbols for later relocation
262
268
  self._extract_symbols(elf)
263
269
 
@@ -296,7 +302,24 @@ class ElfExecutable(Executable):
296
302
  # This is ARMv7a, as built by gcc.
297
303
  architecture = Architecture.ARM_V7A
298
304
  else:
299
- raise ConfigurationError(f"Unknown ARM flags: {list(map(hex, flags))}")
305
+ # The file might be a core dump or some uncommon flavor of ARM.
306
+ # Fallback to a default if flags are missing.
307
+ log.warning(
308
+ f"No recognized ARM flags found. flags={list(map(hex, flags))}, "
309
+ "defaulting to ARM_V7A."
310
+ )
311
+ architecture = Architecture.ARM_V7A
312
+ elif elf.header.machine_type.value == EM_LOONGARCH:
313
+ if elf.header.identity_class.value == 1:
314
+ # 32-bit elf
315
+ raise ConfigurationError("LoongArch32 not supported")
316
+ elif elf.header.identity_class.value == 2:
317
+ # 64-bit elf
318
+ architecture = Architecture.LOONGARCH64
319
+ else:
320
+ raise ConfigurationError(
321
+ f"Unknown value of ei_class: {hex(elf.header.identity_class.value)}"
322
+ )
300
323
  elif elf.header.machine_type.value == EM_MIPS:
301
324
  # Some kind of mips.
302
325
  # TODO: There are more parameters than just word size
@@ -420,6 +443,10 @@ class ElfExecutable(Executable):
420
443
  ), f"Expected {seg_size:x} bytes, got {seg_value._size:x}"
421
444
  self[seg_addr - self.address] = seg_value
422
445
 
446
+ def _extract_dtags(self, elf):
447
+ for dt in elf.dynamic_entries:
448
+ self._dtags[dt.tag.value] = dt.value
449
+
423
450
  def _extract_symbols(self, elf):
424
451
  lief_to_elf = dict()
425
452
 
@@ -435,9 +462,21 @@ class ElfExecutable(Executable):
435
462
  # Relative symbols will be relative to the load address
436
463
  baseaddr = self.address
437
464
 
465
+ dynsyms = set(elf.dynamic_symbols)
466
+ idx = 0
467
+ dynamic = True
438
468
  for s in elf.symbols:
469
+ # Lief lets you access dynamic symbols separately,
470
+ # but you need to access static symbols through
471
+ # the list of all symbols
472
+ if dynamic and s not in dynsyms:
473
+ idx = 0
474
+ dynamic = False
475
+
439
476
  # Build a symbol
440
477
  sym = ElfSymbol(
478
+ idx=idx,
479
+ dynamic=dynamic,
441
480
  name=s.name,
442
481
  type=s.type.value,
443
482
  bind=s.binding.value,
@@ -446,9 +485,14 @@ class ElfExecutable(Executable):
446
485
  value=s.value,
447
486
  size=s.size,
448
487
  baseaddr=baseaddr,
488
+ defined=(s.shndx != 0),
449
489
  )
450
490
  # Save the sym, and temporarily tie it to its lief partner
451
- self._symbols.append(sym)
491
+ if dynamic:
492
+ self._dynamic_symbols.append(sym)
493
+ else:
494
+ self._static_symbols.append(sym)
495
+
452
496
  self._syms_by_name.setdefault(sym.name, list()).append(sym)
453
497
  lief_to_elf[s] = sym
454
498
 
@@ -459,30 +503,20 @@ class ElfExecutable(Executable):
459
503
  # All MIPS dynamic symbols have an implicit rela.
460
504
  # MIPS dynamic symbols always have a GOT entry;
461
505
  # to save space, the ABI just assumes that the rela exists
462
-
463
- # Find the GOT and the number of local entries
464
- gotoff = None
465
- gotsym = None
466
- local_gotno = None
467
- for dt in elf.dynamic_entries:
468
- if dt.tag.value == DT_MIPS_GOTSYM:
469
- gotsym = dt.value
470
- if dt.tag.value == DT_MIPS_LOCAL_GOTNO:
471
- local_gotno = dt.value
472
- if dt.tag.value == DT_PLTGOT:
473
- gotoff = dt.value
474
- if (
475
- local_gotno is not None
476
- and gotsym is not None
477
- and gotoff is not None
478
- ):
479
- break
480
-
481
- if local_gotno is None or gotoff is None or gotsym is None:
482
- log.error("MIPS binary missing got information")
506
+ if (
507
+ DT_MIPS_GOTSYM not in self._dtags
508
+ or DT_MIPS_LOCAL_GOTNO not in self._dtags
509
+ or DT_PLTGOT not in self._dtags
510
+ ):
511
+ # GOT is missing... not sure what's up.
512
+ log.error("MIPS binary missing GOT information")
483
513
  else:
484
514
  # We found the GOT info; we're actually a dynamic binary
485
515
  # Figure out the GOT entry size based on arch
516
+ gotsym = self._dtags[DT_MIPS_GOTSYM]
517
+ local_gotno = self._dtags[DT_MIPS_LOCAL_GOTNO]
518
+ gotoff = self._dtags[DT_PLTGOT]
519
+
486
520
  if self.platform.architecture == Architecture.MIPS32:
487
521
  gotent = 4
488
522
  rela_type = R_MIPS_32
@@ -500,20 +534,35 @@ class ElfExecutable(Executable):
500
534
  sym = lief_to_elf[s]
501
535
  rela = ElfRela(offset=gotoff, type=rela_type, symbol=sym, addend=0)
502
536
  sym.relas.append(rela)
503
- self._relas.append(rela)
537
+ self._dynamic_relas.append(rela)
504
538
 
505
539
  gotoff += gotent
506
540
 
507
- for r in elf.relocations:
541
+ for r in list(elf.dynamic_relocations) + list(elf.pltgot_relocations):
508
542
  # Build a rela, and tie it to its symbol
543
+ # TODO: some relas have no symbols. Live with it.
544
+ if r.symbol is None:
545
+ continue
509
546
  sym = lief_to_elf[r.symbol]
510
547
  rela = ElfRela(
511
548
  offset=r.address + baseaddr, type=r.type, symbol=sym, addend=r.addend
512
549
  )
513
550
  sym.relas.append(rela)
514
- self._relas.append(rela)
551
+ self._dynamic_relas.append(rela)
515
552
 
516
- def _get_symbols(self, name: typing.Union[str, int]) -> typing.List[ElfSymbol]:
553
+ for r in elf.object_relocations:
554
+ if r.symbol is None:
555
+ continue
556
+ sym = lief_to_elf[r.symbol]
557
+ rela = ElfRela(
558
+ offset=r.address + baseaddr, type=r.type, symbol=sym, addend=r.addend
559
+ )
560
+ sym.relas.append(rela)
561
+ self._static_relas.append(rela)
562
+
563
+ def _get_symbols(
564
+ self, name: typing.Union[str, int], dynamic: bool
565
+ ) -> typing.List[ElfSymbol]:
517
566
  if isinstance(name, str):
518
567
  # Caller wants to look up a symbol by name
519
568
  if name not in self._syms_by_name:
@@ -522,14 +571,30 @@ class ElfExecutable(Executable):
522
571
  syms = self._syms_by_name[name]
523
572
  return list(syms)
524
573
  elif isinstance(name, int):
525
- return [self._symbols[name]]
574
+ if dynamic:
575
+ return [self._dynamic_symbols[name]]
576
+ else:
577
+ return [self._static_symbols[name]]
526
578
  else:
527
579
  raise TypeError("Symbols must be specified by str names or int indexes")
528
580
 
529
581
  def get_symbol_value(
530
- self, name: typing.Union[str, int], rebase: bool = True
582
+ self, name: typing.Union[str, int], dynamic: bool = False, rebase: bool = True
531
583
  ) -> int:
532
- syms = self._get_symbols(name)
584
+ """Get the value for a symbol
585
+
586
+ The value of a symbol is usually an address or offset,
587
+ although the precise meaning can vary a little.
588
+
589
+ Arguments:
590
+ name: The name of the symbol, or its index into the symbol table
591
+ dynamic: If specified by index, whether to look in the static or dynamic symbol table
592
+ rebase: Whether the recorded value is relative to the base address of this ELF.
593
+
594
+ Returns:
595
+ The integer value of this symbol
596
+ """
597
+ syms = self._get_symbols(name, dynamic)
533
598
  if len(syms) > 1:
534
599
  for sym in syms:
535
600
  if sym.value != syms[0].value and sym.baseaddr != syms[0].baseaddr:
@@ -540,8 +605,21 @@ class ElfExecutable(Executable):
540
605
  val += syms[0].baseaddr
541
606
  return val
542
607
 
543
- def get_symbol_size(self, name: typing.Union[str, int]):
544
- syms = self._get_symbols(name)
608
+ def get_symbol_size(self, name: typing.Union[str, int], dynamic: bool = False):
609
+ """Get the size for a symbol
610
+
611
+ If a symbol references a function or a data structure,
612
+ this will hold its size in bytes
613
+
614
+ Arguments:
615
+ name: The name of the symbol, or its index into the symbol table
616
+ dynamic: If specified by index, whether to look in the static or dynamic symbol table
617
+ rebase: Whether the recorded value is relative to the base address of this ELF.
618
+
619
+ Returns:
620
+ The size of this symbol
621
+ """
622
+ syms = self._get_symbols(name, dynamic)
545
623
  if len(syms) > 1:
546
624
  for sym in syms:
547
625
  if sym.size != syms[0].size:
@@ -549,12 +627,31 @@ class ElfExecutable(Executable):
549
627
  return syms[0].size
550
628
 
551
629
  def update_symbol_value(
552
- self, name: typing.Union[str, int], value: int, rebase: bool = True
630
+ self,
631
+ name: typing.Union[str, int, ElfSymbol],
632
+ value: int,
633
+ dynamic: bool = False,
634
+ rebase: bool = True,
553
635
  ) -> None:
554
- syms = self._get_symbols(name)
555
- if len(syms) > 1:
556
- raise ConfigurationError(f"Multiple syms named {name}")
557
- sym = syms[0]
636
+ """Update the value of a symbol
637
+
638
+ This will alter the value of the symbol,
639
+ and also propagate that updated value according to any associated relocations.
640
+
641
+ Arguments:
642
+ name: The name of the symbol, its index into the symbol table, or a specific symbol object
643
+ value: The new value for the symbol
644
+ dynamic: If specified by index, whether to look in the static or dynamic symbol table
645
+ rebase: Whether the recorded value is relative to the base address of this ELF.
646
+ """
647
+
648
+ if isinstance(name, ElfSymbol):
649
+ sym = name
650
+ else:
651
+ syms = self._get_symbols(name, dynamic)
652
+ if len(syms) > 1:
653
+ raise ConfigurationError(f"Multiple syms named {name}")
654
+ sym = syms[0]
558
655
 
559
656
  if rebase:
560
657
  # Value provided is absolute; rebase it to the symbol's base address
@@ -563,12 +660,69 @@ class ElfExecutable(Executable):
563
660
  # Update the value
564
661
  sym.value = value
565
662
 
663
+ # Mark this symbol as defined
664
+ sym.defined = True
665
+
566
666
  if self._relocator is not None:
567
667
  for rela in sym.relas:
568
668
  # Relocate!
669
+ log.info(f"Relocating {rela}")
569
670
  self._relocator.relocate(self, rela)
570
671
  else:
571
672
  log.error(f"No platform defined; cannot relocate {name}!")
572
673
 
674
+ def link_elf(self, elf: "ElfExecutable", dynamic: bool = True) -> None:
675
+ """Link one ELF against another
676
+
677
+ This roughly mimics the ELF linker;
678
+ it looks for undefined symbols in the current file,
679
+ and tries to populate their values from matching defined symbols
680
+ from another file.
681
+
682
+ Arguments:
683
+ elf: The ELF from which to draw symbol values
684
+ dynamic: Whether to link static or dynamic symbols
685
+ """
686
+ if dynamic:
687
+ # Relocate rela.dyn and rela.plt
688
+ relas = self._dynamic_relas
689
+ else:
690
+ # relocate static relocations
691
+ relas = self._static_relas
692
+
693
+ for rela in relas:
694
+ my_sym = rela.symbol
695
+ if my_sym.name == "":
696
+ # This isn't a real symbol
697
+ continue
698
+ if my_sym.defined:
699
+ # This is a defined symbol
700
+ continue
701
+
702
+ try:
703
+ o_syms = elf._get_symbols(my_sym.name, dynamic)
704
+ except ConfigurationError:
705
+ continue
706
+
707
+ o_syms = list(filter(lambda x: x.defined, o_syms))
708
+ if len(o_syms) == 0:
709
+ continue
710
+
711
+ if len(set(map(lambda x: x.value, o_syms))) > 1:
712
+ # Catch multiple symbols
713
+ # If they all have the same value, we don't care.
714
+ log.warning(f"Multiple symbols for {my_sym.name}")
715
+ continue
716
+
717
+ o_sym = o_syms[0]
718
+ self.update_symbol_value(my_sym, o_sym.value + o_sym.baseaddr, rebase=True)
719
+
720
+ def __getstate__(self):
721
+ # Override the default pickling mechanism.
722
+ # We can't save any lief data through a copy.
723
+ state = self.__dict__.copy()
724
+ state["_elf"] = None
725
+ return state
726
+
573
727
 
574
728
  __all__ = ["ElfExecutable"]