smallworld-re 1.0.3__py3-none-any.whl → 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smallworld/analyses/__init__.py +8 -0
- smallworld/analyses/analysis.py +8 -67
- smallworld/analyses/code_coverage.py +1 -2
- smallworld/analyses/colorizer.py +301 -534
- smallworld/analyses/colorizer_def_use.py +217 -0
- smallworld/analyses/colorizer_summary.py +173 -83
- smallworld/analyses/field_detection/field_analysis.py +7 -8
- smallworld/analyses/field_detection/hints.py +1 -1
- smallworld/analyses/field_detection/malloc.py +2 -2
- smallworld/analyses/trace_execution.py +160 -0
- smallworld/analyses/trace_execution_types.py +42 -0
- smallworld/analyses/unstable/angr/divergence.py +1 -2
- smallworld/analyses/unstable/angr/model.py +5 -6
- smallworld/analyses/unstable/angr_nwbt.py +3 -4
- smallworld/analyses/unstable/code_coverage.py +2 -3
- smallworld/analyses/unstable/code_reachable.py +2 -3
- smallworld/analyses/unstable/control_flow_tracer.py +2 -3
- smallworld/analyses/unstable/pointer_finder.py +2 -3
- smallworld/analyses/unstable/utils/tui.py +71 -0
- smallworld/emulators/__init__.py +3 -1
- smallworld/emulators/angr/angr.py +30 -9
- smallworld/emulators/angr/machdefs/__init__.py +2 -0
- smallworld/emulators/angr/machdefs/aarch64.py +1 -1
- smallworld/emulators/angr/machdefs/amd64.py +0 -4
- smallworld/emulators/angr/machdefs/arm.py +0 -2
- smallworld/emulators/angr/machdefs/i386.py +0 -2
- smallworld/emulators/angr/machdefs/loongarch.py +340 -0
- smallworld/emulators/angr/machdefs/machdef.py +1 -8
- smallworld/emulators/angr/machdefs/mips.py +0 -2
- smallworld/emulators/angr/machdefs/mips64.py +0 -2
- smallworld/emulators/angr/machdefs/ppc.py +1 -2
- smallworld/emulators/angr/machdefs/riscv.py +8 -10
- smallworld/emulators/angr/machdefs/xtensa.py +7 -4
- smallworld/emulators/emulator.py +22 -0
- smallworld/emulators/ghidra/__init__.py +37 -0
- smallworld/emulators/ghidra/ghidra.py +513 -0
- smallworld/emulators/ghidra/machdefs/__init__.py +31 -0
- smallworld/emulators/ghidra/machdefs/aarch64.py +289 -0
- smallworld/emulators/ghidra/machdefs/amd64.py +185 -0
- smallworld/emulators/ghidra/machdefs/arm.py +370 -0
- smallworld/emulators/ghidra/machdefs/i386.py +109 -0
- smallworld/emulators/ghidra/machdefs/loongarch.py +162 -0
- smallworld/emulators/ghidra/machdefs/machdef.py +81 -0
- smallworld/emulators/ghidra/machdefs/mips.py +163 -0
- smallworld/emulators/ghidra/machdefs/mips64.py +186 -0
- smallworld/emulators/ghidra/machdefs/ppc.py +98 -0
- smallworld/emulators/ghidra/machdefs/riscv.py +208 -0
- smallworld/emulators/ghidra/machdefs/xtensa.py +21 -0
- smallworld/emulators/ghidra/typing.py +28 -0
- smallworld/emulators/hookable.py +18 -4
- smallworld/emulators/panda/machdefs/__init__.py +2 -2
- smallworld/emulators/panda/machdefs/aarch64.py +186 -11
- smallworld/emulators/panda/machdefs/amd64.py +103 -11
- smallworld/emulators/panda/machdefs/arm.py +216 -20
- smallworld/emulators/panda/machdefs/i386.py +30 -7
- smallworld/emulators/panda/machdefs/machdef.py +9 -16
- smallworld/emulators/panda/machdefs/mips.py +49 -5
- smallworld/emulators/panda/machdefs/mips64.py +57 -5
- smallworld/emulators/panda/machdefs/ppc.py +38 -13
- smallworld/emulators/panda/panda.py +146 -44
- smallworld/emulators/unicorn/__init__.py +2 -0
- smallworld/emulators/unicorn/machdefs/aarch64.py +253 -264
- smallworld/emulators/unicorn/machdefs/amd64.py +254 -259
- smallworld/emulators/unicorn/machdefs/arm.py +200 -212
- smallworld/emulators/unicorn/machdefs/i386.py +84 -90
- smallworld/emulators/unicorn/machdefs/machdef.py +2 -23
- smallworld/emulators/unicorn/machdefs/mips.py +127 -135
- smallworld/emulators/unicorn/unicorn.py +52 -13
- smallworld/helpers.py +4 -19
- smallworld/hinting/hinting.py +22 -192
- smallworld/hinting/hints.py +50 -18
- smallworld/instructions/bsid.py +8 -8
- smallworld/logging.py +4 -2
- smallworld/platforms/__init__.py +12 -0
- smallworld/platforms/defs/__init__.py +36 -0
- smallworld/platforms/defs/aarch64.py +450 -0
- smallworld/platforms/defs/amd64.py +463 -0
- smallworld/platforms/defs/arm.py +519 -0
- smallworld/platforms/defs/i386.py +258 -0
- smallworld/platforms/defs/loongarch.py +270 -0
- smallworld/platforms/defs/mips.py +321 -0
- smallworld/platforms/defs/mips64.py +313 -0
- smallworld/platforms/defs/platformdef.py +97 -0
- smallworld/platforms/defs/powerpc.py +259 -0
- smallworld/platforms/defs/riscv.py +257 -0
- smallworld/platforms/defs/xtensa.py +96 -0
- smallworld/{platforms.py → platforms/platforms.py} +3 -0
- smallworld/state/cpus/__init__.py +2 -0
- smallworld/state/cpus/aarch64.py +0 -9
- smallworld/state/cpus/amd64.py +6 -28
- smallworld/state/cpus/arm.py +0 -11
- smallworld/state/cpus/cpu.py +0 -11
- smallworld/state/cpus/i386.py +0 -7
- smallworld/state/cpus/loongarch.py +299 -0
- smallworld/state/cpus/mips.py +4 -47
- smallworld/state/cpus/mips64.py +18 -58
- smallworld/state/cpus/powerpc.py +2 -9
- smallworld/state/cpus/riscv.py +1 -11
- smallworld/state/cpus/xtensa.py +0 -5
- smallworld/state/memory/code.py +38 -2
- smallworld/state/memory/elf/__init__.py +5 -1
- smallworld/state/memory/elf/coredump/__init__.py +3 -0
- smallworld/state/memory/elf/coredump/coredump.py +46 -0
- smallworld/state/memory/elf/coredump/prstatus/__init__.py +27 -0
- smallworld/state/memory/elf/coredump/prstatus/aarch64.py +46 -0
- smallworld/state/memory/elf/coredump/prstatus/amd64.py +40 -0
- smallworld/state/memory/elf/coredump/prstatus/arm.py +53 -0
- smallworld/state/memory/elf/coredump/prstatus/i386.py +30 -0
- smallworld/state/memory/elf/coredump/prstatus/mips.py +55 -0
- smallworld/state/memory/elf/coredump/prstatus/mips64.py +57 -0
- smallworld/state/memory/elf/coredump/prstatus/ppc.py +82 -0
- smallworld/state/memory/elf/coredump/prstatus/prstatus.py +129 -0
- smallworld/state/memory/elf/elf.py +211 -57
- smallworld/state/memory/elf/register_state.py +36 -0
- smallworld/state/memory/elf/rela/__init__.py +2 -0
- smallworld/state/memory/elf/rela/aarch64.py +3 -1
- smallworld/state/memory/elf/rela/amd64.py +4 -2
- smallworld/state/memory/elf/rela/arm.py +4 -2
- smallworld/state/memory/elf/rela/i386.py +4 -2
- smallworld/state/memory/elf/rela/loongarch.py +32 -0
- smallworld/state/memory/elf/rela/mips.py +39 -18
- smallworld/state/memory/elf/rela/ppc.py +31 -14
- smallworld/state/memory/elf/structs.py +3 -0
- smallworld/state/memory/heap.py +2 -2
- smallworld/state/memory/memory.py +18 -0
- smallworld/state/memory/pe/__init__.py +3 -0
- smallworld/state/memory/pe/pe.py +361 -0
- smallworld/state/memory/pe/structs.py +60 -0
- smallworld/state/memory/stack/__init__.py +2 -0
- smallworld/state/memory/stack/loongarch.py +26 -0
- smallworld/state/models/__init__.py +29 -2
- smallworld/state/models/aarch64/__init__.py +1 -0
- smallworld/state/models/aarch64/systemv/__init__.py +6 -0
- smallworld/state/models/aarch64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/aarch64/systemv/c99/signal.py +16 -0
- smallworld/state/models/aarch64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/aarch64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/aarch64/systemv/c99/string.py +139 -0
- smallworld/state/models/aarch64/systemv/c99/time.py +61 -0
- smallworld/state/models/aarch64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/aarch64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/aarch64/systemv/posix/signal.py +157 -0
- smallworld/state/models/aarch64/systemv/systemv.py +80 -0
- smallworld/state/models/amd64/__init__.py +1 -0
- smallworld/state/models/amd64/systemv/__init__.py +6 -0
- smallworld/state/models/amd64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/amd64/systemv/c99/signal.py +16 -0
- smallworld/state/models/amd64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/amd64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/amd64/systemv/c99/string.py +139 -0
- smallworld/state/models/amd64/systemv/c99/time.py +61 -0
- smallworld/state/models/amd64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/amd64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/amd64/systemv/posix/signal.py +157 -0
- smallworld/state/models/amd64/systemv/systemv.py +78 -0
- smallworld/state/models/armel/__init__.py +1 -0
- smallworld/state/models/armel/systemv/__init__.py +6 -0
- smallworld/state/models/armel/systemv/c99/__init__.py +12 -0
- smallworld/state/models/armel/systemv/c99/signal.py +16 -0
- smallworld/state/models/armel/systemv/c99/stdio.py +265 -0
- smallworld/state/models/armel/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/armel/systemv/c99/string.py +139 -0
- smallworld/state/models/armel/systemv/c99/time.py +61 -0
- smallworld/state/models/armel/systemv/posix/__init__.py +6 -0
- smallworld/state/models/armel/systemv/posix/libgen.py +16 -0
- smallworld/state/models/armel/systemv/posix/signal.py +157 -0
- smallworld/state/models/armel/systemv/systemv.py +82 -0
- smallworld/state/models/armhf/__init__.py +1 -0
- smallworld/state/models/armhf/systemv/__init__.py +6 -0
- smallworld/state/models/armhf/systemv/c99/__init__.py +12 -0
- smallworld/state/models/armhf/systemv/c99/signal.py +16 -0
- smallworld/state/models/armhf/systemv/c99/stdio.py +265 -0
- smallworld/state/models/armhf/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/armhf/systemv/c99/string.py +139 -0
- smallworld/state/models/armhf/systemv/c99/time.py +61 -0
- smallworld/state/models/armhf/systemv/posix/__init__.py +6 -0
- smallworld/state/models/armhf/systemv/posix/libgen.py +16 -0
- smallworld/state/models/armhf/systemv/posix/signal.py +157 -0
- smallworld/state/models/armhf/systemv/systemv.py +77 -0
- smallworld/state/models/c99/__init__.py +12 -0
- smallworld/state/models/c99/fmt_print.py +915 -0
- smallworld/state/models/c99/fmt_scan.py +864 -0
- smallworld/state/models/c99/math.py +362 -0
- smallworld/state/models/c99/signal.py +71 -0
- smallworld/state/models/c99/stdio.py +1305 -0
- smallworld/state/models/c99/stdlib.py +595 -0
- smallworld/state/models/c99/string.py +674 -0
- smallworld/state/models/c99/time.py +340 -0
- smallworld/state/models/c99/utils.py +89 -0
- smallworld/state/models/cstd.py +759 -0
- smallworld/state/models/errno.py +581 -0
- smallworld/state/models/filedesc.py +515 -0
- smallworld/state/models/i386/__init__.py +1 -0
- smallworld/state/models/i386/systemv/__init__.py +6 -0
- smallworld/state/models/i386/systemv/c99/__init__.py +12 -0
- smallworld/state/models/i386/systemv/c99/signal.py +16 -0
- smallworld/state/models/i386/systemv/c99/stdio.py +265 -0
- smallworld/state/models/i386/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/i386/systemv/c99/string.py +139 -0
- smallworld/state/models/i386/systemv/c99/time.py +61 -0
- smallworld/state/models/i386/systemv/posix/__init__.py +6 -0
- smallworld/state/models/i386/systemv/posix/libgen.py +16 -0
- smallworld/state/models/i386/systemv/posix/signal.py +157 -0
- smallworld/state/models/i386/systemv/systemv.py +71 -0
- smallworld/state/models/loongarch64/__init__.py +1 -0
- smallworld/state/models/loongarch64/systemv/__init__.py +6 -0
- smallworld/state/models/loongarch64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/loongarch64/systemv/c99/signal.py +16 -0
- smallworld/state/models/loongarch64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/loongarch64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/loongarch64/systemv/c99/string.py +139 -0
- smallworld/state/models/loongarch64/systemv/c99/time.py +61 -0
- smallworld/state/models/loongarch64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/loongarch64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/loongarch64/systemv/posix/signal.py +157 -0
- smallworld/state/models/loongarch64/systemv/systemv.py +83 -0
- smallworld/state/models/mips/__init__.py +1 -0
- smallworld/state/models/mips/systemv/__init__.py +6 -0
- smallworld/state/models/mips/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mips/systemv/c99/signal.py +16 -0
- smallworld/state/models/mips/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mips/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mips/systemv/c99/string.py +139 -0
- smallworld/state/models/mips/systemv/c99/time.py +61 -0
- smallworld/state/models/mips/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mips/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mips/systemv/posix/signal.py +157 -0
- smallworld/state/models/mips/systemv/systemv.py +78 -0
- smallworld/state/models/mips64/__init__.py +1 -0
- smallworld/state/models/mips64/systemv/__init__.py +6 -0
- smallworld/state/models/mips64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mips64/systemv/c99/signal.py +16 -0
- smallworld/state/models/mips64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mips64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mips64/systemv/c99/string.py +139 -0
- smallworld/state/models/mips64/systemv/c99/time.py +61 -0
- smallworld/state/models/mips64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mips64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mips64/systemv/posix/signal.py +157 -0
- smallworld/state/models/mips64/systemv/systemv.py +98 -0
- smallworld/state/models/mips64el/__init__.py +1 -0
- smallworld/state/models/mips64el/systemv/__init__.py +6 -0
- smallworld/state/models/mips64el/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mips64el/systemv/c99/signal.py +16 -0
- smallworld/state/models/mips64el/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mips64el/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mips64el/systemv/c99/string.py +139 -0
- smallworld/state/models/mips64el/systemv/c99/time.py +61 -0
- smallworld/state/models/mips64el/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mips64el/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mips64el/systemv/posix/signal.py +157 -0
- smallworld/state/models/mips64el/systemv/systemv.py +96 -0
- smallworld/state/models/mipsel/__init__.py +1 -0
- smallworld/state/models/mipsel/systemv/__init__.py +6 -0
- smallworld/state/models/mipsel/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mipsel/systemv/c99/signal.py +16 -0
- smallworld/state/models/mipsel/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mipsel/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mipsel/systemv/c99/string.py +139 -0
- smallworld/state/models/mipsel/systemv/c99/time.py +61 -0
- smallworld/state/models/mipsel/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mipsel/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mipsel/systemv/posix/signal.py +157 -0
- smallworld/state/models/mipsel/systemv/systemv.py +78 -0
- smallworld/state/models/model.py +27 -2
- smallworld/state/models/posix/__init__.py +6 -0
- smallworld/state/models/posix/libgen.py +123 -0
- smallworld/state/models/posix/signal.py +690 -0
- smallworld/state/models/powerpc/__init__.py +1 -0
- smallworld/state/models/powerpc/systemv/__init__.py +6 -0
- smallworld/state/models/powerpc/systemv/c99/__init__.py +12 -0
- smallworld/state/models/powerpc/systemv/c99/signal.py +16 -0
- smallworld/state/models/powerpc/systemv/c99/stdio.py +265 -0
- smallworld/state/models/powerpc/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/powerpc/systemv/c99/string.py +139 -0
- smallworld/state/models/powerpc/systemv/c99/time.py +61 -0
- smallworld/state/models/powerpc/systemv/posix/__init__.py +6 -0
- smallworld/state/models/powerpc/systemv/posix/libgen.py +16 -0
- smallworld/state/models/powerpc/systemv/posix/signal.py +157 -0
- smallworld/state/models/powerpc/systemv/systemv.py +93 -0
- smallworld/state/models/riscv64/__init__.py +1 -0
- smallworld/state/models/riscv64/systemv/__init__.py +6 -0
- smallworld/state/models/riscv64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/riscv64/systemv/c99/signal.py +16 -0
- smallworld/state/models/riscv64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/riscv64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/riscv64/systemv/c99/string.py +139 -0
- smallworld/state/models/riscv64/systemv/c99/time.py +61 -0
- smallworld/state/models/riscv64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/riscv64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/riscv64/systemv/posix/signal.py +157 -0
- smallworld/state/models/riscv64/systemv/systemv.py +85 -0
- smallworld/state/state.py +65 -24
- smallworld/state/unstable/elf.py +16 -31
- smallworld/utils.py +6 -1
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/METADATA +74 -42
- smallworld_re-2.0.0.dist-info/RECORD +374 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/WHEEL +1 -1
- smallworld/state/models/x86/__init__.py +0 -2
- smallworld/state/models/x86/microsoftcdecl.py +0 -35
- smallworld/state/models/x86/systemv.py +0 -240
- smallworld_re-1.0.3.dist-info/RECORD +0 -166
- /smallworld/state/models/{posix.py → _posix.py} +0 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/entry_points.txt +0 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/licenses/LICENSE.txt +0 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/top_level.txt +0 -0
@@ -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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
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.
|
537
|
+
self._dynamic_relas.append(rela)
|
504
538
|
|
505
539
|
gotoff += gotent
|
506
540
|
|
507
|
-
for r in elf.
|
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.
|
551
|
+
self._dynamic_relas.append(rela)
|
515
552
|
|
516
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
630
|
+
self,
|
631
|
+
name: typing.Union[str, int, ElfSymbol],
|
632
|
+
value: int,
|
633
|
+
dynamic: bool = False,
|
634
|
+
rebase: bool = True,
|
553
635
|
) -> None:
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
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"]
|